class Dev::UI::Prompt::InteractiveOptions
Constants
- ESC
Public Class Methods
call(options)
click to toggle source
Prompts the user with options Uses an interactive session to allow the user to pick an answer Can use arrows, y/n, numbers (1/2), and vim bindings to control
Example Usage:¶ ↑
Ask an interactive question
Dev::UI::Prompt::InteractiveOptions.call(%w(rails go python))
# File lib/dev/ui/prompt/interactive_options.rb, line 18 def self.call(options) list = new(options) options[list.call - 1] end
new(options)
click to toggle source
Initializes a new InteractiveOptions
Usually called from self.call
Example Usage:¶ ↑
Dev::UI::Prompt::InteractiveOptions.new(%w(rails go python))
# File lib/dev/ui/prompt/interactive_options.rb, line 30 def initialize(options) @options = options @active = 1 @marker = '>' @answer = nil @state = :root end
Public Instance Methods
call()
click to toggle source
Calls the InteractiveOptions
and asks the question Usually used from self.call
# File lib/dev/ui/prompt/interactive_options.rb, line 41 def call Dev::UI.raw { print(ANSI.hide_cursor) } while @answer.nil? render_options wait_for_user_input reset_position end clear_output @answer ensure Dev::UI.raw do print(ANSI.show_cursor) puts(ANSI.previous_line + ANSI.end_of_line) end end
Private Instance Methods
clear_output()
click to toggle source
# File lib/dev/ui/prompt/interactive_options.rb, line 68 def clear_output Dev::UI.raw do # Write over all lines with whitespace num_lines.times { puts(' ' * Dev::UI::Terminal.width) } end reset_position end
down()
click to toggle source
# File lib/dev/ui/prompt/interactive_options.rb, line 89 def down @active = @active + 1 <= @options.length ? @active + 1 : 1 end
num_lines()
click to toggle source
# File lib/dev/ui/prompt/interactive_options.rb, line 76 def num_lines # @options will be an array of questions but each option can be multi-line # so to get the # of lines, you need to join then split joined_options = @options.join("\n") joined_options.split("\n").reject(&:empty?).size end
raw_tty!() { || ... }
click to toggle source
# File lib/dev/ui/prompt/interactive_options.rb, line 141 def raw_tty! if ENV['TEST'] || !$stdin.tty? yield else $stdin.raw { yield } end end
read_char()
click to toggle source
rubocop:enable Style/WhenThen,Layout/SpaceBeforeSemicolon
# File lib/dev/ui/prompt/interactive_options.rb, line 135 def read_char raw_tty! { $stdin.getc.chr } rescue IOError "\e" end
render_options()
click to toggle source
# File lib/dev/ui/prompt/interactive_options.rb, line 149 def render_options @options.each_with_index do |choice, index| num = index + 1 message = " #{num}." message += choice.split("\n").map { |l| " {{bold:#{l}}}" }.join("\n") if num == @active message = message.split("\n").map.with_index do |l, idx| idx == 0 ? "{{blue:> #{l.strip}}}" : "{{blue:>#{l.strip}}}" end.join("\n") end Dev::UI.with_frame_color(:blue) do puts Dev::UI.fmt(message) end end end
reset_position()
click to toggle source
# File lib/dev/ui/prompt/interactive_options.rb, line 59 def reset_position # This will put us back at the beginning of the options # When we redraw the options, they will be overwritten Dev::UI.raw do num_lines.times { print(ANSI.previous_line) } print(ANSI.previous_line + ANSI.end_of_line + "\n") end end
select_bool(char)
click to toggle source
# File lib/dev/ui/prompt/interactive_options.rb, line 98 def select_bool(char) return unless (@options - %w(yes no)).empty? opt = @options.detect { |o| o.start_with?(char) } @active = @options.index(opt) + 1 @answer = @options.index(opt) + 1 end
select_n(n)
click to toggle source
# File lib/dev/ui/prompt/interactive_options.rb, line 93 def select_n(n) @active = n @answer = n end
up()
click to toggle source
# File lib/dev/ui/prompt/interactive_options.rb, line 85 def up @active = @active - 1 >= 1 ? @active - 1 : @options.length end
wait_for_user_input()
click to toggle source
rubocop:disable Style/WhenThen,Layout/SpaceBeforeSemicolon
# File lib/dev/ui/prompt/interactive_options.rb, line 106 def wait_for_user_input char = read_char case @state when :root case char when ESC ; @state = :esc when 'k' ; up when 'j' ; down when ('1'..@options.size.to_s) ; select_n(char.to_i) when 'y', 'n' ; select_bool(char) when " ", "\r", "\n" ; @answer = @active # <enter> when "\u0003" ; raise Interrupt # Ctrl-c end when :esc case char when '[' ; @state = :esc_bracket else ; raise Interrupt # unhandled escape sequence. end when :esc_bracket @state = :root case char when 'A' ; up when 'B' ; down else ; raise Interrupt # unhandled escape sequence. end end end