diff --git a/.travis.yml b/.travis.yml
index f4ee366f..28dd4be6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,15 +3,20 @@ 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
matrix:
allow_failures:
+ - rvm: ruby-head
- rvm: rbx-2
+ - rvm: jruby-19mode # JRuby in 1.9 mode
+ - rvm: jruby-head
diff --git a/Changelog.md b/Changelog.md
index 09fe4f14..00aff0c8 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,58 @@
Below is a complete listing of changes for each revision of HighLine.
+### 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
+* 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 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 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
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/README.rdoc b/README.rdoc
index edae8493..fd5af908 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -3,6 +3,7 @@
by James Edward Gray II
{}[https://travis-ci.org/JEG2/highline]
+{}[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]
diff --git a/Rakefile b/Rakefile
index 4c69fc09..0d730475 100644
--- a/Rakefile
+++ b/Rakefile
@@ -12,13 +12,14 @@ 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|
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"
@@ -27,3 +28,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/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
+
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/lib/highline.rb b/lib/highline.rb
index 2a917c22..08fbad4b 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.
@@ -21,6 +22,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 +34,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
@@ -50,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
@@ -70,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?
@@ -87,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?
- not @@color_scheme.nil?
+ !!@color_scheme
end
# Reset HighLine to default.
@@ -115,94 +119,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_.
@@ -219,12 +135,11 @@ def initialize( input = $stdin, output = $stdout,
self.wrap_at = wrap_at
self.page_at = page_at
- @question = nil
@header = nil
@prompt = nil
@key = nil
- @terminal = HighLine::Terminal.get_terminal
+ @terminal = HighLine::Terminal.get_terminal(input, output)
end
# The current column setting for wrapping output.
@@ -242,8 +157,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.
@@ -277,20 +190,11 @@ 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
- 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
#
@@ -390,24 +294,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
@@ -508,7 +412,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
@@ -522,7 +426,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)
@@ -683,13 +587,13 @@ 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 = ""
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
@@ -732,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
@@ -766,4 +670,4 @@ def actual_length(text)
end
end
-require "highline/string_extensions"
+require "highline/string"
diff --git a/lib/highline/builtin_styles.rb b/lib/highline/builtin_styles.rb
new file mode 100644
index 00000000..4c0a3b4f
--- /dev/null
+++ b/lib/highline/builtin_styles.rb
@@ -0,0 +1,98 @@
+#coding: utf-8
+
+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!
+ #
+
+ 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
+
+ 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
+ raise NameError, "Bad color or uninitialized constant #{name}"
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/lib/highline/color_scheme.rb b/lib/highline/color_scheme.rb
index 0d07c423..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
@@ -50,7 +51,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..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.
@@ -138,7 +139,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 +157,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 +306,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 +314,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 +348,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..5723ce76 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.
@@ -25,6 +26,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.
@@ -65,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
@@ -334,9 +345,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 +366,7 @@ def first_answer( )
# Returns true if _first_answer_ is set.
def first_answer?( )
- not @first_answer.nil?
+ !!@first_answer
end
#
@@ -365,9 +376,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 +401,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 +453,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/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/string.rb b/lib/highline/string.rb
new file mode 100644
index 00000000..94a82717
--- /dev/null
+++ b/lib/highline/string.rb
@@ -0,0 +1,34 @@
+# 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
+ class String < ::String
+ include StringExtensions
+ end
+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
diff --git a/lib/highline/style.rb b/lib/highline/style.rb
index 72871b68..b3b65cd4 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.
@@ -44,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)
@@ -96,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/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/lib/highline/terminal.rb b/lib/highline/terminal.rb
index b23fe653..695a16d5 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
@@ -12,13 +13,34 @@
class HighLine
class Terminal
- def self.get_terminal
- require 'highline/terminal/unix_stty'
- terminal = HighLine::Terminal::UnixStty.new
+ 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(input, output)
+ rescue LoadError
+ end
+
+ # Fall back to UnixStty
+ unless terminal
+ require 'highline/terminal/unix_stty'
+ 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
@@ -30,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
@@ -46,5 +66,13 @@ def get_character
def jruby?
defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
end
+
+ 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/lib/highline/terminal/io_console.rb b/lib/highline/terminal/io_console.rb
new file mode 100644
index 00000000..5515fddf
--- /dev/null
+++ b/lib/highline/terminal/io_console.rb
@@ -0,0 +1,98 @@
+# coding: utf-8
+
+class HighLine
+ class Terminal
+ class IOConsole < Terminal
+ def terminal_size
+ output.winsize.reverse
+ end
+
+ CHARACTER_MODE = "io_console" # For Debugging purposes only.
+
+ def raw_no_echo_mode
+ input.echo = false
+ end
+
+ def restore_mode
+ input.echo = true
+ end
+
+ def get_character
+ input.getch # from ruby io/console
+ end
+
+ def character_mode
+ "io_console"
+ 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
+ unless question.selection.empty?
+ Readline.completion_proc = lambda do |str|
+ question.selection.grep(/\A#{Regexp.escape(str)}/)
+ end
+ end
+
+ # work-around ugly readline() warnings
+ old_verbose = $VERBOSE
+ $VERBOSE = nil
+
+ raw_answer = run_preserving_stty do
+ Readline.readline(string, true)
+ end
+
+ $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
+
+ 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
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 8e9a47db..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.nil? and
- highline.track_eof?
- end
- end
- end
-end
\ No newline at end of file
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
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
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
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
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 7e0c8442..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
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
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
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_helper.rb b/test/test_helper.rb
index 144197b1..449c7d27 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -8,4 +8,19 @@
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"
+debug_message << " - HighLine::VERSION #{HighLine::VERSION}\n"
+
+if defined? RUBY_DESCRIPTION
+ debug_message << " - #{RUBY_DESCRIPTION}\n"
+end
+
+puts debug_message
+
require "minitest/autorun"
diff --git a/test/test_highline.rb b/test/test_highline.rb
index 0eb803e2..19fd9895 100755
--- a/test/test_highline.rb
+++ b/test/test_highline.rb
@@ -15,7 +15,6 @@
require "readline"
require "tempfile"
-
=begin
if HighLine::CHARACTER_MODE == "Win32API"
class HighLine
@@ -303,12 +302,20 @@ 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.
+ #
+ # 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.
+ #
+
+ terminal = @terminal.terminal
- return if RUBY_ENGINE == "rbx"
+ 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
# and Readline.output only accepts a File object
@@ -952,7 +959,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
@@ -1021,7 +1028,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
@@ -1195,8 +1202,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" +
@@ -1220,6 +1227,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. ")