diff options
author | matrinox <geofflee21@me.com> | 2016-01-24 21:06:56 -0800 |
---|---|---|
committer | Abinoam Praxedes Marques Jr <abinoam@gmail.com> | 2016-02-19 03:57:18 -0300 |
commit | 08f7451a9554df8ca2a165c153011844ad46f9e0 (patch) | |
tree | cc794da112e75bf38fb61d6faa9db273926c5468 | |
parent | db74d876215d9ba1ac82ea21d38475fb27e1677c (diff) | |
download | highline-08f7451a9554df8ca2a165c153011844ad46f9e0.tar.gz |
Fix bug with responses hash not updating with each additional menu choice
Originally, build_responses gave precedence to new hash (which makes sense) but then old hash was given precedence because it allowed the user to set things and let that stick
Instead, the solution should be to split the concerns: one hash for user one hash for internal. The hashes are then merged when outputting, giving the user responses precedence
This does have the side effect of taking away responses reflection on the side of the client but that is easily added in build_responses
-rwxr-xr-x | lib/highline.rb | 2 | ||||
-rwxr-xr-x | lib/highline/question.rb | 36 | ||||
-rw-r--r-- | lib/highline/question_asker.rb | 2 | ||||
-rw-r--r-- | test/test_menu.rb | 20 |
4 files changed, 45 insertions, 15 deletions
diff --git a/lib/highline.rb b/lib/highline.rb index ba409b6..0ef2b57 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -485,7 +485,7 @@ class HighLine # of the question. # def explain_error(error, question) - say(question.responses[error]) if error + say(question.final_responses[error]) if error say(question.ask_on_error_msg) end diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 769da39..3724c67 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -61,7 +61,8 @@ class HighLine @first_answer = nil @directory = Pathname.new(File.expand_path(File.dirname($0))) @glob = "*" - @responses = Hash.new + @user_responses = Hash.new + @internal_responses = default_responses_hash @overwrite = false # allow block to override settings @@ -214,7 +215,9 @@ class HighLine # <tt>:not_valid</tt>:: The error message shown when # validation checks fail. # - attr_reader :responses + def responses + @user_responses + end # # When set to +true+ the question is asked, but output does not progress to # the next line. The Cursor is moved back to the beginning of the question @@ -242,16 +245,21 @@ class HighLine # @return [Hash] responses Hash winner (new and old merge). # @param message_source [Class] Array or String for example. # Same as {#answer_type}. - # @param new_hash_wins [Boolean] merge precedence (new vs. old). - def build_responses(message_source = answer_type, new_hash_wins = false) + def build_responses(message_source = answer_type) append_default if [::String, Symbol].include? default.class - old_hash = responses - new_hash = build_responses_new_hash(message_source) + # Update our internal responses with the new hash + # generated from the message source + @internal_responses = @internal_responses.merge(new_hash) + end - @responses = new_hash_wins ? old_hash.merge(new_hash) : new_hash.merge(old_hash) + def default_responses_hash + { + :ask_on_error => "? ", + :mismatch => "Your entries didn't match." + } end # When updating the responses hash, it generates the new one. @@ -260,17 +268,21 @@ class HighLine def build_responses_new_hash(message_source) { :ambiguous_completion => "Ambiguous choice. Please choose one of " + choice_error_str(message_source) + '.', - :ask_on_error => "? ", :invalid_type => "You must enter a valid #{message_source}.", :no_completion => "You must choose one of " + choice_error_str(message_source) + '.', :not_in_range => "Your answer isn't within the expected range " + "(#{expected_range}).", - :mismatch => "Your entries didn't match.", :not_valid => "Your answer isn't valid (must match " + "#{validate.inspect})." } end + # This is the actual responses hash that gets used in determining output + # Notice that we give @user_responses precedence over the responses + # generated internally via build_response + def final_responses + @internal_responses.merge(@user_responses) + end # # Returns the provided _answer_string_ after changing character case by @@ -531,10 +543,10 @@ class HighLine # @return [self] if :ask_on_error on responses Hash is set to :question # @return [String] if :ask_on_error on responses Hash is set to something else def ask_on_error_msg - if responses[:ask_on_error] == :question + if final_responses[:ask_on_error] == :question self - elsif responses[:ask_on_error] - responses[:ask_on_error] + elsif final_responses[:ask_on_error] + final_responses[:ask_on_error] end end diff --git a/lib/highline/question_asker.rb b/lib/highline/question_asker.rb index b8c8ebc..bb10c9e 100644 --- a/lib/highline/question_asker.rb +++ b/lib/highline/question_asker.rb @@ -119,7 +119,7 @@ class HighLine ## Delegate to Highline def explain_error(error) - @highline.say(question.responses[error]) if error + @highline.say(question.final_responses[error]) if error @highline.say(question.ask_on_error_msg) end diff --git a/test/test_menu.rb b/test/test_menu.rb index 1a53f28..2bcd824 100644 --- a/test/test_menu.rb +++ b/test/test_menu.rb @@ -440,7 +440,6 @@ class TestMenu < Minitest::Test assert_equal(selected, 3) end - def test_cancel_paging # Tests that paging can be cancelled halfway through @terminal.page_at = 5 @@ -460,6 +459,25 @@ class TestMenu < Minitest::Test "Paging message appeared more than once." ) end + def test_autocomplete_prompt + @input << "lisp\nRuby\n" + @input.rewind + + answer = @terminal.choose do |menu| + menu.choice(:Perl) + menu.choice(:Python) + menu.choice(:Ruby) + menu.prompt = "What is your favorite programming language? " + end + languages = [:Perl, :Python, :Ruby] + assert_equal("1. Perl\n" + + "2. Python\n" + + "3. Ruby\n" + + "What is your favorite programming language? " + + "You must choose one of [1, 2, 3, Perl, Python, Ruby].\n" + + "? ", @output.string ) + end + # Issue #180 - https://github.com/JEG2/highline/issues/180 def test_menu_prompt @input << "2\n1\n" |