From 64708ae9e40ed401a5476c787e6a6dacd3f5464f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 9 Jul 2015 16:03:01 -0300 Subject: [PATCH 01/43] Extract HighLine::BuiltinStyles as a module --- lib/highline.rb | 91 ++------------------------------- lib/highline/builtin_styles.rb | 93 ++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 88 deletions(-) create mode 100644 lib/highline/builtin_styles.rb diff --git a/lib/highline.rb b/lib/highline.rb index 2a917c22..ac38035a 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -21,6 +21,7 @@ require "highline/version" require "highline/statement" require "highline/list_renderer" +require "highline/builtin_styles" # # A HighLine object is a "high-level line oriented" shell over an input and an @@ -32,6 +33,8 @@ # checking, convert types, etc. # class HighLine + include BuiltinStyles + # An internal HighLine error. User code does not need to trap this. class QuestionError < StandardError # do nothing, just creating a unique error type @@ -115,94 +118,6 @@ def self.reset_color_scheme self.color_scheme = nil end - # - # Embed in a String to clear all previous ANSI sequences. This *MUST* be - # done before the program exits! - # - - ERASE_LINE_STYLE = Style.new(:name=>:erase_line, :builtin=>true, :code=>"\e[K") # Erase the current line of terminal output - ERASE_CHAR_STYLE = Style.new(:name=>:erase_char, :builtin=>true, :code=>"\e[P") # Erase the character under the cursor. - CLEAR_STYLE = Style.new(:name=>:clear, :builtin=>true, :code=>"\e[0m") # Clear color settings - RESET_STYLE = Style.new(:name=>:reset, :builtin=>true, :code=>"\e[0m") # Alias for CLEAR. - BOLD_STYLE = Style.new(:name=>:bold, :builtin=>true, :code=>"\e[1m") # Bold; Note: bold + a color works as you'd expect, - # for example bold black. Bold without a color displays - # the system-defined bold color (e.g. red on Mac iTerm) - DARK_STYLE = Style.new(:name=>:dark, :builtin=>true, :code=>"\e[2m") # Dark; support uncommon - UNDERLINE_STYLE = Style.new(:name=>:underline, :builtin=>true, :code=>"\e[4m") # Underline - UNDERSCORE_STYLE = Style.new(:name=>:underscore, :builtin=>true, :code=>"\e[4m") # Alias for UNDERLINE - BLINK_STYLE = Style.new(:name=>:blink, :builtin=>true, :code=>"\e[5m") # Blink; support uncommon - REVERSE_STYLE = Style.new(:name=>:reverse, :builtin=>true, :code=>"\e[7m") # Reverse foreground and background - CONCEALED_STYLE = Style.new(:name=>:concealed, :builtin=>true, :code=>"\e[8m") # Concealed; support uncommon - - STYLES = %w{CLEAR RESET BOLD DARK UNDERLINE UNDERSCORE BLINK REVERSE CONCEALED} - - # These RGB colors are approximate; see http://en.wikipedia.org/wiki/ANSI_escape_code - BLACK_STYLE = Style.new(:name=>:black, :builtin=>true, :code=>"\e[30m", :rgb=>[ 0, 0, 0]) - RED_STYLE = Style.new(:name=>:red, :builtin=>true, :code=>"\e[31m", :rgb=>[128, 0, 0]) - GREEN_STYLE = Style.new(:name=>:green, :builtin=>true, :code=>"\e[32m", :rgb=>[ 0,128, 0]) - BLUE_STYLE = Style.new(:name=>:blue, :builtin=>true, :code=>"\e[34m", :rgb=>[ 0, 0,128]) - YELLOW_STYLE = Style.new(:name=>:yellow, :builtin=>true, :code=>"\e[33m", :rgb=>[128,128, 0]) - MAGENTA_STYLE = Style.new(:name=>:magenta, :builtin=>true, :code=>"\e[35m", :rgb=>[128, 0,128]) - CYAN_STYLE = Style.new(:name=>:cyan, :builtin=>true, :code=>"\e[36m", :rgb=>[ 0,128,128]) - # On Mac OSX Terminal, white is actually gray - WHITE_STYLE = Style.new(:name=>:white, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192]) - # Alias for WHITE, since WHITE is actually a light gray on Macs - GRAY_STYLE = Style.new(:name=>:gray, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192]) - GREY_STYLE = Style.new(:name=>:grey, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192]) - # On Mac OSX Terminal, this is black foreground, or bright white background. - # Also used as base for RGB colors, if available - NONE_STYLE = Style.new(:name=>:none, :builtin=>true, :code=>"\e[38m", :rgb=>[ 0, 0, 0]) - - BASIC_COLORS = %w{BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE GRAY GREY NONE} - - colors = BASIC_COLORS.dup - BASIC_COLORS.each do |color| - bright_color = "BRIGHT_#{color}" - colors << bright_color - const_set bright_color+'_STYLE', const_get(color + '_STYLE').bright - - light_color = "LIGHT_#{color}" - colors << light_color - const_set light_color+'_STYLE', const_get(color + '_STYLE').light - end - COLORS = colors - - colors.each do |color| - const_set color, const_get("#{color}_STYLE").code - const_set "ON_#{color}_STYLE", const_get("#{color}_STYLE").on - const_set "ON_#{color}", const_get("ON_#{color}_STYLE").code - end - ON_NONE_STYLE.rgb = [255,255,255] # Override; white background - - STYLES.each do |style| - const_set style, const_get("#{style}_STYLE").code - end - - # For RGB colors: - def self.const_missing(name) - if name.to_s =~ /^(ON_)?(RGB_)([A-F0-9]{6})(_STYLE)?$/ # RGB color - on = $1 - suffix = $4 - if suffix - code_name = $1.to_s + $2 + $3 - else - code_name = name.to_s - end - style_name = code_name + '_STYLE' - style = Style.rgb($3) - style = style.on if on - const_set(style_name, style) - const_set(code_name, style.code) - if suffix - style - else - style.code - end - else - raise NameError, "Bad color or uninitialized constant #{name}" - end - end - # # Create an instance of HighLine, connected to the streams _input_ # and _output_. diff --git a/lib/highline/builtin_styles.rb b/lib/highline/builtin_styles.rb new file mode 100644 index 00000000..e228a156 --- /dev/null +++ b/lib/highline/builtin_styles.rb @@ -0,0 +1,93 @@ +#coding: utf-8 + +class HighLine + module BuiltinStyles + # + # Embed in a String to clear all previous ANSI sequences. This *MUST* be + # done before the program exits! + # + + ERASE_LINE_STYLE = Style.new(:name=>:erase_line, :builtin=>true, :code=>"\e[K") # Erase the current line of terminal output + ERASE_CHAR_STYLE = Style.new(:name=>:erase_char, :builtin=>true, :code=>"\e[P") # Erase the character under the cursor. + CLEAR_STYLE = Style.new(:name=>:clear, :builtin=>true, :code=>"\e[0m") # Clear color settings + RESET_STYLE = Style.new(:name=>:reset, :builtin=>true, :code=>"\e[0m") # Alias for CLEAR. + BOLD_STYLE = Style.new(:name=>:bold, :builtin=>true, :code=>"\e[1m") # Bold; Note: bold + a color works as you'd expect, + # for example bold black. Bold without a color displays + # the system-defined bold color (e.g. red on Mac iTerm) + DARK_STYLE = Style.new(:name=>:dark, :builtin=>true, :code=>"\e[2m") # Dark; support uncommon + UNDERLINE_STYLE = Style.new(:name=>:underline, :builtin=>true, :code=>"\e[4m") # Underline + UNDERSCORE_STYLE = Style.new(:name=>:underscore, :builtin=>true, :code=>"\e[4m") # Alias for UNDERLINE + BLINK_STYLE = Style.new(:name=>:blink, :builtin=>true, :code=>"\e[5m") # Blink; support uncommon + REVERSE_STYLE = Style.new(:name=>:reverse, :builtin=>true, :code=>"\e[7m") # Reverse foreground and background + CONCEALED_STYLE = Style.new(:name=>:concealed, :builtin=>true, :code=>"\e[8m") # Concealed; support uncommon + + STYLES = %w{CLEAR RESET BOLD DARK UNDERLINE UNDERSCORE BLINK REVERSE CONCEALED} + + # These RGB colors are approximate; see http://en.wikipedia.org/wiki/ANSI_escape_code + BLACK_STYLE = Style.new(:name=>:black, :builtin=>true, :code=>"\e[30m", :rgb=>[ 0, 0, 0]) + RED_STYLE = Style.new(:name=>:red, :builtin=>true, :code=>"\e[31m", :rgb=>[128, 0, 0]) + GREEN_STYLE = Style.new(:name=>:green, :builtin=>true, :code=>"\e[32m", :rgb=>[ 0,128, 0]) + BLUE_STYLE = Style.new(:name=>:blue, :builtin=>true, :code=>"\e[34m", :rgb=>[ 0, 0,128]) + YELLOW_STYLE = Style.new(:name=>:yellow, :builtin=>true, :code=>"\e[33m", :rgb=>[128,128, 0]) + MAGENTA_STYLE = Style.new(:name=>:magenta, :builtin=>true, :code=>"\e[35m", :rgb=>[128, 0,128]) + CYAN_STYLE = Style.new(:name=>:cyan, :builtin=>true, :code=>"\e[36m", :rgb=>[ 0,128,128]) + # On Mac OSX Terminal, white is actually gray + WHITE_STYLE = Style.new(:name=>:white, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192]) + # Alias for WHITE, since WHITE is actually a light gray on Macs + GRAY_STYLE = Style.new(:name=>:gray, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192]) + GREY_STYLE = Style.new(:name=>:grey, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192]) + # On Mac OSX Terminal, this is black foreground, or bright white background. + # Also used as base for RGB colors, if available + NONE_STYLE = Style.new(:name=>:none, :builtin=>true, :code=>"\e[38m", :rgb=>[ 0, 0, 0]) + + BASIC_COLORS = %w{BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE GRAY GREY NONE} + + colors = BASIC_COLORS.dup + BASIC_COLORS.each do |color| + bright_color = "BRIGHT_#{color}" + colors << bright_color + const_set bright_color+'_STYLE', const_get(color + '_STYLE').bright + + light_color = "LIGHT_#{color}" + colors << light_color + const_set light_color+'_STYLE', const_get(color + '_STYLE').light + end + COLORS = colors + + colors.each do |color| + const_set color, const_get("#{color}_STYLE").code + const_set "ON_#{color}_STYLE", const_get("#{color}_STYLE").on + const_set "ON_#{color}", const_get("ON_#{color}_STYLE").code + end + ON_NONE_STYLE.rgb = [255,255,255] # Override; white background + + STYLES.each do |style| + const_set style, const_get("#{style}_STYLE").code + end + + # For RGB colors: + def self.const_missing(name) + if name.to_s =~ /^(ON_)?(RGB_)([A-F0-9]{6})(_STYLE)?$/ # RGB color + on = $1 + suffix = $4 + if suffix + code_name = $1.to_s + $2 + $3 + else + code_name = name.to_s + end + style_name = code_name + '_STYLE' + style = Style.rgb($3) + style = style.on if on + const_set(style_name, style) + const_set(code_name, style.code) + if suffix + style + else + style.code + end + else + raise NameError, "Bad color or uninitialized constant #{name}" + end + end + end +end \ No newline at end of file From 7a5e96e8aee17d123957d13ef884c842b1d2baff Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 9 Jul 2015 16:13:03 -0300 Subject: [PATCH 02/43] Make const_missing available when HighLine::BuiltinStyles is included --- lib/highline/builtin_styles.rb | 45 +++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/lib/highline/builtin_styles.rb b/lib/highline/builtin_styles.rb index e228a156..4c0a3b4f 100644 --- a/lib/highline/builtin_styles.rb +++ b/lib/highline/builtin_styles.rb @@ -2,6 +2,9 @@ class HighLine module BuiltinStyles + def self.included(base) + base.extend ClassMethods + end # # Embed in a String to clear all previous ANSI sequences. This *MUST* be # done before the program exits! @@ -65,28 +68,30 @@ module BuiltinStyles const_set style, const_get("#{style}_STYLE").code end - # For RGB colors: - def self.const_missing(name) - if name.to_s =~ /^(ON_)?(RGB_)([A-F0-9]{6})(_STYLE)?$/ # RGB color - on = $1 - suffix = $4 - if suffix - code_name = $1.to_s + $2 + $3 - else - code_name = name.to_s - end - style_name = code_name + '_STYLE' - style = Style.rgb($3) - style = style.on if on - const_set(style_name, style) - const_set(code_name, style.code) - if suffix - style + module ClassMethods + # For RGB colors: + def const_missing(name) + if name.to_s =~ /^(ON_)?(RGB_)([A-F0-9]{6})(_STYLE)?$/ # RGB color + on = $1 + suffix = $4 + if suffix + code_name = $1.to_s + $2 + $3 + else + code_name = name.to_s + end + style_name = code_name + '_STYLE' + style = Style.rgb($3) + style = style.on if on + const_set(style_name, style) + const_set(code_name, style.code) + if suffix + style + else + style.code + end else - style.code + raise NameError, "Bad color or uninitialized constant #{name}" end - else - raise NameError, "Bad color or uninitialized constant #{name}" end end end From a498560c95c80c19ec33e346f45e440612188934 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 16 Jul 2015 23:54:48 -0300 Subject: [PATCH 03/43] Review HighLine#say --- lib/highline.rb | 18 +++++++++--------- test/test_highline.rb | 5 +++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index ac38035a..481e5bda 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -305,24 +305,24 @@ def list(items, mode = :rows, option = nil) # ends with a space or tab character, a newline will not be appended (output # will be flush()ed). All other cases are passed straight to Kernel.puts(). # - # The _statement_ parameter is processed as an ERb template, supporting - # embedded Ruby code. The template is evaluated with a binding inside - # the HighLine instance, providing easy access to the ANSI color constants - # and the HighLine.color() method. + # The _statement_ argument is processed as an ERb template, supporting + # embedded Ruby code. The template is evaluated within a HighLine + # instance's binding for providing easy access to the ANSI color constants + # and the HighLine#color() method. # - def say( statement ) + def say(statement) statement = render_statement(statement) return if statement.empty? - out = (indentation+statement) + statement = (indentation+statement) # Don't add a newline if statement ends with whitespace, OR # if statement ends with whitespace before a color escape code. if /[ \t](\e\[\d+(;\d+)*m)?\Z/ =~ statement - @output.print(out) - @output.flush + output.print(statement) + output.flush else - @output.puts(out) + output.puts(statement) end end diff --git a/test/test_highline.rb b/test/test_highline.rb index 0eb803e2..4060c938 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -1220,6 +1220,11 @@ def test_say @terminal.say("This will not have a newline. ") assert_equal("This will not have a newline. ", @output.string) + @output.truncate(@output.rewind) + + @terminal.say("This will not have a newline.\t") + assert_equal("This will not have a newline.\t", @output.string) + @output.truncate(@output.rewind) @terminal.say("This will not\n end with a newline. ") From dd5f8bee32757a081a93899acb6189088e1d5305 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 00:21:36 -0300 Subject: [PATCH 04/43] It's 'nil check' hunting season --- lib/highline.rb | 8 ++++---- lib/highline/color_scheme.rb | 2 +- lib/highline/import.rb | 4 ++-- lib/highline/menu.rb | 14 ++++++-------- lib/highline/question.rb | 18 +++++++++--------- lib/highline/terminal/jruby_jline.rb | 2 +- lib/highline/terminal/unix_stty.rb | 2 +- 7 files changed, 24 insertions(+), 26 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 481e5bda..b0c24ce8 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -104,7 +104,7 @@ def self.color_scheme # Returns +true+ if HighLine is currently using a color scheme. def self.using_color_scheme? - not @@color_scheme.nil? + !!@@color_scheme end # Reset HighLine to default. @@ -423,7 +423,7 @@ def new_scope # of the question. # def explain_error(error, question) - say(question.responses[error]) unless error.nil? + say(question.responses[error]) if error say(question.ask_on_error_msg) end @@ -437,7 +437,7 @@ def ask_once(question) # 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 ((question.readline) and (question.echo == true and question.limit.nil?)) + say(question) unless ((question.readline) and (question.echo == true and !question.limit)) begin question.get_response_or_default(self) @@ -598,7 +598,7 @@ def get_line(question) end def get_response_line_mode(question) - if question.echo == true and question.limit.nil? + if question.echo == true and !question.limit get_line(question) else line = "" diff --git a/lib/highline/color_scheme.rb b/lib/highline/color_scheme.rb index 0d07c423..47032f09 100644 --- a/lib/highline/color_scheme.rb +++ b/lib/highline/color_scheme.rb @@ -50,7 +50,7 @@ class ColorScheme # def initialize( h = nil ) @scheme = Hash.new - load_from_hash(h) unless h.nil? + load_from_hash(h) if h yield self if block_given? end diff --git a/lib/highline/import.rb b/lib/highline/import.rb index 7a0e6fa8..ce6ec0ec 100644 --- a/lib/highline/import.rb +++ b/lib/highline/import.rb @@ -35,9 +35,9 @@ class Object # def or_ask( *args, &details ) ask(*args) do |question| - question.first_answer = String(self) unless nil? + question.first_answer = String(self) - details.call(question) unless details.nil? + details.call(question) if details end end end diff --git a/lib/highline/menu.rb b/lib/highline/menu.rb index 71c4f474..401cdb77 100644 --- a/lib/highline/menu.rb +++ b/lib/highline/menu.rb @@ -138,7 +138,7 @@ def initialize( ) def choice( name, help = nil, &action ) @items << [name, action] - @help[name.to_s.downcase] = help unless help.nil? + @help[name.to_s.downcase] = help if help update_responses # rebuild responses based on our settings end @@ -156,7 +156,7 @@ def choices( *names, &action ) def hidden( name, help = nil, &action ) @hidden_items << [name, action] - @help[name.to_s.downcase] = help unless help.nil? + @help[name.to_s.downcase] = help if help end # @@ -305,7 +305,7 @@ def select( highline_context, selection, details = nil ) end # Run or return it. - if not action.nil? + if action @highline = highline_context if @shell result = action.call(name, details) @@ -313,10 +313,8 @@ def select( highline_context, selection, details = nil ) result = action.call(name) end @nil_on_handled ? nil : result - elsif action.nil? - name else - nil + name end ensure # make sure the hidden items are removed, before we return @@ -349,12 +347,12 @@ def to_ary( ) def to_s( ) case @layout when :list - '<%= if header.nil? then '' else "#{header}:\n" end %>' + + %(<%= header ? "#{header}:\n" : '' %>) + "<%= list( menu, #{@flow.inspect}, #{@list_option.inspect} ) %>" + "<%= prompt %>" when :one_line - '<%= if header.nil? then '' else "#{header}: " end %>' + + %(<%= header ? "#{header}: " : '' %>) + "<%= prompt %>" + "(<%= list( menu, #{@flow.inspect}, #{@list_option.inspect} ) %>)" + diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 97b6f655..385924ae 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -334,9 +334,9 @@ def choices_complete(answer_string) def expected_range( ) expected = [ ] - expected << "above #{@above}" unless @above.nil? - expected << "below #{@below}" unless @below.nil? - expected << "included in #{@in.inspect}" unless @in.nil? + expected << "above #{@above}" if @above + expected << "below #{@below}" if @below + expected << "included in #{@in.inspect}" if @in case expected.size when 0 then "" @@ -355,7 +355,7 @@ def first_answer( ) # Returns true if _first_answer_ is set. def first_answer?( ) - not @first_answer.nil? + !!@first_answer end # @@ -365,9 +365,9 @@ def first_answer?( ) # are not checked. # def in_range? - (@above.nil? or answer > @above) and - (@below.nil? or answer < @below) and - (@in.nil? or @in.include?(answer)) + (!@above or answer > @above) and + (!@below or answer < @below) and + (!@in or @in.include?(answer)) end # @@ -390,7 +390,7 @@ def in_range? # This process is skipped for single character input. # def remove_whitespace( answer_string ) - if @whitespace.nil? + if !@whitespace answer_string elsif [:strip, :chomp].include?(@whitespace) answer_string.send(@whitespace) @@ -442,7 +442,7 @@ def to_s # and case handling. # def valid_answer? - @validate.nil? or + !@validate or (@validate.is_a?(Regexp) and answer =~ @validate) or (@validate.is_a?(Proc) and @validate[answer]) end diff --git a/lib/highline/terminal/jruby_jline.rb b/lib/highline/terminal/jruby_jline.rb index 8e9a47db..ec7b7445 100644 --- a/lib/highline/terminal/jruby_jline.rb +++ b/lib/highline/terminal/jruby_jline.rb @@ -27,7 +27,7 @@ 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 + raise EOFError, "The input stream is exhausted." if !raw_answer and highline.track_eof? end end diff --git a/lib/highline/terminal/unix_stty.rb b/lib/highline/terminal/unix_stty.rb index ba5cc4b7..1d9b3d35 100644 --- a/lib/highline/terminal/unix_stty.rb +++ b/lib/highline/terminal/unix_stty.rb @@ -62,7 +62,7 @@ def get_line_with_readline(question, highline, options={}) raw_answer = readline_read(question_string, question) - if raw_answer.nil? and highline.track_eof? + if !raw_answer and highline.track_eof? raise EOFError, "The input stream is exhausted." end From bd9e74c89807e4a3de7a1920f0d4d9a3c50f6c3d Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 09:59:33 -0300 Subject: [PATCH 05/43] Remove the 'setting environment before invocation' option of HighLine#ask We shouldn't rely on setting instance variables before a method invocation. Let's do it passing arguments only. --- lib/highline.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index b0c24ce8..a15f9142 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -192,10 +192,6 @@ def agree( yes_or_no_question, character = nil ) # HighLine::Question for more information about _answer_type_ and what's # valid in the code block. # - # If @question is set before ask() is called, parameters are - # ignored and that object (must be a HighLine::Question) is used to drive - # the process instead. - # # Raises EOFError if input is exhausted. # def ask(template_or_question, answer_type = nil, options = {}, &details) # :yields: question From 5f6780d4f85272ccae5a81cb08a7811ebd005d65 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 10:02:13 -0300 Subject: [PATCH 06/43] Move the responsabilities of dealing with Question initialization to Question itself It also simplifies HighLine#ask conditionals. At this same commit, remove the dependency on a @question instance variable. --- lib/highline.rb | 11 +++-------- lib/highline/question.rb | 12 ++++++++++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index a15f9142..61646c4a 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -194,14 +194,9 @@ def agree( yes_or_no_question, character = nil ) # # Raises EOFError if input is exhausted. # - 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 question.ask_at(self) + def ask(template_or_question, answer_type = nil, &details) + question = Question.build(template_or_question, answer_type, &details) + question.ask_at(self) end # diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 385924ae..b080c9a9 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -25,6 +25,18 @@ class NoAutoCompleteMatch < StandardError # do nothing, just creating a unique error type end + # + # If _template_or_question_ is already a Question object just return it. + # If not, build it. + # + def self.build(template_or_question, answer_type = nil, &details) + if template_or_question.is_a? Question + template_or_question + else + Question.new(template_or_question, answer_type, &details) + end + end + # # Create an instance of HighLine::Question. Expects a _template_ to ask # (can be "") and an _answer_type_ to convert the answer to. From 3b7d9225df9667000951da9d5e36bdf067afe376 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 10:04:14 -0300 Subject: [PATCH 07/43] Completely remove @question inst var from HighLine objects ... and fix tests accordling. Removing unecessary _state_ handling (inst vars) is a step toward a thiner HighLine class. Question shouldn't be a HighLine's _state_ because the **same** HighLine instance could be able to ask several questions. (At the previous code @question was a kind of _current_question_ state. But this is not really necessary currently.) --- lib/highline.rb | 3 --- lib/highline/template_renderer.rb | 2 +- test/test_highline.rb | 4 ++-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 61646c4a..062cafcf 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -134,7 +134,6 @@ def initialize( input = $stdin, output = $stdout, self.wrap_at = wrap_at self.page_at = page_at - @question = nil @header = nil @prompt = nil @key = nil @@ -157,8 +156,6 @@ def initialize( input = $stdin, output = $stdout, attr_reader :key - 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. diff --git a/lib/highline/template_renderer.rb b/lib/highline/template_renderer.rb index ea439053..5b495f20 100644 --- a/lib/highline/template_renderer.rb +++ b/lib/highline/template_renderer.rb @@ -6,7 +6,7 @@ class HighLine class TemplateRenderer extend Forwardable - def_delegators :@highline, :color, :list, :key, :question + def_delegators :@highline, :color, :list, :key def_delegators :@source, :answer_type, :prompt, :header, :answer attr_reader :template, :source, :highline diff --git a/test/test_highline.rb b/test/test_highline.rb index 4060c938..fe942454 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -1195,8 +1195,8 @@ def test_response_embedding 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 #{q.answer_type}" + + " #{q.expected_range}." end assert_equal(28, answer) assert_equal( "Tell me your age.\n" + From 078c4e8625285657de1ba0c3c99781aca81c03c8 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 16 Jul 2015 14:50:24 -0300 Subject: [PATCH 08/43] Include lib subdirs in RDoc Rake task --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 4c69fc09..00d018f4 100644 --- a/Rakefile +++ b/Rakefile @@ -18,7 +18,7 @@ RDoc::Task.new do |rdoc| rdoc.rdoc_files.include( "README.rdoc", "INSTALL", "TODO", "Changelog.md", "AUTHORS", "COPYING", - "LICENSE", "lib /*.rb" ) + "LICENSE", "lib/**/*.rb") rdoc.main = "README.rdoc" rdoc.rdoc_dir = "doc/html" rdoc.title = "HighLine Documentation" From 7a877e3f03b4c319184e65548891540e31cdbaf6 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 13:49:44 -0300 Subject: [PATCH 09/43] Add some rdoc markup for correct doc generation Some copyright notes above scoped class/module definitions were mixing up with the main scope (HighLine) class documentation. --- lib/highline.rb | 1 + lib/highline/color_scheme.rb | 1 + lib/highline/menu.rb | 1 + lib/highline/question.rb | 1 + lib/highline/simulate.rb | 2 ++ lib/highline/style.rb | 1 + lib/highline/terminal.rb | 1 + 7 files changed, 8 insertions(+) diff --git a/lib/highline.rb b/lib/highline.rb index 062cafcf..89d25231 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -1,5 +1,6 @@ # 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 47032f09..1d2e2840 100644 --- a/lib/highline/color_scheme.rb +++ b/lib/highline/color_scheme.rb @@ -1,5 +1,6 @@ # coding: utf-8 +#-- # color_scheme.rb # # Created by Jeremy Hinegardner on 2007-01-24 diff --git a/lib/highline/menu.rb b/lib/highline/menu.rb index 401cdb77..425a98d6 100644 --- a/lib/highline/menu.rb +++ b/lib/highline/menu.rb @@ -1,5 +1,6 @@ # coding: utf-8 +#-- # menu.rb # # Created by Gregory Thomas Brown on 2005-05-10. diff --git a/lib/highline/question.rb b/lib/highline/question.rb index b080c9a9..9fc70732 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -1,5 +1,6 @@ # 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 4bad8f96..4bc1cc99 100644 --- a/lib/highline/simulate.rb +++ b/lib/highline/simulate.rb @@ -1,5 +1,6 @@ # coding: utf-8 +#-- # simulate.rb # # Created by Andy Rossmeissl on 2012-04-29. @@ -8,6 +9,7 @@ # This is Free Software. See LICENSE and COPYING for details. # # adapted from https://gist.github.com/194554 + class HighLine # Simulates Highline input for use in tests. diff --git a/lib/highline/style.rb b/lib/highline/style.rb index 72871b68..2468ff4f 100755 --- a/lib/highline/style.rb +++ b/lib/highline/style.rb @@ -1,5 +1,6 @@ # coding: utf-8 +#-- # color_scheme.rb # # Created by Richard LeBer on 2011-06-27. diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index b23fe653..10925c18 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -1,5 +1,6 @@ # coding: utf-8 +#-- # terminal.rb # # Originally created by James Edward Gray II on 2006-06-14 as From c343443975341040ad83b6e5ce0e007131a9fca2 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 13:52:48 -0300 Subject: [PATCH 10/43] Extract HighLine::String to its own file and fix doc generation for it --- lib/highline/string.rb | 32 +++++++++++++++++++++++++++++++ lib/highline/string_extensions.rb | 31 ++---------------------------- 2 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 lib/highline/string.rb diff --git a/lib/highline/string.rb b/lib/highline/string.rb new file mode 100644 index 00000000..72784dd0 --- /dev/null +++ b/lib/highline/string.rb @@ -0,0 +1,32 @@ +# coding: utf-8 + +require "highline/string_extensions" + +# +# HighLine::String is a subclass of String with convenience methods added for colorization. +# +# Available convenience methods include: +# * 'color' method e.g. highline_string.color(:bright_blue, :underline) +# * colors e.g. highline_string.magenta +# * RGB colors e.g. highline_string.rgb_ff6000 +# or highline_string.rgb(255,96,0) +# * background colors e.g. highline_string.on_magenta +# * RGB background colors e.g. highline_string.on_rgb_ff6000 +# or highline_string.on_rgb(255,96,0) +# * styles e.g. highline_string.underline +# +# Additionally, convenience methods can be chained, for instance the following are equivalent: +# highline_string.bright_blue.blink.underline +# highline_string.color(:bright_blue, :blink, :underline) +# HighLine.color(highline_string, :bright_blue, :blink, :underline) +# +# For those less squeamish about possible conflicts, the same convenience methods can be +# added to the built-in String class, as follows: +# +# require 'highline' +# Highline.colorize_strings +# + +class HighLine::String < ::String + include StringExtensions +end \ No newline at end of file diff --git a/lib/highline/string_extensions.rb b/lib/highline/string_extensions.rb index a094bb4b..97376e41 100644 --- a/lib/highline/string_extensions.rb +++ b/lib/highline/string_extensions.rb @@ -1,35 +1,12 @@ # coding: utf-8 -# Extensions for class String -# -# HighLine::String is a subclass of String with convenience methods added for colorization. -# -# Available convenience methods include: -# * 'color' method e.g. highline_string.color(:bright_blue, :underline) -# * colors e.g. highline_string.magenta -# * RGB colors e.g. highline_string.rgb_ff6000 -# or highline_string.rgb(255,96,0) -# * background colors e.g. highline_string.on_magenta -# * RGB background colors e.g. highline_string.on_rgb_ff6000 -# or highline_string.on_rgb(255,96,0) -# * styles e.g. highline_string.underline -# -# Additionally, convenience methods can be chained, for instance the following are equivalent: -# highline_string.bright_blue.blink.underline -# highline_string.color(:bright_blue, :blink, :underline) -# HighLine.color(highline_string, :bright_blue, :blink, :underline) -# -# For those less squeamish about possible conflicts, the same convenience methods can be -# added to the built-in String class, as follows: -# -# require 'highline' -# Highline.colorize_strings - class HighLine def self.String(s) HighLine::String.new(s) end + # HighLine extensions for String class + # Included by HighLine::String module StringExtensions def self.included(base) HighLine::COLORS.each do |color| @@ -103,10 +80,6 @@ def method_missing(method, *args, &blk) end end - class HighLine::String < ::String - include StringExtensions - end - def self.colorize_strings ::String.send(:include, StringExtensions) end From 832758241208d77e7acb6c78f11a8dbbbb58b6cf Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 16:09:07 -0300 Subject: [PATCH 11/43] Make the new HighLine::String work With the constricted scope ```class HighLine::String < ::String``` we would have to do a ```include HighLine::StringExtensions``` The alternative fix here was to separate the scopes like ```ruby class HighLine class String < ::String ``` So we could use ```include StringExtensions``` --- lib/highline.rb | 2 +- lib/highline/string.rb | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 89d25231..156f472e 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -670,4 +670,4 @@ def actual_length(text) end end -require "highline/string_extensions" +require "highline/string" diff --git a/lib/highline/string.rb b/lib/highline/string.rb index 72784dd0..94a82717 100644 --- a/lib/highline/string.rb +++ b/lib/highline/string.rb @@ -27,6 +27,8 @@ # Highline.colorize_strings # -class HighLine::String < ::String - include StringExtensions +class HighLine + class String < ::String + include StringExtensions + end end \ No newline at end of file From 8f710dcf8ace52cc70226ea4ba32efda344f3f07 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 17:23:15 -0300 Subject: [PATCH 12/43] Class variable hunting season is open! --- lib/highline.rb | 20 ++++++++++---------- lib/highline/style.rb | 22 +++++++++++----------- lib/highline/terminal/windows_fiddle.rb | 12 ++++++------ 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 156f472e..4e12e1d7 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -54,16 +54,16 @@ class NoConfirmationQuestionError < QuestionError end # The setting used to disable color output. - @@use_color = true + @use_color = true # Pass +false+ to _setting_ to turn off HighLine's color escapes. def self.use_color=( setting ) - @@use_color = setting + @use_color = setting end # Returns true if HighLine is currently using color escapes. def self.use_color? - @@use_color + @use_color end # For checking if the current version of HighLine supports RGB colors @@ -74,16 +74,16 @@ def self.supports_rgb_color? end # The setting used to disable EOF tracking. - @@track_eof = true + @track_eof = true # Pass +false+ to _setting_ to turn off HighLine's EOF tracking. def self.track_eof=( setting ) - @@track_eof = setting + @track_eof = setting end # Returns true if HighLine is currently tracking EOF for input. def self.track_eof? - @@track_eof + @track_eof end def track_eof? @@ -91,21 +91,21 @@ def track_eof? end # The setting used to control color schemes. - @@color_scheme = nil + @color_scheme = nil # Pass ColorScheme to _setting_ to set a HighLine color scheme. def self.color_scheme=( setting ) - @@color_scheme = setting + @color_scheme = setting end # Returns the current color scheme. def self.color_scheme - @@color_scheme + @color_scheme end # Returns +true+ if HighLine is currently using a color scheme. def self.using_color_scheme? - !!@@color_scheme + !!@color_scheme end # Reset HighLine to default. diff --git a/lib/highline/style.rb b/lib/highline/style.rb index 2468ff4f..b3b65cd4 100755 --- a/lib/highline/style.rb +++ b/lib/highline/style.rb @@ -45,23 +45,23 @@ class Style def self.index(style) if style.name - @@styles ||= {} - @@styles[style.name] = style + @styles ||= {} + @styles[style.name] = style end if !style.list - @@code_index ||= {} - @@code_index[style.code] ||= [] - @@code_index[style.code].reject!{|indexed_style| indexed_style.name == style.name} - @@code_index[style.code] << style + @code_index ||= {} + @code_index[style.code] ||= [] + @code_index[style.code].reject!{|indexed_style| indexed_style.name == style.name} + @code_index[style.code] << style end style end def self.clear_index # reset to builtin only styles - @@styles = list.select { |name, style| style.builtin } - @@code_index = {} - @@styles.each { |name, style| index(style) } + @styles = list.select { |name, style| style.builtin } + @code_index = {} + @styles.each { |name, style| index(style) } end def self.rgb_hex(*colors) @@ -97,11 +97,11 @@ def self.ansi_rgb_to_hex(ansi_number) end def self.list - @@styles ||= {} + @styles ||= {} end def self.code_index - @@code_index ||= {} + @code_index ||= {} end def self.uncolor(string) diff --git a/lib/highline/terminal/windows_fiddle.rb b/lib/highline/terminal/windows_fiddle.rb index 7e0c8442..54f5a293 100644 --- a/lib/highline/terminal/windows_fiddle.rb +++ b/lib/highline/terminal/windows_fiddle.rb @@ -12,19 +12,19 @@ module WinAPI Crt = Handle.new("msvcrt") rescue Handle.new("crtdll") def self._getch - @@_m_getch ||= Function.new(Crt["_getch"], [], TYPE_INT) - @@_m_getch.call + @_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) + @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 ||= + @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) + @get_console_screen_buffer_info.call(cons_handle, lp_buffer) end end end From 14e7b9c8c940d8d72f8487b74b8f6df71cb4f3a5 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 17:25:05 -0300 Subject: [PATCH 13/43] Add Terminal::IOConsole (copy Terminal::UnixStty) --- lib/highline/terminal.rb | 18 +++++- lib/highline/terminal/io_console.rb | 96 +++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 lib/highline/terminal/io_console.rb diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index 10925c18..d0ea9065 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -14,8 +14,22 @@ class HighLine class Terminal def self.get_terminal - require 'highline/terminal/unix_stty' - terminal = HighLine::Terminal::UnixStty.new + terminal = nil + + # First of all, probe for io/console + begin + require "io/console" + require "highline/terminal/io_console" + terminal = HighLine::Terminal::IOConsole.new + rescue LoadError + end + + # Fall back to UnixStty + unless terminal + require 'highline/terminal/unix_stty' + terminal = HighLine::Terminal::UnixStty.new + end + terminal.initialize_system_extensions terminal end diff --git a/lib/highline/terminal/io_console.rb b/lib/highline/terminal/io_console.rb new file mode 100644 index 00000000..857a3c7a --- /dev/null +++ b/lib/highline/terminal/io_console.rb @@ -0,0 +1,96 @@ +# coding: utf-8 + +class HighLine + class Terminal + class IOConsole < 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 + + 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 = "unix_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}" + print "\r" + end + + def get_character( input = STDIN ) + input.getc + end + + def character_mode + "unix_stty" + end + + def get_line(question, highline, options={}) + raw_answer = + if question.readline + get_line_with_readline(question, highline, options={}) + else + get_line_default(highline) + end + + question.format_answer(raw_answer) + end + + def get_line_with_readline(question, highline, options={}) + require "readline" # load only if needed + + question_string = highline.render_statement(question) + + raw_answer = readline_read(question_string, question) + + if !raw_answer and highline.track_eof? + raise EOFError, "The input stream is exhausted." + 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 + 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 +end \ No newline at end of file From 6e1878e1f1ea29149fe454c23786c6947f43ee98 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 17:47:51 -0300 Subject: [PATCH 14/43] Make Terminal::IOConsole work --- lib/highline/terminal/io_console.rb | 34 ++++++----------------------- test/test_highline.rb | 2 +- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/lib/highline/terminal/io_console.rb b/lib/highline/terminal/io_console.rb index 857a3c7a..f53489f6 100644 --- a/lib/highline/terminal/io_console.rb +++ b/lib/highline/terminal/io_console.rb @@ -3,46 +3,26 @@ class HighLine class Terminal class IOConsole < 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 - - 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 + IO.console.winsize.reverse end - # *WARNING*: This requires the external "stty" program! - CHARACTER_MODE = "unix_stty" # For Debugging purposes only. + CHARACTER_MODE = "io_console" # For Debugging purposes only. def raw_no_echo_mode - @state = `stty -g` - system "stty raw -echo -icanon isig" + STDIN.echo = false end def restore_mode - system "stty #{@state}" - print "\r" + STDIN.echo = true end - def get_character( input = STDIN ) - input.getc + def get_character(input = STDIN) + input.getch # from ruby io/console end def character_mode - "unix_stty" + "io_console" end def get_line(question, highline, options={}) diff --git a/test/test_highline.rb b/test/test_highline.rb index fe942454..2cddde96 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -952,7 +952,7 @@ def test_lists_with_three_items end def test_mode - assert(%w[Win32API termios ncurses stty unix_stty jline].include?(@terminal.terminal.character_mode), + assert(%w[io_console Win32API termios ncurses stty unix_stty jline].include?(@terminal.terminal.character_mode), "#{@terminal.terminal.character_mode} not in list") end From b336e2fe3535225142215e33ad9f6ffa2b7a6eb4 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 18:50:11 -0300 Subject: [PATCH 15/43] Make tests involving (io/console) #getch and Tempfile work --- test/test_highline.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/test_highline.rb b/test/test_highline.rb index 2cddde96..7b088fa5 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -15,6 +15,12 @@ require "readline" require "tempfile" +class File + # Fake _getch_ method so that Terminal::IOConsole + # works well with File and Tempfile + alias_method :getch, :getc +end + =begin if HighLine::CHARACTER_MODE == "Win32API" From 85f0c933f6ac5de94824cfb7a6d4444e435e3456 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 19:09:50 -0300 Subject: [PATCH 16/43] Advertise what Terminal class in use at tests and examples So one could easily figure out if the "auto-detection" is not working. --- examples/asking_for_arrays.rb | 3 +++ examples/basic_usage.rb | 3 +++ examples/get_character.rb | 3 +++ examples/limit.rb | 3 +++ examples/menus.rb | 3 +++ examples/overwrite.rb | 3 +++ examples/password.rb | 3 +++ examples/repeat_entry.rb | 3 +++ test/test_helper.rb | 3 +++ 9 files changed, 27 insertions(+) diff --git a/examples/asking_for_arrays.rb b/examples/asking_for_arrays.rb index 64caeaf1..fa05a3e5 100644 --- a/examples/asking_for_arrays.rb +++ b/examples/asking_for_arrays.rb @@ -9,6 +9,9 @@ require "highline/import" require "pp" +puts "Using: #{$terminal.terminal.class}" +puts + grades = ask( "Enter test scores (or a blank line to quit):", lambda { |ans| ans =~ /^-?\d+$/ ? Integer(ans) : ans} ) do |q| q.gather = "" diff --git a/examples/basic_usage.rb b/examples/basic_usage.rb index 3f9b5aa4..126c64a7 100644 --- a/examples/basic_usage.rb +++ b/examples/basic_usage.rb @@ -9,6 +9,9 @@ require "highline/import" require "yaml" +puts "Using: #{$terminal.terminal.class}" +puts + contacts = [ ] class NameClass diff --git a/examples/get_character.rb b/examples/get_character.rb index c22d4127..48e4dba7 100644 --- a/examples/get_character.rb +++ b/examples/get_character.rb @@ -3,6 +3,9 @@ require "rubygems" require "highline/import" +puts "Using: #{$terminal.terminal.class}" +puts + choices = "ynaq" answer = ask("Your choice [#{choices}]? ") do |q| q.echo = false diff --git a/examples/limit.rb b/examples/limit.rb index 8b4d1905..6d25cef8 100644 --- a/examples/limit.rb +++ b/examples/limit.rb @@ -8,5 +8,8 @@ require "rubygems" require "highline/import" +puts "Using: #{$terminal.terminal.class}" +puts + text = ask("Enter text (max 10 chars): ") { |q| q.limit = 10 } puts "You entered: #{text}!" diff --git a/examples/menus.rb b/examples/menus.rb index c2bd5e39..ffa63bfd 100644 --- a/examples/menus.rb +++ b/examples/menus.rb @@ -3,6 +3,9 @@ require "rubygems" require "highline/import" +puts "Using: #{$terminal.terminal.class}" +puts + # The old way, using ask() and say()... choices = %w{ruby python perl} say("This is the old way using ask() and say()...") diff --git a/examples/overwrite.rb b/examples/overwrite.rb index 04f3d8b6..83d51a5e 100644 --- a/examples/overwrite.rb +++ b/examples/overwrite.rb @@ -8,6 +8,9 @@ require 'rubygems' require 'highline/import' +puts "Using: #{$terminal.terminal.class}" +puts + prompt = "here is your password:" ask( "#{prompt} <%= color('mypassword', RED, BOLD) %> (Press Any Key to blank) " diff --git a/examples/password.rb b/examples/password.rb index 87fff8dd..a9e591a4 100644 --- a/examples/password.rb +++ b/examples/password.rb @@ -3,5 +3,8 @@ require "rubygems" require "highline/import" +puts "Using: #{$terminal.terminal.class}" +puts + pass = ask("Enter your password: ") { |q| q.echo = false } puts "Your password is #{pass}!" diff --git a/examples/repeat_entry.rb b/examples/repeat_entry.rb index 753262ea..553b7a61 100644 --- a/examples/repeat_entry.rb +++ b/examples/repeat_entry.rb @@ -3,6 +3,9 @@ require "rubygems" require "highline/import" +puts "Using: #{$terminal.terminal.class}" +puts + tounge_twister = ask("... try saying that three times fast") do |q| q.gather = 3 q.verify_match = true diff --git a/test/test_helper.rb b/test/test_helper.rb index 144197b1..e19550f9 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -8,4 +8,7 @@ CodeClimate::TestReporter.start end +require 'highline' +puts "Tests will be run under #{HighLine.new.terminal.class}" + require "minitest/autorun" From 691c1d9043884f99ea6333eb648ae4640b02e725 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 19:10:56 -0300 Subject: [PATCH 17/43] Remove duplicate HighLine#directory accessor There was a "warning" being issued. --- lib/highline/question.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/highline/question.rb b/lib/highline/question.rb index 9fc70732..5723ce76 100755 --- a/lib/highline/question.rb +++ b/lib/highline/question.rb @@ -78,8 +78,6 @@ def initialize( template, answer_type ) build_responses end - attr_reader :directory - # The ERb template of the question to be asked. attr_accessor :template From 8ca40cd1db4e1b6600e4369b73cbd94281372f99 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Fri, 17 Jul 2015 19:12:04 -0300 Subject: [PATCH 18/43] Change local variable name 'string' to 'str' ... so it doesn't shadow an argument with same name. --- lib/highline/terminal/io_console.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/highline/terminal/io_console.rb b/lib/highline/terminal/io_console.rb index f53489f6..1539acbc 100644 --- a/lib/highline/terminal/io_console.rb +++ b/lib/highline/terminal/io_console.rb @@ -52,8 +52,8 @@ def get_line_with_readline(question, highline, options={}) def readline_read(string, question) # prep auto-completion - Readline.completion_proc = lambda do |string| - question.selection.grep(/\A#{Regexp.escape(string)}/) + Readline.completion_proc = lambda do |str| + question.selection.grep(/\A#{Regexp.escape(str)}/) end # work-around ugly readline() warnings From 3ad917e262a84f8f0f875c6a3163d126dbdd5894 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Jul 2015 22:25:17 -0300 Subject: [PATCH 19/43] Make HighLine::Terminal instances respect HighLine defined input and output Also save input and output as HighLine::Terminal instance variables reducing argument passing needs. --- lib/highline.rb | 6 +++--- lib/highline/terminal.rb | 13 ++++++++++--- lib/highline/terminal/io_console.rb | 8 ++++---- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/highline.rb b/lib/highline.rb index 4e12e1d7..08fbad4b 100755 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -139,7 +139,7 @@ def initialize( input = $stdin, output = $stdout, @prompt = nil @key = nil - @terminal = HighLine::Terminal.get_terminal + @terminal = HighLine::Terminal.get_terminal(input, output) end # The current column setting for wrapping output. @@ -593,7 +593,7 @@ def get_response_line_mode(question) line = "" terminal.raw_no_echo_mode_exec do - while character = terminal.get_character(@input) + while character = terminal.get_character break if character == "\n" or character == "\r" # honor backspace and delete @@ -636,7 +636,7 @@ def get_response_getc_mode(question) def get_response_character_mode(question) terminal.raw_no_echo_mode_exec do - response = terminal.get_character(@input) + response = terminal.get_character if question.overwrite erase_current_line else diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index d0ea9065..e7a25168 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -13,27 +13,34 @@ class HighLine class Terminal - def self.get_terminal + def self.get_terminal(input, output) terminal = nil # First of all, probe for io/console begin require "io/console" require "highline/terminal/io_console" - terminal = HighLine::Terminal::IOConsole.new + terminal = HighLine::Terminal::IOConsole.new(input, output) rescue LoadError end # Fall back to UnixStty unless terminal require 'highline/terminal/unix_stty' - terminal = HighLine::Terminal::UnixStty.new + terminal = HighLine::Terminal::UnixStty.new(input, output) end terminal.initialize_system_extensions terminal end + attr_reader :input, :output + + def initialize(input, output) + @input = input + @output = output + end + def initialize_system_extensions end diff --git a/lib/highline/terminal/io_console.rb b/lib/highline/terminal/io_console.rb index 1539acbc..cb09f540 100644 --- a/lib/highline/terminal/io_console.rb +++ b/lib/highline/terminal/io_console.rb @@ -4,20 +4,20 @@ class HighLine class Terminal class IOConsole < Terminal def terminal_size - IO.console.winsize.reverse + output.winsize.reverse end CHARACTER_MODE = "io_console" # For Debugging purposes only. def raw_no_echo_mode - STDIN.echo = false + input.echo = false end def restore_mode - STDIN.echo = true + input.echo = true end - def get_character(input = STDIN) + def get_character input.getch # from ruby io/console end From 02d0f4f6b50a622545db6eea98b86c6c7b781582 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Jul 2015 22:31:36 -0300 Subject: [PATCH 20/43] Make Readline tests be skipped when JRuby or Rubinius We currently didn't find a way to test Readline on JRuby and Rubinius without echoing to console. At MRI Ruby we set Readline.input and Readline.output to File instances. --- lib/highline/terminal.rb | 4 ++++ test/test_highline.rb | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index e7a25168..c0523090 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -68,5 +68,9 @@ def get_character def jruby? defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' end + + def rubinius? + defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' + end end end diff --git a/test/test_highline.rb b/test/test_highline.rb index 7b088fa5..13bbe0c5 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -309,12 +309,18 @@ def test_after_some_chars_backspace_does_not_enter_prompt_when_utf8 end def test_readline_mode - # Rubinius seems to be ignoring Readline input - # and output assignments. This ruins testing. - # but it doesn't mean readline is not working - # properly on rubinius. - - return if RUBY_ENGINE == "rbx" + # + # Rubinius (and JRuby) seems to be ignoring + # Readline input and output assignments. This + # ruins testing. + # + # But it doesn't mean readline is not working + # properly on rubinius or jruby. + # + + if @terminal.terminal.jruby? or @terminal.terminal.rubinius? + skip "We can't test Readline on JRuby nor on Rubinius yet" + end # Creating Tempfiles here because Readline.input # and Readline.output only accepts a File object From ccc05fd56b5e44a4459fae313aeebf6c2cef896b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Jul 2015 22:35:53 -0300 Subject: [PATCH 21/43] Add a compatibility module to give io/console capabilities to StringIO, Tempfile and File We use StringIO, File and Tempfile at tests to mimetize STDIN and STDOUT (with io/console loaded). This modules add some methods (stubs) to give a more complete compatibility. --- test/io_console_compatible.rb | 37 +++++++++++++++++++++++++++++++++++ test/test_highline.rb | 9 +++------ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 test/io_console_compatible.rb diff --git a/test/io_console_compatible.rb b/test/io_console_compatible.rb new file mode 100644 index 00000000..c8e2e707 --- /dev/null +++ b/test/io_console_compatible.rb @@ -0,0 +1,37 @@ +# coding: utf-8 + +require 'stringio' +require 'tempfile' + +# +# On tests, we try to simulate input output with +# StringIO, Tempfile and File objects. +# +# For this to be accomplished, we have to do some +# tweaking so that they respond adequately to the +# called methods during tests. +# + +module IOConsoleCompatible + def getch + getc + end + + attr_accessor :echo + + def winsize + [24, 80] + end +end + +class Tempfile + include IOConsoleCompatible +end + +class File + include IOConsoleCompatible +end + +class StringIO + include IOConsoleCompatible +end \ No newline at end of file diff --git a/test/test_highline.rb b/test/test_highline.rb index 13bbe0c5..5a862623 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -15,12 +15,9 @@ require "readline" require "tempfile" -class File - # Fake _getch_ method so that Terminal::IOConsole - # works well with File and Tempfile - alias_method :getch, :getc -end - +# Compatibility module for StringIO, File +# and Tempfile. Necessary for some tests. +require "io_console_compatible" =begin if HighLine::CHARACTER_MODE == "Win32API" From 3418407ae6566a15821dac7c1715d32f0744c3ba Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Jul 2015 22:39:39 -0300 Subject: [PATCH 22/43] Add some debug information to be show at test run time --- test/test_helper.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index e19550f9..be60e9a3 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -9,6 +9,12 @@ end require 'highline' -puts "Tests will be run under #{HighLine.new.terminal.class}" +debug_message = "Tests will be run under #{HighLine.new.terminal.class} " + +if defined? RUBY_DESCRIPTION + debug_message << "#{RUBY_DESCRIPTION} " +end + +puts debug_message require "minitest/autorun" From a400deb91f63777fbd5627ce7f3d41f4a3247628 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Jul 2015 22:41:45 -0300 Subject: [PATCH 23/43] Add some semi-automatic 'acceptance' tests to HighLine (yup) These 'acceptance' tests guide the user through some steps asking if they SEE what they should be seeing. It summarizes the answers and adds some debug environment information that can be sent to HighLine contributors. It'll be a complementary way of testing HighLine without the caveats of using a fake input/output object like StringIO as we do on automatic unit tests. --- Rakefile | 5 ++ test/acceptance/acceptance.rb | 62 +++++++++++++++++ test/acceptance/acceptance_test.rb | 69 +++++++++++++++++++ .../at_color_output_using_erb_templates.rb | 17 +++++ test/acceptance/at_echo_false.rb | 23 +++++++ test/acceptance/at_readline.rb | 37 ++++++++++ 6 files changed, 213 insertions(+) create mode 100644 test/acceptance/acceptance.rb create mode 100644 test/acceptance/acceptance_test.rb create mode 100644 test/acceptance/at_color_output_using_erb_templates.rb create mode 100644 test/acceptance/at_echo_false.rb create mode 100644 test/acceptance/at_readline.rb diff --git a/Rakefile b/Rakefile index 00d018f4..815e120f 100644 --- a/Rakefile +++ b/Rakefile @@ -27,3 +27,8 @@ end Gem::PackageTask.new(SPEC) do |package| # do nothing: I just need a gem but this block is required end + +desc "Run some interactive acceptance tests" +task :acceptance do + load "test/acceptance/acceptance.rb" +end diff --git a/test/acceptance/acceptance.rb b/test/acceptance/acceptance.rb new file mode 100644 index 00000000..edef4581 --- /dev/null +++ b/test/acceptance/acceptance.rb @@ -0,0 +1,62 @@ +#!/usr/bin/env ruby +# coding: utf-8 + +current_dir = File.dirname(File.expand_path(__FILE__)) + +# All acceptance test files begins with 'at_' +acceptance_test_files = Dir["#{current_dir}/at_*"] + +# Load each acceptance test file making +# all tests to be run +acceptance_test_files.each { |file| load file } + +# Print a report + +report = < should be green!" + end + + t.question = "Do you see the word 'grass' on green color (y/n)? " +end diff --git a/test/acceptance/at_echo_false.rb b/test/acceptance/at_echo_false.rb new file mode 100644 index 00000000..2466b8d7 --- /dev/null +++ b/test/acceptance/at_echo_false.rb @@ -0,0 +1,23 @@ +# coding: utf-8 + +require_relative 'acceptance_test' + +HighLine::AcceptanceTest.check do |t| + t.desc = + "This step checks if the 'echo = false' " \ + "setting is effective in hiding the user " \ + "typed characters.\n" \ + "This functionality is useful when asking " \ + "for passwords.\n" \ + "When typing the characters you should not " \ + "see any of them on the screen." + + t.action = Proc.new do + answer = ask "Enter some characters and press : " do |q| + q.echo = false + end + puts "You've entered -> #{answer} <-" + end + + t.question = "Were the characters adequately hidden when you typed them (y/n)? " +end diff --git a/test/acceptance/at_readline.rb b/test/acceptance/at_readline.rb new file mode 100644 index 00000000..8a66f092 --- /dev/null +++ b/test/acceptance/at_readline.rb @@ -0,0 +1,37 @@ +# coding: utf-8 + +require_relative 'acceptance_test' + +HighLine::AcceptanceTest.check do |t| + t.desc = + "This step checks if the readline autocomplete " \ + "feature is working. \n" \ + "The test has 5 options you can choose from: " \ + "save, sample, exec, exit and load.\n" \ + "If you type the first character of one of them and then press \n" \ + "the key you should see the options available for autocomplete.\n\n" \ + "For example, if I type 's' and then I press I should see a list\n" \ + "with 'save' and 'sample' as possible options for autocomplete.\n\n" \ + "Although, if I type 'l' and then press the key it should be \n" \ + "readly autcompleted as 'load', because 'load' is the only option\n" \ + "that begins with the 'l' letter in this particular case.\n\n" \ + "If I don't type any character but press two times, I should\n" \ + "be able to see ALL available options.\n\n" \ + "Please, play with Readline autocomplete for a while, pressing \n" \ + "to see that it really gets the selected answer.\n" \ + "When ready, just type 'exit' and the loop will finish.\n\n" \ + "Don't forget to answer 'y' (yes) or 'n' (no) to the question at the end." + + t.action = Proc.new do + loop do + cmd = + ask "Enter command: ", %w{ save sample exec exit load } do |q| + q.readline = true + end + say("Executing \"#{cmd}\"...") + break if cmd == "exit" + end + end + + t.question = "Did the Readline autocomplete work fine (y/n)? " +end From 6c930177694b666c39fcf699d6a851f104bda09d Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Jul 2015 23:04:17 -0300 Subject: [PATCH 24/43] Update .travis with JRuby and the head versions of MRI --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index f4ee366f..11f3884b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,14 @@ rvm: - 2.2.0 - 2.2.1 - 2.2.2 + - ruby-head - rbx-2 + - jruby-19mode # JRuby in 1.9 mode + notifications: email: false matrix: allow_failures: + - rvm: ruby-head - rvm: rbx-2 + - rvm: jruby-19mode # JRuby in 1.9 mode From 046719b383780c194f462acafc0f42f4ac3e02cf Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 19 Jul 2015 23:49:31 -0300 Subject: [PATCH 25/43] Update changelog and bump up version to 2.0.0-develop.2 --- Changelog.md | 29 +++++++++++++++++++++++++++++ lib/highline/version.rb | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 09fe4f14..01b37b32 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,35 @@ Below is a complete listing of changes for each revision of HighLine. +### 2.0.0-develop.2 / 2015-07-19 + +(by Abinoam P. Marques Jr. - @abinoam) + +* Fix Simplecov - it was reporting erroneous code coverage +* Add new tests. Improves code coverage +* Extract HighLine::BuiltinStyles +* Try to avoid nil checking +* Try to avoid class variables (mis)use +* Fix RDoc include path and some small fixes to the docs +* Move HighLine::String to its own file +* Add HighLine::Terminal::IOConsole + - Add an IOConsoleCompatibility module with some stubbed + methods for using at StringIO, File and Tempfile to help + on tests. + - Any enviroment that can require 'io/console' will + use HighLine::Terminal::IOConsole by default. This kind + of unifies most environments where HighLine runs. For + example, we can use Terminal::IOConsole on JRuby!!! +* Add JRuby and ruby-head to Travis CI matrix. Yes, this + our first step to a more peaceful JRuby compatibility. +* Add _acceptance_ tests for HighLine + - Use ```rake acceptance``` to run them + - Basically it interactively asks the user to confirm if + some expected HighLine behaviour is actually happening. + After that it gather some environment debug information, + so the use could send to the HighLine contributors in case + of failure. + ### 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. diff --git a/lib/highline/version.rb b/lib/highline/version.rb index 288e4fa0..d7cfecdf 100644 --- a/lib/highline/version.rb +++ b/lib/highline/version.rb @@ -2,5 +2,5 @@ class HighLine # The version of the installed library. - VERSION = "2.0.0-develop.1".freeze + VERSION = "2.0.0-develop.2".freeze end From 803d59cb207eefe964ddc42e9461fdcaeaa2f6ac Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 22 Jul 2015 23:52:50 -0300 Subject: [PATCH 26/43] Specify test files explicitly - good for Windows --- Rakefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Rakefile b/Rakefile index 815e120f..0d730475 100644 --- a/Rakefile +++ b/Rakefile @@ -12,6 +12,7 @@ Rake::TestTask.new do |test| test.libs = ["lib", "test"] test.verbose = true test.warning = true + test.test_files = FileList['test/test*.rb'] end RDoc::Task.new do |rdoc| From b8b1949791d7a1a326fc7dbab94a2ab3c999512f Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 23 Jul 2015 00:01:21 -0300 Subject: [PATCH 27/43] Skip Readline tests for Windows also' --- lib/highline/terminal.rb | 4 ++++ test/test_highline.rb | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index c0523090..787d0591 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -72,5 +72,9 @@ def jruby? def rubinius? defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' end + + def windows? + defined?(RUBY_PLATFORM) && (RUBY_PLATFORM =~ /mswin|mingw|cygwin/) + end end end diff --git a/test/test_highline.rb b/test/test_highline.rb index 5a862623..93ac7e0b 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -315,8 +315,10 @@ def test_readline_mode # properly on rubinius or jruby. # - if @terminal.terminal.jruby? or @terminal.terminal.rubinius? - skip "We can't test Readline on JRuby nor on Rubinius yet" + terminal = @terminal.terminal + + if terminal.jruby? or terminal.rubinius? or terminal.windows? + skip "We can't test Readline on JRuby, Rubinius and Windows yet" end # Creating Tempfiles here because Readline.input From 6eec78714ad0b52bef14b6c0e92945db04e17caa Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 23 Jul 2015 00:07:50 -0300 Subject: [PATCH 28/43] Choose filename from right to left - better for Windows --- test/acceptance/acceptance_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/acceptance/acceptance_test.rb b/test/acceptance/acceptance_test.rb index 0b321a68..19f6deaa 100644 --- a/test/acceptance/acceptance_test.rb +++ b/test/acceptance/acceptance_test.rb @@ -6,7 +6,7 @@ class HighLine::AcceptanceTest @@answers ||= {} def self.check(&block) - caller_file = File.basename(caller[0].split(":")[0]) + caller_file = File.basename(caller[0].split(":")[-3]) test = new yield test From 26770036ffbce74c19e5b04c9631df574def6715 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 23 Jul 2015 00:46:00 -0300 Subject: [PATCH 29/43] Use Encoding::UTF_8 because StringIO always will be that in this case --- 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 93ac7e0b..a5862d24 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -1032,7 +1032,7 @@ def test_correct_string_encoding_when_echo_false end assert_equal "ação", answer - assert_equal Encoding::default_external, answer.encoding + assert_equal Encoding::UTF_8, answer.encoding end def test_backspace_with_ascii_when_echo_false From 1c32748d814e06ac7ad556afc5dfc0ce50203c4b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 23 Jul 2015 00:54:22 -0300 Subject: [PATCH 30/43] Add appveyor.yml - CI on Windows Thanks @mattbrictson at https://mattbrictson.com/how-to-test-ruby-windows --- appveyor.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..da28b2be --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,19 @@ +version: '{build}' + +skip_tags: true + +environment: + matrix: + - ruby_version: "21" + - ruby_version: "21-x64" + +install: + - SET PATH=C:\Ruby%ruby_version%\bin;%PATH% + - gem install bundler --no-document -v 1.10.5 + - bundle install --retry=3 + +test_script: + - bundle exec rake + +build: off + From a9d36045b72359bb9d6c84be5f2b8d69a3b5ea62 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 16 Aug 2015 03:46:55 -0300 Subject: [PATCH 31/43] Encapsulate the Readline.readline in a block that preserves stty state This is related to: - https://github.com/JEG2/highline/pull/149#issuecomment-124687391 - https://github.com/jruby/jruby/issues/3181 --- lib/highline/terminal/io_console.rb | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/highline/terminal/io_console.rb b/lib/highline/terminal/io_console.rb index cb09f540..21042e47 100644 --- a/lib/highline/terminal/io_console.rb +++ b/lib/highline/terminal/io_console.rb @@ -59,7 +59,10 @@ def readline_read(string, question) # work-around ugly readline() warnings old_verbose = $VERBOSE $VERBOSE = nil - raw_answer = Readline.readline(string, true) + + raw_answer = run_preserving_stty do + Readline.readline(string, true) + end $VERBOSE = old_verbose @@ -71,6 +74,23 @@ def get_line_default(highline) highline.input.eof? highline.input.gets end + + private + + def run_preserving_stty + save_stty + yield + ensure + restore_stty + end + + def save_stty + @stty_save = `stty -g`.chomp rescue nil + end + + def restore_stty + system("stty", @stty_save) if @stty_save + end end end end \ No newline at end of file From 8b6b912cf1e950989e524412ac2fc6f86e2b9153 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 16 Aug 2015 03:49:35 -0300 Subject: [PATCH 32/43] Set Readline.completion_proc only if there's a Question#selection given This preserves any default Readline.readline behaviour (ex: automplete with the file names in current dir) --- lib/highline/terminal/io_console.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/highline/terminal/io_console.rb b/lib/highline/terminal/io_console.rb index cb09f540..e96cde90 100644 --- a/lib/highline/terminal/io_console.rb +++ b/lib/highline/terminal/io_console.rb @@ -52,8 +52,10 @@ def get_line_with_readline(question, highline, options={}) def readline_read(string, question) # prep auto-completion - Readline.completion_proc = lambda do |str| - question.selection.grep(/\A#{Regexp.escape(str)}/) + unless question.selection.empty? + Readline.completion_proc = lambda do |str| + question.selection.grep(/\A#{Regexp.escape(str)}/) + end end # work-around ugly readline() warnings From e7b50cd1f6c9a2209e9a9c2a7bd4efdb557a6ce3 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 6 Sep 2015 15:52:28 -0300 Subject: [PATCH 33/43] Add more debug messages on test/test_helper.rb --- test/test_helper.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index be60e9a3..1459ca38 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -9,10 +9,12 @@ end require 'highline' -debug_message = "Tests will be run under #{HighLine.new.terminal.class} " +debug_message = "Tests will be run under:\n" +debug_message << " - #{HighLine.new.terminal.class}\n" +debug_message << " - HighLine::VERSION #{HighLine::VERSION}\n" if defined? RUBY_DESCRIPTION - debug_message << "#{RUBY_DESCRIPTION} " + debug_message << " - #{RUBY_DESCRIPTION}\n" end puts debug_message From 02457e6ea558c963ac0f7abb9cca7ddd4de6c1af Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Sun, 6 Sep 2015 23:09:15 -0300 Subject: [PATCH 34/43] Require io_console_compatible at test_helper so other files benefit from it --- test/test_helper.rb | 4 ++++ test/test_highline.rb | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index 1459ca38..449c7d27 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -8,6 +8,10 @@ CodeClimate::TestReporter.start end +# Compatibility module for StringIO, File +# and Tempfile. Necessary for some tests. +require "io_console_compatible" + require 'highline' debug_message = "Tests will be run under:\n" debug_message << " - #{HighLine.new.terminal.class}\n" diff --git a/test/test_highline.rb b/test/test_highline.rb index a5862d24..19fd9895 100755 --- a/test/test_highline.rb +++ b/test/test_highline.rb @@ -15,10 +15,6 @@ require "readline" require "tempfile" -# Compatibility module for StringIO, File -# and Tempfile. Necessary for some tests. -require "io_console_compatible" - =begin if HighLine::CHARACTER_MODE == "Win32API" class HighLine From 6fea52828d1fbc7af85668bef2dceafeed37419b Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 8 Sep 2015 14:33:56 -0300 Subject: [PATCH 35/43] Remove unecessary begin clause. Use def as 'delimiter'. --- lib/highline/terminal.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/highline/terminal.rb b/lib/highline/terminal.rb index 787d0591..695a16d5 100755 --- a/lib/highline/terminal.rb +++ b/lib/highline/terminal.rb @@ -52,11 +52,9 @@ def raw_no_echo_mode def raw_no_echo_mode_exec raw_no_echo_mode - begin - yield - ensure - restore_mode - end + yield + ensure + restore_mode end def restore_mode From f27035ce8fa5f2e043ab9b7ca0c2153dcfb9f3e4 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 8 Sep 2015 14:35:23 -0300 Subject: [PATCH 36/43] Remove _old_ and broken windows code. We will rely on io/console. --- lib/highline/terminal/windows.rb | 38 ---------------------- lib/highline/terminal/windows_dl_import.rb | 37 --------------------- lib/highline/terminal/windows_fiddle.rb | 32 ------------------ 3 files changed, 107 deletions(-) delete mode 100644 lib/highline/terminal/windows.rb delete mode 100644 lib/highline/terminal/windows_dl_import.rb delete mode 100644 lib/highline/terminal/windows_fiddle.rb diff --git a/lib/highline/terminal/windows.rb b/lib/highline/terminal/windows.rb deleted file mode 100644 index 81b1d671..00000000 --- a/lib/highline/terminal/windows.rb +++ /dev/null @@ -1,38 +0,0 @@ -# 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 deleted file mode 100644 index 721f0485..00000000 --- a/lib/highline/terminal/windows_dl_import.rb +++ /dev/null @@ -1,37 +0,0 @@ -# coding: utf-8 - -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 deleted file mode 100644 index 54f5a293..00000000 --- a/lib/highline/terminal/windows_fiddle.rb +++ /dev/null @@ -1,32 +0,0 @@ -# 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 From 3e33ce063d08f323649f4573dfbf17b752064293 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 8 Sep 2015 14:37:03 -0300 Subject: [PATCH 37/43] Remove _old_ and broken termios code. We will rely on io/console. --- lib/highline/terminal/unix_termios.rb | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 lib/highline/terminal/unix_termios.rb diff --git a/lib/highline/terminal/unix_termios.rb b/lib/highline/terminal/unix_termios.rb deleted file mode 100644 index 3a0a7993..00000000 --- a/lib/highline/terminal/unix_termios.rb +++ /dev/null @@ -1,23 +0,0 @@ -# coding: utf-8 - -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 From a5127fa30e78b5c40c393420e77f1327b3262166 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 8 Sep 2015 14:38:53 -0300 Subject: [PATCH 38/43] Remove _old_, duplicate and broken stty code. There's a new unix_stty in substitution. --- lib/highline/terminal/stty.rb | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 lib/highline/terminal/stty.rb diff --git a/lib/highline/terminal/stty.rb b/lib/highline/terminal/stty.rb deleted file mode 100644 index 695281cc..00000000 --- a/lib/highline/terminal/stty.rb +++ /dev/null @@ -1,20 +0,0 @@ -# coding: utf-8 - -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}" - print "\r" - end - end - end -end \ No newline at end of file From 8a6125373d75956f8175bb68e08fc85f6aac08f9 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 8 Sep 2015 14:40:59 -0300 Subject: [PATCH 39/43] Remove _old_ and broken jruby code. We will rely on io/console. --- lib/highline/terminal/jruby.rb | 37 ---------------------------- lib/highline/terminal/jruby_jline.rb | 35 -------------------------- 2 files changed, 72 deletions(-) delete mode 100644 lib/highline/terminal/jruby.rb delete mode 100644 lib/highline/terminal/jruby_jline.rb diff --git a/lib/highline/terminal/jruby.rb b/lib/highline/terminal/jruby.rb deleted file mode 100644 index 2c1b6da8..00000000 --- a/lib/highline/terminal/jruby.rb +++ /dev/null @@ -1,37 +0,0 @@ -# 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 deleted file mode 100644 index ec7b7445..00000000 --- a/lib/highline/terminal/jruby_jline.rb +++ /dev/null @@ -1,35 +0,0 @@ -# coding: utf-8 - -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 - - # 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 and - highline.track_eof? - end - end - end -end \ No newline at end of file From a994dc48621d81cea87cc211f58dfec0cf45dc60 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Tue, 8 Sep 2015 14:43:01 -0300 Subject: [PATCH 40/43] Add a TODO note on ncurses code. Will we maintain it? --- lib/highline/terminal/ncurses.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/highline/terminal/ncurses.rb b/lib/highline/terminal/ncurses.rb index cb2b593d..10453138 100644 --- a/lib/highline/terminal/ncurses.rb +++ b/lib/highline/terminal/ncurses.rb @@ -1,5 +1,10 @@ # coding: utf-8 +# TODO: +# Code below to be discussed. +# Will we maintain an ncurses version of HighLine::Terminal? +# If so, port it to the new api. + class HighLine module SystemExtensions module NCurses From d890f5e944f3e20253635c8f9af98001320ebab5 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 9 Sep 2015 21:45:57 -0300 Subject: [PATCH 41/43] Add AppVeyor (Windows) CI build status badge to README.rdoc --- README.rdoc | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rdoc b/README.rdoc index edae8493..fd5af908 100644 --- a/README.rdoc +++ b/README.rdoc @@ -3,6 +3,7 @@ by James Edward Gray II {Build Status}[https://travis-ci.org/JEG2/highline] +{AppVeyor Build Status}[https://ci.appveyor.com/project/abinoam/highline] {}[http://rubygems.org/gems/highline] {}[https://codeclimate.com/github/JEG2/highline] {}[https://codeclimate.com/github/JEG2/highline/coverage] From 65ef18de6cc9a799334ffdb8a8f55f794460a044 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Wed, 9 Sep 2015 23:29:58 -0300 Subject: [PATCH 42/43] Update travis rubies versions for JRuby-9.0.2.0 (head) And also simplifies the versions to be tested. --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 11f3884b..28dd4be6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,15 +3,14 @@ language: ruby sudo: false script: "bundle exec rake test" rvm: - - 1.9.3 - - 2.0.0 - - 2.1.5 - - 2.2.0 - - 2.2.1 - - 2.2.2 + - 1.9 + - 2.0 + - 2.1 + - 2.2 - ruby-head - rbx-2 - jruby-19mode # JRuby in 1.9 mode + - jruby-head notifications: email: false @@ -20,3 +19,4 @@ matrix: - rvm: ruby-head - rvm: rbx-2 - rvm: jruby-19mode # JRuby in 1.9 mode + - rvm: jruby-head From 91143b4f5c172dacf38fa74171ec569045217114 Mon Sep 17 00:00:00 2001 From: Abinoam Praxedes Marques Jr Date: Thu, 10 Sep 2015 00:01:01 -0300 Subject: [PATCH 43/43] Update Changelog.md - 2.0.0-develop.2 --- Changelog.md | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index 01b37b32..00aff0c8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,10 +2,25 @@ Below is a complete listing of changes for each revision of HighLine. -### 2.0.0-develop.2 / 2015-07-19 +### 2.0.0-develop.2 / 2015-09-09 (by Abinoam P. Marques Jr. - @abinoam) +#### NOTES + +This version brings greater compatibility with JRuby and Windows. +But we still have a lot of small issues in both platforms. +We were able to unify/converge all approaches into using io/console, +so we could delete old code that relied solely on stty, termios, java api and +windows apis (DL and Fiddle). + +Another improvement is the beginning of what I called "acceptance tests". +If you type ```rake acceptance``` you'll be guided through some tests +where you have to input some thing and see if everything work as expected. +This makes easier to catch bugs that otherwise would be over-sighted. + +#### CHANGES SUMMARY + * Fix Simplecov - it was reporting erroneous code coverage * Add new tests. Improves code coverage * Extract HighLine::BuiltinStyles @@ -21,15 +36,23 @@ Below is a complete listing of changes for each revision of HighLine. use HighLine::Terminal::IOConsole by default. This kind of unifies most environments where HighLine runs. For example, we can use Terminal::IOConsole on JRuby!!! -* Add JRuby and ruby-head to Travis CI matrix. Yes, this +* Add ruby-head and JRuby (19mode and head) to Travis CI matrix. Yes, this our first step to a more peaceful JRuby compatibility. +* Add AppVeyor Continuous Integration for Windows * Add _acceptance_ tests for HighLine - Use ```rake acceptance``` to run them - Basically it interactively asks the user to confirm if - some expected HighLine behaviour is actually happening. + some expected HighLine behavior is actually happening. After that it gather some environment debug information, so the use could send to the HighLine contributors in case of failure. +* Remove old and unused files (as a result of relying on io/console) + - JRuby + - Windows (DL and Fiddle) + - Termios +* Fix some small (old and new) bugs +* Make some more tuning for Windows compatibility +* Make some more tuning for JRuby compatibility ### 2.0.0-develop.1 / 2015-06-11