Highline Wrapper
A little wrapper to help ask some easy questions via the command-line with Highline. The types of questions this wrapper supports is:
- Open-ended question
- Yes/No question
- Multiple choice question where the user is allowed to select one answer
- Multiple choice "checkbox" question where the user is allowed to select multiple answers
Installation
Add this line to your application's Gemfile:
gem 'highline_wrapper'
And then execute:
bundle install
Or install it yourself as:
gem install highline_wrapper
Usage
Once this gem is installed, you can then initiate a new HighlineWrapper
object:
HighlineWrapper.new
Then, add this to the top of your file (or to your gem):
require 'highline_wrapper'
Then, you can call its questions to receive answers. There's several configuration options for each type of question. Look below for the different options for each type of question, and what they each return.
Open-ended questions
Question configuration options:
-
default
: defaults to''
-
indicate_default_message
: defaults totrue
-
required
: defaults tofalse
-
secret
: defaults tofalse
Notes:
- If
default
is''
andrequired
isfalse
, and the user skips the question, the answer will be''
- If
indicate_default_message
istrue
, then the wrapper will tell us what the default value returned is if the user skips the question- If
secret
istrue
, then the wrapper may automatically add a newline after a skipped answer... this is automatic from HighLine and is, unfortunately, out of the wrapper's control
- If
- If
required
istrue
, the question will repeat until the user answers the question - If
required
istrue
, then thedefault
value will be ignored (defaults to''
, but could be set to whatever and the code won't care... the question is required) - If
secret
istrue
, then the command-line will hide the user's answer behind*
> HighlineWrapper.new.ask('What is your favorite number?')
What is your favorite number?
four
=> "four"
> HighlineWrapper.new.ask('What is your favorite number?', {required: true})
What is your favorite number?
--- This question is required ---
What is your favorite number?
--- This question is required ---
What is your favorite number?
--- This question is required ---
What is your favorite number?
2
=> "2"
> HighlineWrapper.new.ask('What is your favorite number?', {required: true, indicate_default_message: false})
What is your favorite number?
--- This question is required ---
What is your favorite number?
--- This question is required ---
What is your favorite number?
5
=> "5"
> HighlineWrapper.new.ask('What is your favorite number?', {indicate_default_message: false})
What is your favorite number?
=> ""
> HighlineWrapper.new.ask('What is your favorite color?')
What is your favorite color?
--- Default selected: EMPTY ---
=> ""
> HighlineWrapper.new.ask('What is your favorite color?', {default: 'orange'})
What is your favorite color?
--- Default selected: orange ---
=> "orange"
> HighlineWrapper.new.ask('Please type your private token:', {secret: true})
Please type your private token?
****************
=> "MY-PRIVATE-TOKEN"
> HighlineWrapper.new.ask('Please type your private token:', {secret: true, indicate_default_message: false})
Please type your private token:
=> ""
> HighlineWrapper.new.ask('Please type your private token:', {secret: true, required: true})
Please type your private token:
--- This question is required ---
Please type your private token:
--- This question is required ---
Please type your private token:
****************
=> "MY-PRIVATE-TOKEN"
> HighlineWrapper.new.ask('Please type your private token:', {secret: true})
Please type your private token:
--- Default selected: HIDDEN ---
=> ""
Yes/No questions
Question configuration options:
-
default
: defaults totrue
(aka 'yes') -
indicate_default_message
: defaults totrue
-
required
: defaults tofalse
Notes:
- If
default
istrue
andrequired
isfalse
, and the user skips the question, the answer will betrue
- If
indicate_default_message
istrue
, then the wrapper will tell us what the default value returned is if the user skips the question - If
required
istrue
, the question will repeat until the user answers the question - If
required
istrue
, then thedefault
value will be ignored (defaults totrue
, but could be set to whatever and the code won't care... the question is required) - The response to the question MUST be given either as
y
/n
/yes
/no
or with any capitalization... anything else given as a response will be unparseable
> HighlineWrapper.new.ask_yes_no('Do you like Ruby?')
Do you like Ruby?
--- Default selected: YES ---
=> true
> HighlineWrapper.new.ask_yes_no('Do you like Ruby?', {indicate_default_message: false})
Do you like Ruby?
=> true
> HighlineWrapper.new.ask_yes_no('Do you like Ruby?')
Do you like Ruby?
no
=> false
> HighlineWrapper.new.ask_yes_no('Do you like Ruby?', {default: false})
Do you like Ruby?
--- Default selected: NO ---
=> false
> HighlineWrapper.new.ask_yes_no('Do you like Ruby?', {required: true})
Do you like Ruby?
--- This question is required ---
Do you like Ruby?
--- This question is required ---
Do you like Ruby?
--- This question is required ---
Do you like Ruby?
N
=> false
> HighlineWrapper.new.ask_yes_no('Do you like Ruby?')
Do you like Ruby?
uh-huh
--- This question is required ---
Do you like Ruby?
YES
=> true
> HighlineWrapper.new.ask_yes_no('Do you like Ruby?')
Do you like Ruby?
yep
--- This question is required ---
Do you like Ruby?
yes
=> true
Multiple choice questions
Question configuration options:
-
default
: defaults tonil
-
indicate_default_message
: defaults totrue
-
required
: defaults tofalse
-
with_index
: defaults tofalse
(particularly handy when there may be duplicate-named but different items in the list—think Sally with ID 45 and Sally with ID 72)
Notes:
- If
default
isnil
andrequired
isfalse
, and the user skips the question, the answer will benil
- If
indicate_default_message
istrue
, then the wrapper will tell us what the default value returned is if the user skips the question - If
required
istrue
, the question will repeat until the user answers the question - If
required
istrue
, then thedefault
value will be ignored (defaults tonil
, but could be set to whatever and the code won't care... the question is required) - If
with_index
istrue
, a hash will be returned with the choice AND the index of the selection in the originalchoices
array- e.g.
{ value: 'c', index: 2 }
- e.g.
- If
with_index
isfalse
, then a hash of one item will be returned- e.g.
{ value: 'c' }
- e.g.
> HighlineWrapper.new.ask_multiple_choice('What is your favorite number of these?', ['one', 'two', 'three'])
What is your favorite number of these?
1. one
2. two
3. three
2
=> {:value=>"two"}
> HighlineWrapper.new.ask_multiple_choice('What is your favorite number of these?', ['one', 'two', 'three'], {with_index: true})
What is your favorite number of these?
1. one
2. two
3. three
2
=> {:value=>"two", :index=>1}
> HighlineWrapper.new.ask_multiple_choice('What is your favorite number of these?', ['one', 'two', 'three'], {default: 'three', required: true, indicate_default_message: false})
What is your favorite number of these?
1. one
2. two
3. three
--- This question is required ---
What is your favorite number of these?
1. one
2. two
3. three
--- This question is required ---
What is your favorite number of these?
1. one
2. two
3. three
2
=> {:value=>"two"}
> HighlineWrapper.new.ask_multiple_choice('What is your favorite number of these?', ['one', 'two', 'three'], {with_index: true, default: 'one'})
What is your favorite number of these?
1. one
2. two
3. three
--- Default selected: 1. one ---
=> {:value=>"one", :index=>0}
> HighlineWrapper.new.ask_multiple_choice('What is your favorite number of these?', ['one', 'two', 'three'], {with_index: true, default: 'one', indicate_default_message: false})
What is your favorite number of these?
1. one
2. two
3. three
=> {:value=>"one", :index=>0}
> HighlineWrapper.new.ask_multiple_choice('What is your favorite number of these?', ['one', 'two', 'three'], {default: 'three', required: true})
What is your favorite number of these?
1. one
2. two
3. three
--- This question is required ---
What is your favorite number of these?
1. one
2. two
3. three
--- This question is required ---
What is your favorite number of these?
1. one
2. two
3. three
1
=> {:value=>"one"}
> HighlineWrapper.new.ask_multiple_choice('What is your favorite number of these?', ['one', 'two', 'three'], {default: nil})
What is your favorite number of these?
1. one
2. two
3. three
--- Default selected: EMPTY ---
=> nil
> HighlineWrapper.new.ask_multiple_choice('What is your favorite number of these?', ['one', 'two', 'three'], {default: nil, with_index: true})
What is your favorite number of these?
1. one
2. two
3. three
--- Default selected: EMPTY ---
=> nil
> HighlineWrapper.new.ask_multiple_choice('What is your favorite number of these?', ['one', 'two', 'three'], {default: nil, with_index: true, indicate_default_message: false})
What is your favorite number of these?
1. one
2. two
3. three
=> nil
Multiple choice "checkbox" questions
Question configuration options:
-
defaults
: defaults to[]
-
indicate_default_message
: defaults totrue
-
required
: defaults tofalse
-
with_indexes
: defaults tofalse
(particularly handy when there may be duplicate-named but different items in the list—think Sally with ID 45 and Sally with ID 72)
Notes:
- If
defaults
is[]
andrequired
isfalse
, then the method will return an empty array - If
indicate_default_message
istrue
, then the wrapper will tell us what the default value returned is if the user skips the question - If
required
istrue
, the question will repeat until the user answers the question - If
required
istrue
, then thedefaults
value will be ignored (this value is defaulting to[]
, but could be set to whatever and the code won't care... the question is required) - If
with_indexes
istrue
, an array of hashes will be returned with the choice AND the index (of the selection in the originalchoices
array) in each hash- e.g.
[{ value: 'a', index: 0 }, { value: 'c', index: 2 }]
- e.g.
- If
with_indexes
isfalse
, then an hashes will be returned where each hash only has a value- e.g.
[{ value: 'a' }, { value: 'c' }]
- e.g.
> HighlineWrapper.new.ask_checkbox("What are your favorite numbers of these?", ['one', 'two','three'])
What are your favorite numbers of these?
1. one
2. two
3. three
1, 3
=> [{:value=>"one"}, {:value=>"three"}]
> HighlineWrapper.new.ask_checkbox("What are your favorite numbers of these?", ['one', 'two','three'], {with_indexes: true})
What are your favorite numbers of these?
1. one
2. two
3. three
1, 3
=> [{:value=>"one", :index=>0}, {:value=>"three", :index=>2}]
> HighlineWrapper.new.ask_checkbox("What are your favorite numbers of these?", ['one', 'two','three'], {with_indexes: true, indicate_default_message: false})
What are your favorite numbers of these?
1. one
2. two
3. three
=> []
> HighlineWrapper.new.ask_checkbox("What are your favorite numbers of these?", ['one', 'two','three'], {with_indexes: true})
What are your favorite numbers of these?
1. one
2. two
3. three
--- Defaults selected: EMPTY ---
=> []
> HighlineWrapper.new.ask_checkbox("What are your favorite numbers of these?", ['one', 'two','three'], {defaults: ['two', 'three']})
What are your favorite numbers of these?
1. one
2. two
3. three
--- Defaults selected: 2. two, 3. three ---
=> [{:value=>"two"}, {:value=>"three"}]
> HighlineWrapper.new.ask_checkbox("What are your favorite numbers of these?", ['one', 'two','three'], {required: true, with_indexes: true})
What are your favorite numbers of these?
1. one
2. two
3. three
--- This question is required ---
What are your favorite numbers of these?
1. one
2. two
3. three
--- This question is required ---
What are your favorite numbers of these?
1. one
2. two
3. three
2
=> [{:value=>"two", :index=>1}]
> HighlineWrapper.new.ask_checkbox("What are your favorite numbers of these?", ['one', 'two','three'], {required: true, with_indexes: false})
What are your favorite numbers of these?
1. one
2. two
3. three
--- This question is required ---
What are your favorite numbers of these?
1. one
2. two
3. three
1
=> [{:value=>"one"}]
> HighlineWrapper.new.ask_checkbox("What are your favorite numbers of these?", ['one', 'two','three'], {defaults: ['two', 'three'], with_indexes: true, indicate_default_message: false})
What are your favorite numbers of these?
1. one
2. two
3. three
=> [{:value=>"two", :index=>1}, {:value=>"three", :index=>2}]
Tests
To run the tests, run bundle exec rspec
from the command-line. GitHub Actions will also run the tests upon every commit to make sure they're up to date and that everything is working correctly. Locally, you can also run bundle exec guard
to automatically run tests as you develop!
Contributing
To submit a feature request, bug ticket, etc, please submit an official GitHub issue. To copy or make changes, please fork this repository. When/if you'd like to contribute back to this upstream, please create a pull request on this repository.
Please follow included Issue Template(s) and Pull Request Template(s) when creating issues or pull requests.
Security Policy
To report any security vulnerabilities, please view this repository's Security Policy.
Licensing
For information on licensing, please see LICENSE.md.
Code of Conduct
When interacting with this repository, please follow Contributor Covenant's Code of Conduct.
Releasing
To make a new release of this gem:
- Merge the pull request via the big green button
- Run
git tag vX.X.X
andgit push --tag
- Make a new release here
- Run
gem build *.gemspec
- Run
gem push *.gem
to push the new gem to RubyGems - Run
rm *.gem
to clean up your local repository
To set up your local machine to push to RubyGems via the API, see the RubyGems documentation.