Module: Philiprehberger::CliKit::Menu
- Defined in:
- lib/philiprehberger/cli_kit/menu.rb
Overview
Numbered menu selection for CLI applications.
Class Method Summary collapse
-
.multi_select(message, choices, defaults: [], input: $stdin, output: $stdout) ⇒ Array<String>
Present a numbered menu and allow multiple selections.
-
.select(message, choices, default: nil, input: $stdin, output: $stdout) ⇒ String
Present a numbered menu and return the selected value.
Class Method Details
.multi_select(message, choices, defaults: [], input: $stdin, output: $stdout) ⇒ Array<String>
Present a numbered menu and allow multiple selections.
The user enters a comma- or space-separated list of numbers (e.g. “1,3” or “1 3”). Unknown or out-of-range entries are ignored, and duplicates are collapsed. An empty answer returns defaults or an empty array if no defaults are given.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/philiprehberger/cli_kit/menu.rb', line 61 def self.multi_select(, choices, defaults: [], input: $stdin, output: $stdout) raise ArgumentError, 'choices must not be empty' if choices.empty? default_indexes = defaults.map { |d| choices.index(d) }.compact output.puts choices.each_with_index do |choice, idx| marker = default_indexes.include?(idx) ? '*' : ' ' output.puts " #{marker} #{idx + 1}) #{choice}" end output.print 'Choose (comma-separated): ' output.flush answer = input.gets&.strip || '' return defaults.dup if answer.empty? picks = answer.split(/[,\s]+/).filter_map do |token| idx = Integer(token, 10) - 1 idx if idx >= 0 && idx < choices.length rescue ArgumentError nil end picks.uniq.sort.map { |i| choices[i] } end |
.select(message, choices, default: nil, input: $stdin, output: $stdout) ⇒ String
Present a numbered menu and return the selected value.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/philiprehberger/cli_kit/menu.rb', line 16 def self.select(, choices, default: nil, input: $stdin, output: $stdout) raise ArgumentError, 'choices must not be empty' if choices.empty? default_index = default ? choices.index(default) : nil output.puts choices.each_with_index do |choice, idx| marker = default_index == idx ? '*' : ' ' output.puts " #{marker} #{idx + 1}) #{choice}" end prompt_text = default ? "Choose [#{default_index + 1}]: " : 'Choose: ' output.print prompt_text output.flush answer = input.gets&.strip || '' if answer.empty? && default return default end index = answer.to_i - 1 if index >= 0 && index < choices.length choices[index] elsif default default else choices.first end end |