From a38ac7c68506c54e327d819daf916a6752c6f495 Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Sat, 18 Apr 2015 08:02:57 +0100 Subject: Added current gem version to README This is very useful when verifying if I run the latest version. It fetches the version automatically from RubyGems.org --- README.rdoc | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rdoc b/README.rdoc index cbf9ee9..934614b 100644 --- a/README.rdoc +++ b/README.rdoc @@ -3,6 +3,7 @@ by James Edward Gray II {Build Status}[https://travis-ci.org/JEG2/highline] +{}[http://rubygems.org/gems/highline] == Description -- cgit v1.2.1 From 563772ac609ded8a9440357775d25b7b923499c7 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Apr 2015 00:41:04 -0300 Subject: Update VERSION to 1.7.2 --- lib/highline/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline/version.rb b/lib/highline/version.rb index d01247e..618c4cd 100644 --- a/lib/highline/version.rb +++ b/lib/highline/version.rb @@ -1,4 +1,4 @@ class HighLine # The version of the installed library. - VERSION = "1.7.1".freeze + VERSION = "1.7.2".freeze end -- cgit v1.2.1 From 975ac5974248fff7fe9c3ff8ae9d7183af620a8c Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Apr 2015 07:28:51 -0300 Subject: Update Changelog.md for 1.7.2 --- Changelog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Changelog.md b/Changelog.md index 9a58217..49e533e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,11 @@ Below is a complete listing of changes for each revision of HighLine. +### 1.7.2 / 2015-04-19 + +#### Bug fixes +* Fix #138 (a regression of #131). PR #139. + ### 1.7.1 / 2015-02-24 #### Enhancements -- cgit v1.2.1 From de4e1dc517edfb246aa42e57cbcf89a08492317c Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 10 Mar 2015 00:49:54 -0300 Subject: Add Code Climate support Have also to setup environment variable at travis. --- Gemfile | 2 ++ test/test_color_scheme.rb | 1 + test/test_helper.rb | 3 +++ test/test_import.rb | 1 + test/test_menu.rb | 1 + test/test_string_extension.rb | 1 + test/test_string_highline.rb | 1 + test/test_style.rb | 1 + 8 files changed, 11 insertions(+) create mode 100644 test/test_helper.rb diff --git a/Gemfile b/Gemfile index d720f61..a3cc974 100644 --- a/Gemfile +++ b/Gemfile @@ -7,3 +7,5 @@ group(:development, :tests) do gem "code_statistics", :require => false gem "minitest", :require => false end + +gem "codeclimate-test-reporter", group: :test, require: nil \ No newline at end of file diff --git a/test/test_color_scheme.rb b/test/test_color_scheme.rb index 7cb57c4..c37308a 100644 --- a/test/test_color_scheme.rb +++ b/test/test_color_scheme.rb @@ -6,6 +6,7 @@ # This is Free Software. See LICENSE and COPYING for details. require "minitest/autorun" +require "test_helper" require "highline" require "stringio" diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..af0bfeb --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,3 @@ +require "codeclimate-test-reporter" +CodeClimate::TestReporter.start + diff --git a/test/test_import.rb b/test/test_import.rb index aa68366..2177daa 100644 --- a/test/test_import.rb +++ b/test/test_import.rb @@ -6,6 +6,7 @@ # This is Free Software. See LICENSE and COPYING for details. require "minitest/autorun" +require "test_helper" require "highline/import" require "stringio" diff --git a/test/test_menu.rb b/test/test_menu.rb index 2b8fddf..f745e04 100644 --- a/test/test_menu.rb +++ b/test/test_menu.rb @@ -7,6 +7,7 @@ # This is Free Software. See LICENSE and COPYING for details. require "minitest/autorun" +require "test_helper" require "highline" require "stringio" diff --git a/test/test_string_extension.rb b/test/test_string_extension.rb index d774e11..caa85a0 100644 --- a/test/test_string_extension.rb +++ b/test/test_string_extension.rb @@ -5,6 +5,7 @@ # This is Free Software. See LICENSE and COPYING for details. require "minitest/autorun" +require "test_helper" require "highline" require "stringio" diff --git a/test/test_string_highline.rb b/test/test_string_highline.rb index 63e5cfc..1a6d0df 100644 --- a/test/test_string_highline.rb +++ b/test/test_string_highline.rb @@ -5,6 +5,7 @@ # This is Free Software. See LICENSE and COPYING for details. require "minitest/autorun" +require "test_helper" require "highline" require "stringio" diff --git a/test/test_style.rb b/test/test_style.rb index 3c3cc14..84e4e6b 100755 --- a/test/test_style.rb +++ b/test/test_style.rb @@ -5,6 +5,7 @@ # This is Free Software. See LICENSE and COPYING for details. require "minitest/autorun" +require "test_helper" require "highline" require "stringio" -- cgit v1.2.1 From be41e9573dc51c82c9ccf4d1df77ed1b229371c9 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 07:50:12 -0300 Subject: Fix typo on Gemfile --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index a3cc974..4013735 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" gem "rake", :require => false gem "rdoc", :require => false -group(:development, :tests) do +group(:development, :test) do gem "code_statistics", :require => false gem "minitest", :require => false end -- cgit v1.2.1 From 66bb452896008f0f5d247c8a5c932f7f0e902474 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 07:57:58 -0300 Subject: Normalize hash syntax on Gemfile --- Gemfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index 4013735..78534ee 100644 --- a/Gemfile +++ b/Gemfile @@ -1,11 +1,11 @@ source "https://rubygems.org" -gem "rake", :require => false -gem "rdoc", :require => false +gem "rake", require: false +gem "rdoc", require: false -group(:development, :test) do - gem "code_statistics", :require => false - gem "minitest", :require => false +group :development, :test do + gem "code_statistics", require: false + gem "minitest", require: false end -gem "codeclimate-test-reporter", group: :test, require: nil \ No newline at end of file +gem "codeclimate-test-reporter", group: :test, require: false \ No newline at end of file -- cgit v1.2.1 From 6ae9ba3b9d4492e1bedb652fbba16c582769cf58 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 10:59:34 -0300 Subject: Move statement formatting code to a separate class --- lib/highline.rb | 64 ---------------------------------------------- lib/highline/statement.rb | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 64 deletions(-) create mode 100644 lib/highline/statement.rb diff --git a/lib/highline.rb b/lib/highline.rb index 4528d44..d4afc6e 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -724,25 +724,6 @@ class HighLine private - def format_statement statement - statement = String(statement || "").dup - return statement unless statement.length > 0 - - template = ERB.new(statement, nil, "%") - statement = template.result(binding) - - statement = wrap(statement) unless @wrap_at.nil? - statement = page_print(statement) unless @page_at.nil? - - # 'statement' is encoded in US-ASCII when using ruby 1.9.3(-p551) - # 'indentation' is correctly encoded (same as default_external encoding) - statement = statement.force_encoding(Encoding.default_external) - - statement = statement.gsub(/\n(?!$)/,"\n#{indentation}") if @multi_indent - - statement - end - # # A helper method for sending the output stream and error and repeat # of the question. @@ -991,25 +972,6 @@ class HighLine end end - # - # Page print a series of at most _page_at_ lines for _output_. After each - # page is printed, HighLine will pause until the user presses enter/return - # then display the next page of data. - # - # Note that the final page of _output_ is *not* printed, but returned - # instead. This is to support any special handling for the final sequence. - # - def page_print( output ) - lines = output.scan(/[^\n]*\n?/) - while lines.size > @page_at - @output.puts lines.slice!(0...@page_at).join - @output.puts - # Return last line if user wants to abort paging - return (["...\n"] + lines.slice(-2,1)).join unless continue_paging? - end - return lines.join - end - # # Ask user if they wish to continue paging output. Allows them to type "q" to # cancel the paging process. @@ -1021,32 +983,6 @@ class HighLine command !~ /\A[qQ]\Z/ # Only continue paging if Q was not hit. end - # - # Wrap a sequence of _lines_ at _wrap_at_ characters per line. Existing - # newlines will not be affected by this process, but additional newlines - # may be added. - # - def wrap( text ) - wrapped = [ ] - text.each_line do |line| - # take into account color escape sequences when wrapping - wrap_at = @wrap_at + (line.length - actual_length(line)) - while line =~ /([^\n]{#{wrap_at + 1},})/ - search = $1.dup - replace = $1.dup - if index = replace.rindex(" ", wrap_at) - replace[index, 1] = "\n" - replace.sub!(/\n[ \t]+/, "\n") - line.sub!(search, replace) - else - line[$~.begin(1) + wrap_at, 0] = "\n" - end - end - wrapped << line - end - return wrapped.join - end - # # Returns the length of the passed +string_with_escapes+, minus and color # sequence escapes. diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb new file mode 100644 index 0000000..c0f1f24 --- /dev/null +++ b/lib/highline/statement.rb @@ -0,0 +1,65 @@ +class HighLine::Statement + def format_statement statement + statement = String(statement || "").dup + return statement unless statement.length > 0 + + template = ERB.new(statement, nil, "%") + statement = template.result(binding) + + statement = wrap(statement) unless @wrap_at.nil? + statement = page_print(statement) unless @page_at.nil? + + # 'statement' is encoded in US-ASCII when using ruby 1.9.3(-p551) + # 'indentation' is correctly encoded (same as default_external encoding) + statement = statement.force_encoding(Encoding.default_external) + + statement = statement.gsub(/\n(?!$)/,"\n#{indentation}") if @multi_indent + + statement + end + + # + # Wrap a sequence of _lines_ at _wrap_at_ characters per line. Existing + # newlines will not be affected by this process, but additional newlines + # may be added. + # + def wrap( text ) + wrapped = [ ] + text.each_line do |line| + # take into account color escape sequences when wrapping + wrap_at = @wrap_at + (line.length - actual_length(line)) + while line =~ /([^\n]{#{wrap_at + 1},})/ + search = $1.dup + replace = $1.dup + if index = replace.rindex(" ", wrap_at) + replace[index, 1] = "\n" + replace.sub!(/\n[ \t]+/, "\n") + line.sub!(search, replace) + else + line[$~.begin(1) + wrap_at, 0] = "\n" + end + end + wrapped << line + end + return wrapped.join + end + + # + # Page print a series of at most _page_at_ lines for _output_. After each + # page is printed, HighLine will pause until the user presses enter/return + # then display the next page of data. + # + # Note that the final page of _output_ is *not* printed, but returned + # instead. This is to support any special handling for the final sequence. + # + def page_print( output ) + lines = output.scan(/[^\n]*\n?/) + while lines.size > @page_at + @output.puts lines.slice!(0...@page_at).join + @output.puts + # Return last line if user wants to abort paging + return (["...\n"] + lines.slice(-2,1)).join unless continue_paging? + end + return lines.join + end +end \ No newline at end of file -- cgit v1.2.1 From af5394a40bc8759c5e823c257a8c75dad140b273 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 14:11:46 -0300 Subject: Make HighLine and HighLine::Statement talk --- lib/highline.rb | 5 +++-- lib/highline/statement.rb | 45 +++++++++++++++++++++++++++++++++------------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index d4afc6e..0fc08ac 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -18,6 +18,7 @@ require "highline/menu" require "highline/color_scheme" require "highline/style" require "highline/version" +require "highline/statement" # # A HighLine object is a "high-level line oriented" shell over an input and an @@ -629,7 +630,7 @@ class HighLine # and the HighLine.color() method. # def say( statement ) - statement = format_statement(statement) + statement = Statement.new(statement, self).to_s return unless statement.length > 0 out = (indentation+statement).encode(Encoding.default_external, { :undef => :replace } ) @@ -851,7 +852,7 @@ class HighLine answer else if JRUBY - statement = format_statement(@question) + statement = Statement.new(@question, self).to_s raw_answer = @java_console.readLine(statement, nil) raise EOFError, "The input stream is exhausted." if raw_answer.nil? and diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index c0f1f24..1e96bef 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -1,20 +1,33 @@ class HighLine::Statement - def format_statement statement - statement = String(statement || "").dup + attr_reader :statement, :highline + + def initialize(statement_string, highline) + @highline = highline + @statement_string = statement_string + @statement = format_statement + end + + def to_s + statement + end + + private + + def format_statement + statement = String(@statement_string || "").dup return statement unless statement.length > 0 template = ERB.new(statement, nil, "%") - statement = template.result(binding) + statement = highline.instance_eval { template.result(binding) } - statement = wrap(statement) unless @wrap_at.nil? - statement = page_print(statement) unless @page_at.nil? + statement = wrap(statement) unless highline.wrap_at.nil? + statement = page_print(statement) unless highline.page_at.nil? # 'statement' is encoded in US-ASCII when using ruby 1.9.3(-p551) # 'indentation' is correctly encoded (same as default_external encoding) statement = statement.force_encoding(Encoding.default_external) - statement = statement.gsub(/\n(?!$)/,"\n#{indentation}") if @multi_indent - + statement = statement.gsub(/\n(?!$)/,"\n#{highline.indentation}") if highline.multi_indent statement end @@ -27,7 +40,7 @@ class HighLine::Statement wrapped = [ ] text.each_line do |line| # take into account color escape sequences when wrapping - wrap_at = @wrap_at + (line.length - actual_length(line)) + wrap_at = highline.wrap_at + (line.length - highline.send(:actual_length, line)) while line =~ /([^\n]{#{wrap_at + 1},})/ search = $1.dup replace = $1.dup @@ -54,12 +67,20 @@ class HighLine::Statement # def page_print( output ) lines = output.scan(/[^\n]*\n?/) - while lines.size > @page_at - @output.puts lines.slice!(0...@page_at).join - @output.puts + while lines.size > highline.page_at + highline_output.puts lines.slice!(0...highline.page_at).join + highline_output.puts # Return last line if user wants to abort paging - return (["...\n"] + lines.slice(-2,1)).join unless continue_paging? + return (["...\n"] + lines.slice(-2,1)).join unless highline.send(:continue_paging?) end return lines.join end + + def highline_output + highline.instance_variable_get(:@output) + end + + def self.const_missing(constant) + HighLine.const_get(constant) + end end \ No newline at end of file -- cgit v1.2.1 From f81469de20b843bf7aa491334c32b2f4dee64884 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 16:15:50 -0300 Subject: Add lazy evaluation of HighLine::Statement#statement --- lib/highline/statement.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 1e96bef..9d35d55 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -4,7 +4,10 @@ class HighLine::Statement def initialize(statement_string, highline) @highline = highline @statement_string = statement_string - @statement = format_statement + end + + def statement + @statement ||= format_statement end def to_s -- cgit v1.2.1 From 06ab98ec0bba92affa1a120e53dc6f77b67594e5 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 16:29:07 -0300 Subject: Remove stringification responsability out of HighLine::Statement#format_statement --- lib/highline/statement.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 9d35d55..ea36c7f 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -1,9 +1,9 @@ class HighLine::Statement - attr_reader :statement, :highline + attr_reader :statement_string, :highline def initialize(statement_string, highline) @highline = highline - @statement_string = statement_string + @statement_string = stringfy_statement(statement_string) end def statement @@ -16,11 +16,14 @@ class HighLine::Statement private + def stringfy_statement(statement) + String(statement || "").dup + end + def format_statement - statement = String(@statement_string || "").dup - return statement unless statement.length > 0 + return statement_string unless statement_string.length > 0 - template = ERB.new(statement, nil, "%") + template = ERB.new(statement_string, nil, "%") statement = highline.instance_eval { template.result(binding) } statement = wrap(statement) unless highline.wrap_at.nil? -- cgit v1.2.1 From c329b9d3a91e591e3c6bfe1878c2744b5740bba7 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 16:38:27 -0300 Subject: Extract template rendering logic into its own method --- lib/highline/statement.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index ea36c7f..80eb348 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -23,8 +23,7 @@ class HighLine::Statement def format_statement return statement_string unless statement_string.length > 0 - template = ERB.new(statement_string, nil, "%") - statement = highline.instance_eval { template.result(binding) } + statement = render_template statement = wrap(statement) unless highline.wrap_at.nil? statement = page_print(statement) unless highline.page_at.nil? @@ -37,6 +36,11 @@ class HighLine::Statement statement end + def render_template + template = ERB.new(statement_string, nil, "%") + statement = highline.instance_eval { template.result(binding) } + end + # # Wrap a sequence of _lines_ at _wrap_at_ characters per line. Existing # newlines will not be affected by this process, but additional newlines -- cgit v1.2.1 From 7df050b1c2225005170650cf3255e617099a8d14 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 16:50:37 -0300 Subject: Rename HighLine::Statement statement_string -> template_string It probably reduces confusion with the proper template. --- lib/highline/statement.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 80eb348..529f7ca 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -1,9 +1,9 @@ class HighLine::Statement - attr_reader :statement_string, :highline + attr_reader :template_string, :highline - def initialize(statement_string, highline) + def initialize(template_string, highline) @highline = highline - @statement_string = stringfy_statement(statement_string) + @template_string = stringfy(template_string) end def statement @@ -16,12 +16,12 @@ class HighLine::Statement private - def stringfy_statement(statement) - String(statement || "").dup + def stringfy(template_string) + String(template_string || "").dup end def format_statement - return statement_string unless statement_string.length > 0 + return template_string unless template_string.length > 0 statement = render_template @@ -37,8 +37,8 @@ class HighLine::Statement end def render_template - template = ERB.new(statement_string, nil, "%") - statement = highline.instance_eval { template.result(binding) } + template = ERB.new(template_string, nil, "%") + highline.instance_eval { template.result(binding) } end # -- cgit v1.2.1 From 11b9800191e98af0be21c1867e35a773b6354e74 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 17:15:10 -0300 Subject: Move HighLine::Statement wrapping logic into its own module --- lib/highline/statement.rb | 33 +++++++-------------------------- lib/highline/wrapper.rb | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 26 deletions(-) create mode 100644 lib/highline/wrapper.rb diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 529f7ca..205b625 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -37,34 +37,15 @@ class HighLine::Statement end def render_template - template = ERB.new(template_string, nil, "%") - highline.instance_eval { template.result(binding) } + # Assigning to a local var so it may be + # used inside instance eval block + + template_var = template + highline.instance_eval { template_var.result(binding) } end - # - # Wrap a sequence of _lines_ at _wrap_at_ characters per line. Existing - # newlines will not be affected by this process, but additional newlines - # may be added. - # - def wrap( text ) - wrapped = [ ] - text.each_line do |line| - # take into account color escape sequences when wrapping - wrap_at = highline.wrap_at + (line.length - highline.send(:actual_length, line)) - while line =~ /([^\n]{#{wrap_at + 1},})/ - search = $1.dup - replace = $1.dup - if index = replace.rindex(" ", wrap_at) - replace[index, 1] = "\n" - replace.sub!(/\n[ \t]+/, "\n") - line.sub!(search, replace) - else - line[$~.begin(1) + wrap_at, 0] = "\n" - end - end - wrapped << line - end - return wrapped.join + def template + @template ||= ERB.new(template_string, nil, "%") end # diff --git a/lib/highline/wrapper.rb b/lib/highline/wrapper.rb new file mode 100644 index 0000000..5fc5d2f --- /dev/null +++ b/lib/highline/wrapper.rb @@ -0,0 +1,30 @@ +class HighLine + module Wrapper + + # + # Wrap a sequence of _lines_ at _wrap_at_ characters per line. Existing + # newlines will not be affected by this process, but additional newlines + # may be added. + # + def self.wrap(text, wrap_at) + wrapped = [ ] + text.each_line do |line| + # take into account color escape sequences when wrapping + wrap_at = highline.wrap_at + (line.length - highline.send(:actual_length, line)) + while line =~ /([^\n]{#{wrap_at + 1},})/ + search = $1.dup + replace = $1.dup + if index = replace.rindex(" ", wrap_at) + replace[index, 1] = "\n" + replace.sub!(/\n[ \t]+/, "\n") + line.sub!(search, replace) + else + line[$~.begin(1) + wrap_at, 0] = "\n" + end + end + wrapped << line + end + return wrapped.join + end + end +end \ No newline at end of file -- cgit v1.2.1 From a5d1365f501201a782d18f03ac30ef88e05a0c77 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 17:49:36 -0300 Subject: Use the new HighLine::Wrapper module in HighLine::Statement --- lib/highline/statement.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 205b625..4a15cb9 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -1,3 +1,5 @@ +require 'highline/wrapper' + class HighLine::Statement attr_reader :template_string, :highline @@ -25,7 +27,7 @@ class HighLine::Statement statement = render_template - statement = wrap(statement) unless highline.wrap_at.nil? + statement = Wrapper.wrap(statement, highline.wrap_at) unless highline.wrap_at.nil? statement = page_print(statement) unless highline.page_at.nil? # 'statement' is encoded in US-ASCII when using ruby 1.9.3(-p551) -- cgit v1.2.1 From 17b3e5feaafa59256e92b8d91a7d7bec80014cbc Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 17:59:23 -0300 Subject: Move HighLine#actual_length to HighLine::Wrapper module --- lib/highline.rb | 8 ++------ lib/highline/wrapper.rb | 10 +++++++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 0fc08ac..b0d9023 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -984,12 +984,8 @@ class HighLine command !~ /\A[qQ]\Z/ # Only continue paging if Q was not hit. end - # - # Returns the length of the passed +string_with_escapes+, minus and color - # sequence escapes. - # - def actual_length( string_with_escapes ) - string_with_escapes.to_s.gsub(/\e\[\d{1,2}m/, "").length + def actual_length(text) + Wrapper.actual_length text end end diff --git a/lib/highline/wrapper.rb b/lib/highline/wrapper.rb index 5fc5d2f..a2ee72f 100644 --- a/lib/highline/wrapper.rb +++ b/lib/highline/wrapper.rb @@ -10,7 +10,7 @@ class HighLine wrapped = [ ] text.each_line do |line| # take into account color escape sequences when wrapping - wrap_at = highline.wrap_at + (line.length - highline.send(:actual_length, line)) + wrap_at = wrap_at + (line.length - actual_length(line)) while line =~ /([^\n]{#{wrap_at + 1},})/ search = $1.dup replace = $1.dup @@ -26,5 +26,13 @@ class HighLine end return wrapped.join end + + # + # Returns the length of the passed +string_with_escapes+, minus and color + # sequence escapes. + # + def self.actual_length( string_with_escapes ) + string_with_escapes.to_s.gsub(/\e\[\d{1,2}m/, "").length + end end end \ No newline at end of file -- cgit v1.2.1 From 850c9ed22f48b336b72d120a81bbce518d0140a2 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 18:23:25 -0300 Subject: Wrapper.wrap returns text unless wrap_at defined --- lib/highline/statement.rb | 2 +- lib/highline/wrapper.rb | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 4a15cb9..5c7a50c 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -27,7 +27,7 @@ class HighLine::Statement statement = render_template - statement = Wrapper.wrap(statement, highline.wrap_at) unless highline.wrap_at.nil? + statement = Wrapper.wrap(statement, highline.wrap_at) statement = page_print(statement) unless highline.page_at.nil? # 'statement' is encoded in US-ASCII when using ruby 1.9.3(-p551) diff --git a/lib/highline/wrapper.rb b/lib/highline/wrapper.rb index a2ee72f..5eb65d8 100644 --- a/lib/highline/wrapper.rb +++ b/lib/highline/wrapper.rb @@ -7,6 +7,9 @@ class HighLine # may be added. # def self.wrap(text, wrap_at) + return text unless wrap_at + wrap_at = Integer(wrap_at) + wrapped = [ ] text.each_line do |line| # take into account color escape sequences when wrapping -- cgit v1.2.1 From 753eb608b5e7ac1117a0da64252f3c583c3a8178 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 18:32:05 -0300 Subject: Move HighLine::Wrapper tests to its own file --- test/test_highline.rb | 35 +---------------------------------- test/test_wrapper.rb | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 34 deletions(-) create mode 100644 test/test_wrapper.rb diff --git a/test/test_highline.rb b/test/test_highline.rb index 3d64870..e114110 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -12,6 +12,7 @@ require "highline" require "stringio" require "readline" require "tempfile" +require "test_helper" if HighLine::CHARACTER_MODE == "Win32API" class HighLine @@ -1304,40 +1305,6 @@ class TestHighLine < Minitest::Test assert_equal(" A lot\tof \t space\t \there! \n", answer) end - def test_wrap - @terminal.wrap_at = 80 - - @terminal.say("This is a very short line.") - assert_equal("This is a very short line.\n", @output.string) - - @output.truncate(@output.rewind) - - @terminal.say( "This is a long flowing paragraph meant to span " + - "several lines. This text should definitely be " + - "wrapped at the set limit, in the result. Your code " + - "does well with things like this.\n\n" + - " * This is a simple embedded list.\n" + - " * You're code should not mess with this...\n" + - " * Because it's already formatted correctly and " + - "does not\n" + - " exceed the limit!" ) - assert_equal( "This is a long flowing paragraph meant to span " + - "several lines. This text should\n" + - "definitely be wrapped at the set limit, in the " + - "result. Your code does well with\n" + - "things like this.\n\n" + - " * This is a simple embedded list.\n" + - " * You're code should not mess with this...\n" + - " * Because it's already formatted correctly and does " + - "not\n" + - " exceed the limit!\n", @output.string ) - - @output.truncate(@output.rewind) - - @terminal.say("-=" * 50) - assert_equal(("-=" * 40 + "\n") + ("-=" * 10 + "\n"), @output.string) - end - def test_track_eof assert_raises(EOFError) { @terminal.ask("Any input left? ") } diff --git a/test/test_wrapper.rb b/test/test_wrapper.rb new file mode 100644 index 0000000..c52888f --- /dev/null +++ b/test/test_wrapper.rb @@ -0,0 +1,45 @@ +require "minitest/autorun" +require "test_helper" + +class TestHighLine < Minitest::Test + def setup + HighLine.reset + @input = StringIO.new + @output = StringIO.new + @terminal = HighLine.new(@input, @output) + end + + def test_wrap + @terminal.wrap_at = 80 + + @terminal.say("This is a very short line.") + assert_equal("This is a very short line.\n", @output.string) + + @output.truncate(@output.rewind) + + @terminal.say( "This is a long flowing paragraph meant to span " + + "several lines. This text should definitely be " + + "wrapped at the set limit, in the result. Your code " + + "does well with things like this.\n\n" + + " * This is a simple embedded list.\n" + + " * You're code should not mess with this...\n" + + " * Because it's already formatted correctly and " + + "does not\n" + + " exceed the limit!" ) + assert_equal( "This is a long flowing paragraph meant to span " + + "several lines. This text should\n" + + "definitely be wrapped at the set limit, in the " + + "result. Your code does well with\n" + + "things like this.\n\n" + + " * This is a simple embedded list.\n" + + " * You're code should not mess with this...\n" + + " * Because it's already formatted correctly and does " + + "not\n" + + " exceed the limit!\n", @output.string ) + + @output.truncate(@output.rewind) + + @terminal.say("-=" * 50) + assert_equal(("-=" * 40 + "\n") + ("-=" * 10 + "\n"), @output.string) + end +end \ No newline at end of file -- cgit v1.2.1 From 28ea6e726b9d9257e428bf91d98a0a7c5f266200 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 18:49:50 -0300 Subject: Split two different case in their own assertions (HighLine::Wrapper) --- test/test_wrapper.rb | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/test/test_wrapper.rb b/test/test_wrapper.rb index c52888f..c585969 100644 --- a/test/test_wrapper.rb +++ b/test/test_wrapper.rb @@ -17,25 +17,34 @@ class TestHighLine < Minitest::Test @output.truncate(@output.rewind) - @terminal.say( "This is a long flowing paragraph meant to span " + - "several lines. This text should definitely be " + - "wrapped at the set limit, in the result. Your code " + - "does well with things like this.\n\n" + - " * This is a simple embedded list.\n" + - " * You're code should not mess with this...\n" + - " * Because it's already formatted correctly and " + - "does not\n" + - " exceed the limit!" ) - assert_equal( "This is a long flowing paragraph meant to span " + - "several lines. This text should\n" + - "definitely be wrapped at the set limit, in the " + - "result. Your code does well with\n" + - "things like this.\n\n" + - " * This is a simple embedded list.\n" + - " * You're code should not mess with this...\n" + - " * Because it's already formatted correctly and does " + - "not\n" + - " exceed the limit!\n", @output.string ) + long_line = + "This is a long flowing paragraph meant to span " + + "several lines. This text should definitely be " + + "wrapped at the set limit, in the result. Your code " + + "does well with things like this.\n\n" + + wrapped_long_line = + "This is a long flowing paragraph meant to span " + + "several lines. This text should\n" + + + "definitely be wrapped at the set limit, in the " + + "result. Your code does well with\n" + + + "things like this.\n\n" + + @terminal.say long_line + assert_equal wrapped_long_line, @output.string + + @output.truncate(@output.rewind) + + well_formatted_text = + " * This is a simple embedded list.\n" + + " * You're code should not mess with this...\n" + + " * Because it's already formatted correctly and does not\n" + + " exceed the limit!\n" + + @terminal.say well_formatted_text + assert_equal well_formatted_text, @output.string @output.truncate(@output.rewind) -- cgit v1.2.1 From fdfcf64eb991397721665bb749a32079e199ef90 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 18:59:37 -0300 Subject: Split each wrapper test in its own method --- test/test_wrapper.rb | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/test/test_wrapper.rb b/test/test_wrapper.rb index c585969..062d6fa 100644 --- a/test/test_wrapper.rb +++ b/test/test_wrapper.rb @@ -1,22 +1,23 @@ require "minitest/autorun" require "test_helper" -class TestHighLine < Minitest::Test +require "highline" + +class TestHighLineWrapper < Minitest::Test def setup HighLine.reset @input = StringIO.new @output = StringIO.new @terminal = HighLine.new(@input, @output) - end - - def test_wrap @terminal.wrap_at = 80 + end - @terminal.say("This is a very short line.") + def test_dont_wrap_if_line_is_shorter_than_wrap_at + @terminal.say("This is a very short line.\n") assert_equal("This is a very short line.\n", @output.string) + end - @output.truncate(@output.rewind) - + def test_wrap_long_lines_correctly long_line = "This is a long flowing paragraph meant to span " + "several lines. This text should definitely be " + @@ -34,9 +35,9 @@ class TestHighLine < Minitest::Test @terminal.say long_line assert_equal wrapped_long_line, @output.string + end - @output.truncate(@output.rewind) - + def test_dont_wrap_already_well_wrapped_text well_formatted_text = " * This is a simple embedded list.\n" + " * You're code should not mess with this...\n" + @@ -45,9 +46,9 @@ class TestHighLine < Minitest::Test @terminal.say well_formatted_text assert_equal well_formatted_text, @output.string + end - @output.truncate(@output.rewind) - + def test_wrap_single_word_longer_than_wrap_at @terminal.say("-=" * 50) assert_equal(("-=" * 40 + "\n") + ("-=" * 10 + "\n"), @output.string) end -- cgit v1.2.1 From 248e60df80040e085b51d3689fa83e3ac92b634d Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 19:14:37 -0300 Subject: Remove HighLine::Wrapper tests' dependency on HighLine --- test/test_wrapper.rb | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/test_wrapper.rb b/test/test_wrapper.rb index 062d6fa..0d1b8a5 100644 --- a/test/test_wrapper.rb +++ b/test/test_wrapper.rb @@ -1,20 +1,20 @@ require "minitest/autorun" require "test_helper" -require "highline" +require "highline/wrapper" class TestHighLineWrapper < Minitest::Test def setup - HighLine.reset - @input = StringIO.new - @output = StringIO.new - @terminal = HighLine.new(@input, @output) - @terminal.wrap_at = 80 + @wrap_at = 80 + end + + def wrap(text) + HighLine::Wrapper.wrap text, @wrap_at end def test_dont_wrap_if_line_is_shorter_than_wrap_at - @terminal.say("This is a very short line.\n") - assert_equal("This is a very short line.\n", @output.string) + wrapped = wrap("This is a very short line.\n") + assert_equal "This is a very short line.\n", wrapped end def test_wrap_long_lines_correctly @@ -33,8 +33,8 @@ class TestHighLineWrapper < Minitest::Test "things like this.\n\n" - @terminal.say long_line - assert_equal wrapped_long_line, @output.string + wrapped = wrap(long_line) + assert_equal wrapped_long_line, wrapped end def test_dont_wrap_already_well_wrapped_text @@ -44,12 +44,12 @@ class TestHighLineWrapper < Minitest::Test " * Because it's already formatted correctly and does not\n" + " exceed the limit!\n" - @terminal.say well_formatted_text - assert_equal well_formatted_text, @output.string + wrapped = wrap(well_formatted_text) + assert_equal well_formatted_text, wrapped end def test_wrap_single_word_longer_than_wrap_at - @terminal.say("-=" * 50) - assert_equal(("-=" * 40 + "\n") + ("-=" * 10 + "\n"), @output.string) + wrapped = wrap("-=" * 50) + assert_equal(("-=" * 40 + "\n") + ("-=" * 10), wrapped) end end \ No newline at end of file -- cgit v1.2.1 From 1dae887af2e2cff6a343a383315d39dfa2e0e8a3 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 13 Mar 2015 23:32:05 -0300 Subject: Add test for multiple wrap sizes and for colored text wrapping --- test/test_wrapper.rb | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/test/test_wrapper.rb b/test/test_wrapper.rb index 0d1b8a5..ae31387 100644 --- a/test/test_wrapper.rb +++ b/test/test_wrapper.rb @@ -52,4 +52,75 @@ class TestHighLineWrapper < Minitest::Test wrapped = wrap("-=" * 50) assert_equal(("-=" * 40 + "\n") + ("-=" * 10), wrapped) end + + def test_wrap_text_on_the_right_place + line = "123 567 901 345" + + 1.upto(25) do |wrap_at| + wrapped = HighLine::Wrapper.wrap(line, wrap_at) + + case wrap_at + when 1 + assert_equal "1\n2\n3\n5\n6\n7\n9\n0\n1\n3\n4\n5", wrapped + when 2 + assert_equal "12\n3\n56\n7\n90\n1\n34\n5", wrapped + when 3..6 + assert_equal "123\n567\n901\n345", wrapped + when 7..10 + assert_equal "123 567\n901 345", wrapped + when 11..14 + assert_equal "123 567 901\n345", wrapped + when 15..25 + assert_equal "123 567 901 345", wrapped + end + end + end + + def test_wrap_whole_colored_text_on_the_right_place + skip "TODO: Implement whole colored text wrapping!" + line = "\e[31m123 567 901 345\e[0m" + + 1.upto(25) do |wrap_at| + wrapped = HighLine::Wrapper.wrap(line, wrap_at) + + case wrap_at + when 1 + assert_equal "\e[31m1\n2\n3\n5\n6\n7\n9\n0\n1\n3\n4\n5\e[0m", wrapped + when 2 + assert_equal "\e[31m12\n3\n56\n7\n90\n1\n34\n5\e[0m", wrapped + when 3..6 + assert_equal "\e[31m123\n567\n901\n345\e[0m", wrapped + when 7..10 + assert_equal "\e[31m123 567\n901 345\e[0m", wrapped + when 11..14 + assert_equal "\e[31m123 567 901\n345\e[0m", wrapped + when 15..25 + assert_equal "\e[31m123 567 901 345\e[0m", wrapped + end + end + end + + def test_wrap_middle_colored_text_on_the_right_place + skip "TODO: Implement middle colored text wrapping!" + line = "123 567 \e[31m901\e[0m 345" + + 1.upto(25) do |wrap_at| + wrapped = HighLine::Wrapper.wrap(line, wrap_at) + + case wrap_at + when 1 + assert_equal "1\n2\n3\n5\n6\n7\n\e[31m9\n0\n1\e[0m\n3\n4\n5", wrapped + when 2 + assert_equal "12\n3\n56\n7\n\e[31m90\n1\e[0m\n34\n5", wrapped + when 3..6 + assert_equal "123\n567\n\e[31m901\e[0m\n345", wrapped + when 7..10 + assert_equal "123 567\n\e[31m901\e[0m 345", wrapped + when 11..14 + assert_equal "123 567 \e[31m901\e[0m\n345", wrapped + when 15..25 + assert_equal "123 567 \e[31m901\e[0m 345", wrapped + end + end + end end \ No newline at end of file -- cgit v1.2.1 From e5404880ed9d0505ba4d856408a600fa219f7127 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 14 Mar 2015 03:21:29 -0300 Subject: Add test for patially colored middle word wrapping --- test/test_wrapper.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/test_wrapper.rb b/test/test_wrapper.rb index ae31387..4c4e289 100644 --- a/test/test_wrapper.rb +++ b/test/test_wrapper.rb @@ -123,4 +123,28 @@ class TestHighLineWrapper < Minitest::Test end end end + + def test_wrap_middle_partially_colored_text_on_the_right_place + skip "TODO: Implement middle partially colored text wrapping!" + line = "123 567 9\e[31m0\e[0m1 345" + + 1.upto(25) do |wrap_at| + wrapped = HighLine::Wrapper.wrap(line, wrap_at) + + case wrap_at + when 1 + assert_equal "1\n2\n3\n5\n6\n7\n9\n\e[31m0\e[0m\n1\n3\n4\n5", wrapped + when 2 + assert_equal "12\n3\n56\n7\n9\e[31m0\e[0m\n1\n34\n5", wrapped + when 3..6 + assert_equal "123\n567\n9\e[31m0\e[0m1\n345", wrapped + when 7..10 + assert_equal "123 567\n9\e[31m0\e[0m1 345", wrapped + when 11..14 + assert_equal "123 567 9\e[31m0\e[0m1\n345", wrapped + when 15..25 + assert_equal "123 567 9\e[31m0\e[0m1 345", wrapped + end + end + end end \ No newline at end of file -- cgit v1.2.1 From d58525477cf8f2caa54a11d042ffb1e45a9f1606 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 14 Mar 2015 03:25:50 -0300 Subject: Shorten some HighLine::Wrapper test name --- test/test_wrapper.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_wrapper.rb b/test/test_wrapper.rb index 4c4e289..c687511 100644 --- a/test/test_wrapper.rb +++ b/test/test_wrapper.rb @@ -53,7 +53,7 @@ class TestHighLineWrapper < Minitest::Test assert_equal(("-=" * 40 + "\n") + ("-=" * 10), wrapped) end - def test_wrap_text_on_the_right_place + def test_wrap_plain_text line = "123 567 901 345" 1.upto(25) do |wrap_at| @@ -76,7 +76,7 @@ class TestHighLineWrapper < Minitest::Test end end - def test_wrap_whole_colored_text_on_the_right_place + def test_wrap_whole_colored_text skip "TODO: Implement whole colored text wrapping!" line = "\e[31m123 567 901 345\e[0m" @@ -100,7 +100,7 @@ class TestHighLineWrapper < Minitest::Test end end - def test_wrap_middle_colored_text_on_the_right_place + def test_wrap_partially_colored_text skip "TODO: Implement middle colored text wrapping!" line = "123 567 \e[31m901\e[0m 345" @@ -124,7 +124,7 @@ class TestHighLineWrapper < Minitest::Test end end - def test_wrap_middle_partially_colored_text_on_the_right_place + def test_wrap_text_with_partially_colored_word_in_the_middle skip "TODO: Implement middle partially colored text wrapping!" line = "123 567 9\e[31m0\e[0m1 345" -- cgit v1.2.1 From b87735d692f2eda5225db1899424b2de85d6175f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 14 Mar 2015 03:48:46 -0300 Subject: Add test for multibyte string wrapping --- test/test_wrapper.rb | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/test_wrapper.rb b/test/test_wrapper.rb index c687511..6c51f2e 100644 --- a/test/test_wrapper.rb +++ b/test/test_wrapper.rb @@ -147,4 +147,40 @@ class TestHighLineWrapper < Minitest::Test end end end + + def test_wrap_when_multibyte_characters_present + line_ascii = "Sera um passaro?" + line_utf8 = "Será um pássaro?" + + assert_equal 16, line_ascii.size + assert_equal 16, line_ascii.bytesize + + assert_equal 16, line_utf8.size + assert_equal 18, line_utf8.bytesize + + 1.upto(18) do |wrap_at| + wrapped = HighLine::Wrapper.wrap(line_utf8, wrap_at) + + case wrap_at + when 1 + assert_equal "S\ne\nr\ná\nu\nm\np\ná\ns\ns\na\nr\no\n?", wrapped + when 2 + assert_equal "Se\nrá\num\npá\nss\nar\no?", wrapped + when 3 + assert_equal "Ser\ná\num\npás\nsar\no?", wrapped + when 4 + assert_equal "Será\num\npáss\naro?", wrapped + when 5 + assert_equal "Será\num\npássa\nro?", wrapped + when 6 + assert_equal "Será\num\npássar\no?", wrapped + when 7 + assert_equal "Será um\npássaro\n?", wrapped + when 15..8 + assert_equal "Será um\npássaro?", wrapped + when 16..18 + assert_equal "Será um pássaro?", wrapped + end + end + end end \ No newline at end of file -- cgit v1.2.1 From d79ddd1507c2c5ec6021636dc1fcb1a0c7050443 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 14 Mar 2015 18:26:49 -0300 Subject: Move pagination related code to its own module --- lib/highline.rb | 11 ----------- lib/highline/paginator.rb | 34 ++++++++++++++++++++++++++++++++++ lib/highline/statement.rb | 19 ------------------- 3 files changed, 34 insertions(+), 30 deletions(-) create mode 100644 lib/highline/paginator.rb diff --git a/lib/highline.rb b/lib/highline.rb index b0d9023..07dd1de 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -973,17 +973,6 @@ class HighLine end end - # - # Ask user if they wish to continue paging output. Allows them to type "q" to - # cancel the paging process. - # - def continue_paging? - command = HighLine.new(@input, @output).ask( - "-- press enter/return to continue or q to stop -- " - ) { |q| q.character = true } - command !~ /\A[qQ]\Z/ # Only continue paging if Q was not hit. - end - def actual_length(text) Wrapper.actual_length text end diff --git a/lib/highline/paginator.rb b/lib/highline/paginator.rb new file mode 100644 index 0000000..5ce236d --- /dev/null +++ b/lib/highline/paginator.rb @@ -0,0 +1,34 @@ +class HighLine + module Paginator + + # + # Page print a series of at most _page_at_ lines for _output_. After each + # page is printed, HighLine will pause until the user presses enter/return + # then display the next page of data. + # + # Note that the final page of _output_ is *not* printed, but returned + # instead. This is to support any special handling for the final sequence. + # + def page_print( output ) + lines = output.scan(/[^\n]*\n?/) + while lines.size > highline.page_at + highline_output.puts lines.slice!(0...highline.page_at).join + highline_output.puts + # Return last line if user wants to abort paging + return (["...\n"] + lines.slice(-2,1)).join unless highline.send(:continue_paging?) + end + return lines.join + end + + # + # Ask user if they wish to continue paging output. Allows them to type "q" to + # cancel the paging process. + # + def continue_paging? + command = HighLine.new(@input, @output).ask( + "-- press enter/return to continue or q to stop -- " + ) { |q| q.character = true } + command !~ /\A[qQ]\Z/ # Only continue paging if Q was not hit. + end + end +end \ No newline at end of file diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 5c7a50c..92d1258 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -50,25 +50,6 @@ class HighLine::Statement @template ||= ERB.new(template_string, nil, "%") end - # - # Page print a series of at most _page_at_ lines for _output_. After each - # page is printed, HighLine will pause until the user presses enter/return - # then display the next page of data. - # - # Note that the final page of _output_ is *not* printed, but returned - # instead. This is to support any special handling for the final sequence. - # - def page_print( output ) - lines = output.scan(/[^\n]*\n?/) - while lines.size > highline.page_at - highline_output.puts lines.slice!(0...highline.page_at).join - highline_output.puts - # Return last line if user wants to abort paging - return (["...\n"] + lines.slice(-2,1)).join unless highline.send(:continue_paging?) - end - return lines.join - end - def highline_output highline.instance_variable_get(:@output) end -- cgit v1.2.1 From b7cc31b3648b91de02d91f87cff405e561f5d080 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 14 Mar 2015 19:17:14 -0300 Subject: Make Paginator and Statemnt talk --- lib/highline.rb | 6 ++++++ lib/highline/paginator.rb | 21 ++++++++++++++------- lib/highline/statement.rb | 7 ++----- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 07dd1de..6db031e 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -226,6 +226,8 @@ class HighLine # The indentation level attr_accessor :indent_level + attr_reader :input, :output + # # A shortcut to HighLine.ask() a question that only accepts "yes" or "no" # answers ("y" and "n" are allowed) and returns +true+ or +false+ @@ -723,6 +725,10 @@ class HighLine return 24 end + def puts(*args) + @output.puts(*args) + end + private # diff --git a/lib/highline/paginator.rb b/lib/highline/paginator.rb index 5ce236d..3c296a3 100644 --- a/lib/highline/paginator.rb +++ b/lib/highline/paginator.rb @@ -1,5 +1,12 @@ +require 'highline' + class HighLine - module Paginator + class Paginator + attr_reader :highline + + def initialize(highline) + @highline = highline + end # # Page print a series of at most _page_at_ lines for _output_. After each @@ -9,13 +16,13 @@ class HighLine # Note that the final page of _output_ is *not* printed, but returned # instead. This is to support any special handling for the final sequence. # - def page_print( output ) - lines = output.scan(/[^\n]*\n?/) + def page_print(text) + lines = text.scan(/[^\n]*\n?/) while lines.size > highline.page_at - highline_output.puts lines.slice!(0...highline.page_at).join - highline_output.puts + highline.puts lines.slice!(0...highline.page_at).join + highline.puts # Return last line if user wants to abort paging - return (["...\n"] + lines.slice(-2,1)).join unless highline.send(:continue_paging?) + return (["...\n"] + lines.slice(-2,1)).join unless continue_paging? end return lines.join end @@ -25,7 +32,7 @@ class HighLine # cancel the paging process. # def continue_paging? - command = HighLine.new(@input, @output).ask( + command = HighLine.new(highline.input, highline.output).ask( "-- press enter/return to continue or q to stop -- " ) { |q| q.character = true } command !~ /\A[qQ]\Z/ # Only continue paging if Q was not hit. diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 92d1258..24dca78 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -1,4 +1,5 @@ require 'highline/wrapper' +require 'highline/paginator' class HighLine::Statement attr_reader :template_string, :highline @@ -28,7 +29,7 @@ class HighLine::Statement statement = render_template statement = Wrapper.wrap(statement, highline.wrap_at) - statement = page_print(statement) unless highline.page_at.nil? + statement = Paginator.new(highline).page_print(statement) unless highline.page_at.nil? # 'statement' is encoded in US-ASCII when using ruby 1.9.3(-p551) # 'indentation' is correctly encoded (same as default_external encoding) @@ -50,10 +51,6 @@ class HighLine::Statement @template ||= ERB.new(template_string, nil, "%") end - def highline_output - highline.instance_variable_get(:@output) - end - def self.const_missing(constant) HighLine.const_get(constant) end -- cgit v1.2.1 From 71362b6e74b5d1bff6f6df38eb91965fa4398661 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 14 Mar 2015 19:23:07 -0300 Subject: Paginate only when page_at defined --- lib/highline/paginator.rb | 2 ++ lib/highline/statement.rb | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/highline/paginator.rb b/lib/highline/paginator.rb index 3c296a3..098ca48 100644 --- a/lib/highline/paginator.rb +++ b/lib/highline/paginator.rb @@ -17,6 +17,8 @@ class HighLine # instead. This is to support any special handling for the final sequence. # def page_print(text) + return text unless highline.page_at + lines = text.scan(/[^\n]*\n?/) while lines.size > highline.page_at highline.puts lines.slice!(0...highline.page_at).join diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 24dca78..4278d6f 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -29,7 +29,7 @@ class HighLine::Statement statement = render_template statement = Wrapper.wrap(statement, highline.wrap_at) - statement = Paginator.new(highline).page_print(statement) unless highline.page_at.nil? + statement = Paginator.new(highline).page_print(statement) # 'statement' is encoded in US-ASCII when using ruby 1.9.3(-p551) # 'indentation' is correctly encoded (same as default_external encoding) -- cgit v1.2.1 From bb00b15f584481aac06958f1aae3b34c69127ea9 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 02:45:18 -0300 Subject: Move paging test to its own file --- test/test_highline.rb | 15 --------------- test/test_paginator.rb | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 test/test_paginator.rb diff --git a/test/test_highline.rb b/test/test_highline.rb index e114110..987eec6 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -964,21 +964,6 @@ class TestHighLine < Minitest::Test assert_equal("Type: ****\n", @output.string) assert_equal("maçã", answer) end - - def test_paging - @terminal.page_at = 22 - - @input << "\n\n" - @input.rewind - - @terminal.say((1..50).map { |n| "This is line #{n}.\n"}.join) - assert_equal( (1..22).map { |n| "This is line #{n}.\n"}.join + - "\n-- press enter/return to continue or q to stop -- \n\n" + - (23..44).map { |n| "This is line #{n}.\n"}.join + - "\n-- press enter/return to continue or q to stop -- \n\n" + - (45..50).map { |n| "This is line #{n}.\n"}.join, - @output.string ) - end def test_range_requirements @input << "112\n-541\n28\n" diff --git a/test/test_paginator.rb b/test/test_paginator.rb new file mode 100644 index 0000000..85ebd61 --- /dev/null +++ b/test/test_paginator.rb @@ -0,0 +1,28 @@ +require "minitest/autorun" +require "test_helper" + +require "highline" + +class TestHighLinePaginator < Minitest::Test + def setup + HighLine.reset + @input = StringIO.new + @output = StringIO.new + @terminal = HighLine.new(@input, @output) + end + + def test_paging + @terminal.page_at = 22 + + @input << "\n\n" + @input.rewind + + @terminal.say((1..50).map { |n| "This is line #{n}.\n"}.join) + assert_equal( (1..22).map { |n| "This is line #{n}.\n"}.join + + "\n-- press enter/return to continue or q to stop -- \n\n" + + (23..44).map { |n| "This is line #{n}.\n"}.join + + "\n-- press enter/return to continue or q to stop -- \n\n" + + (45..50).map { |n| "This is line #{n}.\n"}.join, + @output.string ) + end +end \ No newline at end of file -- cgit v1.2.1 From 0eb282c822577d1a2d65109b929366f777ee1a1f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 02:46:03 -0300 Subject: Fix indent related code's indentation --- lib/highline.rb | 16 ++++++++-------- test/test_highline.rb | 15 ++++++++------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 6db031e..ae8fb1a 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -682,15 +682,15 @@ class HighLine multi = @multi_indent @multi_indent = multiline unless multiline.nil? begin - if block_given? - yield self - else - say(statement) - end + if block_given? + yield self + else + say(statement) + end rescue - @multi_indent = multi - @indent_level -= increase - raise + @multi_indent = multi + @indent_level -= increase + raise end @multi_indent = multi @indent_level -= increase diff --git a/test/test_highline.rb b/test/test_highline.rb index 987eec6..168fc11 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -93,28 +93,29 @@ class TestHighLine < Minitest::Test assert_equal(' '*10+text, @output.string) @output.truncate(@output.rewind) + @terminal.indent_level=0 @terminal.indent_size=4 @terminal.indent { - @terminal.say(text) + @terminal.say(text) } assert_equal(' '*4+text, @output.string) @output.truncate(@output.rewind) @terminal.indent_size=2 @terminal.indent(3) { |t| - t.say(text) + t.say(text) } assert_equal(' '*6+text, @output.string) @output.truncate(@output.rewind) @terminal.indent { |t| + t.indent { t.indent { - t.indent { - t.indent { |tt| - tt.say(text) - } - } + t.indent { |tt| + tt.say(text) + } } + } } assert_equal(' '*8+text, @output.string) -- cgit v1.2.1 From e93eb1baf5c4121d680dba5b9cdff504605d7845 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 02:18:16 -0300 Subject: Use ensure instead of repeating statements --- lib/highline.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index ae8fb1a..e096a51 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -687,13 +687,10 @@ class HighLine else say(statement) end - rescue + ensure @multi_indent = multi @indent_level -= increase - raise end - @multi_indent = multi - @indent_level -= increase end # -- cgit v1.2.1 From 0478b5ab1652267e0a16752b8413b5cce0b2a32f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 09:40:23 -0300 Subject: Add coding information to all files - 1.9 compatibility --- lib/highline.rb | 2 ++ lib/highline/color_scheme.rb | 3 +++ lib/highline/compatibility.rb | 3 +++ lib/highline/import.rb | 3 +++ lib/highline/menu.rb | 3 +++ lib/highline/paginator.rb | 3 +++ lib/highline/question.rb | 3 +++ lib/highline/simulate.rb | 3 +++ lib/highline/statement.rb | 3 +++ lib/highline/string_extensions.rb | 3 +++ lib/highline/style.rb | 3 +++ lib/highline/system_extensions.rb | 3 +++ lib/highline/version.rb | 3 +++ lib/highline/wrapper.rb | 3 +++ test/string_methods.rb | 3 +++ test/test_color_scheme.rb | 3 +++ test/test_helper.rb | 3 +++ test/test_highline.rb | 6 ++++-- test/test_import.rb | 3 +++ test/test_menu.rb | 2 ++ test/test_paginator.rb | 3 +++ test/test_string_extension.rb | 3 +++ test/test_string_highline.rb | 3 +++ test/test_style.rb | 3 +++ test/test_wrapper.rb | 3 +++ 25 files changed, 74 insertions(+), 2 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index e096a51..8c35e31 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -1,4 +1,6 @@ +#!/usr/bin/env ruby # coding: utf-8 + # highline.rb # # Created by James Edward Gray II on 2005-04-26. diff --git a/lib/highline/color_scheme.rb b/lib/highline/color_scheme.rb index 601781f..589127f 100644 --- a/lib/highline/color_scheme.rb +++ b/lib/highline/color_scheme.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # color_scheme.rb # # Created by Jeremy Hinegardner on 2007-01-24 diff --git a/lib/highline/compatibility.rb b/lib/highline/compatibility.rb index 7a99819..5e186ac 100644 --- a/lib/highline/compatibility.rb +++ b/lib/highline/compatibility.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + unless STDIN.respond_to? :getbyte class IO alias_method :getbyte, :getc diff --git a/lib/highline/import.rb b/lib/highline/import.rb index 95f0301..ff03e64 100644 --- a/lib/highline/import.rb +++ b/lib/highline/import.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # import.rb # # Created by James Edward Gray II on 2005-04-26. diff --git a/lib/highline/menu.rb b/lib/highline/menu.rb index 44c41b7..03c5bf0 100644 --- a/lib/highline/menu.rb +++ b/lib/highline/menu.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # menu.rb # # Created by Gregory Thomas Brown on 2005-05-10. diff --git a/lib/highline/paginator.rb b/lib/highline/paginator.rb index 098ca48..1b6125f 100644 --- a/lib/highline/paginator.rb +++ b/lib/highline/paginator.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + require 'highline' class HighLine diff --git a/lib/highline/question.rb b/lib/highline/question.rb index fa8445a..f8fa4d4 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # question.rb # # Created by James Edward Gray II on 2005-04-26. diff --git a/lib/highline/simulate.rb b/lib/highline/simulate.rb index 3596f59..741fe32 100644 --- a/lib/highline/simulate.rb +++ b/lib/highline/simulate.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # simulate.rb # # Created by Andy Rossmeissl on 2012-04-29. diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 4278d6f..3040f3a 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + require 'highline/wrapper' require 'highline/paginator' diff --git a/lib/highline/string_extensions.rb b/lib/highline/string_extensions.rb index c72aff0..e4981ef 100644 --- a/lib/highline/string_extensions.rb +++ b/lib/highline/string_extensions.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # Extensions for class String # # HighLine::String is a subclass of String with convenience methods added for colorization. diff --git a/lib/highline/style.rb b/lib/highline/style.rb index 0d1a1f2..9b87dcd 100755 --- a/lib/highline/style.rb +++ b/lib/highline/style.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # color_scheme.rb # # Created by Richard LeBer on 2011-06-27. diff --git a/lib/highline/system_extensions.rb b/lib/highline/system_extensions.rb index c36af70..5e78505 100755 --- a/lib/highline/system_extensions.rb +++ b/lib/highline/system_extensions.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # system_extensions.rb # # Created by James Edward Gray II on 2006-06-14. diff --git a/lib/highline/version.rb b/lib/highline/version.rb index 618c4cd..8c13579 100644 --- a/lib/highline/version.rb +++ b/lib/highline/version.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + class HighLine # The version of the installed library. VERSION = "1.7.2".freeze diff --git a/lib/highline/wrapper.rb b/lib/highline/wrapper.rb index 5eb65d8..695601c 100644 --- a/lib/highline/wrapper.rb +++ b/lib/highline/wrapper.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + class HighLine module Wrapper diff --git a/test/string_methods.rb b/test/string_methods.rb index 0ae2c5c..9c61359 100644 --- a/test/string_methods.rb +++ b/test/string_methods.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # string_methods.rb # # Created by Richard LeBer 2011-06-27 diff --git a/test/test_color_scheme.rb b/test/test_color_scheme.rb index c37308a..388c0ea 100644 --- a/test/test_color_scheme.rb +++ b/test/test_color_scheme.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # tc_color_scheme.rb # # Created by Jeremy Hinegardner on 2007-01-24. diff --git a/test/test_helper.rb b/test/test_helper.rb index af0bfeb..6068398 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + require "codeclimate-test-reporter" CodeClimate::TestReporter.start diff --git a/test/test_highline.rb b/test/test_highline.rb index 168fc11..4901d9b 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -1,4 +1,6 @@ -# encoding: utf-8 +#!/usr/bin/env ruby +# coding: utf-8 + # tc_highline.rb # # Created by James Edward Gray II on 2005-04-26. @@ -590,7 +592,7 @@ class TestHighLine < Minitest::Test q.glob = "*.rb" end assert_instance_of(File, file) - assert_equal("# encoding: utf-8\n", file.gets) + assert_equal("#!/usr/bin/env ruby\n", file.gets) file.close @input.rewind diff --git a/test/test_import.rb b/test/test_import.rb index 2177daa..4bac518 100644 --- a/test/test_import.rb +++ b/test/test_import.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # tc_import.rb # # Created by James Edward Gray II on 2005-04-26. diff --git a/test/test_menu.rb b/test/test_menu.rb index f745e04..7f3250d 100644 --- a/test/test_menu.rb +++ b/test/test_menu.rb @@ -1,4 +1,6 @@ +#!/usr/bin/env ruby # coding: utf-8 + # tc_menu.rb # # Created by Gregory Thomas Brown on 2005-05-10. diff --git a/test/test_paginator.rb b/test/test_paginator.rb index 85ebd61..5f89899 100644 --- a/test/test_paginator.rb +++ b/test/test_paginator.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + require "minitest/autorun" require "test_helper" diff --git a/test/test_string_extension.rb b/test/test_string_extension.rb index caa85a0..2527da5 100644 --- a/test/test_string_extension.rb +++ b/test/test_string_extension.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # tc_string_extension.rb # # Created by Richard LeBer 2011-06-27 diff --git a/test/test_string_highline.rb b/test/test_string_highline.rb index 1a6d0df..ad450af 100644 --- a/test/test_string_highline.rb +++ b/test/test_string_highline.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # tc_highline_string.rb # # Created by Richard LeBer 2011-06-27 diff --git a/test/test_style.rb b/test/test_style.rb index 84e4e6b..ccba936 100755 --- a/test/test_style.rb +++ b/test/test_style.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + # tc_style.rb # # Created by Richard LeBer on 2011-06-11. diff --git a/test/test_wrapper.rb b/test/test_wrapper.rb index 6c51f2e..6afcdff 100644 --- a/test/test_wrapper.rb +++ b/test/test_wrapper.rb @@ -1,3 +1,6 @@ +#!/usr/bin/env ruby +# coding: utf-8 + require "minitest/autorun" require "test_helper" -- cgit v1.2.1 From 8fbd2cf43fb811c0e9f132ae77bb6d242b561ea2 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 10:37:32 -0300 Subject: Split #ask and group it together with #gather as #ask_once --- lib/highline.rb | 127 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 67 insertions(+), 60 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 8c35e31..0c3ec4d 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -268,66 +268,7 @@ class HighLine @question ||= Question.new(question, answer_type, &details) return gather if @question.gather - - # readline() needs to handle its own output, but readline only supports - # full line reading. Therefore if @question.echo is anything but true, - # the prompt will not be issued. And we have to account for that now. - # Also, JRuby-1.7's ConsoleReader.readLine() needs to be passed the prompt - # to handle line editing properly. - say(@question) unless ((JRUBY or @question.readline) and (@question.echo == true and @question.limit.nil?)) - - begin - @answer = @question.answer_or_default(get_response) - unless @question.valid_answer?(@answer) - explain_error(:not_valid) - raise QuestionError - end - - @answer = @question.convert(@answer) - - if @question.in_range?(@answer) - if @question.confirm - # need to add a layer of scope to ask a question inside a - # question, without destroying instance data - context_change = self.class.new(@input, @output, @wrap_at, @page_at, @indent_size, @indent_level) - if @question.confirm == true - confirm_question = "Are you sure? " - else - # evaluate ERb under initial scope, so it will have - # access to @question and @answer - template = ERB.new(@question.confirm, nil, "%") - confirm_question = template.result(binding) - end - unless context_change.agree(confirm_question) - explain_error(nil) - raise QuestionError - end - end - - @answer - else - explain_error(:not_in_range) - raise QuestionError - end - rescue QuestionError - retry - rescue ArgumentError, NameError => error - raise if error.is_a?(NoMethodError) - if error.message =~ /ambiguous/ - # the assumption here is that OptionParser::Completion#complete - # (used for ambiguity resolution) throws exceptions containing - # the word 'ambiguous' whenever resolution fails - explain_error(:ambiguous_completion) - else - explain_error(:invalid_type) - end - retry - rescue Question::NoAutoCompleteMatch - explain_error(:no_completion) - retry - ensure - @question = nil # Reset Question object. - end + return ask_once end # @@ -743,6 +684,72 @@ class HighLine end end + # + # Gets one answer, as opposed to HighLine#gather + # + def ask_once + + # readline() needs to handle its own output, but readline only supports + # full line reading. Therefore if @question.echo is anything but true, + # the prompt will not be issued. And we have to account for that now. + # Also, JRuby-1.7's ConsoleReader.readLine() needs to be passed the prompt + # to handle line editing properly. + say(@question) unless ((JRUBY or @question.readline) and (@question.echo == true and @question.limit.nil?)) + + begin + @answer = @question.answer_or_default(get_response) + unless @question.valid_answer?(@answer) + explain_error(:not_valid) + raise QuestionError + end + + @answer = @question.convert(@answer) + + if @question.in_range?(@answer) + if @question.confirm + # need to add a layer of scope to ask a question inside a + # question, without destroying instance data + context_change = self.class.new(@input, @output, @wrap_at, @page_at, @indent_size, @indent_level) + if @question.confirm == true + confirm_question = "Are you sure? " + else + # evaluate ERb under initial scope, so it will have + # access to @question and @answer + template = ERB.new(@question.confirm, nil, "%") + confirm_question = template.result(binding) + end + unless context_change.agree(confirm_question) + explain_error(nil) + raise QuestionError + end + end + + @answer + else + explain_error(:not_in_range) + raise QuestionError + end + rescue QuestionError + retry + rescue ArgumentError, NameError => error + raise if error.is_a?(NoMethodError) + if error.message =~ /ambiguous/ + # the assumption here is that OptionParser::Completion#complete + # (used for ambiguity resolution) throws exceptions containing + # the word 'ambiguous' whenever resolution fails + explain_error(:ambiguous_completion) + else + explain_error(:invalid_type) + end + retry + rescue Question::NoAutoCompleteMatch + explain_error(:no_completion) + retry + ensure + @question = nil # Reset Question object. + end + end + # # Collects an Array/Hash full of answers as described in # HighLine::Question.gather(). -- cgit v1.2.1 From bbe378509b51f326eefb43b14cad60d0f781f32e Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 12:02:52 -0300 Subject: Create HighLine#new_scope to duplicate a HighLine instance --- lib/highline.rb | 9 ++++++++- lib/highline/paginator.rb | 4 +--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 0c3ec4d..241daad 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -669,6 +669,13 @@ class HighLine @output.puts(*args) end + # + # Creates a new HighLine instance with the same options + # + def new_scope + self.class.new(@input, @output, @wrap_at, @page_at, @indent_size, @indent_level) + end + private # @@ -709,7 +716,7 @@ class HighLine if @question.confirm # need to add a layer of scope to ask a question inside a # question, without destroying instance data - context_change = self.class.new(@input, @output, @wrap_at, @page_at, @indent_size, @indent_level) + context_change = new_scope if @question.confirm == true confirm_question = "Are you sure? " else diff --git a/lib/highline/paginator.rb b/lib/highline/paginator.rb index 1b6125f..7a80588 100644 --- a/lib/highline/paginator.rb +++ b/lib/highline/paginator.rb @@ -1,8 +1,6 @@ #!/usr/bin/env ruby # coding: utf-8 -require 'highline' - class HighLine class Paginator attr_reader :highline @@ -37,7 +35,7 @@ class HighLine # cancel the paging process. # def continue_paging? - command = HighLine.new(highline.input, highline.output).ask( + command = highline.new_scope.ask( "-- press enter/return to continue or q to stop -- " ) { |q| q.character = true } command !~ /\A[qQ]\Z/ # Only continue paging if Q was not hit. -- cgit v1.2.1 From ab3bdb984467f2971a91cbf15256756656ed5934 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 13:05:07 -0300 Subject: Split gather testing --- test/test_highline.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/test_highline.rb b/test/test_highline.rb index 4901d9b..7430c2c 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -605,7 +605,7 @@ class TestHighLine < Minitest::Test assert_equal(File.size(__FILE__), pathname.size) end - def test_gather + def test_gather_with_integer @input << "James\nDana\nStorm\nGypsy\n\n" @input.rewind @@ -615,25 +615,31 @@ class TestHighLine < Minitest::Test assert_equal(%w{James Dana Storm Gypsy}, answers) assert_equal("\n", @input.gets) assert_equal("Enter four names:\n", @output.string) + end + def test_gather_with_an_empty_string + @input << "James\nDana\nStorm\nGypsy\n\n" @input.rewind answers = @terminal.ask("Enter four names:") do |q| q.gather = "" end assert_equal(%w{James Dana Storm Gypsy}, answers) + end + def test_gather_with_regexp + @input << "James\nDana\nStorm\nGypsy\n\n" @input.rewind answers = @terminal.ask("Enter four names:") do |q| q.gather = /^\s*$/ end assert_equal(%w{James Dana Storm Gypsy}, answers) + end - @input.truncate(@input.rewind) + def test_gather_with_hash @input << "29\n49\n30\n" @input.rewind - @output.truncate(@output.rewind) answers = @terminal.ask("<%= @key %>: ", Integer) do |q| q.gather = { "Age" => 0, "Wife's Age" => 0, "Father's Age" => 0} -- cgit v1.2.1 From 863169c51c47bc5ce4336763398c646d427010f4 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 16:12:33 -0300 Subject: Reduce #ask_once's dependency on @question instance variable --- lib/highline.rb | 24 ++++++++++++------------ lib/highline/question.rb | 6 ++++++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 241daad..2f1f3d7 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -268,7 +268,7 @@ class HighLine @question ||= Question.new(question, answer_type, &details) return gather if @question.gather - return ask_once + return ask_once(@question) end # @@ -694,35 +694,35 @@ class HighLine # # Gets one answer, as opposed to HighLine#gather # - def ask_once + def ask_once(question) # readline() needs to handle its own output, but readline only supports - # full line reading. Therefore if @question.echo is anything but true, + # full line reading. Therefore if question.echo is anything but true, # the prompt will not be issued. And we have to account for that now. # Also, JRuby-1.7's ConsoleReader.readLine() needs to be passed the prompt # to handle line editing properly. - say(@question) unless ((JRUBY or @question.readline) and (@question.echo == true and @question.limit.nil?)) + say(question) unless ((JRUBY or question.readline) and (question.echo == true and question.limit.nil?)) begin - @answer = @question.answer_or_default(get_response) - unless @question.valid_answer?(@answer) + @answer = question.answer_or_default(get_response) + unless question.valid_answer?(@answer) explain_error(:not_valid) raise QuestionError end - @answer = @question.convert(@answer) + @answer = question.convert(@answer) - if @question.in_range?(@answer) - if @question.confirm + if question.in_range?(@answer) + if question.confirm # need to add a layer of scope to ask a question inside a # question, without destroying instance data context_change = new_scope - if @question.confirm == true + if question.confirm == true confirm_question = "Are you sure? " else # evaluate ERb under initial scope, so it will have - # access to @question and @answer - template = ERB.new(@question.confirm, nil, "%") + # access to question and @answer + template = ERB.new(question.confirm, nil, "%") confirm_question = template.result(binding) end unless context_change.agree(confirm_question) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index f8fa4d4..a4f8129 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -25,6 +25,12 @@ class HighLine # do nothing, just creating a unique error type end + def self.new(*args) + question = args.first + return question if question.is_a? Question + super(*args) + end + # # Create an instance of HighLine::Question. Expects a _question_ to ask # (can be "") and an _answer_type_ to convert the answer to. -- cgit v1.2.1 From 3531b325657b7836680f264081ab08c5330ca408 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 18:58:27 -0300 Subject: Reduce #ask_once's dependency on instance variables --- lib/highline.rb | 13 ++++++------- test/test_highline.rb | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 2f1f3d7..7e50152 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -704,15 +704,15 @@ class HighLine say(question) unless ((JRUBY or question.readline) and (question.echo == true and question.limit.nil?)) begin - @answer = question.answer_or_default(get_response) - unless question.valid_answer?(@answer) + answer = question.answer_or_default(get_response) + unless question.valid_answer?(answer) explain_error(:not_valid) raise QuestionError end - @answer = question.convert(@answer) + answer = question.convert(answer) - if question.in_range?(@answer) + if question.in_range?(answer) if question.confirm # need to add a layer of scope to ask a question inside a # question, without destroying instance data @@ -721,7 +721,7 @@ class HighLine confirm_question = "Are you sure? " else # evaluate ERb under initial scope, so it will have - # access to question and @answer + # access to question and answer template = ERB.new(question.confirm, nil, "%") confirm_question = template.result(binding) end @@ -730,8 +730,6 @@ class HighLine raise QuestionError end end - - @answer else explain_error(:not_in_range) raise QuestionError @@ -755,6 +753,7 @@ class HighLine ensure @question = nil # Reset Question object. end + @answer = answer end # diff --git a/test/test_highline.rb b/test/test_highline.rb index 7430c2c..030ff89 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -453,7 +453,7 @@ class TestHighLine < Minitest::Test @input.rewind answer = @terminal.ask("Enter a filename: ") do |q| - q.confirm = "Are you sure you want to overwrite <%= @answer %>? " + q.confirm = "Are you sure you want to overwrite <%= answer %>? " q.responses[:ask_on_error] = :question end assert_equal("save.txt", answer) @@ -469,7 +469,7 @@ class TestHighLine < Minitest::Test @output.truncate(@output.rewind) answer = @terminal.ask("Enter a filename: ") do |q| - q.confirm = "Are you sure you want to overwrite <%= @answer %>? " + q.confirm = "Are you sure you want to overwrite <%= answer %>? " end assert_equal("junk.txt", answer) assert_equal( "Enter a filename: " + -- cgit v1.2.1 From 1a37ef84138684ea76f0c9a38e571364c9885f9f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 19:09:54 -0300 Subject: Reduce #gather's dependency on instance variables --- lib/highline.rb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 7e50152..b02d8c7 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -204,7 +204,6 @@ class HighLine self.page_at = page_at @question = nil - @answer = nil @menu = nil @header = nil @prompt = nil @@ -753,7 +752,7 @@ class HighLine ensure @question = nil # Reset Question object. end - @answer = answer + answer end # @@ -777,23 +776,23 @@ class HighLine case @gather when Integer - @answers << ask(@question) + @answers << last_answer = ask(@question) @gather -= 1 original_question.question = "" until @gather.zero? @question = original_question - @answers << ask(@question) + @answers << last_answer = ask(@question) @gather -= 1 end when ::String, Regexp - @answers << ask(@question) + @answers << last_answer = ask(@question) original_question.question = "" until (@gather.is_a?(::String) and @answers.last.to_s == @gather) or (@gather.is_a?(Regexp) and @answers.last.to_s =~ @gather) @question = original_question - @answers << ask(@question) + @answers << last_answer = ask(@question) end @answers.pop @@ -802,7 +801,7 @@ class HighLine @gather.keys.sort.each do |key| @question = original_question @key = key - @answers[key] = ask(@question) + @answers[key] = last_answer = ask(@question) end end @@ -815,7 +814,7 @@ class HighLine end while verify_match - original_question.verify_match ? @answer : @answers + original_question.verify_match ? last_answer : @answers end # -- cgit v1.2.1 From 8d0d8d03cb7f6eead1cedcefdd02139985ccd5eb Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 22:43:30 -0300 Subject: Reduce #explain_error's dependency on @question instance variable --- lib/highline.rb | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index b02d8c7..0a86433 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -681,12 +681,12 @@ class HighLine # A helper method for sending the output stream and error and repeat # of the question. # - def explain_error( error ) - say(@question.responses[error]) unless error.nil? - if @question.responses[:ask_on_error] == :question - say(@question) - elsif @question.responses[:ask_on_error] - say(@question.responses[:ask_on_error]) + def explain_error(error, question) + say(question.responses[error]) unless error.nil? + if question.responses[:ask_on_error] == :question + say(question) + elsif question.responses[:ask_on_error] + say(question.responses[:ask_on_error]) end end @@ -705,7 +705,7 @@ class HighLine begin answer = question.answer_or_default(get_response) unless question.valid_answer?(answer) - explain_error(:not_valid) + explain_error(:not_valid, question) raise QuestionError end @@ -725,12 +725,12 @@ class HighLine confirm_question = template.result(binding) end unless context_change.agree(confirm_question) - explain_error(nil) + explain_error(nil, question) raise QuestionError end end else - explain_error(:not_in_range) + explain_error(:not_in_range, question) raise QuestionError end rescue QuestionError @@ -741,13 +741,13 @@ class HighLine # the assumption here is that OptionParser::Completion#complete # (used for ambiguity resolution) throws exceptions containing # the word 'ambiguous' whenever resolution fails - explain_error(:ambiguous_completion) + explain_error(:ambiguous_completion, question) else - explain_error(:invalid_type) + explain_error(:invalid_type, question) end retry rescue Question::NoAutoCompleteMatch - explain_error(:no_completion) + explain_error(:no_completion, question) retry ensure @question = nil # Reset Question object. @@ -807,7 +807,7 @@ class HighLine if verify_match && (unique_answers(@answers).size > 1) @question = original_question - explain_error(:mismatch) + explain_error(:mismatch, @question) else verify_match = false end -- cgit v1.2.1 From 975a723b6ed4845c7a1e271ac3bf8dc8f781e6d1 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 22:46:48 -0300 Subject: Reduce #get_response's dependency on @question instance variable --- lib/highline.rb | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 0a86433..fe5d2ea 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -703,7 +703,7 @@ class HighLine say(question) unless ((JRUBY or question.readline) and (question.echo == true and question.limit.nil?)) begin - answer = question.answer_or_default(get_response) + answer = question.answer_or_default(get_response(question)) unless question.valid_answer?(answer) explain_error(:not_valid, question) raise QuestionError @@ -893,11 +893,11 @@ class HighLine # # Raises EOFError if input is exhausted. # - def get_response( ) - return @question.first_answer if @question.first_answer? + def get_response(question) + return question.first_answer if question.first_answer? - if @question.character.nil? - if @question.echo == true and @question.limit.nil? + if question.character.nil? + if question.echo == true and question.limit.nil? get_line else raw_no_echo_mode @@ -920,7 +920,7 @@ class HighLine # looking for carriage return (decimal 13) or # newline (decimal 10) in raw input break if character == 13 or character == 10 - if @question.echo != false + if question.echo != false if character == 127 or character == 8 # only backspace if we have characters on the line to # eliminate, otherwise we'll tromp over the prompt @@ -935,48 +935,48 @@ class HighLine # last character completes the character? # Then print it. if line_with_next_char_encoded.valid_encoding? - if @question.echo == true + if question.echo == true @output.print(line_with_next_char_encoded[-1]) else - @output.print(@question.echo) + @output.print(question.echo) end end end @output.flush end - break if @question.limit and line.size == @question.limit + break if question.limit and line.size == question.limit end ensure restore_mode end - if @question.overwrite + if question.overwrite @output.print("\r#{HighLine.Style(:erase_line).code}") @output.flush else say("\n") end - @question.change_case(@question.remove_whitespace(line.force_encoding(Encoding.default_external))) + question.change_case(question.remove_whitespace(line.force_encoding(Encoding.default_external))) end else if JRUBY #prompt has not been shown - say @question + say question end raw_no_echo_mode begin - if @question.character == :getc + if question.character == :getc response = @input.getbyte.chr else response = get_character(@input).chr - if @question.overwrite + if question.overwrite @output.print("\r#{HighLine.Style(:erase_line).code}") @output.flush else - echo = if @question.echo == true + echo = if question.echo == true response - elsif @question.echo != false - @question.echo + elsif question.echo != false + question.echo else "" end @@ -986,7 +986,7 @@ class HighLine ensure restore_mode end - @question.change_case(response) + question.change_case(response) end end -- cgit v1.2.1 From b1172f46d89f93d0c0ebd26e35dff5179dc2ac7d Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 15 Mar 2015 23:19:02 -0300 Subject: Reduce #gather's dependency on @question instance variable --- lib/highline.rb | 63 ++++++++++++++++++++++++++------------------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index fe5d2ea..dac29f9 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -207,8 +207,6 @@ class HighLine @menu = nil @header = nil @prompt = nil - @gather = nil - @answers = nil @key = nil initialize_system_extensions if respond_to?(:initialize_system_extensions) @@ -264,10 +262,10 @@ class HighLine # Raises EOFError if input is exhausted. # def ask( question, answer_type = nil, &details ) # :yields: question - @question ||= Question.new(question, answer_type, &details) + question = (@question ||= Question.new(question, answer_type, &details)) - return gather if @question.gather - return ask_once(@question) + return gather(question) if question.gather + return ask_once(question) end # @@ -761,60 +759,57 @@ class HighLine # # Raises EOFError if input is exhausted. # - def gather( ) - original_question = @question - original_question_string = @question.question - original_gather = @question.gather + def gather(question) + original_question = question + original_question_string = question.question + original_gather = question.gather - verify_match = @question.verify_match - @question.gather = false + verify_match = question.verify_match + question.gather = false begin # when verify_match is set this loop will repeat until unique_answers == 1 - @answers = [ ] - @gather = original_gather + answers = [] + gather = original_gather original_question.question = original_question_string - case @gather + case gather when Integer - @answers << last_answer = ask(@question) - @gather -= 1 + answers << last_answer = ask(question) + gather -= 1 original_question.question = "" - until @gather.zero? - @question = original_question - @answers << last_answer = ask(@question) - @gather -= 1 + until gather.zero? + answers << last_answer = ask(question) + gather -= 1 end when ::String, Regexp - @answers << last_answer = ask(@question) + answers << last_answer = ask(question) original_question.question = "" - until (@gather.is_a?(::String) and @answers.last.to_s == @gather) or - (@gather.is_a?(Regexp) and @answers.last.to_s =~ @gather) - @question = original_question - @answers << last_answer = ask(@question) + until (gather.is_a?(::String) and answers.last.to_s == gather) or + (gather.is_a?(Regexp) and answers.last.to_s =~ gather) + answers << last_answer = ask(question) end - @answers.pop + answers.pop when Hash - @answers = { } - @gather.keys.sort.each do |key| + answers = {} @question = original_question + gather.keys.sort.each do |key| @key = key - @answers[key] = last_answer = ask(@question) + answers[key] = last_answer = ask(question) end end - if verify_match && (unique_answers(@answers).size > 1) - @question = original_question - explain_error(:mismatch, @question) + if verify_match && (unique_answers(answers).size > 1) + explain_error(:mismatch, question) else verify_match = false end end while verify_match - original_question.verify_match ? last_answer : @answers + original_question.verify_match ? last_answer : answers end # @@ -822,7 +817,7 @@ class HighLine # for finding whether a list of answers match or differ # from each other. # - def unique_answers(list = @answers) + def unique_answers(list) (list.respond_to?(:values) ? list.values : list).uniq end -- cgit v1.2.1 From 0847e13d2d34e1a19751aae4a8de7f607dc7e797 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 16 Mar 2015 03:48:48 -0300 Subject: Remove logic from Question#new to #HighLine#ask --- lib/highline.rb | 8 ++++++-- lib/highline/question.rb | 6 ------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index dac29f9..91c923a 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -261,8 +261,12 @@ class HighLine # # Raises EOFError if input is exhausted. # - def ask( question, answer_type = nil, &details ) # :yields: question - question = (@question ||= Question.new(question, answer_type, &details)) + def ask( question, answer_type = nil, options = {}, &details ) # :yields: question + @question ||= Question.new(question, answer_type, &details) + + unless question.is_a? Question + question = @question + end return gather(question) if question.gather return ask_once(question) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index a4f8129..f8fa4d4 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -25,12 +25,6 @@ class HighLine # do nothing, just creating a unique error type end - def self.new(*args) - question = args.first - return question if question.is_a? Question - super(*args) - end - # # Create an instance of HighLine::Question. Expects a _question_ to ask # (can be "") and an _answer_type_ to convert the answer to. -- cgit v1.2.1 From 5e1d04560ab46f652e45d80b842ccf446491709a Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 29 Mar 2015 22:33:23 -0300 Subject: Cut HighLine#get_line @question ins var dependency --- lib/highline.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 91c923a..2424a8f 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -834,26 +834,26 @@ class HighLine # # Raises EOFError if input is exhausted. # - def get_line( ) - if @question.readline + def get_line(question) + if question.readline require "readline" # load only if needed # capture say()'s work in a String to feed to readline() old_output = @output @output = StringIO.new - say(@question) - question = @output.string + say(question) + question_string = @output.string @output = old_output # prep auto-completion Readline.completion_proc = lambda do |string| - @question.selection.grep(/\A#{Regexp.escape(string)}/) + question.selection.grep(/\A#{Regexp.escape(string)}/) end # work-around ugly readline() warnings old_verbose = $VERBOSE $VERBOSE = nil - raw_answer = Readline.readline(question, true) + raw_answer = Readline.readline(question_string, true) if raw_answer.nil? if @@track_eof raise EOFError, "The input stream is exhausted." @@ -861,14 +861,14 @@ class HighLine raw_answer = String.new # Never return nil end end - answer = @question.change_case( - @question.remove_whitespace(raw_answer)) + answer = question.change_case( + question.remove_whitespace(raw_answer)) $VERBOSE = old_verbose answer else if JRUBY - statement = Statement.new(@question, self).to_s + statement = Statement.new(question, self).to_s raw_answer = @java_console.readLine(statement, nil) raise EOFError, "The input stream is exhausted." if raw_answer.nil? and @@ -879,7 +879,7 @@ class HighLine raw_answer = @input.gets end - @question.change_case(@question.remove_whitespace(raw_answer)) + question.change_case(question.remove_whitespace(raw_answer)) end end @@ -897,7 +897,7 @@ class HighLine if question.character.nil? if question.echo == true and question.limit.nil? - get_line + get_line(question) else raw_no_echo_mode -- cgit v1.2.1 From 0a443c6e9120b629368d51018173e1daf8b9dc6a Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 29 Mar 2015 22:59:46 -0300 Subject: Reduce HighLine#choose @question ins var dependency --- lib/highline.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 2424a8f..6ddbd7e 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -288,7 +288,7 @@ class HighLine # Raises EOFError if input is exhausted. # def choose( *items, &details ) - @menu = @question = Menu.new(&details) + @menu = Menu.new(&details) @menu.choices(*items) unless items.empty? # Set auto-completion @@ -317,10 +317,10 @@ class HighLine @prompt = @menu.prompt if @menu.shell - selected = ask("Ignored", @menu.answer_type) + selected = ask(@menu) @menu.select(self, *selected) else - selected = ask("Ignored", @menu.answer_type) + selected = ask(@menu) @menu.select(self, selected) end end -- cgit v1.2.1 From a0743a7fa47edb64a66708ed3085421178f78cc1 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 30 Mar 2015 00:28:58 -0300 Subject: Add HighLine::TemplateRenderer to aggregate tpl rendering logic --- examples/repeat_entry.rb | 2 +- lib/highline.rb | 25 ++++++++++++++----------- lib/highline/menu.rb | 27 +++++++++++++-------------- lib/highline/question.rb | 4 ++++ lib/highline/statement.rb | 19 +++++++++++-------- lib/highline/template_renderer.rb | 39 +++++++++++++++++++++++++++++++++++++++ test/test_highline.rb | 10 +++++----- test/test_menu.rb | 2 +- 8 files changed, 88 insertions(+), 40 deletions(-) create mode 100644 lib/highline/template_renderer.rb diff --git a/examples/repeat_entry.rb b/examples/repeat_entry.rb index 012e960..753262e 100644 --- a/examples/repeat_entry.rb +++ b/examples/repeat_entry.rb @@ -11,7 +11,7 @@ end puts "Ok, you did it." -pass = ask("<%= @key %>: ") do |q| +pass = ask("<%= key %>: ") do |q| q.echo = '*' q.verify_match = true q.gather = {"Enter a password" => '', diff --git a/lib/highline.rb b/lib/highline.rb index 6ddbd7e..4bdbd93 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -227,6 +227,10 @@ class HighLine attr_reader :input, :output + attr_reader :key + + attr_reader :question + # # A shortcut to HighLine.ask() a question that only accepts "yes" or "no" # answers ("y" and "n" are allowed) and returns +true+ or +false+ @@ -312,10 +316,6 @@ class HighLine @menu.options # normal menu selection, by index or name end - # Provide hooks for ERb layouts. - @header = @menu.header - @prompt = @menu.prompt - if @menu.shell selected = ask(@menu) @menu.select(self, *selected) @@ -404,7 +404,9 @@ class HighLine if item.nil? "" else - ERB.new(item, nil, "%").result(binding) + template = ERB.new(item, nil, "%") + template_renderer = TemplateRenderer.new(template, self, self) + template_renderer.render end end @@ -705,15 +707,15 @@ class HighLine say(question) unless ((JRUBY or question.readline) and (question.echo == true and question.limit.nil?)) begin - answer = question.answer_or_default(get_response(question)) - unless question.valid_answer?(answer) + question.answer = question.answer_or_default(get_response(question)) + unless question.valid_answer?(question.answer) explain_error(:not_valid, question) raise QuestionError end - answer = question.convert(answer) + question.answer = question.convert(question.answer) - if question.in_range?(answer) + if question.in_range?(question.answer) if question.confirm # need to add a layer of scope to ask a question inside a # question, without destroying instance data @@ -724,7 +726,8 @@ class HighLine # evaluate ERb under initial scope, so it will have # access to question and answer template = ERB.new(question.confirm, nil, "%") - confirm_question = template.result(binding) + template_renderer = TemplateRenderer.new(template, question, self) + confirm_question = template_renderer.render end unless context_change.agree(confirm_question) explain_error(nil, question) @@ -754,7 +757,7 @@ class HighLine ensure @question = nil # Reset Question object. end - answer + question.answer end # diff --git a/lib/highline/menu.rb b/lib/highline/menu.rb index 03c5bf0..7856676 100644 --- a/lib/highline/menu.rb +++ b/lib/highline/menu.rb @@ -238,11 +238,10 @@ class HighLine # :menu_only:: Just the menu items, followed up by a likely # short _prompt_. # any ERb String:: Will be taken as the literal _layout_. This - # String can access @header, - # @menu and @prompt, but is - # otherwise evaluated in the typical HighLine - # context, to provide access to utilities like - # HighLine.list() primarily. + # String can access header, + # menu and prompt, but is + # otherwise evaluated in the TemplateRenderer + # context so each method is properly delegated. # # If set to either :one_line, or :menu_only, _index_ # will default to :none and _flow_ will default to @@ -351,19 +350,19 @@ class HighLine def to_s( ) case @layout when :list - '<%= if @header.nil? then '' else "#{@header}:\n" end %>' + - "<%= list( @menu, #{@flow.inspect}, + '<%= if header.nil? then '' else "#{header}:\n" end %>' + + "<%= list( menu, #{@flow.inspect}, #{@list_option.inspect} ) %>" + - "<%= @prompt %>" + "<%= prompt %>" when :one_line - '<%= if @header.nil? then '' else "#{@header}: " end %>' + - "<%= @prompt %>" + - "(<%= list( @menu, #{@flow.inspect}, + '<%= if header.nil? then '' else "#{header}: " end %>' + + "<%= prompt %>" + + "(<%= list( menu, #{@flow.inspect}, #{@list_option.inspect} ) %>)" + - "<%= @prompt[/\s*$/] %>" + "<%= prompt[/\s*$/] %>" when :menu_only - "<%= list( @menu, #{@flow.inspect}, - #{@list_option.inspect} ) %><%= @prompt %>" + "<%= list( menu, #{@flow.inspect}, + #{@list_option.inspect} ) %><%= prompt %>" else @layout end diff --git a/lib/highline/question.rb b/lib/highline/question.rb index f8fa4d4..6045617 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -67,6 +67,10 @@ class HighLine # The ERb template of the question to be asked. attr_accessor :question + + # The answer, set by HighLine#ask + attr_accessor :answer + # The type that will be used to convert this answer. attr_accessor :answer_type # For Auto-completion diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 3040f3a..0c260be 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -3,13 +3,16 @@ require 'highline/wrapper' require 'highline/paginator' +require 'highline/template_renderer' class HighLine::Statement - attr_reader :template_string, :highline + attr_reader :source, :highline + attr_reader :template_string - def initialize(template_string, highline) - @highline = highline - @template_string = stringfy(template_string) + def initialize(source, highline) + @highline = highline + @source = source + @template_string = stringfy(source) end def statement @@ -31,8 +34,8 @@ class HighLine::Statement statement = render_template - statement = Wrapper.wrap(statement, highline.wrap_at) - statement = Paginator.new(highline).page_print(statement) + statement = HighLine::Wrapper.wrap(statement, highline.wrap_at) + statement = HighLine::Paginator.new(highline).page_print(statement) # 'statement' is encoded in US-ASCII when using ruby 1.9.3(-p551) # 'indentation' is correctly encoded (same as default_external encoding) @@ -46,8 +49,8 @@ class HighLine::Statement # Assigning to a local var so it may be # used inside instance eval block - template_var = template - highline.instance_eval { template_var.result(binding) } + template_renderer = TemplateRenderer.new(template, source, highline) + template_renderer.render end def template diff --git a/lib/highline/template_renderer.rb b/lib/highline/template_renderer.rb new file mode 100644 index 0000000..28aba14 --- /dev/null +++ b/lib/highline/template_renderer.rb @@ -0,0 +1,39 @@ +#!/usr/bin/env ruby +# coding: utf-8 + +require 'forwardable' + +class HighLine + class TemplateRenderer + extend Forwardable + + def_delegators :@highline, :color, :list, :key, :question + def_delegators :@source, :answer_type, :prompt, :header, :answer + + attr_reader :template, :source, :highline + + def initialize(template, source, highline) + @template = template + @source = source + @highline = highline + end + + def render + template.result(binding) + end + + def method_missing(method, *args) + "Method #{method} with args #{args.inspect} " + + "is not available on #{self.inspect}. " + + "Try #{methods(false).sort.inspect}" + end + + def menu + source + end + + def self.const_missing(name) + HighLine.const_get(name) + end + end +end \ No newline at end of file diff --git a/test/test_highline.rb b/test/test_highline.rb index 030ff89..d9cedd5 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -641,7 +641,7 @@ class TestHighLine < Minitest::Test @input << "29\n49\n30\n" @input.rewind - answers = @terminal.ask("<%= @key %>: ", Integer) do |q| + answers = @terminal.ask("<%= key %>: ", Integer) do |q| q.gather = { "Age" => 0, "Wife's Age" => 0, "Father's Age" => 0} end assert_equal( { "Age" => 29, "Wife's Age" => 30, "Father's Age" => 49}, @@ -680,7 +680,7 @@ class TestHighLine < Minitest::Test @input.rewind @output.truncate(@output.rewind) - answer = @terminal.ask("<%= @key %>: ") do |q| + answer = @terminal.ask("<%= key %>: ") do |q| q.verify_match = true q.gather = {"Enter a password" => '', "Please type it again" => ''} end @@ -691,7 +691,7 @@ class TestHighLine < Minitest::Test @input.rewind @output.truncate(@output.rewind) - answer = @terminal.ask("<%= @key %>: ") do |q| + answer = @terminal.ask("<%= key %>: ") do |q| q.verify_match = true q.responses[:mismatch] = 'Typing mismatch!' q.responses[:ask_on_error] = '' @@ -1091,8 +1091,8 @@ class TestHighLine < Minitest::Test answer = @terminal.ask("Tell me your age.", Integer) do |q| q.in = 0..105 - q.responses[:not_in_range] = "Need a <%= @question.answer_type %>" + - " <%= @question.expected_range %>." + q.responses[:not_in_range] = "Need a <%= question.answer_type %>" + + " <%= question.expected_range %>." end assert_equal(28, answer) assert_equal( "Tell me your age.\n" + diff --git a/test/test_menu.rb b/test/test_menu.rb index 7f3250d..de01115 100644 --- a/test/test_menu.rb +++ b/test/test_menu.rb @@ -205,7 +205,7 @@ class TestMenu < Minitest::Test @output.truncate(@output.rewind) @terminal.choose(:load, :save, :quit) do |menu| - menu.layout = '<%= list(@menu) %>File Menu: ' + menu.layout = '<%= list(menu) %>File Menu: ' end assert_equal("1. load\n2. save\n3. quit\nFile Menu: ", @output.string) end -- cgit v1.2.1 From 2a2b73feea33cbb7a7201265c67be603fd3ed46f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 30 Mar 2015 00:36:02 -0300 Subject: Deprecate use of @menu instance var on HighLine --- lib/highline.rb | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 4bdbd93..81d3645 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -204,7 +204,6 @@ class HighLine self.page_at = page_at @question = nil - @menu = nil @header = nil @prompt = nil @key = nil @@ -292,17 +291,17 @@ class HighLine # Raises EOFError if input is exhausted. # def choose( *items, &details ) - @menu = Menu.new(&details) - @menu.choices(*items) unless items.empty? + menu = Menu.new(&details) + menu.choices(*items) unless items.empty? # Set auto-completion - @menu.completion = @menu.options + menu.completion = menu.options # Set _answer_type_ so we can double as the Question for ask(). - @menu.answer_type = if @menu.shell + menu.answer_type = if menu.shell lambda do |command| # shell-style selection first_word = command.to_s.split.first || "" - options = @menu.options + options = menu.options options.extend(OptionParser::Completion) answer = options.complete(first_word) @@ -313,15 +312,15 @@ class HighLine [answer.last, command.sub(/^\s*#{first_word}\s*/, "")] end else - @menu.options # normal menu selection, by index or name + menu.options # normal menu selection, by index or name end - if @menu.shell - selected = ask(@menu) - @menu.select(self, *selected) + if menu.shell + selected = ask(menu) + menu.select(self, *selected) else - selected = ask(@menu) - @menu.select(self, selected) + selected = ask(menu) + menu.select(self, selected) end end -- cgit v1.2.1 From 7f2c3a4c31c361c5eee85174b8de0f3e3e7c99ea Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 30 Mar 2015 11:01:29 -0300 Subject: Turn Question #question into #template to reduce confusion with the class name --- lib/highline.rb | 8 ++++---- lib/highline/question.rb | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 81d3645..0aa5aa6 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -767,7 +767,7 @@ class HighLine # def gather(question) original_question = question - original_question_string = question.question + original_question_template = question.template original_gather = question.gather verify_match = question.verify_match @@ -776,14 +776,14 @@ class HighLine begin # when verify_match is set this loop will repeat until unique_answers == 1 answers = [] gather = original_gather - original_question.question = original_question_string + original_question.template = original_question_template case gather when Integer answers << last_answer = ask(question) gather -= 1 - original_question.question = "" + original_question.template = "" until gather.zero? answers << last_answer = ask(question) gather -= 1 @@ -791,7 +791,7 @@ class HighLine when ::String, Regexp answers << last_answer = ask(question) - original_question.question = "" + original_question.template = "" until (gather.is_a?(::String) and answers.last.to_s == gather) or (gather.is_a?(Regexp) and answers.last.to_s =~ gather) answers << last_answer = ask(question) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 6045617..276ead7 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -26,15 +26,15 @@ class HighLine end # - # Create an instance of HighLine::Question. Expects a _question_ to ask + # Create an instance of HighLine::Question. Expects a _template_ to ask # (can be "") and an _answer_type_ to convert the answer to. # The _answer_type_ parameter must be a type recognized by # Question.convert(). If given, a block is yielded the new Question # object to allow custom initialization. # - def initialize( question, answer_type ) + def initialize( template, answer_type ) # initialize instance data - @question = question.dup + @template = template.dup @answer_type = answer_type @completion = @answer_type @@ -66,7 +66,7 @@ class HighLine end # The ERb template of the question to be asked. - attr_accessor :question + attr_accessor :template # The answer, set by HighLine#ask attr_accessor :answer @@ -447,9 +447,9 @@ class HighLine end end - # Stringifies the question to be asked. + # Stringifies the template to be asked. def to_s - @question + @template end # @@ -473,14 +473,14 @@ class HighLine # not affected. # def append_default( ) - if @question =~ /([\t ]+)\Z/ - @question << "|#{@default}|#{$1}" - elsif @question == "" - @question << "|#{@default}| " - elsif @question[-1, 1] == "\n" - @question[-2, 0] = " |#{@default}|" + if @template =~ /([\t ]+)\Z/ + @template << "|#{@default}|#{$1}" + elsif @template == "" + @template << "|#{@default}| " + elsif @template[-1, 1] == "\n" + @template[-2, 0] = " |#{@default}|" else - @question << " |#{@default}|" + @template << " |#{@default}|" end end end -- cgit v1.2.1 From 21f69c1b535dd1285a88e08cf7bd2677c34cf29a Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 00:15:43 -0300 Subject: Improve HighLine#gather - Improve names like gather_count - Use #ask_once directly and remove the need for ovewriting (and restoring) question gather attribute --- lib/highline.rb | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 0aa5aa6..2c997f9 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -766,44 +766,41 @@ class HighLine # Raises EOFError if input is exhausted. # def gather(question) - original_question = question original_question_template = question.template - original_gather = question.gather - verify_match = question.verify_match - question.gather = false begin # when verify_match is set this loop will repeat until unique_answers == 1 answers = [] - gather = original_gather - original_question.template = original_question_template + question.template = original_question_template - case gather + case question.gather when Integer - answers << last_answer = ask(question) - gather -= 1 + gather_count = question.gather + + answers << last_answer = ask_once(question) + gather_count -= 1 - original_question.template = "" - until gather.zero? - answers << last_answer = ask(question) - gather -= 1 + question.template = "" + until gather_count.zero? + answers << last_answer = ask_once(question) + gather_count -= 1 end when ::String, Regexp - answers << last_answer = ask(question) + answers << last_answer = ask_once(question) - original_question.template = "" - until (gather.is_a?(::String) and answers.last.to_s == gather) or - (gather.is_a?(Regexp) and answers.last.to_s =~ gather) - answers << last_answer = ask(question) + question.template = "" + until (question.gather.is_a?(::String) and answers.last.to_s == question.gather) or + (question.gather.is_a?(Regexp) and answers.last.to_s =~ question.gather) + answers << last_answer = ask_once(question) end answers.pop when Hash answers = {} - @question = original_question - gather.keys.sort.each do |key| + @question = question + question.gather.keys.sort.each do |key| @key = key - answers[key] = last_answer = ask(question) + answers[key] = last_answer = ask_once(question) end end @@ -815,7 +812,7 @@ class HighLine end while verify_match - original_question.verify_match ? last_answer : answers + question.verify_match ? last_answer : answers end # -- cgit v1.2.1 From ad3daca53c91d97122bc931ec21453890399a036 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 13:00:00 -0300 Subject: Decompose HighLine#gather type conditional --- lib/highline.rb | 73 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 2c997f9..dbbf47a 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -775,33 +775,14 @@ class HighLine case question.gather when Integer - gather_count = question.gather - - answers << last_answer = ask_once(question) - gather_count -= 1 - - question.template = "" - until gather_count.zero? - answers << last_answer = ask_once(question) - gather_count -= 1 - end + answers = gather_integer(question) + last_answer = answers.last when ::String, Regexp - answers << last_answer = ask_once(question) - - question.template = "" - until (question.gather.is_a?(::String) and answers.last.to_s == question.gather) or - (question.gather.is_a?(Regexp) and answers.last.to_s =~ question.gather) - answers << last_answer = ask_once(question) - end - - answers.pop + answers = gather_regexp(question) + last_answer = answers.last when Hash - answers = {} - @question = question - question.gather.keys.sort.each do |key| - @key = key - answers[key] = last_answer = ask_once(question) - end + answers = gather_hash(question) + last_answer = answers.to_a.last[1] end if verify_match && (unique_answers(answers).size > 1) @@ -815,6 +796,48 @@ class HighLine question.verify_match ? last_answer : answers end + def gather_integer(question) + answers = [] + + gather_count = question.gather + + answers << last_answer = ask_once(question) + gather_count -= 1 + + question.template = "" + until gather_count.zero? + answers << last_answer = ask_once(question) + gather_count -= 1 + end + + answers + end + + def gather_regexp(question) + answers = [] + + answers << last_answer = ask_once(question) + + question.template = "" + until (question.gather.is_a?(::String) and answers.last.to_s == question.gather) or + (question.gather.is_a?(Regexp) and answers.last.to_s =~ question.gather) + answers << last_answer = ask_once(question) + end + + answers.pop + answers + end + + def gather_hash(question) + answers = {} + + question.gather.keys.sort.each do |key| + @key = key + answers[key] = last_answer = ask_once(question) + end + answers + end + # # A helper method used by HighLine::Question.verify_match # for finding whether a list of answers match or differ -- cgit v1.2.1 From c2390dcafce09c4ea9af038aa90ae787a40ef78b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 13:23:10 -0300 Subject: Extract HighLine#last_answer and take advantage of it --- lib/highline.rb | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index dbbf47a..5ba1a70 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -776,13 +776,10 @@ class HighLine case question.gather when Integer answers = gather_integer(question) - last_answer = answers.last when ::String, Regexp answers = gather_regexp(question) - last_answer = answers.last when Hash answers = gather_hash(question) - last_answer = answers.to_a.last[1] end if verify_match && (unique_answers(answers).size > 1) @@ -793,7 +790,7 @@ class HighLine end while verify_match - question.verify_match ? last_answer : answers + question.verify_match ? last_answer(answers) : answers end def gather_integer(question) @@ -801,12 +798,12 @@ class HighLine gather_count = question.gather - answers << last_answer = ask_once(question) + answers << ask_once(question) gather_count -= 1 question.template = "" until gather_count.zero? - answers << last_answer = ask_once(question) + answers << ask_once(question) gather_count -= 1 end @@ -816,12 +813,12 @@ class HighLine def gather_regexp(question) answers = [] - answers << last_answer = ask_once(question) + answers << ask_once(question) question.template = "" until (question.gather.is_a?(::String) and answers.last.to_s == question.gather) or (question.gather.is_a?(Regexp) and answers.last.to_s =~ question.gather) - answers << last_answer = ask_once(question) + answers << ask_once(question) end answers.pop @@ -833,7 +830,7 @@ class HighLine question.gather.keys.sort.each do |key| @key = key - answers[key] = last_answer = ask_once(question) + answers[key] = ask_once(question) end answers end @@ -847,6 +844,10 @@ class HighLine (list.respond_to?(:values) ? list.values : list).uniq end + def last_answer(answers) + answers.respond_to?(:values) ? answers.values.last : answers.last + end + # # Read a line of input from the input stream and process whitespace as # requested by the Question object. -- cgit v1.2.1 From c7cb4e73141c29c6ddd89441c4846e1094f8ac3b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 13:24:40 -0300 Subject: Unify answers assignment to the whole case/when clause --- lib/highline.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 5ba1a70..57c3cf3 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -770,16 +770,16 @@ class HighLine verify_match = question.verify_match begin # when verify_match is set this loop will repeat until unique_answers == 1 - answers = [] question.template = original_question_template + answers = case question.gather when Integer - answers = gather_integer(question) + gather_integer(question) when ::String, Regexp - answers = gather_regexp(question) + gather_regexp(question) when Hash - answers = gather_hash(question) + gather_hash(question) end if verify_match && (unique_answers(answers).size > 1) -- cgit v1.2.1 From 8c3bcac4239e68e441c56e5eceafefc2badad98c Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 16:49:57 -0300 Subject: Simplify looping with an iterator --- lib/highline.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 57c3cf3..5bb2bd3 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -796,15 +796,12 @@ class HighLine def gather_integer(question) answers = [] - gather_count = question.gather - answers << ask_once(question) - gather_count -= 1 question.template = "" - until gather_count.zero? + + (question.gather-1).times do answers << ask_once(question) - gather_count -= 1 end answers -- cgit v1.2.1 From d3096710542e97a9d3635bcdaa2c69f67af2950a Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 16:58:50 -0300 Subject: Use 'unless' inline syntax --- lib/highline.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 5bb2bd3..db7e64e 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -305,9 +305,7 @@ class HighLine options.extend(OptionParser::Completion) answer = options.complete(first_word) - if answer.nil? - raise Question::NoAutoCompleteMatch - end + raise Question::NoAutoCompleteMatch unless answer [answer.last, command.sub(/^\s*#{first_word}\s*/, "")] end -- cgit v1.2.1 From 2222674d8f065cfae22c5a1a68152995c52f2272 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 17:00:29 -0300 Subject: Level up repetitive assignment --- lib/highline.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index db7e64e..c2ee1b7 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -313,11 +313,11 @@ class HighLine menu.options # normal menu selection, by index or name end + selected = ask(menu) + if menu.shell - selected = ask(menu) menu.select(self, *selected) else - selected = ask(menu) menu.select(self, selected) end end -- cgit v1.2.1 From 42b2f741542fdbc0ef2d1c1769323f9b97278f7d Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 17:05:11 -0300 Subject: Assign lambda to a loc var and references it in a shorter line --- lib/highline.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index c2ee1b7..cc13b5a 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -296,23 +296,23 @@ class HighLine # Set auto-completion menu.completion = menu.options - # Set _answer_type_ so we can double as the Question for ask(). - menu.answer_type = if menu.shell - lambda do |command| # shell-style selection - first_word = command.to_s.split.first || "" - options = menu.options - options.extend(OptionParser::Completion) - answer = options.complete(first_word) + shell_style_lambda = lambda do |command| # shell-style selection + first_word = command.to_s.split.first || "" - raise Question::NoAutoCompleteMatch unless answer + options = menu.options + options.extend(OptionParser::Completion) + answer = options.complete(first_word) - [answer.last, command.sub(/^\s*#{first_word}\s*/, "")] - end - else - menu.options # normal menu selection, by index or name + raise Question::NoAutoCompleteMatch unless answer + + [answer.last, command.sub(/^\s*#{first_word}\s*/, "")] end + # Set _answer_type_ so we can double as the Question for ask(). + # menu.option = normal menu selection, by index or name + menu.answer_type = menu.shell ? shell_style_lambda : menu.options + selected = ask(menu) if menu.shell -- cgit v1.2.1 From e6d5d5a21c16c087245ca25192261f52450a8f99 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 23:50:46 -0300 Subject: Add better names for clearer intents --- lib/highline.rb | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index cc13b5a..93f23a0 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -264,11 +264,11 @@ class HighLine # # Raises EOFError if input is exhausted. # - def ask( question, answer_type = nil, options = {}, &details ) # :yields: question - @question ||= Question.new(question, answer_type, &details) - - unless question.is_a? Question - question = @question + def ask(template_or_question, answer_type = nil, options = {}, &details) # :yields: question + if template_or_question.is_a? Question + @question = template_or_question + else + @question = Question.new(template_or_question, answer_type, &details) end return gather(question) if question.gather @@ -751,8 +751,6 @@ class HighLine rescue Question::NoAutoCompleteMatch explain_error(:no_completion, question) retry - ensure - @question = nil # Reset Question object. end question.answer end -- cgit v1.2.1 From 866c49a803b47a8d20aa9b34c8167bdf772da289 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 23:52:43 -0300 Subject: Extract HighLine#render_list_items method from HighLine#list --- lib/highline.rb | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 93f23a0..fa41c42 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -397,15 +397,7 @@ class HighLine # final field width. # def list( items, mode = :rows, option = nil ) - items = items.to_ary.map do |item| - if item.nil? - "" - else - template = ERB.new(item, nil, "%") - template_renderer = TemplateRenderer.new(template, self, self) - template_renderer.render - end - end + items = render_list_items(items) if items.empty? "" @@ -564,6 +556,18 @@ class HighLine end end + def render_list_items(items) + items.to_ary.map do |item| + if item.nil? + "" + else + template = ERB.new(item, nil, "%") + template_renderer = TemplateRenderer.new(template, self, self) + template_renderer.render + end + end + end + # # The basic output method for HighLine objects. If the provided _statement_ # ends with a space or tab character, a newline will not be appended (output -- cgit v1.2.1 From 27aa22af2ab3d366dc5da13ffb1d1ac44e91489a Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 23:54:04 -0300 Subject: Add an early conversion to String and drop a conditional --- lib/highline.rb | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index fa41c42..4d65c9a 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -558,13 +558,10 @@ class HighLine def render_list_items(items) items.to_ary.map do |item| - if item.nil? - "" - else - template = ERB.new(item, nil, "%") - template_renderer = TemplateRenderer.new(template, self, self) - template_renderer.render - end + item = String(item) + template = ERB.new(item, nil, "%") + template_renderer = TemplateRenderer.new(template, self, self) + template_renderer.render end end -- cgit v1.2.1 From 12864ddc4d44ed29b321a4ff07100be54321e44f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 23:57:15 -0300 Subject: Use an early return (guard clause) so we simplify the conditional --- lib/highline.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 4d65c9a..d0059e9 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -399,9 +399,7 @@ class HighLine def list( items, mode = :rows, option = nil ) items = render_list_items(items) - if items.empty? - "" - else + return "" if items.empty? case mode when :inline option = " or " if option.nil? @@ -553,7 +551,6 @@ class HighLine else items.map { |i| "#{i}\n" }.join end - end end def render_list_items(items) -- cgit v1.2.1 From 88d7d42aa56363b8fdb375ff6b92103483bd3919 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 31 Mar 2015 23:57:54 -0300 Subject: Only reindent code --- lib/highline.rb | 231 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 116 insertions(+), 115 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index d0059e9..7585276 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -400,86 +400,63 @@ class HighLine items = render_list_items(items) return "" if items.empty? - case mode - when :inline - option = " or " if option.nil? - if items.size == 1 - items.first - else - items[0..-2].join(", ") + "#{option}#{items.last}" - end - when :columns_across, :columns_down - max_length = actual_length( - items.max { |a, b| actual_length(a) <=> actual_length(b) } - ) - - if option.nil? - limit = @wrap_at || 80 - option = (limit + 2) / (max_length + 2) - end + case mode + when :inline + option = " or " if option.nil? - items = items.map do |item| - pad = max_length + (item.to_s.length - actual_length(item)) - "%-#{pad}s" % item - end - row_count = (items.size / option.to_f).ceil - - if mode == :columns_across - rows = Array.new(row_count) { Array.new } - items.each_with_index do |item, index| - rows[index / option] << item - end + if items.size == 1 + items.first + else + items[0..-2].join(", ") + "#{option}#{items.last}" + end + when :columns_across, :columns_down + max_length = actual_length( + items.max { |a, b| actual_length(a) <=> actual_length(b) } + ) + + if option.nil? + limit = @wrap_at || 80 + option = (limit + 2) / (max_length + 2) + end - rows.map { |row| row.join(" ") + "\n" }.join - else - columns = Array.new(option) { Array.new } - items.each_with_index do |item, index| - columns[index / row_count] << item - end + items = items.map do |item| + pad = max_length + (item.to_s.length - actual_length(item)) + "%-#{pad}s" % item + end + row_count = (items.size / option.to_f).ceil - list = "" - columns.first.size.times do |index| - list << columns.map { |column| column[index] }. - compact.join(" ") + "\n" - end - list + if mode == :columns_across + rows = Array.new(row_count) { Array.new } + items.each_with_index do |item, index| + rows[index / option] << item end - when :uneven_columns_across - if option.nil? - limit = @wrap_at || 80 - items.size.downto(1) do |column_count| - row_count = (items.size / column_count.to_f).ceil - rows = Array.new(row_count) { Array.new } - items.each_with_index do |item, index| - rows[index / column_count] << item - end - widths = Array.new(column_count, 0) - rows.each do |row| - row.each_with_index do |field, column| - size = actual_length(field) - widths[column] = size if size > widths[column] - end - end + rows.map { |row| row.join(" ") + "\n" }.join + else + columns = Array.new(option) { Array.new } + items.each_with_index do |item, index| + columns[index / row_count] << item + end - if column_count == 1 or - widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 - return rows.map { |row| - row.zip(widths).map { |field, i| - "%-#{i + (field.to_s.length - actual_length(field))}s" % field - }.join(" ") + "\n" - }.join - end - end - else - row_count = (items.size / option.to_f).ceil + list = "" + columns.first.size.times do |index| + list << columns.map { |column| column[index] }. + compact.join(" ") + "\n" + end + list + end + when :uneven_columns_across + if option.nil? + limit = @wrap_at || 80 + items.size.downto(1) do |column_count| + row_count = (items.size / column_count.to_f).ceil rows = Array.new(row_count) { Array.new } items.each_with_index do |item, index| - rows[index / option] << item + rows[index / column_count] << item end - widths = Array.new(option, 0) + widths = Array.new(column_count, 0) rows.each do |row| row.each_with_index do |field, column| size = actual_length(field) @@ -487,51 +464,47 @@ class HighLine end end - return rows.map { |row| - row.zip(widths).map { |field, i| - "%-#{i + (field.to_s.length - actual_length(field))}s" % field - }.join(" ") + "\n" - }.join + if column_count == 1 or + widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 + return rows.map { |row| + row.zip(widths).map { |field, i| + "%-#{i + (field.to_s.length - actual_length(field))}s" % field + }.join(" ") + "\n" + }.join + end + end + else + row_count = (items.size / option.to_f).ceil + rows = Array.new(row_count) { Array.new } + items.each_with_index do |item, index| + rows[index / option] << item end - when :uneven_columns_down - if option.nil? - limit = @wrap_at || 80 - items.size.downto(1) do |column_count| - row_count = (items.size / column_count.to_f).ceil - columns = Array.new(column_count) { Array.new } - items.each_with_index do |item, index| - columns[index / row_count] << item - end - - widths = Array.new(column_count, 0) - columns.each_with_index do |column, i| - column.each do |field| - size = actual_length(field) - widths[i] = size if size > widths[i] - end - end - if column_count == 1 or - widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 - list = "" - columns.first.size.times do |index| - list << columns.zip(widths).map { |column, width| - field = column[index] - "%-#{width + (field.to_s.length - actual_length(field))}s" % - field - }.compact.join(" ").strip + "\n" - end - return list - end + widths = Array.new(option, 0) + rows.each do |row| + row.each_with_index do |field, column| + size = actual_length(field) + widths[column] = size if size > widths[column] end - else - row_count = (items.size / option.to_f).ceil - columns = Array.new(option) { Array.new } + end + + return rows.map { |row| + row.zip(widths).map { |field, i| + "%-#{i + (field.to_s.length - actual_length(field))}s" % field + }.join(" ") + "\n" + }.join + end + when :uneven_columns_down + if option.nil? + limit = @wrap_at || 80 + items.size.downto(1) do |column_count| + row_count = (items.size / column_count.to_f).ceil + columns = Array.new(column_count) { Array.new } items.each_with_index do |item, index| columns[index / row_count] << item end - widths = Array.new(option, 0) + widths = Array.new(column_count, 0) columns.each_with_index do |column, i| column.each do |field| size = actual_length(field) @@ -539,18 +512,46 @@ class HighLine end end - list = "" - columns.first.size.times do |index| - list << columns.zip(widths).map { |column, width| - field = column[index] - "%-#{width + (field.to_s.length - actual_length(field))}s" % field - }.compact.join(" ").strip + "\n" + if column_count == 1 or + widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 + list = "" + columns.first.size.times do |index| + list << columns.zip(widths).map { |column, width| + field = column[index] + "%-#{width + (field.to_s.length - actual_length(field))}s" % + field + }.compact.join(" ").strip + "\n" + end + return list end - return list end else - items.map { |i| "#{i}\n" }.join + row_count = (items.size / option.to_f).ceil + columns = Array.new(option) { Array.new } + items.each_with_index do |item, index| + columns[index / row_count] << item + end + + widths = Array.new(option, 0) + columns.each_with_index do |column, i| + column.each do |field| + size = actual_length(field) + widths[i] = size if size > widths[i] + end + end + + list = "" + columns.first.size.times do |index| + list << columns.zip(widths).map { |column, width| + field = column[index] + "%-#{width + (field.to_s.length - actual_length(field))}s" % field + }.compact.join(" ").strip + "\n" + end + return list end + else + items.map { |i| "#{i}\n" }.join + end end def render_list_items(items) -- cgit v1.2.1 From 322f461d80c53e7b345843cf3ec7e80b5e2d8fbf Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 00:19:32 -0300 Subject: Split HighLine#list method in several methods by mode --- lib/highline.rb | 270 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 149 insertions(+), 121 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 7585276..27fb6e2 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -403,84 +403,98 @@ class HighLine case mode when :inline - option = " or " if option.nil? + list_inline_mode(items, option) + when :columns_across + list_columns_across_mode(items, option) + when :columns_down + list_columns_down_mode(items, option) + when :uneven_columns_across + list_uneven_columns_mode(items, option) + when :uneven_columns_down + list_uneven_columns_down_mode(items, option) + else + items.map { |i| "#{i}\n" }.join + end + end - if items.size == 1 - items.first - else - items[0..-2].join(", ") + "#{option}#{items.last}" - end - when :columns_across, :columns_down - max_length = actual_length( - items.max { |a, b| actual_length(a) <=> actual_length(b) } - ) - - if option.nil? - limit = @wrap_at || 80 - option = (limit + 2) / (max_length + 2) - end + def render_list_items(items) + items.to_ary.map do |item| + item = String(item) + template = ERB.new(item, nil, "%") + template_renderer = TemplateRenderer.new(template, self, self) + template_renderer.render + end + end - items = items.map do |item| - pad = max_length + (item.to_s.length - actual_length(item)) - "%-#{pad}s" % item - end - row_count = (items.size / option.to_f).ceil + def list_inline_mode(items, option) + option = " or " if option.nil? - if mode == :columns_across - rows = Array.new(row_count) { Array.new } - items.each_with_index do |item, index| - rows[index / option] << item - end + if items.size == 1 + items.first + else + items[0..-2].join(", ") + "#{option}#{items.last}" + end + end - rows.map { |row| row.join(" ") + "\n" }.join - else - columns = Array.new(option) { Array.new } - items.each_with_index do |item, index| - columns[index / row_count] << item - end + def list_columns_mode_prepare(items, option) + max_length = actual_length( + items.max { |a, b| actual_length(a) <=> actual_length(b) } + ) - list = "" - columns.first.size.times do |index| - list << columns.map { |column| column[index] }. - compact.join(" ") + "\n" - end - list - end - when :uneven_columns_across - if option.nil? - limit = @wrap_at || 80 - items.size.downto(1) do |column_count| - row_count = (items.size / column_count.to_f).ceil - rows = Array.new(row_count) { Array.new } - items.each_with_index do |item, index| - rows[index / column_count] << item - end + if option.nil? + limit = @wrap_at || 80 + option = (limit + 2) / (max_length + 2) + end - widths = Array.new(column_count, 0) - rows.each do |row| - row.each_with_index do |field, column| - size = actual_length(field) - widths[column] = size if size > widths[column] - end - end + items = items.map do |item| + pad = max_length + (item.to_s.length - actual_length(item)) + "%-#{pad}s" % item + end + row_count = (items.size / option.to_f).ceil - if column_count == 1 or - widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 - return rows.map { |row| - row.zip(widths).map { |field, i| - "%-#{i + (field.to_s.length - actual_length(field))}s" % field - }.join(" ") + "\n" - }.join - end - end - else - row_count = (items.size / option.to_f).ceil + [max_length, option, items, row_count] + end + + def list_columns_across_mode(items, option) + max_length, option, items, row_count = + list_columns_mode_prepare(items, option) + + rows = Array.new(row_count) { Array.new } + items.each_with_index do |item, index| + rows[index / option] << item + end + + rows.map { |row| row.join(" ") + "\n" }.join + end + + def list_columns_down_mode(items, option) + max_length, option, items, row_count = + list_columns_mode_prepare(items, option) + + columns = Array.new(option) { Array.new } + items.each_with_index do |item, index| + columns[index / row_count] << item + end + + list = "" + columns.first.size.times do |index| + list << columns.map { |column| column[index] }. + compact.join(" ") + "\n" + end + list + end + + def list_uneven_columns_mode(items, option) + if option.nil? + limit = @wrap_at || 80 + items.size.downto(1) do |column_count| + row_count = (items.size / column_count.to_f).ceil rows = Array.new(row_count) { Array.new } items.each_with_index do |item, index| - rows[index / option] << item + rows[index / column_count] << item end - widths = Array.new(option, 0) + widths = Array.new(column_count, 0) rows.each do |row| row.each_with_index do |field, column| size = actual_length(field) @@ -488,51 +502,49 @@ class HighLine end end - return rows.map { |row| - row.zip(widths).map { |field, i| - "%-#{i + (field.to_s.length - actual_length(field))}s" % field - }.join(" ") + "\n" - }.join + if column_count == 1 or + widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 + return rows.map { |row| + row.zip(widths).map { |field, i| + "%-#{i + (field.to_s.length - actual_length(field))}s" % field + }.join(" ") + "\n" + }.join + end + end + else + row_count = (items.size / option.to_f).ceil + rows = Array.new(row_count) { Array.new } + items.each_with_index do |item, index| + rows[index / option] << item end - when :uneven_columns_down - if option.nil? - limit = @wrap_at || 80 - items.size.downto(1) do |column_count| - row_count = (items.size / column_count.to_f).ceil - columns = Array.new(column_count) { Array.new } - items.each_with_index do |item, index| - columns[index / row_count] << item - end - - widths = Array.new(column_count, 0) - columns.each_with_index do |column, i| - column.each do |field| - size = actual_length(field) - widths[i] = size if size > widths[i] - end - end - if column_count == 1 or - widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 - list = "" - columns.first.size.times do |index| - list << columns.zip(widths).map { |column, width| - field = column[index] - "%-#{width + (field.to_s.length - actual_length(field))}s" % - field - }.compact.join(" ").strip + "\n" - end - return list - end + widths = Array.new(option, 0) + rows.each do |row| + row.each_with_index do |field, column| + size = actual_length(field) + widths[column] = size if size > widths[column] end - else - row_count = (items.size / option.to_f).ceil - columns = Array.new(option) { Array.new } + end + + return rows.map { |row| + row.zip(widths).map { |field, i| + "%-#{i + (field.to_s.length - actual_length(field))}s" % field + }.join(" ") + "\n" + }.join + end + end + + def list_uneven_columns_down_mode(items, option) + if option.nil? + limit = @wrap_at || 80 + items.size.downto(1) do |column_count| + row_count = (items.size / column_count.to_f).ceil + columns = Array.new(column_count) { Array.new } items.each_with_index do |item, index| columns[index / row_count] << item end - widths = Array.new(option, 0) + widths = Array.new(column_count, 0) columns.each_with_index do |column, i| column.each do |field| size = actual_length(field) @@ -540,26 +552,42 @@ class HighLine end end - list = "" - columns.first.size.times do |index| - list << columns.zip(widths).map { |column, width| - field = column[index] - "%-#{width + (field.to_s.length - actual_length(field))}s" % field - }.compact.join(" ").strip + "\n" + if column_count == 1 or + widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 + list = "" + columns.first.size.times do |index| + list << columns.zip(widths).map { |column, width| + field = column[index] + "%-#{width + (field.to_s.length - actual_length(field))}s" % + field + }.compact.join(" ").strip + "\n" + end + return list end - return list end else - items.map { |i| "#{i}\n" }.join - end - end + row_count = (items.size / option.to_f).ceil + columns = Array.new(option) { Array.new } + items.each_with_index do |item, index| + columns[index / row_count] << item + end - def render_list_items(items) - items.to_ary.map do |item| - item = String(item) - template = ERB.new(item, nil, "%") - template_renderer = TemplateRenderer.new(template, self, self) - template_renderer.render + widths = Array.new(option, 0) + columns.each_with_index do |column, i| + column.each do |field| + size = actual_length(field) + widths[i] = size if size > widths[i] + end + end + + list = "" + columns.first.size.times do |index| + list << columns.zip(widths).map { |column, width| + field = column[index] + "%-#{width + (field.to_s.length - actual_length(field))}s" % field + }.compact.join(" ").strip + "\n" + end + return list end end -- cgit v1.2.1 From 3a755f69ffa7abaee437d90a2799715de72428cf Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 15:32:48 -0300 Subject: Move HighLine#list related code to its own class --- lib/highline.rb | 228 -------------------------------------------------- lib/highline/list.rb | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 229 insertions(+), 228 deletions(-) create mode 100644 lib/highline/list.rb diff --git a/lib/highline.rb b/lib/highline.rb index 27fb6e2..85c85a9 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -363,234 +363,6 @@ class HighLine self.class.uncolor(string) end - # - # This method is a utility for quickly and easily laying out lists. It can - # be accessed within ERb replacements of any text that will be sent to the - # user. - # - # The only required parameter is _items_, which should be the Array of items - # to list. A specified _mode_ controls how that list is formed and _option_ - # has different effects, depending on the _mode_. Recognized modes are: - # - # :columns_across:: _items_ will be placed in columns, - # flowing from left to right. If given, - # _option_ is the number of columns to be - # used. When absent, columns will be - # determined based on _wrap_at_ or a - # default of 80 characters. - # :columns_down:: Identical to :columns_across, - # save flow goes down. - # :uneven_columns_across:: Like :columns_across but each - # column is sized independently. - # :uneven_columns_down:: Like :columns_down but each - # column is sized independently. - # :inline:: All _items_ are placed on a single line. - # The last two _items_ are separated by - # _option_ or a default of " or ". All - # other _items_ are separated by ", ". - # :rows:: The default mode. Each of the _items_ is - # placed on its own line. The _option_ - # parameter is ignored in this mode. - # - # Each member of the _items_ Array is passed through ERb and thus can contain - # their own expansions. Color escape expansions do not contribute to the - # final field width. - # - def list( items, mode = :rows, option = nil ) - items = render_list_items(items) - - return "" if items.empty? - - case mode - when :inline - list_inline_mode(items, option) - when :columns_across - list_columns_across_mode(items, option) - when :columns_down - list_columns_down_mode(items, option) - when :uneven_columns_across - list_uneven_columns_mode(items, option) - when :uneven_columns_down - list_uneven_columns_down_mode(items, option) - else - items.map { |i| "#{i}\n" }.join - end - end - - def render_list_items(items) - items.to_ary.map do |item| - item = String(item) - template = ERB.new(item, nil, "%") - template_renderer = TemplateRenderer.new(template, self, self) - template_renderer.render - end - end - - def list_inline_mode(items, option) - option = " or " if option.nil? - - if items.size == 1 - items.first - else - items[0..-2].join(", ") + "#{option}#{items.last}" - end - end - - def list_columns_mode_prepare(items, option) - max_length = actual_length( - items.max { |a, b| actual_length(a) <=> actual_length(b) } - ) - - if option.nil? - limit = @wrap_at || 80 - option = (limit + 2) / (max_length + 2) - end - - items = items.map do |item| - pad = max_length + (item.to_s.length - actual_length(item)) - "%-#{pad}s" % item - end - row_count = (items.size / option.to_f).ceil - - [max_length, option, items, row_count] - end - - def list_columns_across_mode(items, option) - max_length, option, items, row_count = - list_columns_mode_prepare(items, option) - - rows = Array.new(row_count) { Array.new } - items.each_with_index do |item, index| - rows[index / option] << item - end - - rows.map { |row| row.join(" ") + "\n" }.join - end - - def list_columns_down_mode(items, option) - max_length, option, items, row_count = - list_columns_mode_prepare(items, option) - - columns = Array.new(option) { Array.new } - items.each_with_index do |item, index| - columns[index / row_count] << item - end - - list = "" - columns.first.size.times do |index| - list << columns.map { |column| column[index] }. - compact.join(" ") + "\n" - end - list - end - - def list_uneven_columns_mode(items, option) - if option.nil? - limit = @wrap_at || 80 - items.size.downto(1) do |column_count| - row_count = (items.size / column_count.to_f).ceil - rows = Array.new(row_count) { Array.new } - items.each_with_index do |item, index| - rows[index / column_count] << item - end - - widths = Array.new(column_count, 0) - rows.each do |row| - row.each_with_index do |field, column| - size = actual_length(field) - widths[column] = size if size > widths[column] - end - end - - if column_count == 1 or - widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 - return rows.map { |row| - row.zip(widths).map { |field, i| - "%-#{i + (field.to_s.length - actual_length(field))}s" % field - }.join(" ") + "\n" - }.join - end - end - else - row_count = (items.size / option.to_f).ceil - rows = Array.new(row_count) { Array.new } - items.each_with_index do |item, index| - rows[index / option] << item - end - - widths = Array.new(option, 0) - rows.each do |row| - row.each_with_index do |field, column| - size = actual_length(field) - widths[column] = size if size > widths[column] - end - end - - return rows.map { |row| - row.zip(widths).map { |field, i| - "%-#{i + (field.to_s.length - actual_length(field))}s" % field - }.join(" ") + "\n" - }.join - end - end - - def list_uneven_columns_down_mode(items, option) - if option.nil? - limit = @wrap_at || 80 - items.size.downto(1) do |column_count| - row_count = (items.size / column_count.to_f).ceil - columns = Array.new(column_count) { Array.new } - items.each_with_index do |item, index| - columns[index / row_count] << item - end - - widths = Array.new(column_count, 0) - columns.each_with_index do |column, i| - column.each do |field| - size = actual_length(field) - widths[i] = size if size > widths[i] - end - end - - if column_count == 1 or - widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 - list = "" - columns.first.size.times do |index| - list << columns.zip(widths).map { |column, width| - field = column[index] - "%-#{width + (field.to_s.length - actual_length(field))}s" % - field - }.compact.join(" ").strip + "\n" - end - return list - end - end - else - row_count = (items.size / option.to_f).ceil - columns = Array.new(option) { Array.new } - items.each_with_index do |item, index| - columns[index / row_count] << item - end - - widths = Array.new(option, 0) - columns.each_with_index do |column, i| - column.each do |field| - size = actual_length(field) - widths[i] = size if size > widths[i] - end - end - - list = "" - columns.first.size.times do |index| - list << columns.zip(widths).map { |column, width| - field = column[index] - "%-#{width + (field.to_s.length - actual_length(field))}s" % field - }.compact.join(" ").strip + "\n" - end - return list - end - end - # # The basic output method for HighLine objects. If the provided _statement_ # ends with a space or tab character, a newline will not be appended (output diff --git a/lib/highline/list.rb b/lib/highline/list.rb new file mode 100644 index 0000000..2bbd21e --- /dev/null +++ b/lib/highline/list.rb @@ -0,0 +1,229 @@ +class HighLine::List + # + # This method is a utility for quickly and easily laying out lists. It can + # be accessed within ERb replacements of any text that will be sent to the + # user. + # + # The only required parameter is _items_, which should be the Array of items + # to list. A specified _mode_ controls how that list is formed and _option_ + # has different effects, depending on the _mode_. Recognized modes are: + # + # :columns_across:: _items_ will be placed in columns, + # flowing from left to right. If given, + # _option_ is the number of columns to be + # used. When absent, columns will be + # determined based on _wrap_at_ or a + # default of 80 characters. + # :columns_down:: Identical to :columns_across, + # save flow goes down. + # :uneven_columns_across:: Like :columns_across but each + # column is sized independently. + # :uneven_columns_down:: Like :columns_down but each + # column is sized independently. + # :inline:: All _items_ are placed on a single line. + # The last two _items_ are separated by + # _option_ or a default of " or ". All + # other _items_ are separated by ", ". + # :rows:: The default mode. Each of the _items_ is + # placed on its own line. The _option_ + # parameter is ignored in this mode. + # + # Each member of the _items_ Array is passed through ERb and thus can contain + # their own expansions. Color escape expansions do not contribute to the + # final field width. + # + def list( items, mode = :rows, option = nil ) + items = render_list_items(items) + + return "" if items.empty? + + case mode + when :inline + list_inline_mode(items, option) + when :columns_across + list_columns_across_mode(items, option) + when :columns_down + list_columns_down_mode(items, option) + when :uneven_columns_across + list_uneven_columns_mode(items, option) + when :uneven_columns_down + list_uneven_columns_down_mode(items, option) + else + items.map { |i| "#{i}\n" }.join + end + end + + def render_list_items(items) + items.to_ary.map do |item| + item = String(item) + template = ERB.new(item, nil, "%") + template_renderer = TemplateRenderer.new(template, self, self) + template_renderer.render + end + end + + def list_inline_mode(items, option) + option = " or " if option.nil? + + if items.size == 1 + items.first + else + items[0..-2].join(", ") + "#{option}#{items.last}" + end + end + + def list_columns_mode_prepare(items, option) + max_length = actual_length( + items.max { |a, b| actual_length(a) <=> actual_length(b) } + ) + + if option.nil? + limit = @wrap_at || 80 + option = (limit + 2) / (max_length + 2) + end + + items = items.map do |item| + pad = max_length + (item.to_s.length - actual_length(item)) + "%-#{pad}s" % item + end + row_count = (items.size / option.to_f).ceil + + [max_length, option, items, row_count] + end + + def list_columns_across_mode(items, option) + max_length, option, items, row_count = + list_columns_mode_prepare(items, option) + + rows = Array.new(row_count) { Array.new } + items.each_with_index do |item, index| + rows[index / option] << item + end + + rows.map { |row| row.join(" ") + "\n" }.join + end + + def list_columns_down_mode(items, option) + max_length, option, items, row_count = + list_columns_mode_prepare(items, option) + + columns = Array.new(option) { Array.new } + items.each_with_index do |item, index| + columns[index / row_count] << item + end + + list = "" + columns.first.size.times do |index| + list << columns.map { |column| column[index] }. + compact.join(" ") + "\n" + end + list + end + + def list_uneven_columns_mode(items, option) + if option.nil? + limit = @wrap_at || 80 + items.size.downto(1) do |column_count| + row_count = (items.size / column_count.to_f).ceil + rows = Array.new(row_count) { Array.new } + items.each_with_index do |item, index| + rows[index / column_count] << item + end + + widths = Array.new(column_count, 0) + rows.each do |row| + row.each_with_index do |field, column| + size = actual_length(field) + widths[column] = size if size > widths[column] + end + end + + if column_count == 1 or + widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 + return rows.map { |row| + row.zip(widths).map { |field, i| + "%-#{i + (field.to_s.length - actual_length(field))}s" % field + }.join(" ") + "\n" + }.join + end + end + else + row_count = (items.size / option.to_f).ceil + rows = Array.new(row_count) { Array.new } + items.each_with_index do |item, index| + rows[index / option] << item + end + + widths = Array.new(option, 0) + rows.each do |row| + row.each_with_index do |field, column| + size = actual_length(field) + widths[column] = size if size > widths[column] + end + end + + return rows.map { |row| + row.zip(widths).map { |field, i| + "%-#{i + (field.to_s.length - actual_length(field))}s" % field + }.join(" ") + "\n" + }.join + end + end + + def list_uneven_columns_down_mode(items, option) + if option.nil? + limit = @wrap_at || 80 + items.size.downto(1) do |column_count| + row_count = (items.size / column_count.to_f).ceil + columns = Array.new(column_count) { Array.new } + items.each_with_index do |item, index| + columns[index / row_count] << item + end + + widths = Array.new(column_count, 0) + columns.each_with_index do |column, i| + column.each do |field| + size = actual_length(field) + widths[i] = size if size > widths[i] + end + end + + if column_count == 1 or + widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 + list = "" + columns.first.size.times do |index| + list << columns.zip(widths).map { |column, width| + field = column[index] + "%-#{width + (field.to_s.length - actual_length(field))}s" % + field + }.compact.join(" ").strip + "\n" + end + return list + end + end + else + row_count = (items.size / option.to_f).ceil + columns = Array.new(option) { Array.new } + items.each_with_index do |item, index| + columns[index / row_count] << item + end + + widths = Array.new(option, 0) + columns.each_with_index do |column, i| + column.each do |field| + size = actual_length(field) + widths[i] = size if size > widths[i] + end + end + + list = "" + columns.first.size.times do |index| + list << columns.zip(widths).map { |column, width| + field = column[index] + "%-#{width + (field.to_s.length - actual_length(field))}s" % field + }.compact.join(" ").strip + "\n" + end + return list + end + end +end \ No newline at end of file -- cgit v1.2.1 From 91c5431753d5c0c4d220fc0367db1c7c778bd22c Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 18:56:03 -0300 Subject: Add the fixes to make HighLine::List usable --- lib/highline.rb | 5 ++++ lib/highline/list.rb | 70 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 85c85a9..c40fe7f 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -21,6 +21,7 @@ require "highline/color_scheme" require "highline/style" require "highline/version" require "highline/statement" +require "highline/list" # # A HighLine object is a "high-level line oriented" shell over an input and an @@ -363,6 +364,10 @@ class HighLine self.class.uncolor(string) end + def list(items, mode = :rows, option = nil) + List.new(items, mode, option, self).render + end + # # The basic output method for HighLine objects. If the provided _statement_ # ends with a space or tab character, a newline will not be appended (output diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 2bbd21e..060fe9b 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -1,4 +1,16 @@ +require 'highline/template_renderer' +require 'highline/wrapper' + class HighLine::List + attr_reader :items, :mode, :option, :highline + + def initialize(items, mode = :rows, option = nil, highline) + @highline = highline + @mode = mode + @option = option + @items = render_list_items(items) + end + # # This method is a utility for quickly and easily laying out lists. It can # be accessed within ERb replacements of any text that will be sent to the @@ -32,68 +44,66 @@ class HighLine::List # their own expansions. Color escape expansions do not contribute to the # final field width. # - def list( items, mode = :rows, option = nil ) - items = render_list_items(items) - + def render return "" if items.empty? case mode when :inline - list_inline_mode(items, option) + list_inline_mode when :columns_across - list_columns_across_mode(items, option) + list_columns_across_mode when :columns_down - list_columns_down_mode(items, option) + list_columns_down_mode when :uneven_columns_across - list_uneven_columns_mode(items, option) + list_uneven_columns_mode when :uneven_columns_down - list_uneven_columns_down_mode(items, option) + list_uneven_columns_down_mode else items.map { |i| "#{i}\n" }.join end end + private + def render_list_items(items) items.to_ary.map do |item| item = String(item) template = ERB.new(item, nil, "%") - template_renderer = TemplateRenderer.new(template, self, self) + template_renderer = HighLine::TemplateRenderer.new(template, self, highline) template_renderer.render end end - def list_inline_mode(items, option) - option = " or " if option.nil? + def list_inline_mode + end_separator = option || " or " if items.size == 1 items.first else - items[0..-2].join(", ") + "#{option}#{items.last}" + items[0..-2].join(", ") + "#{end_separator}#{items.last}" end end - def list_columns_mode_prepare(items, option) + def list_columns_mode_prepare max_length = actual_length( items.max { |a, b| actual_length(a) <=> actual_length(b) } ) - if option.nil? - limit = @wrap_at || 80 - option = (limit + 2) / (max_length + 2) - end + limit = highline.wrap_at || 80 + width = option || (limit + 2) / (max_length + 2) - items = items.map do |item| + padded_items = items.map do |item| pad = max_length + (item.to_s.length - actual_length(item)) "%-#{pad}s" % item end - row_count = (items.size / option.to_f).ceil + row_count = (padded_items.size / width.to_f).ceil - [max_length, option, items, row_count] + [max_length, width, padded_items, row_count] end - def list_columns_across_mode(items, option) + def list_columns_across_mode max_length, option, items, row_count = - list_columns_mode_prepare(items, option) + list_columns_mode_prepare rows = Array.new(row_count) { Array.new } items.each_with_index do |item, index| @@ -103,9 +113,9 @@ class HighLine::List rows.map { |row| row.join(" ") + "\n" }.join end - def list_columns_down_mode(items, option) + def list_columns_down_mode max_length, option, items, row_count = - list_columns_mode_prepare(items, option) + list_columns_mode_prepare columns = Array.new(option) { Array.new } items.each_with_index do |item, index| @@ -120,9 +130,9 @@ class HighLine::List list end - def list_uneven_columns_mode(items, option) + def list_uneven_columns_mode if option.nil? - limit = @wrap_at || 80 + limit = highline.wrap_at || 80 items.size.downto(1) do |column_count| row_count = (items.size / column_count.to_f).ceil rows = Array.new(row_count) { Array.new } @@ -170,9 +180,9 @@ class HighLine::List end end - def list_uneven_columns_down_mode(items, option) + def list_uneven_columns_down_mode if option.nil? - limit = @wrap_at || 80 + limit = highline.wrap_at || 80 items.size.downto(1) do |column_count| row_count = (items.size / column_count.to_f).ceil columns = Array.new(column_count) { Array.new } @@ -226,4 +236,8 @@ class HighLine::List return list end end + + def actual_length(text) + HighLine::Wrapper.actual_length text + end end \ No newline at end of file -- cgit v1.2.1 From 0b71524a005c0115aa2addf30d4d432230235e7b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 19:10:37 -0300 Subject: Extract HighLine::List#max_length --- lib/highline/list.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 060fe9b..7563325 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -85,10 +85,6 @@ class HighLine::List end def list_columns_mode_prepare - max_length = actual_length( - items.max { |a, b| actual_length(a) <=> actual_length(b) } - ) - limit = highline.wrap_at || 80 width = option || (limit + 2) / (max_length + 2) @@ -98,11 +94,11 @@ class HighLine::List end row_count = (padded_items.size / width.to_f).ceil - [max_length, width, padded_items, row_count] + [width, padded_items, row_count] end def list_columns_across_mode - max_length, option, items, row_count = + option, items, row_count = list_columns_mode_prepare rows = Array.new(row_count) { Array.new } @@ -114,7 +110,7 @@ class HighLine::List end def list_columns_down_mode - max_length, option, items, row_count = + option, items, row_count = list_columns_mode_prepare columns = Array.new(option) { Array.new } @@ -240,4 +236,9 @@ class HighLine::List def actual_length(text) HighLine::Wrapper.actual_length text end + + def max_length + @max_length ||= + items.map { |item| actual_length(item) }.max + end end \ No newline at end of file -- cgit v1.2.1 From 4fcb8a886f92a8fda40617d079fe11d3a0efaaa8 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 19:28:08 -0300 Subject: Extract HighLine::List#limit --- lib/highline/list.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 7563325..551aed3 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -85,7 +85,6 @@ class HighLine::List end def list_columns_mode_prepare - limit = highline.wrap_at || 80 width = option || (limit + 2) / (max_length + 2) padded_items = items.map do |item| @@ -241,4 +240,8 @@ class HighLine::List @max_length ||= items.map { |item| actual_length(item) }.max end + + def limit + @limit ||= ( highline.wrap_at || 80 ) + end end \ No newline at end of file -- cgit v1.2.1 From 594832aab5bd6212bdc370d6e37361ca05ff383d Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 20:51:51 -0300 Subject: Use more explicit names for width, limit and max_length width => col_count limit => line_size_limit max_length => items_max_length --- lib/highline/list.rb | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 551aed3..00c1041 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -85,34 +85,34 @@ class HighLine::List end def list_columns_mode_prepare - width = option || (limit + 2) / (max_length + 2) + col_count = option || (line_size_limit + 2) / (items_max_length + 2) padded_items = items.map do |item| - pad = max_length + (item.to_s.length - actual_length(item)) + pad = items_max_length + (item.to_s.length - actual_length(item)) "%-#{pad}s" % item end - row_count = (padded_items.size / width.to_f).ceil + row_count = (padded_items.size / col_count.to_f).ceil - [width, padded_items, row_count] + [col_count, padded_items, row_count] end def list_columns_across_mode - option, items, row_count = + col_count, items, row_count = list_columns_mode_prepare rows = Array.new(row_count) { Array.new } items.each_with_index do |item, index| - rows[index / option] << item + rows[index / col_count] << item end rows.map { |row| row.join(" ") + "\n" }.join end def list_columns_down_mode - option, items, row_count = + col_count, items, row_count = list_columns_mode_prepare - columns = Array.new(option) { Array.new } + columns = Array.new(col_count) { Array.new } items.each_with_index do |item, index| columns[index / row_count] << item end @@ -127,7 +127,6 @@ class HighLine::List def list_uneven_columns_mode if option.nil? - limit = highline.wrap_at || 80 items.size.downto(1) do |column_count| row_count = (items.size / column_count.to_f).ceil rows = Array.new(row_count) { Array.new } @@ -144,7 +143,7 @@ class HighLine::List end if column_count == 1 or - widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 + widths.inject(0) { |sum, n| sum + n + 2 } <= line_size_limit + 2 return rows.map { |row| row.zip(widths).map { |field, i| "%-#{i + (field.to_s.length - actual_length(field))}s" % field @@ -177,7 +176,6 @@ class HighLine::List def list_uneven_columns_down_mode if option.nil? - limit = highline.wrap_at || 80 items.size.downto(1) do |column_count| row_count = (items.size / column_count.to_f).ceil columns = Array.new(column_count) { Array.new } @@ -194,7 +192,7 @@ class HighLine::List end if column_count == 1 or - widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2 + widths.inject(0) { |sum, n| sum + n + 2 } <= line_size_limit + 2 list = "" columns.first.size.times do |index| list << columns.zip(widths).map { |column, width| @@ -236,12 +234,12 @@ class HighLine::List HighLine::Wrapper.actual_length text end - def max_length - @max_length ||= + def items_max_length + @items_max_length ||= items.map { |item| actual_length(item) }.max end - def limit - @limit ||= ( highline.wrap_at || 80 ) + def line_size_limit + @line_size_limit ||= ( highline.wrap_at || 80 ) end end \ No newline at end of file -- cgit v1.2.1 From b7a28ea606a1d51dce1d9f086231614d70c8d9fd Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 20:58:01 -0300 Subject: Change for a simpler padding calculation --- lib/highline/list.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 00c1041..2f22bcd 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -88,10 +88,10 @@ class HighLine::List col_count = option || (line_size_limit + 2) / (items_max_length + 2) padded_items = items.map do |item| - pad = items_max_length + (item.to_s.length - actual_length(item)) - "%-#{pad}s" % item + pad_size = items_max_length - actual_length(item) + item + (" " * pad_size) end - row_count = (padded_items.size / col_count.to_f).ceil + row_count = (padded_items.count / col_count.to_f).ceil [col_count, padded_items, row_count] end -- cgit v1.2.1 From 1469a43b470195064fa13260c44931a2058f48a1 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 22:01:04 -0300 Subject: Add HighLine::List #row_join_string and #get_col_count --- lib/highline/list.rb | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 2f22bcd..6edc392 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -85,7 +85,7 @@ class HighLine::List end def list_columns_mode_prepare - col_count = option || (line_size_limit + 2) / (items_max_length + 2) + col_count = option || get_col_count padded_items = items.map do |item| pad_size = items_max_length - actual_length(item) @@ -105,7 +105,7 @@ class HighLine::List rows[index / col_count] << item end - rows.map { |row| row.join(" ") + "\n" }.join + rows.map { |row| row.join(row_join_string) + "\n" }.join end def list_columns_down_mode @@ -120,7 +120,7 @@ class HighLine::List list = "" columns.first.size.times do |index| list << columns.map { |column| column[index] }. - compact.join(" ") + "\n" + compact.join(row_join_string) + "\n" end list end @@ -147,7 +147,7 @@ class HighLine::List return rows.map { |row| row.zip(widths).map { |field, i| "%-#{i + (field.to_s.length - actual_length(field))}s" % field - }.join(" ") + "\n" + }.join(row_join_string) + "\n" }.join end end @@ -169,7 +169,7 @@ class HighLine::List return rows.map { |row| row.zip(widths).map { |field, i| "%-#{i + (field.to_s.length - actual_length(field))}s" % field - }.join(" ") + "\n" + }.join(row_join_string) + "\n" }.join end end @@ -199,7 +199,7 @@ class HighLine::List field = column[index] "%-#{width + (field.to_s.length - actual_length(field))}s" % field - }.compact.join(" ").strip + "\n" + }.compact.join(row_join_string).strip + "\n" end return list end @@ -224,7 +224,7 @@ class HighLine::List list << columns.zip(widths).map { |column, width| field = column[index] "%-#{width + (field.to_s.length - actual_length(field))}s" % field - }.compact.join(" ").strip + "\n" + }.compact.join(row_join_string).strip + "\n" end return list end @@ -242,4 +242,21 @@ class HighLine::List def line_size_limit @line_size_limit ||= ( highline.wrap_at || 80 ) end + + def row_join_string + @row_join_string ||= " " + end + + def row_join_string=(string) + @row_join_string = string + end + + def row_join_str_size + row_join_string.size + end + + def get_col_count + (line_size_limit + row_join_str_size) / + (items_max_length + row_join_str_size) + end end \ No newline at end of file -- cgit v1.2.1 From 26389ed539b8963fdf988a9b11e3ed74482332f5 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 22:06:42 -0300 Subject: Array#each_slice makes rows slicing simpler --- lib/highline/list.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 6edc392..86bb22e 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -100,10 +100,7 @@ class HighLine::List col_count, items, row_count = list_columns_mode_prepare - rows = Array.new(row_count) { Array.new } - items.each_with_index do |item, index| - rows[index / col_count] << item - end + rows = items.each_slice(col_count) rows.map { |row| row.join(row_join_string) + "\n" }.join end -- cgit v1.2.1 From 63d1546cd98694d6966109ca8f3441d718e214d9 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 22:09:19 -0300 Subject: Use padded_items to keep different from HighLine::List#items --- lib/highline/list.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 86bb22e..a14b995 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -97,20 +97,20 @@ class HighLine::List end def list_columns_across_mode - col_count, items, row_count = + col_count, padded_items, row_count = list_columns_mode_prepare - rows = items.each_slice(col_count) + rows = padded_items.each_slice(col_count) rows.map { |row| row.join(row_join_string) + "\n" }.join end def list_columns_down_mode - col_count, items, row_count = + col_count, padded_items, row_count = list_columns_mode_prepare columns = Array.new(col_count) { Array.new } - items.each_with_index do |item, index| + padded_items.each_with_index do |item, index| columns[index / row_count] << item end -- cgit v1.2.1 From 495bb3da6f66322463d62503a587656da892fc0d Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 22:14:33 -0300 Subject: Extract HighLine::Line #col_count #padded_items and #row_count --- lib/highline/list.rb | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index a14b995..cbf5eeb 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -84,31 +84,13 @@ class HighLine::List end end - def list_columns_mode_prepare - col_count = option || get_col_count - - padded_items = items.map do |item| - pad_size = items_max_length - actual_length(item) - item + (" " * pad_size) - end - row_count = (padded_items.count / col_count.to_f).ceil - - [col_count, padded_items, row_count] - end - def list_columns_across_mode - col_count, padded_items, row_count = - list_columns_mode_prepare - rows = padded_items.each_slice(col_count) rows.map { |row| row.join(row_join_string) + "\n" }.join end def list_columns_down_mode - col_count, padded_items, row_count = - list_columns_mode_prepare - columns = Array.new(col_count) { Array.new } padded_items.each_with_index do |item, index| columns[index / row_count] << item @@ -256,4 +238,19 @@ class HighLine::List (line_size_limit + row_join_str_size) / (items_max_length + row_join_str_size) end + + def col_count + option || get_col_count + end + + def padded_items + items.map do |item| + pad_size = items_max_length - actual_length(item) + item + (" " * pad_size) + end + end + + def row_count + (padded_items.count / col_count.to_f).ceil + end end \ No newline at end of file -- cgit v1.2.1 From acbbb54f880f3e165ee45f42cd3de9ad9e619f04 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 22:53:33 -0300 Subject: Use Array #each_slice and #zip to transpose lines into cols --- lib/highline/list.rb | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index cbf5eeb..82f3cff 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -91,17 +91,13 @@ class HighLine::List end def list_columns_down_mode - columns = Array.new(col_count) { Array.new } - padded_items.each_with_index do |item, index| - columns[index / row_count] << item - end + cols = padded_items.each_slice(row_count).to_a - list = "" - columns.first.size.times do |index| - list << columns.map { |column| column[index] }. - compact.join(row_join_string) + "\n" - end - list + first_col = cols.shift + + rows = first_col.zip(*cols) + + rows.map { |row| row.compact.join(row_join_string) + "\n" }.join end def list_uneven_columns_mode -- cgit v1.2.1 From a1205e04f3eb6fa02bdacdaf4b33d9570b0e27df Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 23:31:19 -0300 Subject: No need to use padded_items over here. Fixing it --- lib/highline/list.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 82f3cff..967421b 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -247,6 +247,6 @@ class HighLine::List end def row_count - (padded_items.count / col_count.to_f).ceil + (items.count / col_count.to_f).ceil end end \ No newline at end of file -- cgit v1.2.1 From 54483319a51f8c2469b47db182db971132a5576e Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 23:31:48 -0300 Subject: Extract HighLine::Line#max_length --- lib/highline/list.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 967421b..ec573ba 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -210,8 +210,11 @@ class HighLine::List end def items_max_length - @items_max_length ||= - items.map { |item| actual_length(item) }.max + @items_max_length ||= max_length(items) + end + + def max_length(items) + items.map { |item| actual_length(item) }.max end def line_size_limit -- cgit v1.2.1 From db9875c106813c408d676e19c7255f2af66a8039 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 1 Apr 2015 23:46:51 -0300 Subject: Simplifies using Array#each_slice --- lib/highline/list.rb | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index ec573ba..26c5ab5 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -104,10 +104,7 @@ class HighLine::List if option.nil? items.size.downto(1) do |column_count| row_count = (items.size / column_count.to_f).ceil - rows = Array.new(row_count) { Array.new } - items.each_with_index do |item, index| - rows[index / column_count] << item - end + rows = items.each_slice(column_count) widths = Array.new(column_count, 0) rows.each do |row| @@ -128,10 +125,7 @@ class HighLine::List end else row_count = (items.size / option.to_f).ceil - rows = Array.new(row_count) { Array.new } - items.each_with_index do |item, index| - rows[index / option] << item - end + rows = items.each_slice(option) widths = Array.new(option, 0) rows.each do |row| @@ -153,10 +147,7 @@ class HighLine::List if option.nil? items.size.downto(1) do |column_count| row_count = (items.size / column_count.to_f).ceil - columns = Array.new(column_count) { Array.new } - items.each_with_index do |item, index| - columns[index / row_count] << item - end + columns = items.each_slice(row_count) widths = Array.new(column_count, 0) columns.each_with_index do |column, i| @@ -181,10 +172,7 @@ class HighLine::List end else row_count = (items.size / option.to_f).ceil - columns = Array.new(option) { Array.new } - items.each_with_index do |item, index| - columns[index / row_count] << item - end + columns = items.each_slice(row_count) widths = Array.new(option, 0) columns.each_with_index do |column, i| -- cgit v1.2.1 From 5092288da88bc12ee385450c255a16452a80fd99 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 2 Apr 2015 14:25:41 -0300 Subject: Extract HighLine::List #get_row_widths and #get_col_widths --- lib/highline/list.rb | 56 ++++++++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 26c5ab5..bd827f2 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -103,16 +103,9 @@ class HighLine::List def list_uneven_columns_mode if option.nil? items.size.downto(1) do |column_count| - row_count = (items.size / column_count.to_f).ceil rows = items.each_slice(column_count) - widths = Array.new(column_count, 0) - rows.each do |row| - row.each_with_index do |field, column| - size = actual_length(field) - widths[column] = size if size > widths[column] - end - end + widths = get_col_widths(rows, column_count) if column_count == 1 or widths.inject(0) { |sum, n| sum + n + 2 } <= line_size_limit + 2 @@ -124,16 +117,9 @@ class HighLine::List end end else - row_count = (items.size / option.to_f).ceil rows = items.each_slice(option) - widths = Array.new(option, 0) - rows.each do |row| - row.each_with_index do |field, column| - size = actual_length(field) - widths[column] = size if size > widths[column] - end - end + widths = get_col_widths(rows, option) return rows.map { |row| row.zip(widths).map { |field, i| @@ -143,19 +129,35 @@ class HighLine::List end end + def get_col_widths(rows, col_count) + widths = Array.new(col_count, 0) + rows.each do |row| + row.each_with_index do |field, column| + size = actual_length(field) + widths[column] = size if size > widths[column] + end + end + widths + end + + def get_row_widths(cols, row_count) + widths = Array.new(row_count, 0) + cols.each_with_index do |column, row| + column.each do |field| + size = actual_length(field) + widths[row] = size if size > widths[row] + end + end + widths + end + def list_uneven_columns_down_mode if option.nil? items.size.downto(1) do |column_count| row_count = (items.size / column_count.to_f).ceil columns = items.each_slice(row_count) - widths = Array.new(column_count, 0) - columns.each_with_index do |column, i| - column.each do |field| - size = actual_length(field) - widths[i] = size if size > widths[i] - end - end + widths = get_row_widths(columns, column_count) if column_count == 1 or widths.inject(0) { |sum, n| sum + n + 2 } <= line_size_limit + 2 @@ -174,13 +176,7 @@ class HighLine::List row_count = (items.size / option.to_f).ceil columns = items.each_slice(row_count) - widths = Array.new(option, 0) - columns.each_with_index do |column, i| - column.each do |field| - size = actual_length(field) - widths[i] = size if size > widths[i] - end - end + widths = get_row_widths(columns, option) list = "" columns.first.size.times do |index| -- cgit v1.2.1 From a016f7efe00a46876d4af8ccc9dbe31b55919d6b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 2 Apr 2015 14:47:34 -0300 Subject: Extract HighLine::List #pad_uneven_rows --- lib/highline/list.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index bd827f2..b6d1594 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -109,11 +109,7 @@ class HighLine::List if column_count == 1 or widths.inject(0) { |sum, n| sum + n + 2 } <= line_size_limit + 2 - return rows.map { |row| - row.zip(widths).map { |field, i| - "%-#{i + (field.to_s.length - actual_length(field))}s" % field - }.join(row_join_string) + "\n" - }.join + return pad_uneven_rows(rows, widths) end end else @@ -121,14 +117,18 @@ class HighLine::List widths = get_col_widths(rows, option) - return rows.map { |row| - row.zip(widths).map { |field, i| - "%-#{i + (field.to_s.length - actual_length(field))}s" % field - }.join(row_join_string) + "\n" - }.join + return pad_uneven_rows(rows, widths) end end + def pad_uneven_rows(rows, widths) + rows.map do |row| + row.zip(widths).map do |field, i| + "%-#{i + (field.to_s.length - actual_length(field))}s" % field + end.join(row_join_string) + "\n" + end.join + end + def get_col_widths(rows, col_count) widths = Array.new(col_count, 0) rows.each do |row| -- cgit v1.2.1 From fa276ad3aeb09c426afd09b1979f719606f1b681 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 2 Apr 2015 14:51:59 -0300 Subject: Extract HighLine::List#pad_uneven_cols --- lib/highline/list.rb | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index b6d1594..79cbe7a 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -161,15 +161,8 @@ class HighLine::List if column_count == 1 or widths.inject(0) { |sum, n| sum + n + 2 } <= line_size_limit + 2 - list = "" - columns.first.size.times do |index| - list << columns.zip(widths).map { |column, width| - field = column[index] - "%-#{width + (field.to_s.length - actual_length(field))}s" % - field - }.compact.join(row_join_string).strip + "\n" - end - return list + + return pad_uneven_cols(columns, widths) end end else @@ -178,15 +171,19 @@ class HighLine::List widths = get_row_widths(columns, option) - list = "" - columns.first.size.times do |index| - list << columns.zip(widths).map { |column, width| - field = column[index] - "%-#{width + (field.to_s.length - actual_length(field))}s" % field - }.compact.join(row_join_string).strip + "\n" - end - return list + return pad_uneven_cols(columns, widths) + end + end + + def pad_uneven_cols(columns, widths) + list = "" + columns.first.size.times do |index| + list << columns.zip(widths).map { |column, width| + field = column[index] + "%-#{width + (field.to_s.length - actual_length(field))}s" % field + }.compact.join(row_join_string).strip + "\n" end + list end def actual_length(text) -- cgit v1.2.1 From e4db145ebeb0cda34f06ffec26c31faa4f63d9b2 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 2 Apr 2015 23:27:37 -0300 Subject: Extract HighLine::List#inside_line_size_limit? --- lib/highline/list.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 79cbe7a..965295b 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -107,8 +107,7 @@ class HighLine::List widths = get_col_widths(rows, column_count) - if column_count == 1 or - widths.inject(0) { |sum, n| sum + n + 2 } <= line_size_limit + 2 + if column_count == 1 or inside_line_size_limit?(widths) return pad_uneven_rows(rows, widths) end end @@ -159,9 +158,7 @@ class HighLine::List widths = get_row_widths(columns, column_count) - if column_count == 1 or - widths.inject(0) { |sum, n| sum + n + 2 } <= line_size_limit + 2 - + if column_count == 1 or inside_line_size_limit?(widths) return pad_uneven_cols(columns, widths) end end @@ -175,6 +172,11 @@ class HighLine::List end end + def inside_line_size_limit?(widths) + line_size = widths.inject(0) { |sum, n| sum + n + row_join_str_size } + line_size <= line_size_limit + row_join_str_size + end + def pad_uneven_cols(columns, widths) list = "" columns.first.size.times do |index| -- cgit v1.2.1 From c7ae9440cc472785387419055ceef303f063a6d4 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 3 Apr 2015 00:34:33 -0300 Subject: Extract HighLine::List#pad_field --- lib/highline/list.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 965295b..0f6e91f 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -123,11 +123,15 @@ class HighLine::List def pad_uneven_rows(rows, widths) rows.map do |row| row.zip(widths).map do |field, i| - "%-#{i + (field.to_s.length - actual_length(field))}s" % field + pad_field(field, i) end.join(row_join_string) + "\n" end.join end + def pad_field(field, pad_size) + "%-#{pad_size + (field.to_s.length - actual_length(field))}s" % field + end + def get_col_widths(rows, col_count) widths = Array.new(col_count, 0) rows.each do |row| @@ -182,7 +186,7 @@ class HighLine::List columns.first.size.times do |index| list << columns.zip(widths).map { |column, width| field = column[index] - "%-#{width + (field.to_s.length - actual_length(field))}s" % field + pad_field(field, width) }.compact.join(row_join_string).strip + "\n" end list -- cgit v1.2.1 From 3f87c81a4ae6401ff8e7ff89bcd2f0a7254f4cad Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 3 Apr 2015 01:05:06 -0300 Subject: Reduce duplication on HighLine::List #list_uneven_columns_mode and #list_uneven_columns_down_mode --- lib/highline/list.rb | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 0f6e91f..d9eac57 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -101,22 +101,17 @@ class HighLine::List end def list_uneven_columns_mode - if option.nil? - items.size.downto(1) do |column_count| - rows = items.each_slice(column_count) + col_max = option || items.size + col_max.downto(1) do |column_count| + rows = items.each_slice(column_count) - widths = get_col_widths(rows, column_count) + widths = get_col_widths(rows, column_count) - if column_count == 1 or inside_line_size_limit?(widths) - return pad_uneven_rows(rows, widths) - end + if column_count == 1 or # last guess + inside_line_size_limit?(widths) or # good guess + option # defined by user + return pad_uneven_rows(rows, widths) end - else - rows = items.each_slice(option) - - widths = get_col_widths(rows, option) - - return pad_uneven_rows(rows, widths) end end @@ -155,24 +150,19 @@ class HighLine::List end def list_uneven_columns_down_mode - if option.nil? - items.size.downto(1) do |column_count| - row_count = (items.size / column_count.to_f).ceil - columns = items.each_slice(row_count) - - widths = get_row_widths(columns, column_count) + col_max = option || items.size - if column_count == 1 or inside_line_size_limit?(widths) - return pad_uneven_cols(columns, widths) - end - end - else - row_count = (items.size / option.to_f).ceil + col_max.downto(1) do |column_count| + row_count = (items.size / column_count.to_f).ceil columns = items.each_slice(row_count) - widths = get_row_widths(columns, option) + widths = get_row_widths(columns, column_count) - return pad_uneven_cols(columns, widths) + if column_count == 1 or + inside_line_size_limit?(widths) or + option + return pad_uneven_cols(columns, widths) + end end end -- cgit v1.2.1 From f89dd27899fd1a5ea4b7ea0be603f1f32fde346a Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 3 Apr 2015 01:20:10 -0300 Subject: Extract HighLine::List#transpose --- lib/highline/list.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index d9eac57..cc57197 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -93,9 +93,7 @@ class HighLine::List def list_columns_down_mode cols = padded_items.each_slice(row_count).to_a - first_col = cols.shift - - rows = first_col.zip(*cols) + rows = transpose(cols) rows.map { |row| row.compact.join(row_join_string) + "\n" }.join end @@ -149,6 +147,11 @@ class HighLine::List widths end + def transpose(lines) + first_line = Array(lines).shift + first_line.zip(*lines) + end + def list_uneven_columns_down_mode col_max = option || items.size -- cgit v1.2.1 From eae164bc948d745b3dc8f26459500bf7f9161fb0 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 3 Apr 2015 01:20:47 -0300 Subject: Reduce duplication by extracting HighLine::List#get_segment_widths --- lib/highline/list.rb | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index cc57197..d3a1fef 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -126,22 +126,20 @@ class HighLine::List end def get_col_widths(rows, col_count) - widths = Array.new(col_count, 0) - rows.each do |row| - row.each_with_index do |field, column| - size = actual_length(field) - widths[column] = size if size > widths[column] - end - end - widths + cols = transpose(rows) + get_segment_widths(cols, col_count) end def get_row_widths(cols, row_count) - widths = Array.new(row_count, 0) - cols.each_with_index do |column, row| - column.each do |field| - size = actual_length(field) - widths[row] = size if size > widths[row] + get_segment_widths(cols, row_count) + end + + def get_segment_widths(lines, segment_count) + widths = Array.new(segment_count, 0) + lines.each_with_index do |line, line_ix| + line.each do |col| + size = actual_length(col) + widths[line_ix] = size if size > widths[line_ix] end end widths -- cgit v1.2.1 From 11250f78168f51b5c89cef63a3c29abb5f53060c Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 5 Apr 2015 23:03:26 -0300 Subject: Extract HighLine::List #right_pad_row #right_pad_field #row_to_s #list_to_s --- lib/highline/list.rb | 52 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index d3a1fef..4533552 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -85,17 +85,17 @@ class HighLine::List end def list_columns_across_mode - rows = padded_items.each_slice(col_count) + list = right_padded_items.each_slice(col_count) - rows.map { |row| row.join(row_join_string) + "\n" }.join + list_to_s(list) end def list_columns_down_mode - cols = padded_items.each_slice(row_count).to_a + list = right_padded_items.each_slice(row_count).to_a - rows = transpose(cols) + list = transpose(list) - rows.map { |row| row.compact.join(row_join_string) + "\n" }.join + list_to_s(list) end def list_uneven_columns_mode @@ -113,16 +113,31 @@ class HighLine::List end end - def pad_uneven_rows(rows, widths) - rows.map do |row| - row.zip(widths).map do |field, i| - pad_field(field, i) - end.join(row_join_string) + "\n" - end.join + def pad_uneven_rows(list, widths) + right_padded_list = list.map do |row| + right_pad_row(row, widths) + end + list_to_s(right_padded_list) + end + + def list_to_s(list) + list.map { |row| row_to_s(row) }.join + end + + def row_to_s(row) + row.compact.join(row_join_string) + "\n" end - def pad_field(field, pad_size) - "%-#{pad_size + (field.to_s.length - actual_length(field))}s" % field + def right_pad_row(row, widths) + row.zip(widths).map do |field, width| + right_pad_field(field, width) + end + end + + def right_pad_field(field, width) + field = String(field) # nil protection + pad_size = width - actual_length(field) + field + (pad_char * pad_size) end def get_col_widths(rows, col_count) @@ -177,7 +192,7 @@ class HighLine::List columns.first.size.times do |index| list << columns.zip(widths).map { |column, width| field = column[index] - pad_field(field, width) + right_pad_field(field, width) }.compact.join(row_join_string).strip + "\n" end list @@ -220,13 +235,16 @@ class HighLine::List option || get_col_count end - def padded_items + def right_padded_items items.map do |item| - pad_size = items_max_length - actual_length(item) - item + (" " * pad_size) + right_pad_field(item, items_max_length) end end + def pad_char + " " + end + def row_count (items.count / col_count.to_f).ceil end -- cgit v1.2.1 From d2a52370bd3db1aee96f3f5702fd01e06ef6e35f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 5 Apr 2015 23:51:44 -0300 Subject: Simplify HighLine::List #get_segment_widths --- lib/highline/list.rb | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index 4533552..16b0a4f 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -103,7 +103,7 @@ class HighLine::List col_max.downto(1) do |column_count| rows = items.each_slice(column_count) - widths = get_col_widths(rows, column_count) + widths = get_col_widths(rows) if column_count == 1 or # last guess inside_line_size_limit?(widths) or # good guess @@ -140,28 +140,30 @@ class HighLine::List field + (pad_char * pad_size) end - def get_col_widths(rows, col_count) - cols = transpose(rows) - get_segment_widths(cols, col_count) + def get_col_widths(lines) + lines = transpose(lines) + get_segment_widths(lines) end - def get_row_widths(cols, row_count) - get_segment_widths(cols, row_count) + def get_row_widths(lines) + get_segment_widths(lines) end - def get_segment_widths(lines, segment_count) - widths = Array.new(segment_count, 0) - lines.each_with_index do |line, line_ix| - line.each do |col| - size = actual_length(col) - widths[line_ix] = size if size > widths[line_ix] - end + def get_segment_widths(lines) + lines.map do |col| + actual_lengths_for(col).max + end + end + + def actual_lengths_for(line) + line.map do |item| + actual_length(item) end - widths end def transpose(lines) - first_line = Array(lines).shift + lines = Array(lines) + first_line = lines.shift first_line.zip(*lines) end @@ -172,7 +174,7 @@ class HighLine::List row_count = (items.size / column_count.to_f).ceil columns = items.each_slice(row_count) - widths = get_row_widths(columns, column_count) + widths = get_row_widths(columns) if column_count == 1 or inside_line_size_limit?(widths) or -- cgit v1.2.1 From b8da936b8f42f5eea896e6b7ea0b2e2de99c4d2e Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 6 Apr 2015 05:43:59 -0300 Subject: Rename list.rb -> list_renderer.rb --- lib/highline/list.rb | 253 ------------------------------------------ lib/highline/list_renderer.rb | 253 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+), 253 deletions(-) delete mode 100644 lib/highline/list.rb create mode 100644 lib/highline/list_renderer.rb diff --git a/lib/highline/list.rb b/lib/highline/list.rb deleted file mode 100644 index 16b0a4f..0000000 --- a/lib/highline/list.rb +++ /dev/null @@ -1,253 +0,0 @@ -require 'highline/template_renderer' -require 'highline/wrapper' - -class HighLine::List - attr_reader :items, :mode, :option, :highline - - def initialize(items, mode = :rows, option = nil, highline) - @highline = highline - @mode = mode - @option = option - @items = render_list_items(items) - end - - # - # This method is a utility for quickly and easily laying out lists. It can - # be accessed within ERb replacements of any text that will be sent to the - # user. - # - # The only required parameter is _items_, which should be the Array of items - # to list. A specified _mode_ controls how that list is formed and _option_ - # has different effects, depending on the _mode_. Recognized modes are: - # - # :columns_across:: _items_ will be placed in columns, - # flowing from left to right. If given, - # _option_ is the number of columns to be - # used. When absent, columns will be - # determined based on _wrap_at_ or a - # default of 80 characters. - # :columns_down:: Identical to :columns_across, - # save flow goes down. - # :uneven_columns_across:: Like :columns_across but each - # column is sized independently. - # :uneven_columns_down:: Like :columns_down but each - # column is sized independently. - # :inline:: All _items_ are placed on a single line. - # The last two _items_ are separated by - # _option_ or a default of " or ". All - # other _items_ are separated by ", ". - # :rows:: The default mode. Each of the _items_ is - # placed on its own line. The _option_ - # parameter is ignored in this mode. - # - # Each member of the _items_ Array is passed through ERb and thus can contain - # their own expansions. Color escape expansions do not contribute to the - # final field width. - # - def render - return "" if items.empty? - - case mode - when :inline - list_inline_mode - when :columns_across - list_columns_across_mode - when :columns_down - list_columns_down_mode - when :uneven_columns_across - list_uneven_columns_mode - when :uneven_columns_down - list_uneven_columns_down_mode - else - items.map { |i| "#{i}\n" }.join - end - end - - private - - def render_list_items(items) - items.to_ary.map do |item| - item = String(item) - template = ERB.new(item, nil, "%") - template_renderer = HighLine::TemplateRenderer.new(template, self, highline) - template_renderer.render - end - end - - def list_inline_mode - end_separator = option || " or " - - if items.size == 1 - items.first - else - items[0..-2].join(", ") + "#{end_separator}#{items.last}" - end - end - - def list_columns_across_mode - list = right_padded_items.each_slice(col_count) - - list_to_s(list) - end - - def list_columns_down_mode - list = right_padded_items.each_slice(row_count).to_a - - list = transpose(list) - - list_to_s(list) - end - - def list_uneven_columns_mode - col_max = option || items.size - col_max.downto(1) do |column_count| - rows = items.each_slice(column_count) - - widths = get_col_widths(rows) - - if column_count == 1 or # last guess - inside_line_size_limit?(widths) or # good guess - option # defined by user - return pad_uneven_rows(rows, widths) - end - end - end - - def pad_uneven_rows(list, widths) - right_padded_list = list.map do |row| - right_pad_row(row, widths) - end - list_to_s(right_padded_list) - end - - def list_to_s(list) - list.map { |row| row_to_s(row) }.join - end - - def row_to_s(row) - row.compact.join(row_join_string) + "\n" - end - - def right_pad_row(row, widths) - row.zip(widths).map do |field, width| - right_pad_field(field, width) - end - end - - def right_pad_field(field, width) - field = String(field) # nil protection - pad_size = width - actual_length(field) - field + (pad_char * pad_size) - end - - def get_col_widths(lines) - lines = transpose(lines) - get_segment_widths(lines) - end - - def get_row_widths(lines) - get_segment_widths(lines) - end - - def get_segment_widths(lines) - lines.map do |col| - actual_lengths_for(col).max - end - end - - def actual_lengths_for(line) - line.map do |item| - actual_length(item) - end - end - - def transpose(lines) - lines = Array(lines) - first_line = lines.shift - first_line.zip(*lines) - end - - def list_uneven_columns_down_mode - col_max = option || items.size - - col_max.downto(1) do |column_count| - row_count = (items.size / column_count.to_f).ceil - columns = items.each_slice(row_count) - - widths = get_row_widths(columns) - - if column_count == 1 or - inside_line_size_limit?(widths) or - option - return pad_uneven_cols(columns, widths) - end - end - end - - def inside_line_size_limit?(widths) - line_size = widths.inject(0) { |sum, n| sum + n + row_join_str_size } - line_size <= line_size_limit + row_join_str_size - end - - def pad_uneven_cols(columns, widths) - list = "" - columns.first.size.times do |index| - list << columns.zip(widths).map { |column, width| - field = column[index] - right_pad_field(field, width) - }.compact.join(row_join_string).strip + "\n" - end - list - end - - def actual_length(text) - HighLine::Wrapper.actual_length text - end - - def items_max_length - @items_max_length ||= max_length(items) - end - - def max_length(items) - items.map { |item| actual_length(item) }.max - end - - def line_size_limit - @line_size_limit ||= ( highline.wrap_at || 80 ) - end - - def row_join_string - @row_join_string ||= " " - end - - def row_join_string=(string) - @row_join_string = string - end - - def row_join_str_size - row_join_string.size - end - - def get_col_count - (line_size_limit + row_join_str_size) / - (items_max_length + row_join_str_size) - end - - def col_count - option || get_col_count - end - - def right_padded_items - items.map do |item| - right_pad_field(item, items_max_length) - end - end - - def pad_char - " " - end - - def row_count - (items.count / col_count.to_f).ceil - end -end \ No newline at end of file diff --git a/lib/highline/list_renderer.rb b/lib/highline/list_renderer.rb new file mode 100644 index 0000000..16b0a4f --- /dev/null +++ b/lib/highline/list_renderer.rb @@ -0,0 +1,253 @@ +require 'highline/template_renderer' +require 'highline/wrapper' + +class HighLine::List + attr_reader :items, :mode, :option, :highline + + def initialize(items, mode = :rows, option = nil, highline) + @highline = highline + @mode = mode + @option = option + @items = render_list_items(items) + end + + # + # This method is a utility for quickly and easily laying out lists. It can + # be accessed within ERb replacements of any text that will be sent to the + # user. + # + # The only required parameter is _items_, which should be the Array of items + # to list. A specified _mode_ controls how that list is formed and _option_ + # has different effects, depending on the _mode_. Recognized modes are: + # + # :columns_across:: _items_ will be placed in columns, + # flowing from left to right. If given, + # _option_ is the number of columns to be + # used. When absent, columns will be + # determined based on _wrap_at_ or a + # default of 80 characters. + # :columns_down:: Identical to :columns_across, + # save flow goes down. + # :uneven_columns_across:: Like :columns_across but each + # column is sized independently. + # :uneven_columns_down:: Like :columns_down but each + # column is sized independently. + # :inline:: All _items_ are placed on a single line. + # The last two _items_ are separated by + # _option_ or a default of " or ". All + # other _items_ are separated by ", ". + # :rows:: The default mode. Each of the _items_ is + # placed on its own line. The _option_ + # parameter is ignored in this mode. + # + # Each member of the _items_ Array is passed through ERb and thus can contain + # their own expansions. Color escape expansions do not contribute to the + # final field width. + # + def render + return "" if items.empty? + + case mode + when :inline + list_inline_mode + when :columns_across + list_columns_across_mode + when :columns_down + list_columns_down_mode + when :uneven_columns_across + list_uneven_columns_mode + when :uneven_columns_down + list_uneven_columns_down_mode + else + items.map { |i| "#{i}\n" }.join + end + end + + private + + def render_list_items(items) + items.to_ary.map do |item| + item = String(item) + template = ERB.new(item, nil, "%") + template_renderer = HighLine::TemplateRenderer.new(template, self, highline) + template_renderer.render + end + end + + def list_inline_mode + end_separator = option || " or " + + if items.size == 1 + items.first + else + items[0..-2].join(", ") + "#{end_separator}#{items.last}" + end + end + + def list_columns_across_mode + list = right_padded_items.each_slice(col_count) + + list_to_s(list) + end + + def list_columns_down_mode + list = right_padded_items.each_slice(row_count).to_a + + list = transpose(list) + + list_to_s(list) + end + + def list_uneven_columns_mode + col_max = option || items.size + col_max.downto(1) do |column_count| + rows = items.each_slice(column_count) + + widths = get_col_widths(rows) + + if column_count == 1 or # last guess + inside_line_size_limit?(widths) or # good guess + option # defined by user + return pad_uneven_rows(rows, widths) + end + end + end + + def pad_uneven_rows(list, widths) + right_padded_list = list.map do |row| + right_pad_row(row, widths) + end + list_to_s(right_padded_list) + end + + def list_to_s(list) + list.map { |row| row_to_s(row) }.join + end + + def row_to_s(row) + row.compact.join(row_join_string) + "\n" + end + + def right_pad_row(row, widths) + row.zip(widths).map do |field, width| + right_pad_field(field, width) + end + end + + def right_pad_field(field, width) + field = String(field) # nil protection + pad_size = width - actual_length(field) + field + (pad_char * pad_size) + end + + def get_col_widths(lines) + lines = transpose(lines) + get_segment_widths(lines) + end + + def get_row_widths(lines) + get_segment_widths(lines) + end + + def get_segment_widths(lines) + lines.map do |col| + actual_lengths_for(col).max + end + end + + def actual_lengths_for(line) + line.map do |item| + actual_length(item) + end + end + + def transpose(lines) + lines = Array(lines) + first_line = lines.shift + first_line.zip(*lines) + end + + def list_uneven_columns_down_mode + col_max = option || items.size + + col_max.downto(1) do |column_count| + row_count = (items.size / column_count.to_f).ceil + columns = items.each_slice(row_count) + + widths = get_row_widths(columns) + + if column_count == 1 or + inside_line_size_limit?(widths) or + option + return pad_uneven_cols(columns, widths) + end + end + end + + def inside_line_size_limit?(widths) + line_size = widths.inject(0) { |sum, n| sum + n + row_join_str_size } + line_size <= line_size_limit + row_join_str_size + end + + def pad_uneven_cols(columns, widths) + list = "" + columns.first.size.times do |index| + list << columns.zip(widths).map { |column, width| + field = column[index] + right_pad_field(field, width) + }.compact.join(row_join_string).strip + "\n" + end + list + end + + def actual_length(text) + HighLine::Wrapper.actual_length text + end + + def items_max_length + @items_max_length ||= max_length(items) + end + + def max_length(items) + items.map { |item| actual_length(item) }.max + end + + def line_size_limit + @line_size_limit ||= ( highline.wrap_at || 80 ) + end + + def row_join_string + @row_join_string ||= " " + end + + def row_join_string=(string) + @row_join_string = string + end + + def row_join_str_size + row_join_string.size + end + + def get_col_count + (line_size_limit + row_join_str_size) / + (items_max_length + row_join_str_size) + end + + def col_count + option || get_col_count + end + + def right_padded_items + items.map do |item| + right_pad_field(item, items_max_length) + end + end + + def pad_char + " " + end + + def row_count + (items.count / col_count.to_f).ceil + end +end \ No newline at end of file -- cgit v1.2.1 From 61a264d290f5394bba459e754405f17d1ef4dee1 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 6 Apr 2015 05:46:28 -0300 Subject: Rename HighLine::List -> HighLine::ListRenderer --- lib/highline.rb | 4 ++-- lib/highline/list_renderer.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index c40fe7f..abe3533 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -21,7 +21,7 @@ require "highline/color_scheme" require "highline/style" require "highline/version" require "highline/statement" -require "highline/list" +require "highline/list_renderer" # # A HighLine object is a "high-level line oriented" shell over an input and an @@ -365,7 +365,7 @@ class HighLine end def list(items, mode = :rows, option = nil) - List.new(items, mode, option, self).render + ListRenderer.new(items, mode, option, self).render end # diff --git a/lib/highline/list_renderer.rb b/lib/highline/list_renderer.rb index 16b0a4f..2ca194d 100644 --- a/lib/highline/list_renderer.rb +++ b/lib/highline/list_renderer.rb @@ -1,7 +1,7 @@ require 'highline/template_renderer' require 'highline/wrapper' -class HighLine::List +class HighLine::ListRenderer attr_reader :items, :mode, :option, :highline def initialize(items, mode = :rows, option = nil, highline) -- cgit v1.2.1 From bd77998c9c342eb3d690f5de9c7dc30939b80fef Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Apr 2015 08:04:21 -0300 Subject: Extract HighLine::ListRenderer#list_default_mode --- lib/highline/list_renderer.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/highline/list_renderer.rb b/lib/highline/list_renderer.rb index 2ca194d..3c16436 100644 --- a/lib/highline/list_renderer.rb +++ b/lib/highline/list_renderer.rb @@ -59,7 +59,7 @@ class HighLine::ListRenderer when :uneven_columns_down list_uneven_columns_down_mode else - items.map { |i| "#{i}\n" }.join + list_default_mode end end @@ -74,6 +74,10 @@ class HighLine::ListRenderer end end + def list_default_mode + items.map { |i| "#{i}\n" }.join + end + def list_inline_mode end_separator = option || " or " -- cgit v1.2.1 From 596c4c7a9ddc1b65e580758f696c868b745f25be Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Apr 2015 10:13:19 -0300 Subject: Extract some common list logic into HighLine::List This is a first try. Let's see how we can reduce complexity of HighLine::ListRenderer by encapsulating some of the logic into this generic list (HighLine::List). --- lib/highline/list.rb | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/test_list.rb | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 lib/highline/list.rb create mode 100644 test/test_list.rb diff --git a/lib/highline/list.rb b/lib/highline/list.rb new file mode 100644 index 0000000..cc57618 --- /dev/null +++ b/lib/highline/list.rb @@ -0,0 +1,63 @@ +class HighLine + class List + attr_reader :items, :cols, :list + attr_reader :transpose_mode, :col_down_mode + + def initialize(items, options = {}) + @items = items + @transpose_mode = options.fetch(:transpose) { false } + @col_down_mode = options.fetch(:col_down) { false } + @cols = options.fetch(:cols) { 1 } + build + end + + def transpose + first_row = @list[0] + other_rows = @list[1..-1] + @list = first_row.zip(*other_rows) + self + end + + def col_down + slice_by_rows + transpose + self + end + + def slice_by_rows + @list = items_sliced_by_rows + self + end + + def slice_by_cols + @list = items_sliced_by_cols + self + end + + def cols=(cols) + @cols = cols + build + end + + private + + def build + slice_by_cols + transpose if transpose_mode + col_down if col_down_mode + self + end + + def items_sliced_by_cols + items.each_slice(cols).to_a + end + + def items_sliced_by_rows + items.each_slice(row_count).to_a + end + + def row_count + (items.count / cols.to_f).ceil + end + end +end \ No newline at end of file diff --git a/test/test_list.rb b/test/test_list.rb new file mode 100644 index 0000000..385e73d --- /dev/null +++ b/test/test_list.rb @@ -0,0 +1,60 @@ +#!/usr/bin/env ruby +# coding: utf-8 + +require "minitest/autorun" +require "test_helper" +require "highline/list" + +class TestHighLineList < Minitest::Test + def setup + @items = [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" ] + end + + def test_in_2_cols + list_in_two_cols = + [ [ "a", "b" ], + [ "c", "d" ], + [ "e", "f" ], + [ "g", "h" ], + [ "i", "j" ] ] + + highline_list = HighLine::List.new(@items, cols: 2) + + assert_equal list_in_two_cols, highline_list.list + end + + def test_in_2_cols_col_down + col_down_list = + [ [ "a", "f"], + [ "b", "g"], + [ "c", "h"], + [ "d", "i"], + [ "e", "j"] ] + + highline_list = HighLine::List.new(@items, cols: 2, col_down: true) + + assert_equal col_down_list, highline_list.list + end + + def test_in_2_cols_transposed + transposed_list = + [ [ "a", "c", "e", "g", "i" ], + [ "b", "d", "f", "h", "j" ] ] + + highline_list = HighLine::List.new(@items, cols: 2, transpose: true) + + assert_equal transposed_list, highline_list.list + end + + def test_in_3_cols + list_in_three_cols = + [ [ "a", "b", "c" ], + [ "d", "e", "f" ], + [ "g", "h", "i" ], + [ "j" ] ] + + highline_list = HighLine::List.new(@items, cols: 3) + + assert_equal list_in_three_cols, highline_list.list + end +end \ No newline at end of file -- cgit v1.2.1 From 3ce9480f32fd8ea46692d27274e4d7309290ff41 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 20 Apr 2015 02:01:55 -0300 Subject: Add Array, String coercion and row_join_string support to HighLine::List --- lib/highline/list.rb | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index cc57618..b81c4f3 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -1,6 +1,6 @@ class HighLine class List - attr_reader :items, :cols, :list + attr_reader :items, :cols attr_reader :transpose_mode, :col_down_mode def initialize(items, options = {}) @@ -39,6 +39,30 @@ class HighLine build end + def to_a + list + end + + def list + @list.dup + end + + def to_s + list.map { |row| stringfy(row) }.join + end + + def row_join_string + @row_join_string ||= " " + end + + def row_join_string=(string) + @row_join_string = string + end + + def row_join_str_size + row_join_string.size + end + private def build @@ -59,5 +83,9 @@ class HighLine def row_count (items.count / cols.to_f).ceil end + + def stringfy(row) + row.compact.join(row_join_string) + "\n" + end end end \ No newline at end of file -- cgit v1.2.1 From 1c0e036a140fadf68e5d3d11f9c37b09f020dd1a Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 20 Apr 2015 02:03:53 -0300 Subject: Use HighLine::List on HighLine::ListRenderer columns accross and down modes --- lib/highline/list_renderer.rb | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/highline/list_renderer.rb b/lib/highline/list_renderer.rb index 3c16436..d4d90ae 100644 --- a/lib/highline/list_renderer.rb +++ b/lib/highline/list_renderer.rb @@ -1,5 +1,6 @@ require 'highline/template_renderer' require 'highline/wrapper' +require 'highline/list' class HighLine::ListRenderer attr_reader :items, :mode, :option, :highline @@ -89,17 +90,11 @@ class HighLine::ListRenderer end def list_columns_across_mode - list = right_padded_items.each_slice(col_count) - - list_to_s(list) + HighLine::List.new(right_padded_items, cols: col_count).to_s end def list_columns_down_mode - list = right_padded_items.each_slice(row_count).to_a - - list = transpose(list) - - list_to_s(list) + HighLine::List.new(right_padded_items, cols: col_count, col_down: true).to_s end def list_uneven_columns_mode -- cgit v1.2.1 From 7bf234586637b1453ea66cf032d32420a0a6db32 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 20 Apr 2015 02:06:24 -0300 Subject: Rename HighLine::ListRenderer#list_to_s to #stringfy_list --- lib/highline/list_renderer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/highline/list_renderer.rb b/lib/highline/list_renderer.rb index d4d90ae..872ba85 100644 --- a/lib/highline/list_renderer.rb +++ b/lib/highline/list_renderer.rb @@ -116,10 +116,10 @@ class HighLine::ListRenderer right_padded_list = list.map do |row| right_pad_row(row, widths) end - list_to_s(right_padded_list) + stringfy_list(right_padded_list) end - def list_to_s(list) + def stringfy_list(list) list.map { |row| row_to_s(row) }.join end -- cgit v1.2.1 From 2de885846514d8c3a44cf5ca219b69e47c34824c Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 20 Apr 2015 02:07:53 -0300 Subject: Use HighLine::List on HighLine::ListRenderer#list_uneven_columns_mode --- lib/highline/list_renderer.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/highline/list_renderer.rb b/lib/highline/list_renderer.rb index 872ba85..22b74f1 100644 --- a/lib/highline/list_renderer.rb +++ b/lib/highline/list_renderer.rb @@ -97,24 +97,25 @@ class HighLine::ListRenderer HighLine::List.new(right_padded_items, cols: col_count, col_down: true).to_s end - def list_uneven_columns_mode + def list_uneven_columns_mode(list=nil) + list ||= HighLine::List.new(items) + col_max = option || items.size col_max.downto(1) do |column_count| - rows = items.each_slice(column_count) - - widths = get_col_widths(rows) + list.cols = column_count + widths = get_col_widths(list) if column_count == 1 or # last guess inside_line_size_limit?(widths) or # good guess option # defined by user - return pad_uneven_rows(rows, widths) + return pad_uneven_rows(list, widths) end end end def pad_uneven_rows(list, widths) - right_padded_list = list.map do |row| - right_pad_row(row, widths) + right_padded_list = Array(list).map do |row| + right_pad_row(row.compact, widths) end stringfy_list(right_padded_list) end -- cgit v1.2.1 From b8af3e6c69944c5748326f20d841d7dacc0b5951 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 20 Apr 2015 02:09:14 -0300 Subject: Simplify uneven columns down mode using HighLine::List Make uneven columns down mode be just a special case of uneven columns mode. Using a separate HighLine::List made this more clearly possible. --- lib/highline/list_renderer.rb | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/lib/highline/list_renderer.rb b/lib/highline/list_renderer.rb index 22b74f1..55ea2cd 100644 --- a/lib/highline/list_renderer.rb +++ b/lib/highline/list_renderer.rb @@ -113,6 +113,11 @@ class HighLine::ListRenderer end end + def list_uneven_columns_down_mode + list = HighLine::List.new(items, col_down: true) + list_uneven_columns_mode(list) + end + def pad_uneven_rows(list, widths) right_padded_list = Array(list).map do |row| right_pad_row(row.compact, widths) @@ -167,39 +172,11 @@ class HighLine::ListRenderer first_line.zip(*lines) end - def list_uneven_columns_down_mode - col_max = option || items.size - - col_max.downto(1) do |column_count| - row_count = (items.size / column_count.to_f).ceil - columns = items.each_slice(row_count) - - widths = get_row_widths(columns) - - if column_count == 1 or - inside_line_size_limit?(widths) or - option - return pad_uneven_cols(columns, widths) - end - end - end - def inside_line_size_limit?(widths) line_size = widths.inject(0) { |sum, n| sum + n + row_join_str_size } line_size <= line_size_limit + row_join_str_size end - def pad_uneven_cols(columns, widths) - list = "" - columns.first.size.times do |index| - list << columns.zip(widths).map { |column, width| - field = column[index] - right_pad_field(field, width) - }.compact.join(row_join_string).strip + "\n" - end - list - end - def actual_length(text) HighLine::Wrapper.actual_length text end -- cgit v1.2.1 From 474bdfbbe0ac64a5a020f2e3cbc8f78baf2cdf83 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 24 Apr 2015 15:41:04 -0300 Subject: Add HighLine::Question#format_answer convenience method --- lib/highline.rb | 7 +++---- lib/highline/question.rb | 5 +++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index abe3533..4364229 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -681,8 +681,7 @@ class HighLine raw_answer = String.new # Never return nil end end - answer = question.change_case( - question.remove_whitespace(raw_answer)) + answer = question.format_answer(raw_answer) $VERBOSE = old_verbose answer @@ -699,7 +698,7 @@ class HighLine raw_answer = @input.gets end - question.change_case(question.remove_whitespace(raw_answer)) + question.format_answer(raw_answer) end end @@ -775,7 +774,7 @@ class HighLine say("\n") end - question.change_case(question.remove_whitespace(line.force_encoding(Encoding.default_external))) + question.format_answer(line.force_encoding(Encoding.default_external)) end else if JRUBY #prompt has not been shown diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 276ead7..477e819 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -430,6 +430,11 @@ class HighLine end end + def format_answer(answer_string) + answer_string = remove_whitespace(answer_string) + change_case(answer_string) + end + # # Returns an Array of valid answers to this question. These answers are # only known when _answer_type_ is set to an Array of choices, File, or -- cgit v1.2.1 From 2813366f7eafafb455967d194f9241026df7eb4a Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 24 Apr 2015 17:01:53 -0300 Subject: Use #empty? and don't test for nil at Question#answer_or_default --- lib/highline/question.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 477e819..e21e122 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -222,7 +222,7 @@ class HighLine # Question if a default was set and the answer is empty. # def answer_or_default( answer_string ) - if answer_string.length == 0 and not @default.nil? + if answer_string.empty? and @default @default else answer_string -- cgit v1.2.1 From 0a6ea9e27142852dbb06ce5d5045d0b121eb258b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 24 Apr 2015 17:11:01 -0300 Subject: Turn conditional into a guard clause --- lib/highline/question.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index e21e122..b1dad35 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -222,11 +222,8 @@ class HighLine # Question if a default was set and the answer is empty. # def answer_or_default( answer_string ) - if answer_string.empty? and @default - @default - else - answer_string - end + return @default if answer_string.empty? && @default + answer_string end # -- cgit v1.2.1 From 81ffa24677f3d92823b77ccba4b891411a1eb7bc Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 24 Apr 2015 17:23:57 -0300 Subject: Remove unecessary #map on HighLine::Question#build_responses --- lib/highline/question.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index b1dad35..b407668 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -236,7 +236,7 @@ class HighLine choice_error_str_func = lambda do message_source.is_a?(Array) \ - ? '[' + message_source.map { |s| "#{s}" }.join(', ') + ']' \ + ? '[' + message_source.join(', ') + ']' \ : message_source.inspect end -- cgit v1.2.1 From 09de05af2c885c046a5cba6d46662d13554bc250 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 24 Apr 2015 17:28:50 -0300 Subject: Change lambda to a method (HighLine::Question#choice_error_str) --- lib/highline/question.rb | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index b407668..5a0199f 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -234,23 +234,17 @@ class HighLine def build_responses(message_source = answer_type, new_hash_wins = false) append_default if [::String, Symbol].include? default.class - choice_error_str_func = lambda do - message_source.is_a?(Array) \ - ? '[' + message_source.join(', ') + ']' \ - : message_source.inspect - end - old_hash = @responses new_hash = { :ambiguous_completion => "Ambiguous choice. Please choose one of " + - choice_error_str_func.call + '.', + 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_func.call + '.', + "You must choose one of " + choice_error_str(message_source) + '.', :not_in_range => "Your answer isn't within the expected range " + "(#{expected_range}).", @@ -485,5 +479,13 @@ class HighLine @template << " |#{@default}|" end end + + def choice_error_str(message_source) + if message_source.is_a? Array + '[' + message_source.join(', ') + ']' + else + message_source.inspect + end + end end end -- cgit v1.2.1 From 6888de76a9a186682f81c05a27beff45d359eba9 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 24 Apr 2015 17:35:55 -0300 Subject: Split HighLine#Question#build_responses --- lib/highline/question.rb | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 5a0199f..0211945 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -236,27 +236,26 @@ class HighLine old_hash = @responses - new_hash = { :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})." } + new_hash = build_responses_new_hash(message_source) @responses = new_hash_wins ? old_hash.merge(new_hash) : new_hash.merge(old_hash) end + 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 + + # # Returns the provided _answer_string_ after changing character case by # the rules of this Question. Valid settings for whitespace are: -- cgit v1.2.1 From 2aacef68962ce6610babbbb86309cc31c8ab60d5 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 24 Apr 2015 18:03:11 -0300 Subject: Use 'unless' one line syntax --- lib/highline/question.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 0211945..9d897c3 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -327,9 +327,7 @@ class HighLine choices = selection choices.extend(OptionParser::Completion) answer = choices.complete(answer_string) - if answer.nil? - raise NoAutoCompleteMatch - end + raise NoAutoCompleteMatch unless answer if @answer_type.is_a?(Array) answer.last elsif @answer_type == File -- cgit v1.2.1 From 4dacdf3b79e2dbce37336074354f86aa446d3d37 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 24 Apr 2015 18:04:40 -0300 Subject: Extract HighLine::Question#choices_complete --- lib/highline/question.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 9d897c3..c9d9530 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -323,11 +323,7 @@ class HighLine elsif @answer_type == Regexp Regexp.new(answer_string) elsif @answer_type.is_a?(Array) or [File, Pathname].include?(@answer_type) - # cheating, using OptionParser's Completion module - choices = selection - choices.extend(OptionParser::Completion) - answer = choices.complete(answer_string) - raise NoAutoCompleteMatch unless answer + answer = choices_complete(answer_string) if @answer_type.is_a?(Array) answer.last elsif @answer_type == File @@ -342,6 +338,15 @@ class HighLine end end + def choices_complete(answer_string) + # cheating, using OptionParser's Completion module + choices = selection + choices.extend(OptionParser::Completion) + answer = choices.complete(answer_string) + raise NoAutoCompleteMatch unless answer + answer + end + # Returns an English explanation of the current range settings. def expected_range( ) expected = [ ] -- cgit v1.2.1 From 4a16ff6d47df999c527ea7ce7a77fda305c6af70 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 24 Apr 2015 18:56:16 -0300 Subject: Make default case a guard clause --- lib/highline/question.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index c9d9530..944796e 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -312,9 +312,9 @@ class HighLine # completed for any reason. # def convert( answer_string ) - if @answer_type.nil? - answer_string - elsif [::String, HighLine::String].include?(@answer_type) + return answer_string unless @answer_type + + if [::String, HighLine::String].include?(@answer_type) HighLine::String(answer_string) elsif [Float, Integer, String].include?(@answer_type) Kernel.send(@answer_type.to_s.to_sym, answer_string) -- cgit v1.2.1 From 853f2cbab252d814aea5a6624d7db7d9c1e89108 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 24 Apr 2015 18:56:38 -0300 Subject: Reduce line size/complexity by testing for a Duck type --- lib/highline/question.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 944796e..ebb9649 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -331,7 +331,7 @@ class HighLine else Pathname.new(File.join(@directory.to_s, answer.last)) end - elsif [Date, DateTime].include?(@answer_type) or @answer_type.is_a?(Class) + elsif @answer_type.respond_to? :parse @answer_type.parse(answer_string) elsif @answer_type.is_a?(Proc) @answer_type[answer_string] -- cgit v1.2.1 From 04abc552c3a9a2ec0fb3c8133d686d95343f58ec Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 25 Apr 2015 23:47:22 -0300 Subject: Use #empty? instead of testing for #length > 0 --- lib/highline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline.rb b/lib/highline.rb index 4364229..0208ad0 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -380,7 +380,7 @@ class HighLine # def say( statement ) statement = Statement.new(statement, self).to_s - return unless statement.length > 0 + return if statement.empty? out = (indentation+statement).encode(Encoding.default_external, { :undef => :replace } ) -- cgit v1.2.1 From ac41ad4c7f6608c85bf7c2513ef3e6546b042f74 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 25 Apr 2015 23:53:58 -0300 Subject: Remove unecessary return --- lib/highline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline.rb b/lib/highline.rb index 0208ad0..f75fdbc 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -418,7 +418,7 @@ class HighLine # Outputs indentation with current settings # def indentation - return ' '*@indent_size*@indent_level + ' '*@indent_size*@indent_level end # -- cgit v1.2.1 From 2d458d576b4b4f8a616ec977ce72aa22d1d2e3a2 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 26 Apr 2015 12:12:07 -0300 Subject: Remove nil testing --- lib/highline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline.rb b/lib/highline.rb index f75fdbc..fa66e5f 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -427,7 +427,7 @@ class HighLine def indent(increase=1, statement=nil, multiline=nil) @indent_level += increase multi = @multi_indent - @multi_indent = multiline unless multiline.nil? + @multi_indent = multiline || @multi_indent begin if block_given? yield self -- cgit v1.2.1 From 4430164a40103a190c4b3552a56a4dcb380c1756 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 26 Apr 2015 12:13:26 -0300 Subject: A first step toward replacing conditionals with polymorphism https://sourcemaking.com/refactoring/replace-conditional-with-polymorphism --- lib/highline/system_extensions.rb | 218 ++------------------- lib/highline/system_extensions/jruby.rb | 38 ++++ lib/highline/system_extensions/jruby_jline.rb | 24 +++ lib/highline/system_extensions/ncurses.rb | 31 +++ lib/highline/system_extensions/stty.rb | 17 ++ lib/highline/system_extensions/unix_stty.rb | 25 +++ lib/highline/system_extensions/unix_termios.rb | 21 ++ lib/highline/system_extensions/windows.rb | 39 ++++ .../system_extensions/windows_dl_import.rb | 35 ++++ lib/highline/system_extensions/windows_fiddle.rb | 33 ++++ 10 files changed, 281 insertions(+), 200 deletions(-) create mode 100644 lib/highline/system_extensions/jruby.rb create mode 100644 lib/highline/system_extensions/jruby_jline.rb create mode 100644 lib/highline/system_extensions/ncurses.rb create mode 100644 lib/highline/system_extensions/stty.rb create mode 100644 lib/highline/system_extensions/unix_stty.rb create mode 100644 lib/highline/system_extensions/unix_termios.rb create mode 100644 lib/highline/system_extensions/windows.rb create mode 100644 lib/highline/system_extensions/windows_dl_import.rb create mode 100644 lib/highline/system_extensions/windows_fiddle.rb diff --git a/lib/highline/system_extensions.rb b/lib/highline/system_extensions.rb index 5e78505..671cbb1 100755 --- a/lib/highline/system_extensions.rb +++ b/lib/highline/system_extensions.rb @@ -15,35 +15,8 @@ class HighLine JRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' if JRUBY - def initialize_system_extensions - require 'java' - require 'readline' - if JRUBY_VERSION =~ /^1.7/ - java_import 'jline.console.ConsoleReader' - - input = @input && @input.to_inputstream - output = @output && @output.to_outputstream - - @java_console = ConsoleReader.new(input, output) - @java_console.set_history_enabled(false) - @java_console.set_bell_enabled(true) - @java_console.set_pagination_enabled(false) - @java_terminal = @java_console.getTerminal - elsif JRUBY_VERSION =~ /^1.6/ - java_import 'java.io.OutputStreamWriter' - java_import 'java.nio.channels.Channels' - java_import 'jline.ConsoleReader' - java_import 'jline.Terminal' - - @java_input = Channels.newInputStream(@input.to_channel) - @java_output = OutputStreamWriter.new(Channels.newOutputStream(@output.to_channel)) - @java_terminal = Terminal.getTerminal - @java_console = ConsoleReader.new(@java_input, @java_output) - @java_console.setUseHistory(false) - @java_console.setBellEnabled(true) - @java_console.setUsePagination(false) - end - end + require 'highline/system_extensions/jruby' + include HighLine::SystemExtensions::JRuby end extend self @@ -55,193 +28,38 @@ class HighLine # if RUBY_PLATFORM =~ /mswin(?!ce)|mingw|bccwin/i begin - require "fiddle" - - module WinAPI - include Fiddle - Handle = RUBY_VERSION >= "2.0.0" ? Fiddle::Handle : DL::Handle - Kernel32 = Handle.new("kernel32") - Crt = Handle.new("msvcrt") rescue Handle.new("crtdll") - - def self._getch - @@_m_getch ||= Function.new(Crt["_getch"], [], TYPE_INT) - @@_m_getch.call - end - - def self.GetStdHandle(handle_type) - @@get_std_handle ||= Function.new(Kernel32["GetStdHandle"], [-TYPE_INT], -TYPE_INT) - @@get_std_handle.call(handle_type) - end - - def self.GetConsoleScreenBufferInfo(cons_handle, lp_buffer) - @@get_console_screen_buffer_info ||= - Function.new(Kernel32["GetConsoleScreenBufferInfo"], [TYPE_LONG, TYPE_VOIDP], TYPE_INT) - @@get_console_screen_buffer_info.call(cons_handle, lp_buffer) - end - end + require 'highline/system_extensions/windows_fiddle' + include HighLine::SystemExtensions::WindowsFiddle rescue LoadError - require "dl/import" - - module WinAPI - if defined?(DL::Importer) - # Ruby 1.9 - extend DL::Importer - else - # Ruby 1.8 - extend DL::Importable - end - begin - dlload "msvcrt", "kernel32" - rescue DL::DLError - dlload "crtdll", "kernel32" - end - extern "unsigned long _getch()" - extern "unsigned long GetConsoleScreenBufferInfo(unsigned long, void*)" - extern "unsigned long GetStdHandle(unsigned long)" - - # Ruby 1.8 DL::Importable.import does mname[0,1].downcase so FooBar becomes fooBar - if defined?(getConsoleScreenBufferInfo) - alias_method :GetConsoleScreenBufferInfo, :getConsoleScreenBufferInfo - module_function :GetConsoleScreenBufferInfo - end - if defined?(getStdHandle) - alias_method :GetStdHandle, :getStdHandle - module_function :GetStdHandle - end - end - end - - CHARACTER_MODE = "Win32API" # For Debugging purposes only. - - # - # Windows savvy getc(). - # - # *WARNING*: This method ignores input and reads one - # character from +STDIN+! - # - def get_character( input = STDIN ) - WinAPI._getch - end - - # We do not define a raw_no_echo_mode for Windows as _getch turns off echo - def raw_no_echo_mode - end - - def restore_mode + require 'highline/system_extensions/windows_dl_import' + include HighLine::SystemExtensions::WindowsDlImport end - # A Windows savvy method to fetch the console columns, and rows. - def terminal_size - format = 'SSSSSssssSS' - buf = ([0] * format.size).pack(format) - stdout_handle = WinAPI.GetStdHandle(0xFFFFFFF5) - - WinAPI.GetConsoleScreenBufferInfo(stdout_handle, buf) - _, _, _, _, _, - left, top, right, bottom, _, _ = buf.unpack(format) - return right - left + 1, bottom - top + 1 - end + require 'highline/system_extensions/windows' + include HighLine::SystemExtensions::Windows else # If we're not on Windows try... begin - require "termios" # Unix, first choice termios. - - CHARACTER_MODE = "termios" # For Debugging purposes only. - - def raw_no_echo_mode - @state = Termios.getattr(@input) - new_settings = @state.dup - new_settings.c_lflag &= ~(Termios::ECHO | Termios::ICANON) - new_settings.c_cc[Termios::VMIN] = 1 - Termios.setattr(@input, Termios::TCSANOW, new_settings) - end - - def restore_mode - Termios.setattr(@input, Termios::TCSANOW, @state) - end + require 'highline/system_extensions/unix_termios' + include HighLine::SystemExtensions::UnixTermios rescue LoadError # If our first choice fails, try using JLine if JRUBY # if we are on JRuby. JLine is bundled with JRuby. - CHARACTER_MODE = "jline" # For Debugging purposes only. - - def terminal_size - if JRUBY_VERSION =~ /^1.7/ - [ @java_terminal.get_width, @java_terminal.get_height ] - else - [ @java_terminal.getTerminalWidth, @java_terminal.getTerminalHeight ] - end - end - - def raw_no_echo_mode - @state = @java_console.getEchoCharacter - @java_console.setEchoCharacter 0 - end - - def restore_mode - @java_console.setEchoCharacter @state - end + require 'highline/system_extensions/jruby_jline' + include HighLine::SystemExtensions::JRubyJLine else # If we are not on JRuby, try ncurses begin - require 'ffi-ncurses' - CHARACTER_MODE = "ncurses" # For Debugging purposes only. - - def raw_no_echo_mode - FFI::NCurses.initscr - FFI::NCurses.cbreak - end - - def restore_mode - FFI::NCurses.endwin - end - - # - # A ncurses savvy method to fetch the console columns, and rows. - # - def terminal_size - size = [80, 40] - FFI::NCurses.initscr - begin - size = FFI::NCurses.getmaxyx(FFI::NCurses.stdscr).reverse - ensure - FFI::NCurses.endwin - end - size - end + require 'highline/system_extensions/ncurses' + include HighLine::SystemExtensions::NCurses rescue LoadError # Finally, if all else fails, use stty - # *WARNING*: This requires the external "stty" program! - CHARACTER_MODE = "stty" # For Debugging purposes only. - - def raw_no_echo_mode - @state = `stty -g` - system "stty raw -echo -icanon isig" - end - - def restore_mode - system "stty #{@state}" - end + require 'highline/system_extensions/stty' + include HighLine::SystemExtensions::Stty end end end # For termios and stty if not method_defined?(:terminal_size) - # A Unix savvy method using stty to fetch the console columns, and rows. - # ... stty does not work in JRuby - def terminal_size - begin - require "io/console" - winsize = IO.console.winsize.reverse rescue nil - return winsize if winsize - rescue LoadError - end - - if /solaris/ =~ RUBY_PLATFORM and - `stty` =~ /\brows = (\d+).*\bcolumns = (\d+)/ - [$2, $1].map { |c| x.to_i } - elsif `stty size` =~ /^(\d+)\s(\d+)$/ - [$2.to_i, $1.to_i] - else - [ 80, 24 ] - end - end + require 'highline/system_extensions/unix_stty' + include HighLine::SystemExtensions::UnixStty end end diff --git a/lib/highline/system_extensions/jruby.rb b/lib/highline/system_extensions/jruby.rb new file mode 100644 index 0000000..5e85024 --- /dev/null +++ b/lib/highline/system_extensions/jruby.rb @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby +#coding: utf-8 + +class HighLine + module SystemExtensions + module JRuby + def initialize_system_extensions + require 'java' + require 'readline' + if JRUBY_VERSION =~ /^1.7/ + java_import 'jline.console.ConsoleReader' + + input = @input && @input.to_inputstream + output = @output && @output.to_outputstream + + @java_console = ConsoleReader.new(input, output) + @java_console.set_history_enabled(false) + @java_console.set_bell_enabled(true) + @java_console.set_pagination_enabled(false) + @java_terminal = @java_console.getTerminal + elsif JRUBY_VERSION =~ /^1.6/ + java_import 'java.io.OutputStreamWriter' + java_import 'java.nio.channels.Channels' + java_import 'jline.ConsoleReader' + java_import 'jline.Terminal' + + @java_input = Channels.newInputStream(@input.to_channel) + @java_output = OutputStreamWriter.new(Channels.newOutputStream(@output.to_channel)) + @java_terminal = Terminal.getTerminal + @java_console = ConsoleReader.new(@java_input, @java_output) + @java_console.setUseHistory(false) + @java_console.setBellEnabled(true) + @java_console.setUsePagination(false) + end + end + end + end +end \ No newline at end of file diff --git a/lib/highline/system_extensions/jruby_jline.rb b/lib/highline/system_extensions/jruby_jline.rb new file mode 100644 index 0000000..8f3a590 --- /dev/null +++ b/lib/highline/system_extensions/jruby_jline.rb @@ -0,0 +1,24 @@ +class HighLine + module SystemExtensions + module JRubyJLine + CHARACTER_MODE = "jline" # For Debugging purposes only. + + def terminal_size + if JRUBY_VERSION =~ /^1.7/ + [ @java_terminal.get_width, @java_terminal.get_height ] + else + [ @java_terminal.getTerminalWidth, @java_terminal.getTerminalHeight ] + end + end + + def raw_no_echo_mode + @state = @java_console.getEchoCharacter + @java_console.setEchoCharacter 0 + end + + def restore_mode + @java_console.setEchoCharacter @state + end + end + end +end \ No newline at end of file diff --git a/lib/highline/system_extensions/ncurses.rb b/lib/highline/system_extensions/ncurses.rb new file mode 100644 index 0000000..8ac672f --- /dev/null +++ b/lib/highline/system_extensions/ncurses.rb @@ -0,0 +1,31 @@ +class HighLine + module SystemExtensions + module NCurses + require 'ffi-ncurses' + CHARACTER_MODE = "ncurses" # For Debugging purposes only. + + def raw_no_echo_mode + FFI::NCurses.initscr + FFI::NCurses.cbreak + end + + def restore_mode + FFI::NCurses.endwin + end + + # + # A ncurses savvy method to fetch the console columns, and rows. + # + def terminal_size + size = [80, 40] + FFI::NCurses.initscr + begin + size = FFI::NCurses.getmaxyx(FFI::NCurses.stdscr).reverse + ensure + FFI::NCurses.endwin + end + size + end + end + end +end \ No newline at end of file diff --git a/lib/highline/system_extensions/stty.rb b/lib/highline/system_extensions/stty.rb new file mode 100644 index 0000000..ecc039b --- /dev/null +++ b/lib/highline/system_extensions/stty.rb @@ -0,0 +1,17 @@ +class HighLine + module SystemExtensions + module Stty + # *WARNING*: This requires the external "stty" program! + CHARACTER_MODE = "stty" # For Debugging purposes only. + + def raw_no_echo_mode + @state = `stty -g` + system "stty raw -echo -icanon isig" + end + + def restore_mode + system "stty #{@state}" + end + end + end +end \ No newline at end of file diff --git a/lib/highline/system_extensions/unix_stty.rb b/lib/highline/system_extensions/unix_stty.rb new file mode 100644 index 0000000..eecdba1 --- /dev/null +++ b/lib/highline/system_extensions/unix_stty.rb @@ -0,0 +1,25 @@ +class HighLine + module SystemExtensions + module UnixStty + # A Unix savvy method using stty to fetch the console columns, and rows. + # ... stty does not work in JRuby + def terminal_size + begin + require "io/console" + winsize = IO.console.winsize.reverse rescue nil + return winsize if winsize + rescue LoadError + end + + if /solaris/ =~ RUBY_PLATFORM and + `stty` =~ /\brows = (\d+).*\bcolumns = (\d+)/ + [$2, $1].map { |c| x.to_i } + elsif `stty size` =~ /^(\d+)\s(\d+)$/ + [$2.to_i, $1.to_i] + else + [ 80, 24 ] + end + end + end + end +end \ No newline at end of file diff --git a/lib/highline/system_extensions/unix_termios.rb b/lib/highline/system_extensions/unix_termios.rb new file mode 100644 index 0000000..5b285ff --- /dev/null +++ b/lib/highline/system_extensions/unix_termios.rb @@ -0,0 +1,21 @@ +class HighLine + module SystemExtensions + module UnixTermios + require "termios" # Unix, first choice termios. + + CHARACTER_MODE = "termios" # For Debugging purposes only. + + def raw_no_echo_mode + @state = Termios.getattr(@input) + new_settings = @state.dup + new_settings.c_lflag &= ~(Termios::ECHO | Termios::ICANON) + new_settings.c_cc[Termios::VMIN] = 1 + Termios.setattr(@input, Termios::TCSANOW, new_settings) + end + + def restore_mode + Termios.setattr(@input, Termios::TCSANOW, @state) + end + end + end +end \ No newline at end of file diff --git a/lib/highline/system_extensions/windows.rb b/lib/highline/system_extensions/windows.rb new file mode 100644 index 0000000..005045e --- /dev/null +++ b/lib/highline/system_extensions/windows.rb @@ -0,0 +1,39 @@ +#!/usr/bin/env ruby +#coding: utf-8 + +class HighLine + module SystemExtensions + module Windows + CHARACTER_MODE = "Win32API" # For Debugging purposes only. + + # + # Windows savvy getc(). + # + # *WARNING*: This method ignores input and reads one + # character from +STDIN+! + # + def get_character( input = STDIN ) + WinAPI._getch + end + + # We do not define a raw_no_echo_mode for Windows as _getch turns off echo + def raw_no_echo_mode + end + + def restore_mode + end + + # A Windows savvy method to fetch the console columns, and rows. + def terminal_size + format = 'SSSSSssssSS' + buf = ([0] * format.size).pack(format) + stdout_handle = WinAPI.GetStdHandle(0xFFFFFFF5) + + WinAPI.GetConsoleScreenBufferInfo(stdout_handle, buf) + _, _, _, _, _, + left, top, right, bottom, _, _ = buf.unpack(format) + return right - left + 1, bottom - top + 1 + end + end + end +end diff --git a/lib/highline/system_extensions/windows_dl_import.rb b/lib/highline/system_extensions/windows_dl_import.rb new file mode 100644 index 0000000..597374e --- /dev/null +++ b/lib/highline/system_extensions/windows_dl_import.rb @@ -0,0 +1,35 @@ +class HighLine + module SystemExtensions + module WindowsDlImport + require "dl/import" + + module WinAPI + if defined?(DL::Importer) + # Ruby 1.9 + extend DL::Importer + else + # Ruby 1.8 + extend DL::Importable + end + begin + dlload "msvcrt", "kernel32" + rescue DL::DLError + dlload "crtdll", "kernel32" + end + extern "unsigned long _getch()" + extern "unsigned long GetConsoleScreenBufferInfo(unsigned long, void*)" + extern "unsigned long GetStdHandle(unsigned long)" + + # Ruby 1.8 DL::Importable.import does mname[0,1].downcase so FooBar becomes fooBar + if defined?(getConsoleScreenBufferInfo) + alias_method :GetConsoleScreenBufferInfo, :getConsoleScreenBufferInfo + module_function :GetConsoleScreenBufferInfo + end + if defined?(getStdHandle) + alias_method :GetStdHandle, :getStdHandle + module_function :GetStdHandle + end + end + end + end +end diff --git a/lib/highline/system_extensions/windows_fiddle.rb b/lib/highline/system_extensions/windows_fiddle.rb new file mode 100644 index 0000000..8a2a4af --- /dev/null +++ b/lib/highline/system_extensions/windows_fiddle.rb @@ -0,0 +1,33 @@ +#!/usr/bin/env ruby +#coding: utf-8 + +class HighLine + module SystemExtensions + module WindowsFiddle + require "fiddle" + + module WinAPI + include Fiddle + Handle = RUBY_VERSION >= "2.0.0" ? Fiddle::Handle : DL::Handle + Kernel32 = Handle.new("kernel32") + Crt = Handle.new("msvcrt") rescue Handle.new("crtdll") + + def self._getch + @@_m_getch ||= Function.new(Crt["_getch"], [], TYPE_INT) + @@_m_getch.call + end + + def self.GetStdHandle(handle_type) + @@get_std_handle ||= Function.new(Kernel32["GetStdHandle"], [-TYPE_INT], -TYPE_INT) + @@get_std_handle.call(handle_type) + end + + def self.GetConsoleScreenBufferInfo(cons_handle, lp_buffer) + @@get_console_screen_buffer_info ||= + Function.new(Kernel32["GetConsoleScreenBufferInfo"], [TYPE_LONG, TYPE_VOIDP], TYPE_INT) + @@get_console_screen_buffer_info.call(cons_handle, lp_buffer) + end + end + end + end +end \ No newline at end of file -- cgit v1.2.1 From 3e352b1fc7b2db1210410d8ea4df7c8d095f1e1b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 27 Apr 2015 00:12:31 -0300 Subject: Turn SystemExtensions into Terminal --- lib/highline.rb | 11 ++-- lib/highline/system_extensions.rb | 72 -------------------- lib/highline/system_extensions/jruby.rb | 38 ----------- lib/highline/system_extensions/jruby_jline.rb | 24 ------- lib/highline/system_extensions/ncurses.rb | 31 --------- lib/highline/system_extensions/stty.rb | 17 ----- lib/highline/system_extensions/unix_stty.rb | 25 ------- lib/highline/system_extensions/unix_termios.rb | 21 ------ lib/highline/system_extensions/windows.rb | 39 ----------- .../system_extensions/windows_dl_import.rb | 35 ---------- lib/highline/system_extensions/windows_fiddle.rb | 33 ---------- lib/highline/terminal.rb | 76 ++++++++++++++++++++++ lib/highline/terminal/jruby.rb | 38 +++++++++++ lib/highline/terminal/jruby_jline.rb | 24 +++++++ lib/highline/terminal/ncurses.rb | 31 +++++++++ lib/highline/terminal/stty.rb | 17 +++++ lib/highline/terminal/unix_stty.rb | 25 +++++++ lib/highline/terminal/unix_termios.rb | 21 ++++++ lib/highline/terminal/windows.rb | 39 +++++++++++ lib/highline/terminal/windows_dl_import.rb | 35 ++++++++++ lib/highline/terminal/windows_fiddle.rb | 33 ++++++++++ 21 files changed, 346 insertions(+), 339 deletions(-) delete mode 100755 lib/highline/system_extensions.rb delete mode 100644 lib/highline/system_extensions/jruby.rb delete mode 100644 lib/highline/system_extensions/jruby_jline.rb delete mode 100644 lib/highline/system_extensions/ncurses.rb delete mode 100644 lib/highline/system_extensions/stty.rb delete mode 100644 lib/highline/system_extensions/unix_stty.rb delete mode 100644 lib/highline/system_extensions/unix_termios.rb delete mode 100644 lib/highline/system_extensions/windows.rb delete mode 100644 lib/highline/system_extensions/windows_dl_import.rb delete mode 100644 lib/highline/system_extensions/windows_fiddle.rb create mode 100755 lib/highline/terminal.rb create mode 100644 lib/highline/terminal/jruby.rb create mode 100644 lib/highline/terminal/jruby_jline.rb create mode 100644 lib/highline/terminal/ncurses.rb create mode 100644 lib/highline/terminal/stty.rb create mode 100644 lib/highline/terminal/unix_stty.rb create mode 100644 lib/highline/terminal/unix_termios.rb create mode 100644 lib/highline/terminal/windows.rb create mode 100644 lib/highline/terminal/windows_dl_import.rb create mode 100644 lib/highline/terminal/windows_fiddle.rb diff --git a/lib/highline.rb b/lib/highline.rb index fa66e5f..d62f102 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -14,7 +14,7 @@ require "erb" require "optparse" require "stringio" require "abbrev" -require "highline/system_extensions" +require "highline/terminal" require "highline/question" require "highline/menu" require "highline/color_scheme" @@ -209,11 +209,9 @@ class HighLine @prompt = nil @key = nil - initialize_system_extensions if respond_to?(:initialize_system_extensions) + @terminal = HighLine::Terminal.get_terminal end - include HighLine::SystemExtensions - # The current column setting for wrapping output. attr_reader :wrap_at # The current row setting for paging output. @@ -231,6 +229,11 @@ class HighLine attr_reader :question + # System specific that responds to #initialize_system_extensions, + # #terminal_size, #raw_no_echo_mode, #restore_mode, #get_character. + # It polymorphically handles specific cases for different platforms. + attr_reader :terminal + # # A shortcut to HighLine.ask() a question that only accepts "yes" or "no" # answers ("y" and "n" are allowed) and returns +true+ or +false+ diff --git a/lib/highline/system_extensions.rb b/lib/highline/system_extensions.rb deleted file mode 100755 index 671cbb1..0000000 --- a/lib/highline/system_extensions.rb +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env ruby -# coding: utf-8 - -# system_extensions.rb -# -# Created by James Edward Gray II on 2006-06-14. -# Copyright 2006 Gray Productions. All rights reserved. -# -# This is Free Software. See LICENSE and COPYING for details. - -require "highline/compatibility" - -class HighLine - module SystemExtensions - JRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' - - if JRUBY - require 'highline/system_extensions/jruby' - include HighLine::SystemExtensions::JRuby - end - - extend self - - # - # This section builds character reading and terminal size functions - # to suit the proper platform we're running on. Be warned: Here be - # dragons! - # - if RUBY_PLATFORM =~ /mswin(?!ce)|mingw|bccwin/i - begin - require 'highline/system_extensions/windows_fiddle' - include HighLine::SystemExtensions::WindowsFiddle - rescue LoadError - require 'highline/system_extensions/windows_dl_import' - include HighLine::SystemExtensions::WindowsDlImport - end - - require 'highline/system_extensions/windows' - include HighLine::SystemExtensions::Windows - else # If we're not on Windows try... - begin - require 'highline/system_extensions/unix_termios' - include HighLine::SystemExtensions::UnixTermios - rescue LoadError # If our first choice fails, try using JLine - if JRUBY # if we are on JRuby. JLine is bundled with JRuby. - require 'highline/system_extensions/jruby_jline' - include HighLine::SystemExtensions::JRubyJLine - else # If we are not on JRuby, try ncurses - begin - require 'highline/system_extensions/ncurses' - include HighLine::SystemExtensions::NCurses - rescue LoadError # Finally, if all else fails, use stty - require 'highline/system_extensions/stty' - include HighLine::SystemExtensions::Stty - end - end - end - - # For termios and stty - if not method_defined?(:terminal_size) - require 'highline/system_extensions/unix_stty' - include HighLine::SystemExtensions::UnixStty - end - end - - if not method_defined?(:get_character) - def get_character( input = STDIN ) - input.getbyte - end - end - end -end diff --git a/lib/highline/system_extensions/jruby.rb b/lib/highline/system_extensions/jruby.rb deleted file mode 100644 index 5e85024..0000000 --- a/lib/highline/system_extensions/jruby.rb +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env ruby -#coding: utf-8 - -class HighLine - module SystemExtensions - module JRuby - def initialize_system_extensions - require 'java' - require 'readline' - if JRUBY_VERSION =~ /^1.7/ - java_import 'jline.console.ConsoleReader' - - input = @input && @input.to_inputstream - output = @output && @output.to_outputstream - - @java_console = ConsoleReader.new(input, output) - @java_console.set_history_enabled(false) - @java_console.set_bell_enabled(true) - @java_console.set_pagination_enabled(false) - @java_terminal = @java_console.getTerminal - elsif JRUBY_VERSION =~ /^1.6/ - java_import 'java.io.OutputStreamWriter' - java_import 'java.nio.channels.Channels' - java_import 'jline.ConsoleReader' - java_import 'jline.Terminal' - - @java_input = Channels.newInputStream(@input.to_channel) - @java_output = OutputStreamWriter.new(Channels.newOutputStream(@output.to_channel)) - @java_terminal = Terminal.getTerminal - @java_console = ConsoleReader.new(@java_input, @java_output) - @java_console.setUseHistory(false) - @java_console.setBellEnabled(true) - @java_console.setUsePagination(false) - end - end - end - end -end \ No newline at end of file diff --git a/lib/highline/system_extensions/jruby_jline.rb b/lib/highline/system_extensions/jruby_jline.rb deleted file mode 100644 index 8f3a590..0000000 --- a/lib/highline/system_extensions/jruby_jline.rb +++ /dev/null @@ -1,24 +0,0 @@ -class HighLine - module SystemExtensions - module JRubyJLine - CHARACTER_MODE = "jline" # For Debugging purposes only. - - def terminal_size - if JRUBY_VERSION =~ /^1.7/ - [ @java_terminal.get_width, @java_terminal.get_height ] - else - [ @java_terminal.getTerminalWidth, @java_terminal.getTerminalHeight ] - end - end - - def raw_no_echo_mode - @state = @java_console.getEchoCharacter - @java_console.setEchoCharacter 0 - end - - def restore_mode - @java_console.setEchoCharacter @state - end - end - end -end \ No newline at end of file diff --git a/lib/highline/system_extensions/ncurses.rb b/lib/highline/system_extensions/ncurses.rb deleted file mode 100644 index 8ac672f..0000000 --- a/lib/highline/system_extensions/ncurses.rb +++ /dev/null @@ -1,31 +0,0 @@ -class HighLine - module SystemExtensions - module NCurses - require 'ffi-ncurses' - CHARACTER_MODE = "ncurses" # For Debugging purposes only. - - def raw_no_echo_mode - FFI::NCurses.initscr - FFI::NCurses.cbreak - end - - def restore_mode - FFI::NCurses.endwin - end - - # - # A ncurses savvy method to fetch the console columns, and rows. - # - def terminal_size - size = [80, 40] - FFI::NCurses.initscr - begin - size = FFI::NCurses.getmaxyx(FFI::NCurses.stdscr).reverse - ensure - FFI::NCurses.endwin - end - size - end - end - end -end \ No newline at end of file diff --git a/lib/highline/system_extensions/stty.rb b/lib/highline/system_extensions/stty.rb deleted file mode 100644 index ecc039b..0000000 --- a/lib/highline/system_extensions/stty.rb +++ /dev/null @@ -1,17 +0,0 @@ -class HighLine - module SystemExtensions - module Stty - # *WARNING*: This requires the external "stty" program! - CHARACTER_MODE = "stty" # For Debugging purposes only. - - def raw_no_echo_mode - @state = `stty -g` - system "stty raw -echo -icanon isig" - end - - def restore_mode - system "stty #{@state}" - end - end - end -end \ No newline at end of file diff --git a/lib/highline/system_extensions/unix_stty.rb b/lib/highline/system_extensions/unix_stty.rb deleted file mode 100644 index eecdba1..0000000 --- a/lib/highline/system_extensions/unix_stty.rb +++ /dev/null @@ -1,25 +0,0 @@ -class HighLine - module SystemExtensions - module UnixStty - # A Unix savvy method using stty to fetch the console columns, and rows. - # ... stty does not work in JRuby - def terminal_size - begin - require "io/console" - winsize = IO.console.winsize.reverse rescue nil - return winsize if winsize - rescue LoadError - end - - if /solaris/ =~ RUBY_PLATFORM and - `stty` =~ /\brows = (\d+).*\bcolumns = (\d+)/ - [$2, $1].map { |c| x.to_i } - elsif `stty size` =~ /^(\d+)\s(\d+)$/ - [$2.to_i, $1.to_i] - else - [ 80, 24 ] - end - end - end - end -end \ No newline at end of file diff --git a/lib/highline/system_extensions/unix_termios.rb b/lib/highline/system_extensions/unix_termios.rb deleted file mode 100644 index 5b285ff..0000000 --- a/lib/highline/system_extensions/unix_termios.rb +++ /dev/null @@ -1,21 +0,0 @@ -class HighLine - module SystemExtensions - module UnixTermios - require "termios" # Unix, first choice termios. - - CHARACTER_MODE = "termios" # For Debugging purposes only. - - def raw_no_echo_mode - @state = Termios.getattr(@input) - new_settings = @state.dup - new_settings.c_lflag &= ~(Termios::ECHO | Termios::ICANON) - new_settings.c_cc[Termios::VMIN] = 1 - Termios.setattr(@input, Termios::TCSANOW, new_settings) - end - - def restore_mode - Termios.setattr(@input, Termios::TCSANOW, @state) - end - end - end -end \ No newline at end of file diff --git a/lib/highline/system_extensions/windows.rb b/lib/highline/system_extensions/windows.rb deleted file mode 100644 index 005045e..0000000 --- a/lib/highline/system_extensions/windows.rb +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env ruby -#coding: utf-8 - -class HighLine - module SystemExtensions - module Windows - CHARACTER_MODE = "Win32API" # For Debugging purposes only. - - # - # Windows savvy getc(). - # - # *WARNING*: This method ignores input and reads one - # character from +STDIN+! - # - def get_character( input = STDIN ) - WinAPI._getch - end - - # We do not define a raw_no_echo_mode for Windows as _getch turns off echo - def raw_no_echo_mode - end - - def restore_mode - end - - # A Windows savvy method to fetch the console columns, and rows. - def terminal_size - format = 'SSSSSssssSS' - buf = ([0] * format.size).pack(format) - stdout_handle = WinAPI.GetStdHandle(0xFFFFFFF5) - - WinAPI.GetConsoleScreenBufferInfo(stdout_handle, buf) - _, _, _, _, _, - left, top, right, bottom, _, _ = buf.unpack(format) - return right - left + 1, bottom - top + 1 - end - end - end -end diff --git a/lib/highline/system_extensions/windows_dl_import.rb b/lib/highline/system_extensions/windows_dl_import.rb deleted file mode 100644 index 597374e..0000000 --- a/lib/highline/system_extensions/windows_dl_import.rb +++ /dev/null @@ -1,35 +0,0 @@ -class HighLine - module SystemExtensions - module WindowsDlImport - require "dl/import" - - module WinAPI - if defined?(DL::Importer) - # Ruby 1.9 - extend DL::Importer - else - # Ruby 1.8 - extend DL::Importable - end - begin - dlload "msvcrt", "kernel32" - rescue DL::DLError - dlload "crtdll", "kernel32" - end - extern "unsigned long _getch()" - extern "unsigned long GetConsoleScreenBufferInfo(unsigned long, void*)" - extern "unsigned long GetStdHandle(unsigned long)" - - # Ruby 1.8 DL::Importable.import does mname[0,1].downcase so FooBar becomes fooBar - if defined?(getConsoleScreenBufferInfo) - alias_method :GetConsoleScreenBufferInfo, :getConsoleScreenBufferInfo - module_function :GetConsoleScreenBufferInfo - end - if defined?(getStdHandle) - alias_method :GetStdHandle, :getStdHandle - module_function :GetStdHandle - end - end - end - end -end diff --git a/lib/highline/system_extensions/windows_fiddle.rb b/lib/highline/system_extensions/windows_fiddle.rb deleted file mode 100644 index 8a2a4af..0000000 --- a/lib/highline/system_extensions/windows_fiddle.rb +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env ruby -#coding: utf-8 - -class HighLine - module SystemExtensions - module WindowsFiddle - require "fiddle" - - module WinAPI - include Fiddle - Handle = RUBY_VERSION >= "2.0.0" ? Fiddle::Handle : DL::Handle - Kernel32 = Handle.new("kernel32") - Crt = Handle.new("msvcrt") rescue Handle.new("crtdll") - - def self._getch - @@_m_getch ||= Function.new(Crt["_getch"], [], TYPE_INT) - @@_m_getch.call - end - - def self.GetStdHandle(handle_type) - @@get_std_handle ||= Function.new(Kernel32["GetStdHandle"], [-TYPE_INT], -TYPE_INT) - @@get_std_handle.call(handle_type) - end - - def self.GetConsoleScreenBufferInfo(cons_handle, lp_buffer) - @@get_console_screen_buffer_info ||= - Function.new(Kernel32["GetConsoleScreenBufferInfo"], [TYPE_LONG, TYPE_VOIDP], TYPE_INT) - @@get_console_screen_buffer_info.call(cons_handle, lp_buffer) - end - end - end - end -end \ No newline at end of file diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb new file mode 100755 index 0000000..c7422b3 --- /dev/null +++ b/lib/highline/terminal.rb @@ -0,0 +1,76 @@ +#!/usr/bin/env ruby +# coding: utf-8 + +# terminal.rb +# +# Originally created by James Edward Gray II on 2006-06-14 as +# system_extensions.rb. +# Copyright 2006 Gray Productions. All rights reserved. +# +# This is Free Software. See LICENSE and COPYING for details. + +require "highline/compatibility" + +class HighLine + class Terminal + def get_terminal + + JRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' + + if JRUBY + require 'highline/terminal/jruby' + return HighLine::Terminal::JRuby + end + + extend self + + # + # This section builds character reading and terminal size functions + # to suit the proper platform we're running on. Be warned: Here be + # dragons! + # + if RUBY_PLATFORM =~ /mswin(?!ce)|mingw|bccwin/i + begin + require 'highline/terminal/windows_fiddle' + return HighLine::Terminal::WindowsFiddle + rescue LoadError + require 'highline/terminal/windows_dl_import' + return HighLine::Terminal::WindowsDlImport + end + + require 'highline/terminal/windows' + return HighLine::Terminal::Windows + else # If we're not on Windows try... + begin + require 'highline/terminal/unix_termios' + return HighLine::Terminal::UnixTermios + rescue LoadError # If our first choice fails, try using JLine + if JRUBY # if we are on JRuby. JLine is bundled with JRuby. + require 'highline/terminal/jruby_jline' + return HighLine::Terminal::JRubyJLine + else # If we are not on JRuby, try ncurses + begin + require 'highline/terminal/ncurses' + return HighLine::Terminal::NCurses + rescue LoadError # Finally, if all else fails, use stty + require 'highline/terminal/stty' + return HighLine::Terminal::Stty + end + end + end + + # For termios and stty + if not method_defined?(:terminal_size) + require 'highline/terminal/unix_stty' + return HighLine::Terminal::UnixStty + end + end + + if not method_defined?(:get_character) + def get_character( input = STDIN ) + input.getbyte + end + end + end + end +end diff --git a/lib/highline/terminal/jruby.rb b/lib/highline/terminal/jruby.rb new file mode 100644 index 0000000..5e85024 --- /dev/null +++ b/lib/highline/terminal/jruby.rb @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby +#coding: utf-8 + +class HighLine + module SystemExtensions + module JRuby + def initialize_system_extensions + require 'java' + require 'readline' + if JRUBY_VERSION =~ /^1.7/ + java_import 'jline.console.ConsoleReader' + + input = @input && @input.to_inputstream + output = @output && @output.to_outputstream + + @java_console = ConsoleReader.new(input, output) + @java_console.set_history_enabled(false) + @java_console.set_bell_enabled(true) + @java_console.set_pagination_enabled(false) + @java_terminal = @java_console.getTerminal + elsif JRUBY_VERSION =~ /^1.6/ + java_import 'java.io.OutputStreamWriter' + java_import 'java.nio.channels.Channels' + java_import 'jline.ConsoleReader' + java_import 'jline.Terminal' + + @java_input = Channels.newInputStream(@input.to_channel) + @java_output = OutputStreamWriter.new(Channels.newOutputStream(@output.to_channel)) + @java_terminal = Terminal.getTerminal + @java_console = ConsoleReader.new(@java_input, @java_output) + @java_console.setUseHistory(false) + @java_console.setBellEnabled(true) + @java_console.setUsePagination(false) + end + end + end + end +end \ No newline at end of file diff --git a/lib/highline/terminal/jruby_jline.rb b/lib/highline/terminal/jruby_jline.rb new file mode 100644 index 0000000..8f3a590 --- /dev/null +++ b/lib/highline/terminal/jruby_jline.rb @@ -0,0 +1,24 @@ +class HighLine + module SystemExtensions + module JRubyJLine + CHARACTER_MODE = "jline" # For Debugging purposes only. + + def terminal_size + if JRUBY_VERSION =~ /^1.7/ + [ @java_terminal.get_width, @java_terminal.get_height ] + else + [ @java_terminal.getTerminalWidth, @java_terminal.getTerminalHeight ] + end + end + + def raw_no_echo_mode + @state = @java_console.getEchoCharacter + @java_console.setEchoCharacter 0 + end + + def restore_mode + @java_console.setEchoCharacter @state + end + end + end +end \ No newline at end of file diff --git a/lib/highline/terminal/ncurses.rb b/lib/highline/terminal/ncurses.rb new file mode 100644 index 0000000..8ac672f --- /dev/null +++ b/lib/highline/terminal/ncurses.rb @@ -0,0 +1,31 @@ +class HighLine + module SystemExtensions + module NCurses + require 'ffi-ncurses' + CHARACTER_MODE = "ncurses" # For Debugging purposes only. + + def raw_no_echo_mode + FFI::NCurses.initscr + FFI::NCurses.cbreak + end + + def restore_mode + FFI::NCurses.endwin + end + + # + # A ncurses savvy method to fetch the console columns, and rows. + # + def terminal_size + size = [80, 40] + FFI::NCurses.initscr + begin + size = FFI::NCurses.getmaxyx(FFI::NCurses.stdscr).reverse + ensure + FFI::NCurses.endwin + end + size + end + end + end +end \ No newline at end of file diff --git a/lib/highline/terminal/stty.rb b/lib/highline/terminal/stty.rb new file mode 100644 index 0000000..ecc039b --- /dev/null +++ b/lib/highline/terminal/stty.rb @@ -0,0 +1,17 @@ +class HighLine + module SystemExtensions + module Stty + # *WARNING*: This requires the external "stty" program! + CHARACTER_MODE = "stty" # For Debugging purposes only. + + def raw_no_echo_mode + @state = `stty -g` + system "stty raw -echo -icanon isig" + end + + def restore_mode + system "stty #{@state}" + end + end + end +end \ No newline at end of file diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb new file mode 100644 index 0000000..eecdba1 --- /dev/null +++ b/lib/highline/terminal/unix_stty.rb @@ -0,0 +1,25 @@ +class HighLine + module SystemExtensions + module UnixStty + # A Unix savvy method using stty to fetch the console columns, and rows. + # ... stty does not work in JRuby + def terminal_size + begin + require "io/console" + winsize = IO.console.winsize.reverse rescue nil + return winsize if winsize + rescue LoadError + end + + if /solaris/ =~ RUBY_PLATFORM and + `stty` =~ /\brows = (\d+).*\bcolumns = (\d+)/ + [$2, $1].map { |c| x.to_i } + elsif `stty size` =~ /^(\d+)\s(\d+)$/ + [$2.to_i, $1.to_i] + else + [ 80, 24 ] + end + end + end + end +end \ No newline at end of file diff --git a/lib/highline/terminal/unix_termios.rb b/lib/highline/terminal/unix_termios.rb new file mode 100644 index 0000000..5b285ff --- /dev/null +++ b/lib/highline/terminal/unix_termios.rb @@ -0,0 +1,21 @@ +class HighLine + module SystemExtensions + module UnixTermios + require "termios" # Unix, first choice termios. + + CHARACTER_MODE = "termios" # For Debugging purposes only. + + def raw_no_echo_mode + @state = Termios.getattr(@input) + new_settings = @state.dup + new_settings.c_lflag &= ~(Termios::ECHO | Termios::ICANON) + new_settings.c_cc[Termios::VMIN] = 1 + Termios.setattr(@input, Termios::TCSANOW, new_settings) + end + + def restore_mode + Termios.setattr(@input, Termios::TCSANOW, @state) + end + end + end +end \ No newline at end of file diff --git a/lib/highline/terminal/windows.rb b/lib/highline/terminal/windows.rb new file mode 100644 index 0000000..005045e --- /dev/null +++ b/lib/highline/terminal/windows.rb @@ -0,0 +1,39 @@ +#!/usr/bin/env ruby +#coding: utf-8 + +class HighLine + module SystemExtensions + module Windows + CHARACTER_MODE = "Win32API" # For Debugging purposes only. + + # + # Windows savvy getc(). + # + # *WARNING*: This method ignores input and reads one + # character from +STDIN+! + # + def get_character( input = STDIN ) + WinAPI._getch + end + + # We do not define a raw_no_echo_mode for Windows as _getch turns off echo + def raw_no_echo_mode + end + + def restore_mode + end + + # A Windows savvy method to fetch the console columns, and rows. + def terminal_size + format = 'SSSSSssssSS' + buf = ([0] * format.size).pack(format) + stdout_handle = WinAPI.GetStdHandle(0xFFFFFFF5) + + WinAPI.GetConsoleScreenBufferInfo(stdout_handle, buf) + _, _, _, _, _, + left, top, right, bottom, _, _ = buf.unpack(format) + return right - left + 1, bottom - top + 1 + end + end + end +end diff --git a/lib/highline/terminal/windows_dl_import.rb b/lib/highline/terminal/windows_dl_import.rb new file mode 100644 index 0000000..597374e --- /dev/null +++ b/lib/highline/terminal/windows_dl_import.rb @@ -0,0 +1,35 @@ +class HighLine + module SystemExtensions + module WindowsDlImport + require "dl/import" + + module WinAPI + if defined?(DL::Importer) + # Ruby 1.9 + extend DL::Importer + else + # Ruby 1.8 + extend DL::Importable + end + begin + dlload "msvcrt", "kernel32" + rescue DL::DLError + dlload "crtdll", "kernel32" + end + extern "unsigned long _getch()" + extern "unsigned long GetConsoleScreenBufferInfo(unsigned long, void*)" + extern "unsigned long GetStdHandle(unsigned long)" + + # Ruby 1.8 DL::Importable.import does mname[0,1].downcase so FooBar becomes fooBar + if defined?(getConsoleScreenBufferInfo) + alias_method :GetConsoleScreenBufferInfo, :getConsoleScreenBufferInfo + module_function :GetConsoleScreenBufferInfo + end + if defined?(getStdHandle) + alias_method :GetStdHandle, :getStdHandle + module_function :GetStdHandle + end + end + end + end +end diff --git a/lib/highline/terminal/windows_fiddle.rb b/lib/highline/terminal/windows_fiddle.rb new file mode 100644 index 0000000..8a2a4af --- /dev/null +++ b/lib/highline/terminal/windows_fiddle.rb @@ -0,0 +1,33 @@ +#!/usr/bin/env ruby +#coding: utf-8 + +class HighLine + module SystemExtensions + module WindowsFiddle + require "fiddle" + + module WinAPI + include Fiddle + Handle = RUBY_VERSION >= "2.0.0" ? Fiddle::Handle : DL::Handle + Kernel32 = Handle.new("kernel32") + Crt = Handle.new("msvcrt") rescue Handle.new("crtdll") + + def self._getch + @@_m_getch ||= Function.new(Crt["_getch"], [], TYPE_INT) + @@_m_getch.call + end + + def self.GetStdHandle(handle_type) + @@get_std_handle ||= Function.new(Kernel32["GetStdHandle"], [-TYPE_INT], -TYPE_INT) + @@get_std_handle.call(handle_type) + end + + def self.GetConsoleScreenBufferInfo(cons_handle, lp_buffer) + @@get_console_screen_buffer_info ||= + Function.new(Kernel32["GetConsoleScreenBufferInfo"], [TYPE_LONG, TYPE_VOIDP], TYPE_INT) + @@get_console_screen_buffer_info.call(cons_handle, lp_buffer) + end + end + end + end +end \ No newline at end of file -- cgit v1.2.1 From c63b55db00ba3266a8b71e013d93185e4acfc4b5 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 27 Apr 2015 00:14:12 -0300 Subject: Indent only --- lib/highline/terminal.rb | 92 ++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index c7422b3..b3a235a 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -15,62 +15,62 @@ class HighLine class Terminal def get_terminal - JRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' + JRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' - if JRUBY - require 'highline/terminal/jruby' - return HighLine::Terminal::JRuby - end + if JRUBY + require 'highline/terminal/jruby' + return HighLine::Terminal::JRuby + end - extend self + extend self - # - # This section builds character reading and terminal size functions - # to suit the proper platform we're running on. Be warned: Here be - # dragons! - # - if RUBY_PLATFORM =~ /mswin(?!ce)|mingw|bccwin/i - begin - require 'highline/terminal/windows_fiddle' - return HighLine::Terminal::WindowsFiddle - rescue LoadError - require 'highline/terminal/windows_dl_import' - return HighLine::Terminal::WindowsDlImport - end + # + # This section builds character reading and terminal size functions + # to suit the proper platform we're running on. Be warned: Here be + # dragons! + # + if RUBY_PLATFORM =~ /mswin(?!ce)|mingw|bccwin/i + begin + require 'highline/terminal/windows_fiddle' + return HighLine::Terminal::WindowsFiddle + rescue LoadError + require 'highline/terminal/windows_dl_import' + return HighLine::Terminal::WindowsDlImport + end - require 'highline/terminal/windows' - return HighLine::Terminal::Windows - else # If we're not on Windows try... - begin - require 'highline/terminal/unix_termios' - return HighLine::Terminal::UnixTermios - rescue LoadError # If our first choice fails, try using JLine - if JRUBY # if we are on JRuby. JLine is bundled with JRuby. - require 'highline/terminal/jruby_jline' - return HighLine::Terminal::JRubyJLine - else # If we are not on JRuby, try ncurses - begin - require 'highline/terminal/ncurses' - return HighLine::Terminal::NCurses - rescue LoadError # Finally, if all else fails, use stty - require 'highline/terminal/stty' - return HighLine::Terminal::Stty + require 'highline/terminal/windows' + return HighLine::Terminal::Windows + else # If we're not on Windows try... + begin + require 'highline/terminal/unix_termios' + return HighLine::Terminal::UnixTermios + rescue LoadError # If our first choice fails, try using JLine + if JRUBY # if we are on JRuby. JLine is bundled with JRuby. + require 'highline/terminal/jruby_jline' + return HighLine::Terminal::JRubyJLine + else # If we are not on JRuby, try ncurses + begin + require 'highline/terminal/ncurses' + return HighLine::Terminal::NCurses + rescue LoadError # Finally, if all else fails, use stty + require 'highline/terminal/stty' + return HighLine::Terminal::Stty + end end end - end - # For termios and stty - if not method_defined?(:terminal_size) - require 'highline/terminal/unix_stty' - return HighLine::Terminal::UnixStty + # For termios and stty + if not method_defined?(:terminal_size) + require 'highline/terminal/unix_stty' + return HighLine::Terminal::UnixStty + end end - end - if not method_defined?(:get_character) - def get_character( input = STDIN ) - input.getbyte + if not method_defined?(:get_character) + def get_character( input = STDIN ) + input.getbyte + end end end end - end end -- cgit v1.2.1 From c0bf2542f7abeeeb562ccd5f5a5c1e7f6eaa6f0c Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 27 Apr 2015 00:21:24 -0300 Subject: Scaffold HighLine::Terminal base class --- lib/highline/terminal.rb | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index b3a235a..bd65ec0 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -13,7 +13,36 @@ require "highline/compatibility" class HighLine class Terminal - def get_terminal + def self.get_terminal + require 'highline/terminal/unix_stty' + terminal = HighLine::Terminal::UnixStty.new + terminal.initialize_system_extensions + terminal + end + + def initialize_system_extensions + end + + def terminal_size + end + + def raw_no_echo_mode + end + + def restore_mode + end + + def get_character + end + end +end + +=begin + +# Meanwhile, we're concentratring on making a standard +# terminal to work using this new approach. +# +# We'll try to revive the code bellow as soon as possible. JRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' @@ -74,3 +103,4 @@ class HighLine end end end +=end -- cgit v1.2.1 From d8fc12d18fd5c1fe6b8f3720b54f793835576d66 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 27 Apr 2015 00:23:23 -0300 Subject: Change to UnixStty < Terminal --- lib/highline/terminal/unix_stty.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index eecdba1..04499f3 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -1,6 +1,6 @@ class HighLine - module SystemExtensions - module UnixStty + class Terminal::UnixStty < Terminal + # A Unix savvy method using stty to fetch the console columns, and rows. # ... stty does not work in JRuby def terminal_size @@ -20,6 +20,6 @@ class HighLine [ 80, 24 ] end end - end + end end \ No newline at end of file -- cgit v1.2.1 From 6975c875082bf7029ba41df939463448a9a0052e Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 27 Apr 2015 00:25:21 -0300 Subject: Add remaining methods to complete Terminal class --- lib/highline/terminal/unix_stty.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index 04499f3..5007e70 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -21,5 +21,20 @@ class HighLine end end + # *WARNING*: This requires the external "stty" program! + CHARACTER_MODE = "stty" # For Debugging purposes only. + + def raw_no_echo_mode + @state = `stty -g` + system "stty raw -echo -icanon isig" + end + + def restore_mode + system "stty #{@state}" + end + + def get_character( input = STDIN ) + input.getbyte + end end end \ No newline at end of file -- cgit v1.2.1 From 0d374b767fff71e1520df71bd8678857084e23d3 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 27 Apr 2015 00:25:44 -0300 Subject: Indent only --- lib/highline/terminal/unix_stty.rb | 58 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index 5007e70..ddac6f7 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -1,40 +1,40 @@ class HighLine class Terminal::UnixStty < Terminal - # A Unix savvy method using stty to fetch the console columns, and rows. - # ... stty does not work in JRuby - def terminal_size - begin - require "io/console" - winsize = IO.console.winsize.reverse rescue nil - return winsize if winsize - rescue LoadError - end + # A Unix savvy method using stty to fetch the console columns, and rows. + # ... stty does not work in JRuby + def terminal_size + begin + require "io/console" + winsize = IO.console.winsize.reverse rescue nil + return winsize if winsize + rescue LoadError + end - if /solaris/ =~ RUBY_PLATFORM and - `stty` =~ /\brows = (\d+).*\bcolumns = (\d+)/ - [$2, $1].map { |c| x.to_i } - elsif `stty size` =~ /^(\d+)\s(\d+)$/ - [$2.to_i, $1.to_i] - else - [ 80, 24 ] - end + if /solaris/ =~ RUBY_PLATFORM and + `stty` =~ /\brows = (\d+).*\bcolumns = (\d+)/ + [$2, $1].map { |c| x.to_i } + elsif `stty size` =~ /^(\d+)\s(\d+)$/ + [$2.to_i, $1.to_i] + else + [ 80, 24 ] end + end - # *WARNING*: This requires the external "stty" program! - CHARACTER_MODE = "stty" # For Debugging purposes only. + # *WARNING*: This requires the external "stty" program! + CHARACTER_MODE = "stty" # For Debugging purposes only. - def raw_no_echo_mode - @state = `stty -g` - system "stty raw -echo -icanon isig" - end + def raw_no_echo_mode + @state = `stty -g` + system "stty raw -echo -icanon isig" + end - def restore_mode - system "stty #{@state}" - end + def restore_mode + system "stty #{@state}" + end - def get_character( input = STDIN ) - input.getbyte - end + def get_character( input = STDIN ) + input.getbyte + end end end \ No newline at end of file -- cgit v1.2.1 From 7a5e4177b2a3f804b7afa08bf257734c2e2e5fae Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 27 Apr 2015 00:31:44 -0300 Subject: Use the new HighLine::Terminal class --- lib/highline.rb | 16 ++++++++-------- test/test_highline.rb | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index d62f102..09b9bd6 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -456,7 +456,7 @@ class HighLine # def output_cols return 80 unless @output.tty? - terminal_size.first + terminal.terminal_size.first rescue return 80 end @@ -467,7 +467,7 @@ class HighLine # def output_rows return 24 unless @output.tty? - terminal_size.last + terminal.terminal_size.last rescue return 24 end @@ -721,13 +721,13 @@ class HighLine if question.echo == true and question.limit.nil? get_line(question) else - raw_no_echo_mode + terminal.raw_no_echo_mode line = "".encode(Encoding::BINARY) backspace_limit = 0 begin - while character = get_character(@input) + while character = terminal.get_character(@input) # honor backspace and delete if character == 127 or character == 8 line = line.force_encoding(Encoding.default_external) @@ -768,7 +768,7 @@ class HighLine break if question.limit and line.size == question.limit end ensure - restore_mode + terminal.restore_mode end if question.overwrite @output.print("\r#{HighLine.Style(:erase_line).code}") @@ -784,12 +784,12 @@ class HighLine say question end - raw_no_echo_mode + terminal.raw_no_echo_mode begin if question.character == :getc response = @input.getbyte.chr else - response = get_character(@input).chr + response = terminal.get_character(@input).chr if question.overwrite @output.print("\r#{HighLine.Style(:erase_line).code}") @output.flush @@ -805,7 +805,7 @@ class HighLine end end ensure - restore_mode + terminal.restore_mode end question.change_case(response) end diff --git a/test/test_highline.rb b/test/test_highline.rb index d9cedd5..6ae499f 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -1158,8 +1158,8 @@ class TestHighLine < Minitest::Test end def test_terminal_size - assert_instance_of(Fixnum, @terminal.terminal_size[0]) - assert_instance_of(Fixnum, @terminal.terminal_size[1]) + assert_instance_of(Fixnum, @terminal.terminal.terminal_size[0]) + assert_instance_of(Fixnum, @terminal.terminal.terminal_size[1]) end def test_type_conversion -- cgit v1.2.1 From ac297adafde6dbc012e8a2140db2a8a86e06c86d Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 27 Apr 2015 00:45:12 -0300 Subject: Ask 'terminal' for jruby? status. Don't rely on Constants --- lib/highline.rb | 6 +++--- lib/highline/terminal.rb | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 09b9bd6..1a46875 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -508,7 +508,7 @@ class HighLine # the prompt will not be issued. And we have to account for that now. # Also, JRuby-1.7's ConsoleReader.readLine() needs to be passed the prompt # to handle line editing properly. - say(question) unless ((JRUBY or question.readline) and (question.echo == true and question.limit.nil?)) + say(question) unless ((terminal.jruby? or question.readline) and (question.echo == true and question.limit.nil?)) begin question.answer = question.answer_or_default(get_response(question)) @@ -689,7 +689,7 @@ class HighLine answer else - if JRUBY + if terminal.jruby? statement = Statement.new(question, self).to_s raw_answer = @java_console.readLine(statement, nil) @@ -780,7 +780,7 @@ class HighLine question.format_answer(line.force_encoding(Encoding.default_external)) end else - if JRUBY #prompt has not been shown + if terminal.jruby? #prompt has not been shown say question end diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index bd65ec0..14dfdfd 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -34,6 +34,10 @@ class HighLine def get_character end + + def jruby? + defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' + end end end -- cgit v1.2.1 From ebce6d9036d8427b5d65366c2311985909e89578 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 27 Apr 2015 00:45:54 -0300 Subject: Fix character_mode testing --- lib/highline/terminal/unix_stty.rb | 6 +++++- test/test_highline.rb | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index ddac6f7..7dc5ef6 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -22,7 +22,7 @@ class HighLine end # *WARNING*: This requires the external "stty" program! - CHARACTER_MODE = "stty" # For Debugging purposes only. + CHARACTER_MODE = "unix_stty" # For Debugging purposes only. def raw_no_echo_mode @state = `stty -g` @@ -36,5 +36,9 @@ class HighLine def get_character( input = STDIN ) input.getbyte end + + def character_mode + "unix_stty" + end end end \ No newline at end of file diff --git a/test/test_highline.rb b/test/test_highline.rb index 6ae499f..3c3e63f 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -16,6 +16,7 @@ require "readline" require "tempfile" require "test_helper" +=begin if HighLine::CHARACTER_MODE == "Win32API" class HighLine # Override Windows' character reading so it's not tied to STDIN. @@ -24,6 +25,7 @@ if HighLine::CHARACTER_MODE == "Win32API" end end end +=end class TestHighLine < Minitest::Test def setup @@ -866,8 +868,8 @@ class TestHighLine < Minitest::Test end def test_mode - assert(%w[Win32API termios ncurses stty jline].include?(HighLine::CHARACTER_MODE), - "#{HighLine::CHARACTER_MODE} not in list") + assert(%w[Win32API termios ncurses stty unix_stty jline].include?(@terminal.terminal.character_mode), + "#{@terminal.terminal.character_mode} not in list") end class NameClass -- cgit v1.2.1 From b39c6691f9d3085a31df5efe873533cb5fb366fe Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 3 May 2015 15:21:20 -0300 Subject: Add convenience #render_statement method --- lib/highline.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 1a46875..bc52e62 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -382,7 +382,7 @@ class HighLine # and the HighLine.color() method. # def say( statement ) - statement = Statement.new(statement, self).to_s + statement = render_statement(statement) return if statement.empty? out = (indentation+statement).encode(Encoding.default_external, { :undef => :replace } ) @@ -397,6 +397,10 @@ class HighLine end end + def render_statement(statement) + Statement.new(statement, self).to_s + end + # # Set to an integer value to cause HighLine to wrap output lines at the # indicated character limit. When +nil+, the default, no wrapping occurs. If @@ -690,7 +694,7 @@ class HighLine answer else if terminal.jruby? - statement = Statement.new(question, self).to_s + statement = render_statement(question) raw_answer = @java_console.readLine(statement, nil) raise EOFError, "The input stream is exhausted." if raw_answer.nil? and -- cgit v1.2.1 From 1430c99958a6ff2e0205d8efd9fd31da7c682bf2 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 3 May 2015 15:21:54 -0300 Subject: Simplify by directly rendering the statement --- lib/highline.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index bc52e62..4bea2ee 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -665,12 +665,7 @@ class HighLine if question.readline require "readline" # load only if needed - # capture say()'s work in a String to feed to readline() - old_output = @output - @output = StringIO.new - say(question) - question_string = @output.string - @output = old_output + question_string = render_statement(question) # prep auto-completion Readline.completion_proc = lambda do |string| -- cgit v1.2.1 From f483b89996db6119ec114bc40395e3418b5d2322 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 12 May 2015 23:06:37 -0300 Subject: Temporarily move the complete HighLine#get_line logic to HighLine::Terminal::UnixStty --- lib/highline.rb | 41 +----------------------------------- lib/highline/terminal/unix_stty.rb | 43 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 4bea2ee..09ae697 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -662,46 +662,7 @@ class HighLine # Raises EOFError if input is exhausted. # def get_line(question) - if question.readline - require "readline" # load only if needed - - question_string = render_statement(question) - - # prep auto-completion - Readline.completion_proc = lambda do |string| - question.selection.grep(/\A#{Regexp.escape(string)}/) - end - - # work-around ugly readline() warnings - old_verbose = $VERBOSE - $VERBOSE = nil - raw_answer = Readline.readline(question_string, true) - if raw_answer.nil? - if @@track_eof - raise EOFError, "The input stream is exhausted." - else - raw_answer = String.new # Never return nil - end - end - answer = question.format_answer(raw_answer) - $VERBOSE = old_verbose - - answer - else - if terminal.jruby? - statement = render_statement(question) - raw_answer = @java_console.readLine(statement, nil) - - raise EOFError, "The input stream is exhausted." if raw_answer.nil? and - @@track_eof - else - raise EOFError, "The input stream is exhausted." if @@track_eof and - @input.eof? - raw_answer = @input.gets - end - - question.format_answer(raw_answer) - end + terminal.get_line(question, self) end # diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index 7dc5ef6..da743fa 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -40,5 +40,48 @@ class HighLine def character_mode "unix_stty" end + + def get_line(question, highline, options={}) + if question.readline + require "readline" # load only if needed + + question_string = render_statement(question) + + # prep auto-completion + Readline.completion_proc = lambda do |string| + question.selection.grep(/\A#{Regexp.escape(string)}/) + end + + # work-around ugly readline() warnings + old_verbose = $VERBOSE + $VERBOSE = nil + raw_answer = Readline.readline(question_string, true) + if raw_answer.nil? + if @@track_eof + raise EOFError, "The input stream is exhausted." + else + raw_answer = String.new # Never return nil + end + end + answer = question.format_answer(raw_answer) + $VERBOSE = old_verbose + + answer + else + if terminal.jruby? + statement = render_statement(question) + raw_answer = @java_console.readLine(statement, nil) + + raise EOFError, "The input stream is exhausted." if raw_answer.nil? and + @@track_eof + else + raise EOFError, "The input stream is exhausted." if @@track_eof and + @input.eof? + raw_answer = @input.gets + end + + question.format_answer(raw_answer) + end + end end end \ No newline at end of file -- cgit v1.2.1 From 1d9fe0dd9fa73a426a5762cca87f402e90e85368 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 12 May 2015 23:07:28 -0300 Subject: Fix reference to terminal at HighLine::Terminal::UnixStty --- lib/highline/terminal/unix_stty.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index da743fa..1e1c7ae 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -68,7 +68,7 @@ class HighLine answer else - if terminal.jruby? + if highline.terminal.jruby? # This is "self" and will be removed soon. statement = render_statement(question) raw_answer = @java_console.readLine(statement, nil) -- cgit v1.2.1 From 3c4d00ea46b9dbc11a0d5582bf29cb4bd7bf5595 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 12 May 2015 23:11:11 -0300 Subject: Fix @@track_eof references on HighLine::Terminal::UnixStty --- lib/highline.rb | 4 ++++ lib/highline/terminal/unix_stty.rb | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 09ae697..2a492b1 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -71,6 +71,10 @@ class HighLine @@track_eof end + def track_eof? + self.class.track_eof? + end + # The setting used to control color schemes. @@color_scheme = nil diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index 1e1c7ae..fcaf8e7 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -57,7 +57,7 @@ class HighLine $VERBOSE = nil raw_answer = Readline.readline(question_string, true) if raw_answer.nil? - if @@track_eof + if highline.track_eof? raise EOFError, "The input stream is exhausted." else raw_answer = String.new # Never return nil @@ -73,9 +73,9 @@ class HighLine raw_answer = @java_console.readLine(statement, nil) raise EOFError, "The input stream is exhausted." if raw_answer.nil? and - @@track_eof + highline.track_eof? else - raise EOFError, "The input stream is exhausted." if @@track_eof and + raise EOFError, "The input stream is exhausted." if highline.track_eof? and @input.eof? raw_answer = @input.gets end -- cgit v1.2.1 From 625b05e7fc15e5349388d79a69bd8a0c0b69b87b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 12 May 2015 23:14:20 -0300 Subject: Fix #render_statement reference on HighLine::Terminal::UnixStty --- lib/highline/terminal/unix_stty.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index fcaf8e7..f2990a8 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -45,7 +45,7 @@ class HighLine if question.readline require "readline" # load only if needed - question_string = render_statement(question) + question_string = highline.render_statement(question) # prep auto-completion Readline.completion_proc = lambda do |string| @@ -69,7 +69,7 @@ class HighLine answer else if highline.terminal.jruby? # This is "self" and will be removed soon. - statement = render_statement(question) + statement = highline.render_statement(question) raw_answer = @java_console.readLine(statement, nil) raise EOFError, "The input stream is exhausted." if raw_answer.nil? and -- cgit v1.2.1 From d3289050bea14b85068abc7b01034e6379faa722 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 12 May 2015 23:22:52 -0300 Subject: Fix input references on HighLine::Terminal:UnixStty --- lib/highline/terminal/unix_stty.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index f2990a8..0eaf7ef 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -76,8 +76,8 @@ class HighLine highline.track_eof? else raise EOFError, "The input stream is exhausted." if highline.track_eof? and - @input.eof? - raw_answer = @input.gets + highline.input.eof? + raw_answer = highline.input.gets end question.format_answer(raw_answer) -- cgit v1.2.1 From 9de196a4b20da19b9cae819b330893e38b2c7fe0 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 12 May 2015 23:33:48 -0300 Subject: Remove JRuby specific code from HighLine::Terminal::UnixStty --- lib/highline/terminal/jruby_jline.rb | 9 +++++++++ lib/highline/terminal/unix_stty.rb | 15 +++------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/highline/terminal/jruby_jline.rb b/lib/highline/terminal/jruby_jline.rb index 8f3a590..a0d48c3 100644 --- a/lib/highline/terminal/jruby_jline.rb +++ b/lib/highline/terminal/jruby_jline.rb @@ -19,6 +19,15 @@ class HighLine def restore_mode @java_console.setEchoCharacter @state end + + # Saving this legacy JRuby code for future reference + def get_line(question, highline, options={}) + statement = highline.render_statement(question) + raw_answer = @java_console.readLine(statement, nil) + + raise EOFError, "The input stream is exhausted." if raw_answer.nil? and + highline.track_eof? + end end end end \ No newline at end of file diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index 0eaf7ef..9c81375 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -68,18 +68,9 @@ class HighLine answer else - if highline.terminal.jruby? # This is "self" and will be removed soon. - statement = highline.render_statement(question) - raw_answer = @java_console.readLine(statement, nil) - - raise EOFError, "The input stream is exhausted." if raw_answer.nil? and - highline.track_eof? - else - raise EOFError, "The input stream is exhausted." if highline.track_eof? and - highline.input.eof? - raw_answer = highline.input.gets - end - + raise EOFError, "The input stream is exhausted." if highline.track_eof? and + highline.input.eof? + raw_answer = highline.input.gets question.format_answer(raw_answer) end end -- cgit v1.2.1 From fbc711c42be2159c72e1b0ce28cd09d64bd5b369 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 12 May 2015 23:35:44 -0300 Subject: Cut off small repetition on HighLine::Terminal::UnixStty --- lib/highline/terminal/unix_stty.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index 9c81375..f2a63ac 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -63,16 +63,14 @@ class HighLine raw_answer = String.new # Never return nil end end - answer = question.format_answer(raw_answer) $VERBOSE = old_verbose - - answer else raise EOFError, "The input stream is exhausted." if highline.track_eof? and highline.input.eof? raw_answer = highline.input.gets - question.format_answer(raw_answer) end + + question.format_answer(raw_answer) end end end \ No newline at end of file -- cgit v1.2.1 From cafc2201d8091f771789a9c6ff04acc8b226fa00 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 13 May 2015 00:39:24 -0300 Subject: Split Terminal::UnixStty#get_line in #get_line_default and #get_line_with_readline --- lib/highline/terminal/unix_stty.rb | 55 +++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index f2a63ac..fa2b8f1 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -42,35 +42,46 @@ class HighLine end def get_line(question, highline, options={}) + raw_answer = if question.readline - require "readline" # load only if needed + get_line_with_readline(question, highline, options={}) + else + get_line_default(highline) + end - question_string = highline.render_statement(question) + question.format_answer(raw_answer) + end - # prep auto-completion - Readline.completion_proc = lambda do |string| - question.selection.grep(/\A#{Regexp.escape(string)}/) - end + def get_line_with_readline(question, highline, options={}) + require "readline" # load only if needed + + question_string = highline.render_statement(question) + + # prep auto-completion + Readline.completion_proc = lambda do |string| + question.selection.grep(/\A#{Regexp.escape(string)}/) + end - # work-around ugly readline() warnings - old_verbose = $VERBOSE - $VERBOSE = nil - raw_answer = Readline.readline(question_string, true) - if raw_answer.nil? - if highline.track_eof? - raise EOFError, "The input stream is exhausted." - else - raw_answer = String.new # Never return nil - end + # work-around ugly readline() warnings + old_verbose = $VERBOSE + $VERBOSE = nil + raw_answer = Readline.readline(question_string, true) + if raw_answer.nil? + if highline.track_eof? + raise EOFError, "The input stream is exhausted." + else + raw_answer = String.new # Never return nil end - $VERBOSE = old_verbose - else - raise EOFError, "The input stream is exhausted." if highline.track_eof? and - highline.input.eof? - raw_answer = highline.input.gets end + $VERBOSE = old_verbose - question.format_answer(raw_answer) + raw_answer + end + + def get_line_default(highline) + raise EOFError, "The input stream is exhausted." if highline.track_eof? and + highline.input.eof? + highline.input.gets end end end \ No newline at end of file -- cgit v1.2.1 From b279e916847b8b8326ebd441a1612e839b501de1 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 13 May 2015 00:44:17 -0300 Subject: Extract Terminal::UnixStty#readline_read --- lib/highline/terminal/unix_stty.rb | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index fa2b8f1..9a9dea4 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -57,15 +57,8 @@ class HighLine question_string = highline.render_statement(question) - # prep auto-completion - Readline.completion_proc = lambda do |string| - question.selection.grep(/\A#{Regexp.escape(string)}/) - end + raw_answer = readline_read(question_string, question) - # work-around ugly readline() warnings - old_verbose = $VERBOSE - $VERBOSE = nil - raw_answer = Readline.readline(question_string, true) if raw_answer.nil? if highline.track_eof? raise EOFError, "The input stream is exhausted." @@ -73,6 +66,21 @@ class HighLine raw_answer = String.new # Never return nil end end + + raw_answer + end + + def readline_read(string, question) + # prep auto-completion + Readline.completion_proc = lambda do |string| + question.selection.grep(/\A#{Regexp.escape(string)}/) + end + + # work-around ugly readline() warnings + old_verbose = $VERBOSE + $VERBOSE = nil + raw_answer = Readline.readline(string, true) + $VERBOSE = old_verbose raw_answer -- cgit v1.2.1 From 085efbda87572ae1238a137faa47789089293aac Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 13 May 2015 00:46:05 -0300 Subject: Simplify conditionals in Terminal::UnixStty --- lib/highline/terminal/unix_stty.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index 9a9dea4..00bb60f 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -59,15 +59,11 @@ class HighLine raw_answer = readline_read(question_string, question) - if raw_answer.nil? - if highline.track_eof? - raise EOFError, "The input stream is exhausted." - else - raw_answer = String.new # Never return nil - end + if raw_answer.nil? and highline.track_eof? + raise EOFError, "The input stream is exhausted." end - raw_answer + raw_answer || "" end def readline_read(string, question) -- cgit v1.2.1 From fdc19a66d2c99ba0016c5b7139b84d136e439573 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 18 May 2015 21:22:19 -0300 Subject: Split HighLine#get_response in #get_response_character_mode and #get_response_line_mode --- lib/highline.rb | 153 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 80 insertions(+), 73 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 2a492b1..9367f89 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -681,98 +681,105 @@ class HighLine def get_response(question) return question.first_answer if question.first_answer? - if question.character.nil? - if question.echo == true and question.limit.nil? - get_line(question) - else - terminal.raw_no_echo_mode + if question.character + get_response_character_mode(question) + else + get_response_line_mode(question) + end + end - line = "".encode(Encoding::BINARY) - backspace_limit = 0 - begin + def get_response_line_mode(question) + if question.echo == true and question.limit.nil? + get_line(question) + else + terminal.raw_no_echo_mode - while character = terminal.get_character(@input) - # honor backspace and delete + line = "".encode(Encoding::BINARY) + backspace_limit = 0 + begin + while character = terminal.get_character(@input) + # honor backspace and delete + if character == 127 or character == 8 + line = line.force_encoding(Encoding.default_external) + line.slice!(-1, 1) + backspace_limit -= 1 + line = line.force_encoding(Encoding::BINARY) + else + line << character.chr + backspace_limit = line.dup.force_encoding(Encoding.default_external).size + end + # looking for carriage return (decimal 13) or + # newline (decimal 10) in raw input + break if character == 13 or character == 10 + if question.echo != false if character == 127 or character == 8 - line = line.force_encoding(Encoding.default_external) - line.slice!(-1, 1) - backspace_limit -= 1 - line = line.force_encoding(Encoding::BINARY) + # only backspace if we have characters on the line to + # eliminate, otherwise we'll tromp over the prompt + if backspace_limit >= 0 then + @output.print("\b#{HighLine.Style(:erase_char).code}") + else + # do nothing + end else - line << character.chr - backspace_limit = line.dup.force_encoding(Encoding.default_external).size - end - # looking for carriage return (decimal 13) or - # newline (decimal 10) in raw input - break if character == 13 or character == 10 - if question.echo != false - if character == 127 or character == 8 - # only backspace if we have characters on the line to - # eliminate, otherwise we'll tromp over the prompt - if backspace_limit >= 0 then - @output.print("\b#{HighLine.Style(:erase_char).code}") + line_with_next_char_encoded = line.dup.force_encoding(Encoding.default_external) + # For multi-byte character, does this + # last character completes the character? + # Then print it. + if line_with_next_char_encoded.valid_encoding? + if question.echo == true + @output.print(line_with_next_char_encoded[-1]) else - # do nothing - end - else - line_with_next_char_encoded = line.dup.force_encoding(Encoding.default_external) - # For multi-byte character, does this - # last character completes the character? - # Then print it. - if line_with_next_char_encoded.valid_encoding? - if question.echo == true - @output.print(line_with_next_char_encoded[-1]) - else - @output.print(question.echo) - end + @output.print(question.echo) end end - @output.flush end - break if question.limit and line.size == question.limit + @output.flush end - ensure - terminal.restore_mode + break if question.limit and line.size == question.limit end - if question.overwrite - @output.print("\r#{HighLine.Style(:erase_line).code}") - @output.flush - else - say("\n") - end - - question.format_answer(line.force_encoding(Encoding.default_external)) + ensure + terminal.restore_mode end - else - if terminal.jruby? #prompt has not been shown - say question + if question.overwrite + @output.print("\r#{HighLine.Style(:erase_line).code}") + @output.flush + else + say("\n") end - terminal.raw_no_echo_mode - begin - if question.character == :getc - response = @input.getbyte.chr + question.format_answer(line.force_encoding(Encoding.default_external)) + end + end + + def get_response_character_mode(question) + if terminal.jruby? #prompt has not been shown + say question + end + + terminal.raw_no_echo_mode + begin + if question.character == :getc + response = @input.getbyte.chr + else + response = terminal.get_character(@input).chr + if question.overwrite + @output.print("\r#{HighLine.Style(:erase_line).code}") + @output.flush else - response = terminal.get_character(@input).chr - if question.overwrite - @output.print("\r#{HighLine.Style(:erase_line).code}") - @output.flush + echo = if question.echo == true + response + elsif question.echo != false + question.echo else - echo = if question.echo == true - response - elsif question.echo != false - question.echo - else - "" - end - say("#{echo}\n") + "" end + say("#{echo}\n") end - ensure - terminal.restore_mode end - question.change_case(response) + ensure + terminal.restore_mode end + question.change_case(response) end def actual_length(text) -- cgit v1.2.1 From cccfc2a357cae05c4e988f5402a066198049c075 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 18 May 2015 21:25:11 -0300 Subject: Move HighLine#get_response to Question#get_response Try to invert dependency --- lib/highline.rb | 8 +------- lib/highline/question.rb | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 9367f89..eca6cde 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -679,13 +679,7 @@ class HighLine # Raises EOFError if input is exhausted. # def get_response(question) - return question.first_answer if question.first_answer? - - if question.character - get_response_character_mode(question) - else - get_response_line_mode(question) - end + question.get_response(self) end def get_response_line_mode(question) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index ebb9649..b678d58 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -463,6 +463,25 @@ class HighLine (@validate.is_a?(Proc) and @validate[answer_string]) end + # + # Return a line or character of input, as requested for this question. + # Character input will be returned as a single character String, + # not an Integer. + # + # This question's _first_answer_ will be returned instead of input, if set. + # + # Raises EOFError if input is exhausted. + # + def get_response(question) + return question.first_answer if question.first_answer? + + if question.character + get_response_character_mode(question) + else + get_response_line_mode(question) + end + end + private # -- cgit v1.2.1 From 20eea1381470d81f49cc1c4d2db1b2f2725c62e0 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 18 May 2015 21:27:34 -0300 Subject: Fix Question#get_response references --- lib/highline.rb | 4 +++- lib/highline/question.rb | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index eca6cde..5d93486 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -519,7 +519,7 @@ class HighLine say(question) unless ((terminal.jruby? or question.readline) and (question.echo == true and question.limit.nil?)) begin - question.answer = question.answer_or_default(get_response(question)) + question.answer = question.answer_or_default(question.get_response(self)) unless question.valid_answer?(question.answer) explain_error(:not_valid, question) raise QuestionError @@ -776,6 +776,8 @@ class HighLine question.change_case(response) end + public :get_response_character_mode, :get_response_line_mode + def actual_length(text) Wrapper.actual_length text end diff --git a/lib/highline/question.rb b/lib/highline/question.rb index b678d58..880794d 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -472,13 +472,13 @@ class HighLine # # Raises EOFError if input is exhausted. # - def get_response(question) - return question.first_answer if question.first_answer? + def get_response(highline) + return first_answer if first_answer? - if question.character - get_response_character_mode(question) + if character + highline.get_response_character_mode(self) else - get_response_line_mode(question) + highline.get_response_line_mode(self) end end -- cgit v1.2.1 From afbcef372060082b3f351cbceae210c4381915a8 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 18 May 2015 15:14:29 -0300 Subject: Add a TODO note. Remove ArgumentError and NameError rescue and retry. --- lib/highline.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/highline.rb b/lib/highline.rb index 5d93486..4c05f20 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -552,6 +552,12 @@ class HighLine end rescue QuestionError retry + + # TODO: So we don't forget it!!! + # This is a HUGE source of error mask + # It's hiding errors deep in the code + # It rescues and retries + # We gotta remove it soon rescue ArgumentError, NameError => error raise if error.is_a?(NoMethodError) if error.message =~ /ambiguous/ -- cgit v1.2.1 From 1d8af36fdbe913201fe41267689ea1f7167dbc5b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 18 May 2015 21:50:12 -0300 Subject: Remove deprecated HighLine#get_response --- lib/highline.rb | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 4c05f20..8af3622 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -675,18 +675,6 @@ class HighLine terminal.get_line(question, self) end - # - # Return a line or character of input, as requested for this question. - # Character input will be returned as a single character String, - # not an Integer. - # - # This question's _first_answer_ will be returned instead of input, if set. - # - # Raises EOFError if input is exhausted. - # - def get_response(question) - question.get_response(self) - end def get_response_line_mode(question) if question.echo == true and question.limit.nil? -- cgit v1.2.1 From 4f455141f8c531649e0140dde9434580f566b565 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 18 May 2015 22:06:01 -0300 Subject: Make the rescue clause a little more specific. Don't hide errors! The rescue for invalid type was made a little more specific. So, when we have another kind of error, it don't just rescue and retry infinitely. Damage controlled meantime! TODO: Work on this later to improve it. --- lib/highline.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 8af3622..1ccc758 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -558,6 +558,10 @@ class HighLine # It's hiding errors deep in the code # It rescues and retries # We gotta remove it soon + # + # UPDATE: The rescue for invalid type + # was made a little more specific. + # Damage controlled meantime! rescue ArgumentError, NameError => error raise if error.is_a?(NoMethodError) if error.message =~ /ambiguous/ @@ -565,10 +569,13 @@ class HighLine # (used for ambiguity resolution) throws exceptions containing # the word 'ambiguous' whenever resolution fails explain_error(:ambiguous_completion, question) - else + retry + elsif error.is_a? ArgumentError and error.message =~ /invalid value for/ explain_error(:invalid_type, question) + retry + else + raise end - retry rescue Question::NoAutoCompleteMatch explain_error(:no_completion, question) retry @@ -675,7 +682,6 @@ class HighLine terminal.get_line(question, self) end - def get_response_line_mode(question) if question.echo == true and question.limit.nil? get_line(question) -- cgit v1.2.1 From 19de6eadc4687dfa0988a02c7b7537439f0e61c7 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 19 May 2015 22:45:07 -0300 Subject: Extract Question#ask_at --- lib/highline.rb | 7 +++++-- lib/highline/question.rb | 5 +++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 1ccc758..860315a 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -279,8 +279,7 @@ class HighLine @question = Question.new(template_or_question, answer_type, &details) end - return gather(question) if question.gather - return ask_once(question) + return question.ask_at(self) end # @@ -583,6 +582,8 @@ class HighLine question.answer end + public :ask_once + # # Collects an Array/Hash full of answers as described in # HighLine::Question.gather(). @@ -617,6 +618,8 @@ class HighLine question.verify_match ? last_answer(answers) : answers end + public :gather + def gather_integer(question) answers = [] diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 880794d..9d7992f 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -482,6 +482,11 @@ class HighLine end end + def ask_at(highline) + return highline.gather(self) if gather + return highline.ask_once(self) + end + private # -- cgit v1.2.1 From 3b78aeaa0e324ee0ea56cf6b923476fa5a42e830 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 19 May 2015 22:46:04 -0300 Subject: Extract Question#get_echo --- lib/highline.rb | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 860315a..f3dbade 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -763,13 +763,7 @@ class HighLine @output.print("\r#{HighLine.Style(:erase_line).code}") @output.flush else - echo = if question.echo == true - response - elsif question.echo != false - question.echo - else - "" - end + echo = get_echo(question, response) say("#{echo}\n") end end @@ -779,6 +773,16 @@ class HighLine question.change_case(response) end + def get_echo(question, response) + if question.echo == true + response + elsif question.echo != false + question.echo + else + "" + end + end + public :get_response_character_mode, :get_response_line_mode def actual_length(text) -- cgit v1.2.1 From 37030873e4c7b7cafa17904c182b850c8d628ec7 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 19 May 2015 22:58:48 -0300 Subject: Remove jruby conditionals --- lib/highline.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index f3dbade..73f1685 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -515,7 +515,7 @@ class HighLine # the prompt will not be issued. And we have to account for that now. # Also, JRuby-1.7's ConsoleReader.readLine() needs to be passed the prompt # to handle line editing properly. - say(question) unless ((terminal.jruby? or question.readline) and (question.echo == true and question.limit.nil?)) + say(question) unless ((question.readline) and (question.echo == true and question.limit.nil?)) begin question.answer = question.answer_or_default(question.get_response(self)) @@ -749,10 +749,6 @@ class HighLine end def get_response_character_mode(question) - if terminal.jruby? #prompt has not been shown - say question - end - terminal.raw_no_echo_mode begin if question.character == :getc -- cgit v1.2.1 From 5ce99662840ae748884be6253cb92bc51000c04f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 19 May 2015 23:23:30 -0300 Subject: Unify answer formatting --- lib/highline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline.rb b/lib/highline.rb index 73f1685..e74da67 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -766,7 +766,7 @@ class HighLine ensure terminal.restore_mode end - question.change_case(response) + question.format_answer(response) end def get_echo(question, response) -- cgit v1.2.1 From 03f730d5b54e86e395b202dc8141da5b3cadee1c Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 19 May 2015 23:37:37 -0300 Subject: Extract HighLine#get_response_getc_mode --- lib/highline.rb | 22 ++++++++++++---------- lib/highline/question.rb | 5 ++++- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index e74da67..50170f4 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -748,20 +748,21 @@ class HighLine end end + def get_response_getc_mode(question) + response = @input.getbyte.chr + question.format_answer(response) + end + def get_response_character_mode(question) terminal.raw_no_echo_mode begin - if question.character == :getc - response = @input.getbyte.chr + response = terminal.get_character(@input).chr + if question.overwrite + @output.print("\r#{HighLine.Style(:erase_line).code}") + @output.flush else - response = terminal.get_character(@input).chr - if question.overwrite - @output.print("\r#{HighLine.Style(:erase_line).code}") - @output.flush - else - echo = get_echo(question, response) - say("#{echo}\n") - end + echo = get_echo(question, response) + say("#{echo}\n") end ensure terminal.restore_mode @@ -780,6 +781,7 @@ class HighLine end public :get_response_character_mode, :get_response_line_mode + public :get_response_getc_mode def actual_length(text) Wrapper.actual_length text diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 9d7992f..673d139 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -475,7 +475,10 @@ class HighLine def get_response(highline) return first_answer if first_answer? - if character + case character + when :getc + highline.get_response_getc_mode(self) + when true highline.get_response_character_mode(self) else highline.get_response_line_mode(self) -- cgit v1.2.1 From 0314f13764ca31916e83a75fb2a571f05f432c68 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 19 May 2015 23:40:38 -0300 Subject: Extract (unifying) HighLine#raw_no_echo_mode_exec --- lib/highline.rb | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 50170f4..2580c7b 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -748,14 +748,24 @@ class HighLine end end + def raw_no_echo_mode_exec + terminal.raw_no_echo_mode + begin + yield + ensure + terminal.restore_mode + end + end + def get_response_getc_mode(question) - response = @input.getbyte.chr - question.format_answer(response) + raw_no_echo_mode_exec do + response = @input.getbyte.chr + question.format_answer(response) + end end def get_response_character_mode(question) - terminal.raw_no_echo_mode - begin + raw_no_echo_mode_exec do response = terminal.get_character(@input).chr if question.overwrite @output.print("\r#{HighLine.Style(:erase_line).code}") @@ -764,10 +774,8 @@ class HighLine echo = get_echo(question, response) say("#{echo}\n") end - ensure - terminal.restore_mode + question.format_answer(response) end - question.format_answer(response) end def get_echo(question, response) -- cgit v1.2.1 From 2bbc051a5c908d947d5f22a1d4a0e92eaacbd0bb Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 19 May 2015 23:45:56 -0300 Subject: Move #raw_no_echo_mode_exec from HighLine to Terminal I think the "knowledge" about how to exec a block in raw no echo mode should be contained in the HighLine::Terminal itself. (It doesn't depend on anything outside that class!) With the help of the recent commit, we could move it to there in this step. --- lib/highline.rb | 21 +++++---------------- lib/highline/terminal.rb | 9 +++++++++ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 2580c7b..fb25396 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -689,11 +689,10 @@ class HighLine if question.echo == true and question.limit.nil? get_line(question) else - terminal.raw_no_echo_mode - line = "".encode(Encoding::BINARY) backspace_limit = 0 - begin + + terminal.raw_no_echo_mode_exec do while character = terminal.get_character(@input) # honor backspace and delete if character == 127 or character == 8 @@ -734,9 +733,8 @@ class HighLine end break if question.limit and line.size == question.limit end - ensure - terminal.restore_mode end + if question.overwrite @output.print("\r#{HighLine.Style(:erase_line).code}") @output.flush @@ -748,24 +746,15 @@ class HighLine end end - def raw_no_echo_mode_exec - terminal.raw_no_echo_mode - begin - yield - ensure - terminal.restore_mode - end - end - def get_response_getc_mode(question) - raw_no_echo_mode_exec do + terminal.raw_no_echo_mode_exec do response = @input.getbyte.chr question.format_answer(response) end end def get_response_character_mode(question) - raw_no_echo_mode_exec do + terminal.raw_no_echo_mode_exec do response = terminal.get_character(@input).chr if question.overwrite @output.print("\r#{HighLine.Style(:erase_line).code}") diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index 14dfdfd..aef6ad2 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -29,6 +29,15 @@ class HighLine def raw_no_echo_mode end + def raw_no_echo_mode_exec + raw_no_echo_mode + begin + yield + ensure + restore_mode + end + end + def restore_mode end -- cgit v1.2.1 From 34dc2c64f0ceadaa4bfe6dde8bae1bac18ca346e Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 20 May 2015 00:01:47 -0300 Subject: Extract HighLine#erase_current_line --- lib/highline.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index fb25396..dad66dd 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -757,8 +757,7 @@ class HighLine terminal.raw_no_echo_mode_exec do response = terminal.get_character(@input).chr if question.overwrite - @output.print("\r#{HighLine.Style(:erase_line).code}") - @output.flush + erase_current_line else echo = get_echo(question, response) say("#{echo}\n") @@ -767,6 +766,11 @@ class HighLine end end + def erase_current_line + @output.print("\r#{HighLine.Style(:erase_line).code}") + @output.flush + end + def get_echo(question, response) if question.echo == true response -- cgit v1.2.1 From 63a90463bf3b5bcc12f1c4cfe57b7d69c1adb46e Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 24 May 2015 00:37:55 -0300 Subject: Change getbyte -> getc and easy all encoding issues There was a lot of encoding handling because of compatibility with old Ruby versions. Using getc handles the multibyte chars correctly (with current Ruby versions) and make us be able to drop all the encoding handling. --- lib/highline.rb | 36 ++++++++++++++---------------------- lib/highline/statement.rb | 4 ---- lib/highline/terminal/unix_stty.rb | 2 +- 3 files changed, 15 insertions(+), 27 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index dad66dd..9adcdde 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -388,7 +388,7 @@ class HighLine statement = render_statement(statement) return if statement.empty? - out = (indentation+statement).encode(Encoding.default_external, { :undef => :replace } ) + out = (indentation+statement) # Don't add a newline if statement ends with whitespace, OR # if statement ends with whitespace before a color escape code. @@ -689,26 +689,24 @@ class HighLine if question.echo == true and question.limit.nil? get_line(question) else - line = "".encode(Encoding::BINARY) + line = "" backspace_limit = 0 terminal.raw_no_echo_mode_exec do while character = terminal.get_character(@input) # honor backspace and delete - if character == 127 or character == 8 - line = line.force_encoding(Encoding.default_external) + if character == "\b" line.slice!(-1, 1) backspace_limit -= 1 - line = line.force_encoding(Encoding::BINARY) else - line << character.chr - backspace_limit = line.dup.force_encoding(Encoding.default_external).size + line << character + backspace_limit = line.size end # looking for carriage return (decimal 13) or # newline (decimal 10) in raw input - break if character == 13 or character == 10 + break if character == "\n" or character == "\r" if question.echo != false - if character == 127 or character == 8 + if character == "\b" # only backspace if we have characters on the line to # eliminate, otherwise we'll tromp over the prompt if backspace_limit >= 0 then @@ -717,16 +715,10 @@ class HighLine # do nothing end else - line_with_next_char_encoded = line.dup.force_encoding(Encoding.default_external) - # For multi-byte character, does this - # last character completes the character? - # Then print it. - if line_with_next_char_encoded.valid_encoding? - if question.echo == true - @output.print(line_with_next_char_encoded[-1]) - else - @output.print(question.echo) - end + if question.echo == true + @output.print(line[-1]) + else + @output.print(question.echo) end end @output.flush @@ -742,20 +734,20 @@ class HighLine say("\n") end - question.format_answer(line.force_encoding(Encoding.default_external)) + question.format_answer(line) end end def get_response_getc_mode(question) terminal.raw_no_echo_mode_exec do - response = @input.getbyte.chr + response = @input.getc question.format_answer(response) end end def get_response_character_mode(question) terminal.raw_no_echo_mode_exec do - response = terminal.get_character(@input).chr + response = terminal.get_character(@input) if question.overwrite erase_current_line else diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 0c260be..4d386d3 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -37,10 +37,6 @@ class HighLine::Statement statement = HighLine::Wrapper.wrap(statement, highline.wrap_at) statement = HighLine::Paginator.new(highline).page_print(statement) - # 'statement' is encoded in US-ASCII when using ruby 1.9.3(-p551) - # 'indentation' is correctly encoded (same as default_external encoding) - statement = statement.force_encoding(Encoding.default_external) - statement = statement.gsub(/\n(?!$)/,"\n#{highline.indentation}") if highline.multi_indent statement end diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index 00bb60f..1a3501d 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -34,7 +34,7 @@ class HighLine end def get_character( input = STDIN ) - input.getbyte + input.getc end def character_mode -- cgit v1.2.1 From 97c0bec2158f083d41bf692bc33c896603f45fcb Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 24 May 2015 08:59:34 -0300 Subject: Change String#slice!(-1, 1) to a more native way - String#chop! --- lib/highline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline.rb b/lib/highline.rb index 9adcdde..85d43bb 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -696,7 +696,7 @@ class HighLine while character = terminal.get_character(@input) # honor backspace and delete if character == "\b" - line.slice!(-1, 1) + line.chop! backspace_limit -= 1 else line << character -- cgit v1.2.1 From 9351eaefe67c6176cb9b5a0df996988bf6655e41 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 24 May 2015 11:02:07 -0300 Subject: Extract HighLine#output_erase_char --- lib/highline.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/highline.rb b/lib/highline.rb index 85d43bb..5ff9de9 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -710,7 +710,7 @@ class HighLine # only backspace if we have characters on the line to # eliminate, otherwise we'll tromp over the prompt if backspace_limit >= 0 then - @output.print("\b#{HighLine.Style(:erase_char).code}") + output_erase_char else # do nothing end @@ -738,6 +738,10 @@ class HighLine end end + def output_erase_char + @output.print("\b#{HighLine.Style(:erase_char).code}") + end + def get_response_getc_mode(question) terminal.raw_no_echo_mode_exec do response = @input.getc -- cgit v1.2.1 From f8ce3e971b34e2ab5db66db0a05e3869281b2c10 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 24 May 2015 11:08:19 -0300 Subject: Remove backspace_limit tracking need Put the "echoing" with "chopping" altogether and remove the need for tracking a backspace_limit --- lib/highline.rb | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 5ff9de9..b7f0d86 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -690,30 +690,22 @@ class HighLine get_line(question) else line = "" - backspace_limit = 0 terminal.raw_no_echo_mode_exec do while character = terminal.get_character(@input) # honor backspace and delete if character == "\b" - line.chop! - backspace_limit -= 1 + chopped = line.chop! + output_erase_char if chopped and question.echo else line << character - backspace_limit = line.size end # looking for carriage return (decimal 13) or # newline (decimal 10) in raw input break if character == "\n" or character == "\r" if question.echo != false if character == "\b" - # only backspace if we have characters on the line to - # eliminate, otherwise we'll tromp over the prompt - if backspace_limit >= 0 then - output_erase_char - else - # do nothing - end + # Do nothing - zombie code TODO: Remove it else if question.echo == true @output.print(line[-1]) -- cgit v1.2.1 From fbfd29f5175caac64e5c215d099c5f6a7446c496 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 24 May 2015 11:31:05 -0300 Subject: Aggregate code and simplify conditionals --- lib/highline.rb | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index b7f0d86..21cd60c 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -689,32 +689,24 @@ class HighLine if question.echo == true and question.limit.nil? get_line(question) else - line = "" + line = "" terminal.raw_no_echo_mode_exec do while character = terminal.get_character(@input) + break if character == "\n" or character == "\r" + # honor backspace and delete if character == "\b" chopped = line.chop! output_erase_char if chopped and question.echo else line << character + @output.print(line[-1]) if question.echo == true + @output.print(question.echo) if question.echo and question.echo != true end - # looking for carriage return (decimal 13) or - # newline (decimal 10) in raw input - break if character == "\n" or character == "\r" - if question.echo != false - if character == "\b" - # Do nothing - zombie code TODO: Remove it - else - if question.echo == true - @output.print(line[-1]) - else - @output.print(question.echo) - end - end - @output.flush - end + + @output.flush + break if question.limit and line.size == question.limit end end -- cgit v1.2.1 From b977d8237845983018e1bf810dcdb77341e74fd4 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 00:19:51 -0300 Subject: Add NotValidQuestionError. Simplify error handling using an specific error class. --- lib/highline.rb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 21cd60c..19c8b55 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -38,6 +38,10 @@ class HighLine # do nothing, just creating a unique error type end + class NotValidQuestionError < QuestionError + # do nothing, just creating a unique error type + end + # The setting used to disable color output. @@use_color = true @@ -519,10 +523,7 @@ class HighLine begin question.answer = question.answer_or_default(question.get_response(self)) - unless question.valid_answer?(question.answer) - explain_error(:not_valid, question) - raise QuestionError - end + raise NotValidQuestionError unless question.valid_answer?(question.answer) question.answer = question.convert(question.answer) @@ -549,6 +550,11 @@ class HighLine explain_error(:not_in_range, question) raise QuestionError end + + rescue NotValidQuestionError + explain_error(:not_valid, question) + retry + rescue QuestionError retry -- cgit v1.2.1 From 22f5c6b3bb5fe314e8b2926237e26a13568a0986 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 00:23:55 -0300 Subject: Add NotInRangeQuestionError. Simplify error handling using an specific error class. --- lib/highline.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 19c8b55..1fc7b0e 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -42,6 +42,10 @@ class HighLine # do nothing, just creating a unique error type end + class NotInRangeQuestionError < QuestionError + # do nothing, just creating a unique error type + end + # The setting used to disable color output. @@use_color = true @@ -547,10 +551,13 @@ class HighLine end end else - explain_error(:not_in_range, question) - raise QuestionError + raise NotInRangeQuestionError end + rescue NotInRangeQuestionError + explain_error(:not_in_range, question) + retry + rescue NotValidQuestionError explain_error(:not_valid, question) retry -- cgit v1.2.1 From de934b4ee1109277a8c5e7b97d59c14ac4240c44 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 00:29:52 -0300 Subject: Add NoConfirmationQuestionError. Simplify error handling using an specific error class. --- lib/highline.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 1fc7b0e..e6fd95a 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -46,6 +46,10 @@ class HighLine # do nothing, just creating a unique error type end + class NoConfirmationQuestionError < QuestionError + # do nothing, just creating a unique error type + end + # The setting used to disable color output. @@use_color = true @@ -545,15 +549,16 @@ class HighLine template_renderer = TemplateRenderer.new(template, question, self) confirm_question = template_renderer.render end - unless context_change.agree(confirm_question) - explain_error(nil, question) - raise QuestionError - end + raise NoConfirmationQuestionError unless context_change.agree(confirm_question) end else raise NotInRangeQuestionError end + rescue NoConfirmationQuestionError + explain_error(nil, question) + retry + rescue NotInRangeQuestionError explain_error(:not_in_range, question) retry -- cgit v1.2.1 From b6bc845d06544a94f4466110b7e97d3ab1fb8ad9 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 00:32:29 -0300 Subject: Add Question#get_response_or_default and simplify HighLine#ask_once --- lib/highline.rb | 2 +- lib/highline/question.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/highline.rb b/lib/highline.rb index e6fd95a..8cdb7f9 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -530,7 +530,7 @@ class HighLine say(question) unless ((question.readline) and (question.echo == true and question.limit.nil?)) begin - question.answer = question.answer_or_default(question.get_response(self)) + question.answer = question.get_response_or_default(self) raise NotValidQuestionError unless question.valid_answer?(question.answer) question.answer = question.convert(question.answer) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 673d139..4d1069e 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -485,6 +485,10 @@ class HighLine end end + def get_response_or_default(highline) + answer_or_default(get_response(highline)) + end + def ask_at(highline) return highline.gather(self) if gather return highline.ask_once(self) -- cgit v1.2.1 From 5130d68b729d90e90c8d70d8a7faac0d9c60c409 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 00:35:52 -0300 Subject: Remove Question#in_range? #valid_answer? and #convert parameters. Use self.answer as default. --- lib/highline.rb | 6 +++--- lib/highline/question.rb | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 8cdb7f9..784a93b 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -531,11 +531,11 @@ class HighLine begin question.answer = question.get_response_or_default(self) - raise NotValidQuestionError unless question.valid_answer?(question.answer) + raise NotValidQuestionError unless question.valid_answer? - question.answer = question.convert(question.answer) + question.answer = question.convert - if question.in_range?(question.answer) + if question.in_range? if question.confirm # need to add a layer of scope to ask a question inside a # question, without destroying instance data diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 4d1069e..96f2df8 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -311,19 +311,19 @@ class HighLine # This method throws ArgumentError, if the conversion cannot be # completed for any reason. # - def convert( answer_string ) - return answer_string unless @answer_type + def convert + return answer unless @answer_type if [::String, HighLine::String].include?(@answer_type) - HighLine::String(answer_string) + HighLine::String(answer) elsif [Float, Integer, String].include?(@answer_type) - Kernel.send(@answer_type.to_s.to_sym, answer_string) + Kernel.send(@answer_type.to_s.to_sym, answer) elsif @answer_type == Symbol - answer_string.to_sym + answer.to_sym elsif @answer_type == Regexp - Regexp.new(answer_string) + Regexp.new(answer) elsif @answer_type.is_a?(Array) or [File, Pathname].include?(@answer_type) - answer = choices_complete(answer_string) + self.answer = choices_complete(answer) if @answer_type.is_a?(Array) answer.last elsif @answer_type == File @@ -332,9 +332,9 @@ class HighLine Pathname.new(File.join(@directory.to_s, answer.last)) end elsif @answer_type.respond_to? :parse - @answer_type.parse(answer_string) + @answer_type.parse(answer) elsif @answer_type.is_a?(Proc) - @answer_type[answer_string] + @answer_type[answer] end end @@ -381,10 +381,10 @@ class HighLine # _in_ attribute. Otherwise, +false+ is returned. Any +nil+ attributes # are not checked. # - def in_range?( answer_object ) - (@above.nil? or answer_object > @above) and - (@below.nil? or answer_object < @below) and - (@in.nil? or @in.include?(answer_object)) + def in_range? + (@above.nil? or answer > @above) and + (@below.nil? or answer < @below) and + (@in.nil? or @in.include?(answer)) end # @@ -457,10 +457,10 @@ class HighLine # It's important to realize that an answer is validated after whitespace # and case handling. # - def valid_answer?( answer_string ) + def valid_answer? @validate.nil? or - (@validate.is_a?(Regexp) and answer_string =~ @validate) or - (@validate.is_a?(Proc) and @validate[answer_string]) + (@validate.is_a?(Regexp) and answer =~ @validate) or + (@validate.is_a?(Proc) and @validate[answer]) end # -- cgit v1.2.1 From dd406657ead08e38d496107a704547dc8086fd0d Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 00:58:34 -0300 Subject: Set Question#answer on Question#get_response_or_default and #convert. Simplify assignments on HighLine#ask_once --- lib/highline.rb | 4 ++-- lib/highline/question.rb | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 784a93b..65845e1 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -530,10 +530,10 @@ class HighLine say(question) unless ((question.readline) and (question.echo == true and question.limit.nil?)) begin - question.answer = question.get_response_or_default(self) + question.get_response_or_default(self) raise NotValidQuestionError unless question.valid_answer? - question.answer = question.convert + question.convert if question.in_range? if question.confirm diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 96f2df8..c03fb5c 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -312,8 +312,9 @@ class HighLine # completed for any reason. # def convert - return answer unless @answer_type + return unless @answer_type + self.answer = if [::String, HighLine::String].include?(@answer_type) HighLine::String(answer) elsif [Float, Integer, String].include?(@answer_type) @@ -486,7 +487,7 @@ class HighLine end def get_response_or_default(highline) - answer_or_default(get_response(highline)) + self.answer = answer_or_default(get_response(highline)) end def ask_at(highline) -- cgit v1.2.1 From 10ddd179168f3fa447cff120b60cf7edfff46c10 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 01:02:26 -0300 Subject: Extract Question#confirm_question --- lib/highline.rb | 12 ++---------- lib/highline/question.rb | 12 ++++++++++++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 65845e1..e787629 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -540,16 +540,8 @@ class HighLine # need to add a layer of scope to ask a question inside a # question, without destroying instance data context_change = new_scope - if question.confirm == true - confirm_question = "Are you sure? " - else - # evaluate ERb under initial scope, so it will have - # access to question and answer - template = ERB.new(question.confirm, nil, "%") - template_renderer = TemplateRenderer.new(template, question, self) - confirm_question = template_renderer.render - end - raise NoConfirmationQuestionError unless context_change.agree(confirm_question) + + raise NoConfirmationQuestionError unless context_change.agree(question.confirm_question(self)) end else raise NotInRangeQuestionError diff --git a/lib/highline/question.rb b/lib/highline/question.rb index c03fb5c..948383d 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -495,6 +495,18 @@ class HighLine return highline.ask_once(self) end + def confirm_question(highline) + if confirm == true + "Are you sure? " + else + # evaluate ERb under initial scope, so it will have + # access to question and answer + template = ERB.new(confirm, nil, "%") + template_renderer = TemplateRenderer.new(template, self, highline) + template_renderer.render + end + end + private # -- cgit v1.2.1 From 99febf851a2fff19a8871e6bbd9d3d9fd95e1c67 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 01:03:43 -0300 Subject: Remove unecessary assignment --- lib/highline.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index e787629..be43fd5 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -537,11 +537,10 @@ class HighLine if question.in_range? if question.confirm - # need to add a layer of scope to ask a question inside a + # need to add a layer of scope (new_scope) to ask a question inside a # question, without destroying instance data - context_change = new_scope - raise NoConfirmationQuestionError unless context_change.agree(question.confirm_question(self)) + raise NoConfirmationQuestionError unless new_scope.agree(question.confirm_question(self)) end else raise NotInRangeQuestionError -- cgit v1.2.1 From 1709704ecd0ed2e96061ea151bb9e20c2ebb504e Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 01:11:40 -0300 Subject: Simplify conditionals raising earlier --- lib/highline.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index be43fd5..7f2b164 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -535,15 +535,13 @@ class HighLine question.convert - if question.in_range? - if question.confirm - # need to add a layer of scope (new_scope) to ask a question inside a - # question, without destroying instance data + raise NotInRangeQuestionError unless question.in_range? - raise NoConfirmationQuestionError unless new_scope.agree(question.confirm_question(self)) - end - else - raise NotInRangeQuestionError + if question.confirm + # need to add a layer of scope (new_scope) to ask a question inside a + # question, without destroying instance data + + raise NoConfirmationQuestionError unless new_scope.agree(question.confirm_question(self)) end rescue NoConfirmationQuestionError -- cgit v1.2.1 From d754383a2623cfcec2563cc44b386f2905c627d4 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 12:49:27 -0300 Subject: Extract HighLine#ask_on_error_msg --- lib/highline.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 7f2b164..dfa0c31 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -510,10 +510,14 @@ class HighLine # def explain_error(error, question) say(question.responses[error]) unless error.nil? + say(ask_on_error_msg(question)) + end + + def ask_on_error_msg(question) if question.responses[:ask_on_error] == :question - say(question) + question elsif question.responses[:ask_on_error] - say(question.responses[:ask_on_error]) + question.responses[:ask_on_error] end end -- cgit v1.2.1 From dcaf5d6a1a4f7970474db4ee9cf4e81f1886787a Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 31 May 2015 12:53:10 -0300 Subject: Move HighLine#ask_on_error_msg to Question. Make it simpler and it's the right place to be. It's good to note after extracting it that now the method has dependency only on a Question instance. So its home is inside Question class. --- lib/highline.rb | 10 +--------- lib/highline/question.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index dfa0c31..b2d058e 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -510,15 +510,7 @@ class HighLine # def explain_error(error, question) say(question.responses[error]) unless error.nil? - say(ask_on_error_msg(question)) - end - - def ask_on_error_msg(question) - if question.responses[:ask_on_error] == :question - question - elsif question.responses[:ask_on_error] - question.responses[:ask_on_error] - end + say(question.ask_on_error_msg) end # diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 948383d..b92335b 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -507,6 +507,14 @@ class HighLine end end + def ask_on_error_msg + if responses[:ask_on_error] == :question + self + elsif responses[:ask_on_error] + responses[:ask_on_error] + end + end + private # -- cgit v1.2.1 From 65843e749da3c5100f28b354ef465cf7d838553c Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 3 Jun 2015 23:41:17 -0300 Subject: Extract HighLine#confirm(question) --- lib/highline.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/highline.rb b/lib/highline.rb index b2d058e..ddf1ed0 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -537,7 +537,7 @@ class HighLine # need to add a layer of scope (new_scope) to ask a question inside a # question, without destroying instance data - raise NoConfirmationQuestionError unless new_scope.agree(question.confirm_question(self)) + raise NoConfirmationQuestionError unless confirm(question) end rescue NoConfirmationQuestionError @@ -585,6 +585,11 @@ class HighLine question.answer end + def confirm(question) + new_scope.agree(question.confirm_question(self)) + end + + public :ask_once # -- cgit v1.2.1 From 7677e33c0377cc8d964679f544ac4f1f81c00112 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 4 Jun 2015 00:15:08 -0300 Subject: Add String convertion/coercion to HighLine::Question#format_answer --- lib/highline/question.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index b92335b..d48fcd2 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -425,6 +425,7 @@ class HighLine end def format_answer(answer_string) + answer_string = String(answer_string) answer_string = remove_whitespace(answer_string) change_case(answer_string) end -- cgit v1.2.1 From e6fc542a33cf1e0af7d6fff1a2ae653e808bb01e Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 4 Jun 2015 00:16:44 -0300 Subject: Remove rescueing for NameError/NoMethdoError I just couldn't see where these errors could be triggered in a way that we would like to "treat" them. Now it's simpler with only ArgumentError handling. --- lib/highline.rb | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index ddf1ed0..9bc7855 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -555,29 +555,20 @@ class HighLine rescue QuestionError retry - # TODO: So we don't forget it!!! - # This is a HUGE source of error mask - # It's hiding errors deep in the code - # It rescues and retries - # We gotta remove it soon - # - # UPDATE: The rescue for invalid type - # was made a little more specific. - # Damage controlled meantime! - rescue ArgumentError, NameError => error - raise if error.is_a?(NoMethodError) + rescue ArgumentError => error if error.message =~ /ambiguous/ # the assumption here is that OptionParser::Completion#complete # (used for ambiguity resolution) throws exceptions containing # the word 'ambiguous' whenever resolution fails explain_error(:ambiguous_completion, question) retry - elsif error.is_a? ArgumentError and error.message =~ /invalid value for/ + elsif error.message =~ /invalid value for/ explain_error(:invalid_type, question) retry else raise end + rescue Question::NoAutoCompleteMatch explain_error(:no_completion, question) retry -- cgit v1.2.1 From 69b1357c143be77edf6a366a419fa052e5ddb79f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 4 Jun 2015 00:20:06 -0300 Subject: Use case/when not if/elsif/else --- lib/highline.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 9bc7855..fa71793 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -556,13 +556,14 @@ class HighLine retry rescue ArgumentError => error - if error.message =~ /ambiguous/ + case error.message + when /ambiguous/ # the assumption here is that OptionParser::Completion#complete # (used for ambiguity resolution) throws exceptions containing # the word 'ambiguous' whenever resolution fails explain_error(:ambiguous_completion, question) retry - elsif error.message =~ /invalid value for/ + when /invalid value for/ explain_error(:invalid_type, question) retry else -- cgit v1.2.1 From 71f4f8f1d50fcf824966f24e19959272bf1ebb93 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 5 Jun 2015 00:39:43 -0300 Subject: Extract HighLine::Question::AnswerConverter It makes the dependencies clear. Preparing for refactoring this long chain of conditionals into something not that long. It also changes where NotInRangeQuestionError is raised, simplifying HighLine a little bit. --- lib/highline.rb | 2 -- lib/highline/question.rb | 33 +++++-------------- lib/highline/question/answer_converter.rb | 53 +++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 27 deletions(-) create mode 100644 lib/highline/question/answer_converter.rb diff --git a/lib/highline.rb b/lib/highline.rb index fa71793..98cdab9 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -531,8 +531,6 @@ class HighLine question.convert - raise NotInRangeQuestionError unless question.in_range? - if question.confirm # need to add a layer of scope (new_scope) to ask a question inside a # question, without destroying instance data diff --git a/lib/highline/question.rb b/lib/highline/question.rb index d48fcd2..664fac9 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -11,6 +11,7 @@ require "optparse" require "date" require "pathname" +require "highline/question/answer_converter" class HighLine # @@ -65,6 +66,8 @@ class HighLine build_responses end + attr_reader :directory + # The ERb template of the question to be asked. attr_accessor :template @@ -312,31 +315,11 @@ class HighLine # completed for any reason. # def convert - return unless @answer_type - - self.answer = - if [::String, HighLine::String].include?(@answer_type) - HighLine::String(answer) - elsif [Float, Integer, String].include?(@answer_type) - Kernel.send(@answer_type.to_s.to_sym, answer) - elsif @answer_type == Symbol - answer.to_sym - elsif @answer_type == Regexp - Regexp.new(answer) - elsif @answer_type.is_a?(Array) or [File, Pathname].include?(@answer_type) - self.answer = choices_complete(answer) - if @answer_type.is_a?(Array) - answer.last - elsif @answer_type == File - File.open(File.join(@directory.to_s, answer.last)) - else - Pathname.new(File.join(@directory.to_s, answer.last)) - end - elsif @answer_type.respond_to? :parse - @answer_type.parse(answer) - elsif @answer_type.is_a?(Proc) - @answer_type[answer] - end + Question::AnswerConverter.new(self).convert + end + + def check_range + raise NotInRangeQuestionError unless in_range? end def choices_complete(answer_string) diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb new file mode 100644 index 0000000..0176854 --- /dev/null +++ b/lib/highline/question/answer_converter.rb @@ -0,0 +1,53 @@ +#!/usr/bin/env ruby + +# TODO: This module was extracted from HighLine::Question +# Now the dependencies are clear. See the delegators. +# Remember to refactor it! + +class HighLine + class Question + class AnswerConverter + extend Forwardable + + def_delegators :@question, + :answer, :answer=, :check_range, + :directory, :answer_type, :choices_complete + + def initialize(question) + @question = question + end + + def convert + return unless answer_type + + self.answer = + if [::String, HighLine::String].include?(answer_type) + HighLine::String(answer) + elsif [Float, Integer, String].include?(answer_type) + Kernel.send(answer_type.to_s.to_sym, answer) + elsif answer_type == Symbol + answer.to_sym + elsif answer_type == Regexp + Regexp.new(answer) + elsif answer_type.is_a?(Array) or [File, Pathname].include?(answer_type) + self.answer = choices_complete(answer) + if answer_type.is_a?(Array) + answer.last + elsif answer_type == File + File.open(File.join(directory.to_s, answer.last)) + else + Pathname.new(File.join(directory.to_s, answer.last)) + end + elsif answer_type.respond_to? :parse + answer_type.parse(answer) + elsif answer_type.is_a?(Proc) + answer_type[answer] + end + + check_range + + answer + end + end + end +end \ No newline at end of file -- cgit v1.2.1 From 7493893624524e0228c4a0de309c6b1428bcec7b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 6 Jun 2015 01:13:39 -0300 Subject: Remove duplicate String handling in AnswerConverter#convert --- lib/highline/question/answer_converter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb index 0176854..5e1d9b7 100644 --- a/lib/highline/question/answer_converter.rb +++ b/lib/highline/question/answer_converter.rb @@ -23,7 +23,7 @@ class HighLine self.answer = if [::String, HighLine::String].include?(answer_type) HighLine::String(answer) - elsif [Float, Integer, String].include?(answer_type) + elsif [Float, Integer].include?(answer_type) Kernel.send(answer_type.to_s.to_sym, answer) elsif answer_type == Symbol answer.to_sym -- cgit v1.2.1 From fbd248da4acf3d281c7672f2456afc7f0033b656 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 6 Jun 2015 01:14:08 -0300 Subject: Use a more natural calling syntax for procs --- lib/highline/question/answer_converter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb index 5e1d9b7..3121246 100644 --- a/lib/highline/question/answer_converter.rb +++ b/lib/highline/question/answer_converter.rb @@ -41,7 +41,7 @@ class HighLine elsif answer_type.respond_to? :parse answer_type.parse(answer) elsif answer_type.is_a?(Proc) - answer_type[answer] + answer_type.call(answer) end check_range -- cgit v1.2.1 From c1c69f85f89cd305456d1f50152dd7cbe285080c Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 6 Jun 2015 01:58:34 -0300 Subject: Split some AnswerConverter conversions separate methods - simplify conditional --- lib/highline/question/answer_converter.rb | 60 +++++++++++++++++++++---------- test/test_highline.rb | 19 ++++++++++ 2 files changed, 61 insertions(+), 18 deletions(-) diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb index 3121246..cd2666f 100644 --- a/lib/highline/question/answer_converter.rb +++ b/lib/highline/question/answer_converter.rb @@ -21,25 +21,13 @@ class HighLine return unless answer_type self.answer = - if [::String, HighLine::String].include?(answer_type) - HighLine::String(answer) - elsif [Float, Integer].include?(answer_type) - Kernel.send(answer_type.to_s.to_sym, answer) - elsif answer_type == Symbol - answer.to_sym - elsif answer_type == Regexp - Regexp.new(answer) - elsif answer_type.is_a?(Array) or [File, Pathname].include?(answer_type) - self.answer = choices_complete(answer) - if answer_type.is_a?(Array) - answer.last - elsif answer_type == File - File.open(File.join(directory.to_s, answer.last)) - else - Pathname.new(File.join(directory.to_s, answer.last)) - end - elsif answer_type.respond_to? :parse + if answer_type.respond_to? :parse answer_type.parse(answer) + elsif answer_type.is_a? Class + send(answer_type.name.to_sym) + elsif answer_type.is_a?(Array) + self.answer = choices_complete(answer) + answer.last elsif answer_type.is_a?(Proc) answer_type.call(answer) end @@ -48,6 +36,42 @@ class HighLine answer end + + def String + HighLine::String(answer) + end + + # That's a weird name for a method! + # But it's working ;-) + define_method "HighLine::String" do + HighLine::String(answer) + end + + def Integer + Kernel.send(:Integer, answer) + end + + def Float + Kernel.send(:Float, answer) + end + + def Symbol + answer.to_sym + end + + def Regexp + Regexp.new(answer) + end + + def File + self.answer = choices_complete(answer) + File.open(File.join(directory.to_s, answer.last)) + end + + def Pathname + self.answer = choices_complete(answer) + Pathname.new(File.join(directory.to_s, answer.last)) + end end end end \ No newline at end of file diff --git a/test/test_highline.rb b/test/test_highline.rb index 3c3e63f..04781f3 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -79,6 +79,25 @@ class TestHighLine < Minitest::Test assert_raises(EOFError) { @terminal.ask("Any input left? ", String) } end + def test_ask_string_converting + name = "James Edward Gray II" + @input << name << "\n" + @input.rewind + + answer = @terminal.ask("What is your name? ", String) + + assert_instance_of HighLine::String, answer + + @input.rewind + + answer = @terminal.ask("What is your name? ", HighLine::String) + + assert_instance_of HighLine::String, answer + + assert_raises(EOFError) { @terminal.ask("Any input left? ", HighLine::String) } + end + + def test_indent text = "Testing...\n" @terminal.indent_level=1 -- cgit v1.2.1 From 714643db83097f426346df63230bfb1500e93678 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 6 Jun 2015 02:07:38 -0300 Subject: Send the name (string) directly. No need to convert to symbol here --- lib/highline/question/answer_converter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb index cd2666f..0aa81c8 100644 --- a/lib/highline/question/answer_converter.rb +++ b/lib/highline/question/answer_converter.rb @@ -24,7 +24,7 @@ class HighLine if answer_type.respond_to? :parse answer_type.parse(answer) elsif answer_type.is_a? Class - send(answer_type.name.to_sym) + send(answer_type.name) elsif answer_type.is_a?(Array) self.answer = choices_complete(answer) answer.last -- cgit v1.2.1 From 6c03788b0aaa7afe5016302fb7c9dc9ca47cae3a Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 6 Jun 2015 02:08:17 -0300 Subject: Unify Array and Proc AnswerConverter convertions --- lib/highline/question/answer_converter.rb | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb index 0aa81c8..3f73f9f 100644 --- a/lib/highline/question/answer_converter.rb +++ b/lib/highline/question/answer_converter.rb @@ -25,11 +25,8 @@ class HighLine answer_type.parse(answer) elsif answer_type.is_a? Class send(answer_type.name) - elsif answer_type.is_a?(Array) - self.answer = choices_complete(answer) - answer.last - elsif answer_type.is_a?(Proc) - answer_type.call(answer) + else + send(answer_type.class.name) end check_range @@ -72,6 +69,15 @@ class HighLine self.answer = choices_complete(answer) Pathname.new(File.join(directory.to_s, answer.last)) end + + def Array + self.answer = choices_complete(answer) + answer.last + end + + def Proc + answer_type.call(answer) + end end end end \ No newline at end of file -- cgit v1.2.1 From 9736ad9375d9a6922d17a1c0ab39894e3eb10ce0 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 6 Jun 2015 02:10:59 -0300 Subject: Make all convertion methods private to AnswerConverter And remove TODO message --- lib/highline/question/answer_converter.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb index 3f73f9f..2bc90bb 100644 --- a/lib/highline/question/answer_converter.rb +++ b/lib/highline/question/answer_converter.rb @@ -1,9 +1,5 @@ #!/usr/bin/env ruby -# TODO: This module was extracted from HighLine::Question -# Now the dependencies are clear. See the delegators. -# Remember to refactor it! - class HighLine class Question class AnswerConverter @@ -34,6 +30,8 @@ class HighLine answer end + private + def String HighLine::String(answer) end -- cgit v1.2.1 From 78fcfcc0541e30a4b4e17a49ea88e6848a3e5388 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 6 Jun 2015 02:22:58 -0300 Subject: Extract AnswerConverter#convert_by_answer_type --- lib/highline/question/answer_converter.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb index 2bc90bb..de54397 100644 --- a/lib/highline/question/answer_converter.rb +++ b/lib/highline/question/answer_converter.rb @@ -16,7 +16,14 @@ class HighLine def convert return unless answer_type - self.answer = + self.answer = convert_by_answer_type + check_range + answer + end + + private + + def convert_by_answer_type if answer_type.respond_to? :parse answer_type.parse(answer) elsif answer_type.is_a? Class @@ -24,14 +31,8 @@ class HighLine else send(answer_type.class.name) end - - check_range - - answer end - private - def String HighLine::String(answer) end -- cgit v1.2.1 From 0807afd2af0ce2d8133ef01bf7767fc0236c1228 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 11 Jun 2015 15:54:04 -0300 Subject: Add .DS_Store (mac) files to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index de31a45..d558527 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ doc pkg +.DS_Store -- cgit v1.2.1 From 05c1c45792b655981615d8b32149508f604dccac Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 12 Jun 2015 16:03:50 -0300 Subject: Bump up version to 2.0.0-develop.1 --- lib/highline/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline/version.rb b/lib/highline/version.rb index 8c13579..a54e222 100644 --- a/lib/highline/version.rb +++ b/lib/highline/version.rb @@ -3,5 +3,5 @@ class HighLine # The version of the installed library. - VERSION = "1.7.2".freeze + VERSION = "2.0.0-develop.1".freeze end -- cgit v1.2.1 From 179715b61fc69d91124ae02c8a32abf6d6dc6232 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 12 Jun 2015 16:05:07 -0300 Subject: Update Changelog.md - 2.0.0-develop.1 --- Changelog.md | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/Changelog.md b/Changelog.md index 49e533e..c732281 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,67 @@ Below is a complete listing of changes for each revision of HighLine. +### 2.0.0-develop.1 / 2015-06-11 + +This is the first development version of the 2.0.0 series. It's the begining of a refactoring phase on HighLine development cycle. + +#### SOME HISTORY + +In 2014 I emailed James Edward Gray II (@JEG2) about HighLine. One of his ideas was to completely refactor the library so that it could be easier to reuse and improve it. I've began my contributions to HighLine trying to fix some of the open issues at that time so that we could "freeze" a stable version of HighLine that people could rely on. Then I've began to study HighLine source code with James' help and started to refactor some parts of the code. + +#### NOTES + +* This release differs from current master branch by more than 180 commits. +* The main changes will be only summarized bellow (as there are many, and a detailed description of each is not productive). +* You could try `git log -p` to see all of them. +* During the last commits, all possible efforts were taken to preserve the tests passing status. +* 100% test passing gives you no guarantee that this new version will work for you. This happens for many reasons. One of them is that we don't currently have 100% test coverage. +* So, this version is not suitable for use in production. +* [Metric_fu](https://github.com/metricfu/metric_fu) and [Code Climate](https://codeclimate.com/github/abinoam/highline) were used here not to strictly "guide" what should be changed, but to have some way to objectively measure the progresses made so far. + +#### CHANGES SUMMARY +* Extracted a lot of smaller methods from bigger ones +* Extracted smaller classes/modules from bigger ones, so they could be self contained with less external dependencies as possible, for example: + * HighLine::Statement + * HighLine::List + * HighLine::ListRenderer + * HighLine::TemplateRenderer + * HighLine::Question::AnswerConverter + * HighLine::Terminal + * HighLine::Terminal::UnixStty + * HighLine::Paginator + * HighLine::Wrapper +* After extracting each class/module some refactoring were applied to them lowering code complexity + +#### METRICS SUMMARY +Some of the metrics used to track progress are summarized bellow. Some of them have got a lot better as Flay, Flog and Reek, others like Cane haven't (probably because we didn't commented out the new code yet) + +__CODECLIMATE__ + +* GPA: 3.60 -> 3.67 (higher is better) + +__CANE__ - reports code quality threshold violations (lower is better) + +* Total 92 -> 105 + * Methods exceeding allowed Abc complexity: 14 -> 10 + * Lines violating style requirements: 69 -> 72 + * Class definitions requiring comments: 9 -> 23 + +__FLAY__ - analyzes ruby code for structural similarities (code duplication - lower is better) + +* Total: 490 -> 94 + +__FLOG__ - measures code complexity (lower is better) + +* Top 5% average: 127.9458 -> 40.99812 +* Average: 17.37982 -> 7.663875 +* Total: 2158.5 -> 1969.6 + +__REEK__ - detects common code smells in ruby code (lower is better) + +* DuplicateMethodCall: 144 -> 54 +* TooManyStatements: 26 -> 30 + ### 1.7.2 / 2015-04-19 #### Bug fixes -- cgit v1.2.1 From 463802bf15e634923dd2fe8edc78dd92cb9f0e28 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 12 Jun 2015 19:38:20 -0300 Subject: Fix version testing to accomodate pre release versions --- test/test_highline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_highline.rb b/test/test_highline.rb index 04781f3..779db3a 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -1338,6 +1338,6 @@ class TestHighLine < Minitest::Test refute_nil(HighLine::VERSION) assert_instance_of(String, HighLine::VERSION) assert(HighLine::VERSION.frozen?) - assert_match(/\A\d+\.\d+\.\d+\Z/, HighLine::VERSION) + assert_match(/\A\d+\.\d+\.\d+(-.*)?/, HighLine::VERSION) end end -- cgit v1.2.1 From cd0fa20b041fa68f741fbee4cc5f9f97604b5d62 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 12 Jun 2015 20:13:10 -0300 Subject: Require forwardable as AnswerConverter depends on it --- lib/highline/question/answer_converter.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb index de54397..622acec 100644 --- a/lib/highline/question/answer_converter.rb +++ b/lib/highline/question/answer_converter.rb @@ -1,5 +1,7 @@ #!/usr/bin/env ruby +require 'forwardable' + class HighLine class Question class AnswerConverter -- cgit v1.2.1 From a1004a994779fae3869f3bd2abdc535e864f84ea Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sat, 13 Jun 2015 23:54:52 -0300 Subject: Minor update to Changelog.md --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index c732281..b690369 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,7 +8,7 @@ This is the first development version of the 2.0.0 series. It's the begining of #### SOME HISTORY -In 2014 I emailed James Edward Gray II (@JEG2) about HighLine. One of his ideas was to completely refactor the library so that it could be easier to reuse and improve it. I've began my contributions to HighLine trying to fix some of the open issues at that time so that we could "freeze" a stable version of HighLine that people could rely on. Then I've began to study HighLine source code with James' help and started to refactor some parts of the code. +In 2014 I emailed James Edward Gray II (@JEG2) about HighLine. One of his ideas was to completely refactor the library so that it could be easier to reuse and improve it. I've began my contributions to HighLine trying to fix some of the open issues at that time so that we could "freeze" a stable version of HighLine that people could rely on. Then I've began to study HighLine source code with James' help and started to refactor some parts of the code. Abinoam P. Marques Jr. (@abinoam) #### NOTES -- cgit v1.2.1 From efb16ae0538877da931039d7e941b1f08f2b2db2 Mon Sep 17 00:00:00 2001 From: Michal Cichra Date: Mon, 15 Jun 2015 10:19:26 +0200 Subject: remove unneccessary shebang lines from *.rb files in lib --- lib/highline.rb | 1 - lib/highline/color_scheme.rb | 1 - lib/highline/compatibility.rb | 1 - lib/highline/import.rb | 1 - lib/highline/menu.rb | 1 - lib/highline/paginator.rb | 1 - lib/highline/question.rb | 1 - lib/highline/question/answer_converter.rb | 1 - lib/highline/simulate.rb | 1 - lib/highline/statement.rb | 1 - lib/highline/string_extensions.rb | 1 - lib/highline/style.rb | 1 - lib/highline/template_renderer.rb | 1 - lib/highline/terminal.rb | 1 - lib/highline/terminal/jruby.rb | 1 - lib/highline/terminal/windows.rb | 1 - lib/highline/terminal/windows_fiddle.rb | 1 - lib/highline/version.rb | 1 - lib/highline/wrapper.rb | 1 - 19 files changed, 19 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 98cdab9..db0c0bf 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 # highline.rb diff --git a/lib/highline/color_scheme.rb b/lib/highline/color_scheme.rb index 589127f..0d07c42 100644 --- a/lib/highline/color_scheme.rb +++ b/lib/highline/color_scheme.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 # color_scheme.rb diff --git a/lib/highline/compatibility.rb b/lib/highline/compatibility.rb index 5e186ac..1083686 100644 --- a/lib/highline/compatibility.rb +++ b/lib/highline/compatibility.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 unless STDIN.respond_to? :getbyte diff --git a/lib/highline/import.rb b/lib/highline/import.rb index ff03e64..7a0e6fa 100644 --- a/lib/highline/import.rb +++ b/lib/highline/import.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 # import.rb diff --git a/lib/highline/menu.rb b/lib/highline/menu.rb index 7856676..71c4f47 100644 --- a/lib/highline/menu.rb +++ b/lib/highline/menu.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 # menu.rb diff --git a/lib/highline/paginator.rb b/lib/highline/paginator.rb index 7a80588..f02ea8c 100644 --- a/lib/highline/paginator.rb +++ b/lib/highline/paginator.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 class HighLine diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 664fac9..0ad9607 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 # question.rb diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb index 622acec..f1f3670 100644 --- a/lib/highline/question/answer_converter.rb +++ b/lib/highline/question/answer_converter.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby require 'forwardable' diff --git a/lib/highline/simulate.rb b/lib/highline/simulate.rb index 741fe32..4bad8f9 100644 --- a/lib/highline/simulate.rb +++ b/lib/highline/simulate.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 # simulate.rb diff --git a/lib/highline/statement.rb b/lib/highline/statement.rb index 4d386d3..870495c 100644 --- a/lib/highline/statement.rb +++ b/lib/highline/statement.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 require 'highline/wrapper' diff --git a/lib/highline/string_extensions.rb b/lib/highline/string_extensions.rb index e4981ef..a094bb4 100644 --- a/lib/highline/string_extensions.rb +++ b/lib/highline/string_extensions.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 # Extensions for class String diff --git a/lib/highline/style.rb b/lib/highline/style.rb index 9b87dcd..72871b6 100755 --- a/lib/highline/style.rb +++ b/lib/highline/style.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 # color_scheme.rb diff --git a/lib/highline/template_renderer.rb b/lib/highline/template_renderer.rb index 28aba14..ea43905 100644 --- a/lib/highline/template_renderer.rb +++ b/lib/highline/template_renderer.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 require 'forwardable' diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index aef6ad2..0136f06 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 # terminal.rb diff --git a/lib/highline/terminal/jruby.rb b/lib/highline/terminal/jruby.rb index 5e85024..8f3456f 100644 --- a/lib/highline/terminal/jruby.rb +++ b/lib/highline/terminal/jruby.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby #coding: utf-8 class HighLine diff --git a/lib/highline/terminal/windows.rb b/lib/highline/terminal/windows.rb index 005045e..26d4a2f 100644 --- a/lib/highline/terminal/windows.rb +++ b/lib/highline/terminal/windows.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby #coding: utf-8 class HighLine diff --git a/lib/highline/terminal/windows_fiddle.rb b/lib/highline/terminal/windows_fiddle.rb index 8a2a4af..b0e4280 100644 --- a/lib/highline/terminal/windows_fiddle.rb +++ b/lib/highline/terminal/windows_fiddle.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby #coding: utf-8 class HighLine diff --git a/lib/highline/version.rb b/lib/highline/version.rb index a54e222..288e4fa 100644 --- a/lib/highline/version.rb +++ b/lib/highline/version.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 class HighLine diff --git a/lib/highline/wrapper.rb b/lib/highline/wrapper.rb index 695601c..98f713f 100644 --- a/lib/highline/wrapper.rb +++ b/lib/highline/wrapper.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # coding: utf-8 class HighLine -- cgit v1.2.1 From a71aae0f69199d228596a23cb12553f6762db466 Mon Sep 17 00:00:00 2001 From: Michal Cichra Date: Mon, 15 Jun 2015 10:20:10 +0200 Subject: unify 'coding: utf-8' headers --- lib/highline/list.rb | 2 ++ lib/highline/list_renderer.rb | 2 ++ lib/highline/question/answer_converter.rb | 1 + lib/highline/terminal/jruby.rb | 2 +- lib/highline/terminal/jruby_jline.rb | 2 ++ lib/highline/terminal/ncurses.rb | 2 ++ lib/highline/terminal/stty.rb | 2 ++ lib/highline/terminal/unix_stty.rb | 2 ++ lib/highline/terminal/unix_termios.rb | 2 ++ lib/highline/terminal/windows.rb | 2 +- lib/highline/terminal/windows_dl_import.rb | 2 ++ lib/highline/terminal/windows_fiddle.rb | 2 +- 12 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/highline/list.rb b/lib/highline/list.rb index b81c4f3..d5c127b 100644 --- a/lib/highline/list.rb +++ b/lib/highline/list.rb @@ -1,3 +1,5 @@ +# coding: utf-8 + class HighLine class List attr_reader :items, :cols diff --git a/lib/highline/list_renderer.rb b/lib/highline/list_renderer.rb index 55ea2cd..95fc490 100644 --- a/lib/highline/list_renderer.rb +++ b/lib/highline/list_renderer.rb @@ -1,3 +1,5 @@ +# coding: utf-8 + require 'highline/template_renderer' require 'highline/wrapper' require 'highline/list' diff --git a/lib/highline/question/answer_converter.rb b/lib/highline/question/answer_converter.rb index f1f3670..b840440 100644 --- a/lib/highline/question/answer_converter.rb +++ b/lib/highline/question/answer_converter.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require 'forwardable' diff --git a/lib/highline/terminal/jruby.rb b/lib/highline/terminal/jruby.rb index 8f3456f..2c1b6da 100644 --- a/lib/highline/terminal/jruby.rb +++ b/lib/highline/terminal/jruby.rb @@ -1,4 +1,4 @@ -#coding: utf-8 +# coding: utf-8 class HighLine module SystemExtensions diff --git a/lib/highline/terminal/jruby_jline.rb b/lib/highline/terminal/jruby_jline.rb index a0d48c3..8e9a47d 100644 --- a/lib/highline/terminal/jruby_jline.rb +++ b/lib/highline/terminal/jruby_jline.rb @@ -1,3 +1,5 @@ +# coding: utf-8 + class HighLine module SystemExtensions module JRubyJLine diff --git a/lib/highline/terminal/ncurses.rb b/lib/highline/terminal/ncurses.rb index 8ac672f..cb2b593 100644 --- a/lib/highline/terminal/ncurses.rb +++ b/lib/highline/terminal/ncurses.rb @@ -1,3 +1,5 @@ +# coding: utf-8 + class HighLine module SystemExtensions module NCurses diff --git a/lib/highline/terminal/stty.rb b/lib/highline/terminal/stty.rb index ecc039b..168f8c5 100644 --- a/lib/highline/terminal/stty.rb +++ b/lib/highline/terminal/stty.rb @@ -1,3 +1,5 @@ +# coding: utf-8 + class HighLine module SystemExtensions module Stty diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index 1a3501d..7914c12 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -1,3 +1,5 @@ +# coding: utf-8 + class HighLine class Terminal::UnixStty < Terminal diff --git a/lib/highline/terminal/unix_termios.rb b/lib/highline/terminal/unix_termios.rb index 5b285ff..3a0a799 100644 --- a/lib/highline/terminal/unix_termios.rb +++ b/lib/highline/terminal/unix_termios.rb @@ -1,3 +1,5 @@ +# coding: utf-8 + class HighLine module SystemExtensions module UnixTermios diff --git a/lib/highline/terminal/windows.rb b/lib/highline/terminal/windows.rb index 26d4a2f..81b1d67 100644 --- a/lib/highline/terminal/windows.rb +++ b/lib/highline/terminal/windows.rb @@ -1,4 +1,4 @@ -#coding: utf-8 +# coding: utf-8 class HighLine module SystemExtensions diff --git a/lib/highline/terminal/windows_dl_import.rb b/lib/highline/terminal/windows_dl_import.rb index 597374e..721f048 100644 --- a/lib/highline/terminal/windows_dl_import.rb +++ b/lib/highline/terminal/windows_dl_import.rb @@ -1,3 +1,5 @@ +# coding: utf-8 + class HighLine module SystemExtensions module WindowsDlImport diff --git a/lib/highline/terminal/windows_fiddle.rb b/lib/highline/terminal/windows_fiddle.rb index b0e4280..7e0c844 100644 --- a/lib/highline/terminal/windows_fiddle.rb +++ b/lib/highline/terminal/windows_fiddle.rb @@ -1,4 +1,4 @@ -#coding: utf-8 +# coding: utf-8 class HighLine module SystemExtensions -- cgit v1.2.1 From 4081a804495034217a63eb90bf80c0a6f290fb34 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 15 Jun 2015 13:13:33 -0300 Subject: Use a conditional assignment operator As suggested by @plribeiro3000 at https://github.com/JEG2/highline/pull/140#discussion_r32379527 --- lib/highline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/highline.rb b/lib/highline.rb index db0c0bf..2a917c2 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -448,7 +448,7 @@ class HighLine def indent(increase=1, statement=nil, multiline=nil) @indent_level += increase multi = @multi_indent - @multi_indent = multiline || @multi_indent + @multi_indent ||= multiline begin if block_given? yield self -- cgit v1.2.1 From 4d8dc67327a64ceb1e361c39b2006b8f70e7d981 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 17 Jun 2015 22:00:34 -0300 Subject: Add SimpleCov support As suggested by @maurogeorge at https://github.com/JEG2/highline/pull/140#issuecomment-112963251 --- .gitignore | 1 + Gemfile | 3 ++- test/test_helper.rb | 5 +++++ test/test_highline.rb | 3 ++- test/test_list.rb | 1 + 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index d558527..a49838e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ doc pkg .DS_Store +coverage diff --git a/Gemfile b/Gemfile index 78534ee..820bc6d 100644 --- a/Gemfile +++ b/Gemfile @@ -8,4 +8,5 @@ group :development, :test do gem "minitest", require: false end -gem "codeclimate-test-reporter", group: :test, require: false \ No newline at end of file +gem "codeclimate-test-reporter", group: :test, require: false +gem "simplecov", group: :test, require: false \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index 6068398..ac8e809 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,6 +1,11 @@ #!/usr/bin/env ruby # coding: utf-8 +require 'simplecov' +SimpleCov.start do + add_filter "test_" +end + require "codeclimate-test-reporter" CodeClimate::TestReporter.start diff --git a/test/test_highline.rb b/test/test_highline.rb index 779db3a..b3e822b 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -9,12 +9,13 @@ # This is Free Software. See LICENSE and COPYING for details. require "minitest/autorun" +require "test_helper" require "highline" require "stringio" require "readline" require "tempfile" -require "test_helper" + =begin if HighLine::CHARACTER_MODE == "Win32API" diff --git a/test/test_list.rb b/test/test_list.rb index 385e73d..c363642 100644 --- a/test/test_list.rb +++ b/test/test_list.rb @@ -3,6 +3,7 @@ require "minitest/autorun" require "test_helper" + require "highline/list" class TestHighLineList < Minitest::Test -- cgit v1.2.1 From 445a3fe4634390323b25b0188d6e458418f77ef4 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 17 Jun 2015 22:32:07 -0300 Subject: Remove commented (non functional) code As suggested by @maurogeorge at https://github.com/JEG2/highline/pull/140#discussion_r32679353 --- lib/highline/terminal.rb | 68 ------------------------------------------------ 1 file changed, 68 deletions(-) diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index 0136f06..b23fe65 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -48,71 +48,3 @@ class HighLine end end end - -=begin - -# Meanwhile, we're concentratring on making a standard -# terminal to work using this new approach. -# -# We'll try to revive the code bellow as soon as possible. - - JRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' - - if JRUBY - require 'highline/terminal/jruby' - return HighLine::Terminal::JRuby - end - - extend self - - # - # This section builds character reading and terminal size functions - # to suit the proper platform we're running on. Be warned: Here be - # dragons! - # - if RUBY_PLATFORM =~ /mswin(?!ce)|mingw|bccwin/i - begin - require 'highline/terminal/windows_fiddle' - return HighLine::Terminal::WindowsFiddle - rescue LoadError - require 'highline/terminal/windows_dl_import' - return HighLine::Terminal::WindowsDlImport - end - - require 'highline/terminal/windows' - return HighLine::Terminal::Windows - else # If we're not on Windows try... - begin - require 'highline/terminal/unix_termios' - return HighLine::Terminal::UnixTermios - rescue LoadError # If our first choice fails, try using JLine - if JRUBY # if we are on JRuby. JLine is bundled with JRuby. - require 'highline/terminal/jruby_jline' - return HighLine::Terminal::JRubyJLine - else # If we are not on JRuby, try ncurses - begin - require 'highline/terminal/ncurses' - return HighLine::Terminal::NCurses - rescue LoadError # Finally, if all else fails, use stty - require 'highline/terminal/stty' - return HighLine::Terminal::Stty - end - end - end - - # For termios and stty - if not method_defined?(:terminal_size) - require 'highline/terminal/unix_stty' - return HighLine::Terminal::UnixStty - end - end - - if not method_defined?(:get_character) - def get_character( input = STDIN ) - input.getbyte - end - end - end - end -end -=end -- cgit v1.2.1 From 73bb8790d499bb7d5ad6b1205e13d917e12bae38 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 29 Jun 2015 18:24:38 -0300 Subject: Add ruby 2.2.1 and 2.2.2 to travis matrix --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 87c2844..f4ee366 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,8 @@ rvm: - 2.0.0 - 2.1.5 - 2.2.0 + - 2.2.1 + - 2.2.2 - rbx-2 notifications: email: false -- cgit v1.2.1 From 88978cd2ff5da525f4feb81abcf32767e40790fa Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Mon, 29 Jun 2015 18:41:13 -0300 Subject: Add tests for HighLine::Simulator - Issue #142 As suggested by @bparanj on https://github.com/JEG2/highline/issues/142 Note: cherry picked from master and adapted to develop branch. --- test/test_simulator.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 test/test_simulator.rb diff --git a/test/test_simulator.rb b/test/test_simulator.rb new file mode 100644 index 0000000..15691d9 --- /dev/null +++ b/test/test_simulator.rb @@ -0,0 +1,25 @@ +require "minitest/autorun" +require "test_helper" + +require "highline/import" +require "highline/simulate" + +class SimulatorTest < Minitest::Test + def setup + input = StringIO.new + output = StringIO.new + $terminal = HighLine.new(input, output) + end + + def test_simulator + HighLine::Simulate.with("Bugs Bunny", "18") do + name = ask("What is your name?") + + assert_equal "Bugs Bunny", name + + age = ask("What is your age?") + + assert_equal "18", age + end + end +end \ No newline at end of file -- cgit v1.2.1