Module: CommandKit::Interactive

Includes:
Stdio
Defined in:
lib/command_kit/interactive.rb

Overview

Provides methods for asking the user for input.

Examples

first_name = ask("First name")
last_name = ask("Last name")

Asking for secret input

password = ask_secret("Password")

Asking Y/N?

if ask_yes_or_no("Proceed anyways?")
  # ...
else
  stderr.puts "Aborting!"
end

Asking multi-choice questions

ask_multiple_choice("Select a flavor", %w[Apple Orange Lemon Lime])
#   1) Apple
#   2) Orange
#   3) Lemon
#   4) Lime
#   Select a flavor: 4
#
# => "Lime"

Instance Method Summary collapse

Methods included from Stdio

#abort, #gets, #initialize, #print, #printf, #putc, #puts, #readline, #readlines, #stderr, #stdin, #stdout

Instance Method Details

#ask(prompt, default: nil, required: false) ⇒ String

Asks the user for input.

Examples:

first_name = ask("First name")
last_name = ask("Last name")

Default value:

ask("Country", default: "EU")
# Country [EU]: <enter>
# => "EU"

Required non-empty input:

ask("Email", required: true)
# Email: <enter>
# Email: [email protected]<enter>
# => "[email protected]"

Parameters:

  • prompt (String)

    The prompt that will be printed before reading input.

  • default (String, nil) (defaults to: nil)

    The default value to return if no input is given.

  • required (Boolean) (defaults to: false)

    Requires non-empty input.

Returns:

  • (String)

    The user input.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/command_kit/interactive.rb', line 72

def ask(prompt, default: nil, required: false)
  prompt = prompt.chomp
  prompt << " [#{default}]" if default
  prompt << ": "

  stdout.print(prompt)

  loop do
    value = stdin.gets(chomp: true)
    value ||= '' # convert nil values (ctrl^D) to an empty String

    if value.empty?
      if required
        next
      else
        return (default || value)
      end
    else
      return value
    end
  end
end

#ask_multiple_choice(prompt, choices, **kwargs) ⇒ String

Asks the user to select a choice from a list of options.

Examples:

Array of choices:

ask_multiple_choice("Select a flavor", %w[Apple Orange Lemon Lime])
#   1) Apple
#   2) Orange
#   3) Lemon
#   4) Lime
#   Select a flavor: 4
#
# => "Lime"

Hash of choices:

ask_multiple_choice("Select an option", {'A' => 'Foo',
                                         'B' => 'Bar',
                                         'X' => 'All of the above'})
#   A) Foo
#   B) Bar
#   X) All of the above
#   Select an option: X
#
# => "All of the above"

Parameters:

  • prompt (String)

    The prompt that will be printed before reading input.

  • choices (Hash{String => String}, Array<String>)

    The choices to select from.

  • kwargs (Hash{Symbol => Object})

    Additional keyword arguments for #ask.

Options Hash (**kwargs):

  • default (String, nil)

    The default option to fallback to, if no input is given.

  • required (Boolean)

    Requires non-empty input.

Returns:

  • (String)

    The selected choice.



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/command_kit/interactive.rb', line 185

def ask_multiple_choice(prompt,choices,**kwargs)
  choices = case choices
            when Array
              Hash[choices.each_with_index.map { |value,i|
                [(i+1).to_s, value]
              }]
            when Hash
              choices
            else
              raise(TypeError,"unsupported choices class #{choices.class}: #{choices.inspect}")
            end

  prompt = "#{prompt} (#{choices.keys.join(', ')})"

  loop do
    # print the choices
    choices.each do |choice,value|
      stdout.puts "  #{choice}) #{value}"
    end
    stdout.puts

    # read the choice
    choice = ask(prompt,**kwargs)

    if choices.has_key?(choice)
      # if a valid choice is given, return the value
      return choices[choice]
    else
      stderr.puts "Invalid selection: #{choice}"
    end
  end
end

#ask_secret(prompt, required: true) ⇒ String

Asks the user for secret input.

Examples:

ask_secret("Password")
# Password: 
# => "s3cr3t"

Parameters:

  • prompt (String)

    The prompt that will be printed before reading input.

  • required (Boolean) (defaults to: true)

    Requires non-empty input.

Returns:

  • (String)

    The user input.



237
238
239
240
241
242
243
244
245
# File 'lib/command_kit/interactive.rb', line 237

def ask_secret(prompt, required: true)
  if stdin.respond_to?(:noecho)
    stdin.noecho do
      ask(prompt, required: required)
    end
  else
    ask(prompt, required: required)
  end
end

#ask_yes_or_no(prompt, default: nil, **kwargs) ⇒ Boolean

Asks the user a yes or no question.

Examples:

ask_yes_or_no("Proceed anyways?")
# Proceed anyways? (Y/N): Y
# => true

Default value:

ask_yes_or_no("Proceed anyways?", default: true)
# Proceed anyways? (Y/N) [Y]: <enter>
# => true

Parameters:

  • prompt (String)

    The prompt that will be printed before reading input.

  • default (true, false, nil) (defaults to: nil)

Returns:

  • (Boolean)

    Specifies whether the user entered Y/yes.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/command_kit/interactive.rb', line 118

def ask_yes_or_no(prompt, default: nil, **kwargs)
  default = case default
            when true  then 'Y'
            when false then 'N'
            when nil  then nil
            else
              raise(ArgumentError,"invalid default: #{default.inspect}")
            end

  prompt = "#{prompt} (Y/N)"

  loop do
    answer = ask(prompt, **kwargs, default: default)

    case answer.downcase
    when 'y', 'yes'
      return true
    else
      return false
    end
  end
end