highline 1.6.21 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rake", :require => false
4
+ gem "rdoc", :require => false
5
+
6
+ group(:development, :tests) do
7
+ gem "code_statistics", :require => false
8
+ gem "test-unit", :require => false
9
+ end
data/INSTALL CHANGED
@@ -3,6 +3,10 @@
3
3
  RubyGems is the preferred easy install method for HighLine. However, you can
4
4
  install HighLine manually as described below.
5
5
 
6
+ == Requirements
7
+
8
+ HighLine from version >= 1.7.0 requires ruby >= 1.9.3
9
+
6
10
  == Installing the Gem
7
11
 
8
12
  HighLine is intended to be installed via the
@@ -1,7 +1,9 @@
1
- = Read Me
1
+ = HighLine
2
2
 
3
3
  by James Edward Gray II
4
4
 
5
+ {<img src="https://travis-ci.org/JEG2/highline.svg" alt="Build Status" />}[https://travis-ci.org/JEG2/highline]
6
+
5
7
  == Description
6
8
 
7
9
  Welcome to HighLine.
@@ -57,6 +59,10 @@ Menus:
57
59
 
58
60
  For more examples see the examples/ directory of this project.
59
61
 
62
+ == Requirements
63
+
64
+ HighLine from version >= 1.7.0 requires ruby >= 1.9.3
65
+
60
66
  == Installing
61
67
 
62
68
  See the INSTALL file for instructions.
data/Rakefile CHANGED
@@ -1,50 +1,30 @@
1
1
  require "rdoc/task"
2
2
  require "rake/testtask"
3
3
  require "rubygems/package_task"
4
+ require "bundler/gem_tasks"
5
+ require "code_statistics"
4
6
 
5
7
  require "rubygems"
6
8
 
7
9
  task :default => [:test]
8
10
 
9
11
  Rake::TestTask.new do |test|
10
- test.libs << "test"
11
- test.test_files = [ "test/ts_all.rb"]
12
- test.verbose = true
13
- test.ruby_opts << "-w"
12
+ test.libs = ["lib", "test"]
13
+ test.test_files = FileList[ "test/tc_*.rb"]
14
+ test.verbose = true
15
+ test.warning = true
14
16
  end
15
17
 
16
- Rake::RDocTask.new do |rdoc|
18
+ RDoc::Task.new do |rdoc|
17
19
  rdoc.rdoc_files.include( "README.rdoc", "INSTALL",
18
- "TODO", "CHANGELOG",
20
+ "TODO", "Changelog.md",
19
21
  "AUTHORS", "COPYING",
20
- "LICENSE", "lib/" )
22
+ "LICENSE", "lib /*.rb" )
21
23
  rdoc.main = "README.rdoc"
22
24
  rdoc.rdoc_dir = "doc/html"
23
25
  rdoc.title = "HighLine Documentation"
24
26
  end
25
27
 
26
- desc "Upload current documentation to Rubyforge"
27
- task :upload_docs => [:rdoc] do
28
- sh "scp -r doc/html/* " +
29
- "bbazzarrakk@rubyforge.org:/var/www/gforge-projects/highline/doc/"
30
- sh "scp -r site/* " +
31
- "bbazzarrakk@rubyforge.org:/var/www/gforge-projects/highline/"
32
- end
33
-
34
- load(File.join(File.dirname(__FILE__), "highline.gemspec"))
35
28
  Gem::PackageTask.new(SPEC) do |package|
36
29
  # do nothing: I just need a gem but this block is required
37
30
  end
38
-
39
- desc "Show library's code statistics"
40
- task :stats do
41
- require 'code_statistics'
42
- CodeStatistics.new( ["HighLine", "lib"],
43
- ["Functionals", "examples"],
44
- ["Units", "test"] ).to_s
45
- end
46
-
47
- desc "Add new files to Subversion"
48
- task :add_to_svn do
49
- sh %Q{svn status | ruby -nae 'system "svn add \#{$F[1]}" if $F[0] == "?"' }
50
- end
@@ -1,12 +1,9 @@
1
- DIR = File.dirname(__FILE__)
2
- LIB = File.join(DIR, *%w[lib highline.rb])
3
- GEM_VERSION = open(LIB) { |lib|
4
- lib.each { |line|
5
- if v = line[/^\s*VERSION\s*=\s*(['"])(\d+\.\d+\.\d+)\1/, 2]
6
- break v
7
- end
8
- }
9
- }
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'highline/version'
5
+
6
+ GEM_VERSION = HighLine::VERSION
10
7
 
11
8
  SPEC = Gem::Specification.new do |spec|
12
9
  spec.name = "highline"
@@ -17,7 +14,7 @@ SPEC = Gem::Specification.new do |spec|
17
14
 
18
15
  spec.test_files = `git ls-files -- test/*.rb`.split("\n")
19
16
  spec.has_rdoc = true
20
- spec.extra_rdoc_files = %w[README.rdoc INSTALL TODO CHANGELOG LICENSE]
17
+ spec.extra_rdoc_files = %w[README.rdoc INSTALL TODO Changelog.md LICENSE]
21
18
  spec.rdoc_options << '--title' << 'HighLine Documentation' <<
22
19
  '--main' << 'README'
23
20
 
@@ -26,7 +23,7 @@ SPEC = Gem::Specification.new do |spec|
26
23
  spec.author = "James Edward Gray II"
27
24
  spec.email = "james@graysoftinc.com"
28
25
  spec.rubyforge_project = "highline"
29
- spec.homepage = "http://highline.rubyforge.org"
26
+ spec.homepage = "https://github.com/JEG2/highline"
30
27
  spec.license = "Ruby"
31
28
  spec.description = <<END_DESC
32
29
  A high-level IO library that provides validation, type conversion, and more for
@@ -34,4 +31,7 @@ command-line interfaces. HighLine also includes a complete menu system that can
34
31
  crank out anything from simple list selection to complete shells with just
35
32
  minutes of work.
36
33
  END_DESC
34
+
35
+ spec.add_development_dependency "code_statistics"
36
+ spec.required_ruby_version = '>= 1.9.3'
37
37
  end
@@ -1,3 +1,4 @@
1
+ # coding: utf-8
1
2
  # highline.rb
2
3
  #
3
4
  # Created by James Edward Gray II on 2005-04-26.
@@ -16,6 +17,7 @@ require "highline/question"
16
17
  require "highline/menu"
17
18
  require "highline/color_scheme"
18
19
  require "highline/style"
20
+ require "highline/version"
19
21
 
20
22
  #
21
23
  # A HighLine object is a "high-level line oriented" shell over an input and an
@@ -27,9 +29,6 @@ require "highline/style"
27
29
  # checking, convert types, etc.
28
30
  #
29
31
  class HighLine
30
- # The version of the installed library.
31
- VERSION = "1.6.21".freeze
32
-
33
32
  # An internal HighLine error. User code does not need to trap this.
34
33
  class QuestionError < StandardError
35
34
  # do nothing, just creating a unique error type
@@ -119,17 +118,22 @@ class HighLine
119
118
  WHITE_STYLE = Style.new(:name=>:white, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192])
120
119
  # Alias for WHITE, since WHITE is actually a light gray on Macs
121
120
  GRAY_STYLE = Style.new(:name=>:gray, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192])
121
+ GREY_STYLE = Style.new(:name=>:grey, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192])
122
122
  # On Mac OSX Terminal, this is black foreground, or bright white background.
123
123
  # Also used as base for RGB colors, if available
124
124
  NONE_STYLE = Style.new(:name=>:none, :builtin=>true, :code=>"\e[38m", :rgb=>[ 0, 0, 0])
125
125
 
126
- BASIC_COLORS = %w{BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE GRAY NONE}
126
+ BASIC_COLORS = %w{BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE GRAY GREY NONE}
127
127
 
128
128
  colors = BASIC_COLORS.dup
129
129
  BASIC_COLORS.each do |color|
130
130
  bright_color = "BRIGHT_#{color}"
131
131
  colors << bright_color
132
132
  const_set bright_color+'_STYLE', const_get(color + '_STYLE').bright
133
+
134
+ light_color = "LIGHT_#{color}"
135
+ colors << light_color
136
+ const_set light_color+'_STYLE', const_get(color + '_STYLE').light
133
137
  end
134
138
  COLORS = colors
135
139
 
@@ -244,7 +248,7 @@ class HighLine
244
248
  #
245
249
  # Raises EOFError if input is exhausted.
246
250
  #
247
- def ask( question, answer_type = String, &details ) # :yields: question
251
+ def ask( question, answer_type = nil, &details ) # :yields: question
248
252
  @question ||= Question.new(question, answer_type, &details)
249
253
 
250
254
  return gather if @question.gather
@@ -254,7 +258,7 @@ class HighLine
254
258
  # the prompt will not be issued. And we have to account for that now.
255
259
  # Also, JRuby-1.7's ConsoleReader.readLine() needs to be passed the prompt
256
260
  # to handle line editing properly.
257
- say(@question) unless ((JRUBY or @question.readline) and @question.echo == true)
261
+ say(@question) unless ((JRUBY or @question.readline) and (@question.echo == true and @question.limit.nil?))
258
262
 
259
263
  begin
260
264
  @answer = @question.answer_or_default(get_response)
@@ -617,13 +621,15 @@ class HighLine
617
621
  statement = format_statement(statement)
618
622
  return unless statement.length > 0
619
623
 
620
- # Don't add a newline if statement ends with whitespace, OR
624
+ out = (indentation+statement).encode(Encoding.default_external, { :undef => :replace } )
625
+
626
+ # Don't add a newline if statement ends with whitespace, OR
621
627
  # if statement ends with whitespace before a color escape code.
622
628
  if /[ \t](\e\[\d+(;\d+)*m)?\Z/ =~ statement
623
- @output.print(indentation+statement)
629
+ @output.print(out)
624
630
  @output.flush
625
631
  else
626
- @output.puts(indentation+statement)
632
+ @output.puts(out)
627
633
  end
628
634
  end
629
635
 
@@ -708,19 +714,19 @@ class HighLine
708
714
  private
709
715
 
710
716
  def format_statement statement
711
- statement = statement.dup.to_str
717
+ statement = String(statement || "").dup
712
718
  return statement unless statement.length > 0
713
719
 
714
- # Allow non-ascii menu prompts in ruby > 1.9.2. ERB eval the menu statement
715
- # with the environment's default encoding(usually utf8)
716
- statement.force_encoding(Encoding.default_external) if defined?(Encoding) && Encoding.default_external
717
-
718
720
  template = ERB.new(statement, nil, "%")
719
721
  statement = template.result(binding)
720
722
 
721
723
  statement = wrap(statement) unless @wrap_at.nil?
722
724
  statement = page_print(statement) unless @page_at.nil?
723
725
 
726
+ # 'statement' is encoded in US-ASCII when using ruby 1.9.3(-p551)
727
+ # 'indentation' is correctly encoded (same as default_external encoding)
728
+ statement = statement.force_encoding(Encoding.default_external)
729
+
724
730
  statement = statement.gsub(/\n(?!$)/,"\n#{indentation}") if @multi_indent
725
731
 
726
732
  statement
@@ -886,18 +892,20 @@ class HighLine
886
892
  else
887
893
  raw_no_echo_mode
888
894
 
889
- line = ""
895
+ line = "".encode(Encoding::BINARY)
890
896
  backspace_limit = 0
891
897
  begin
892
898
 
893
899
  while character = get_character(@input)
894
900
  # honor backspace and delete
895
901
  if character == 127 or character == 8
902
+ line = line.force_encoding(Encoding.default_external)
896
903
  line.slice!(-1, 1)
897
904
  backspace_limit -= 1
905
+ line = line.force_encoding(Encoding::BINARY)
898
906
  else
899
907
  line << character.chr
900
- backspace_limit = line.size
908
+ backspace_limit = line.dup.force_encoding(Encoding.default_external).size
901
909
  end
902
910
  # looking for carriage return (decimal 13) or
903
911
  # newline (decimal 10) in raw input
@@ -912,10 +920,16 @@ class HighLine
912
920
  # do nothing
913
921
  end
914
922
  else
915
- if @question.echo == true
916
- @output.print(character.chr)
917
- else
918
- @output.print(@question.echo)
923
+ line_with_next_char_encoded = line.dup.force_encoding(Encoding.default_external)
924
+ # For multi-byte character, does this
925
+ # last character completes the character?
926
+ # Then print it.
927
+ if line_with_next_char_encoded.valid_encoding?
928
+ if @question.echo == true
929
+ @output.print(line_with_next_char_encoded[-1])
930
+ else
931
+ @output.print(@question.echo)
932
+ end
919
933
  end
920
934
  end
921
935
  @output.flush
@@ -932,7 +946,7 @@ class HighLine
932
946
  say("\n")
933
947
  end
934
948
 
935
- @question.change_case(@question.remove_whitespace(line))
949
+ @question.change_case(@question.remove_whitespace(line.force_encoding(Encoding.default_external)))
936
950
  end
937
951
  else
938
952
  if JRUBY #prompt has not been shown
@@ -345,7 +345,7 @@ class HighLine
345
345
  # Allows Menu to behave as a String, just like Question. Returns the
346
346
  # _layout_ to be rendered, which is used by HighLine.say().
347
347
  #
348
- def to_str( )
348
+ def to_s( )
349
349
  case @layout
350
350
  when :list
351
351
  '<%= if @header.nil? then '' else "#{@header}:\n" end %>' +
@@ -228,8 +228,7 @@ class HighLine
228
228
  # Also used by Menu#update_responses.
229
229
  #
230
230
  def build_responses(message_source = answer_type, new_hash_wins = false)
231
-
232
- append_default unless default.nil?
231
+ append_default if [::String, Symbol].include? default.class
233
232
 
234
233
  choice_error_str_func = lambda do
235
234
  message_source.is_a?(Array) \
@@ -442,7 +441,7 @@ class HighLine
442
441
  end
443
442
 
444
443
  # Stringifies the question to be asked.
445
- def to_str( )
444
+ def to_s
446
445
  @question
447
446
  end
448
447
 
@@ -168,14 +168,25 @@ class HighLine
168
168
  end
169
169
 
170
170
  def bright
171
- raise "Cannot create a bright variant of a style list (#{inspect})" if @list
172
- new_name = ('bright_'+@name.to_s).to_sym
173
- if style = self.class.list[new_name]
174
- style
175
- else
176
- new_rgb = @rgb == [0,0,0] ? [128, 128, 128] : @rgb.map {|color| color==0 ? 0 : [color+128,255].min }
177
- variant(new_name, :increment=>60, :rgb=>new_rgb)
178
- end
171
+ create_bright_variant(:bright)
172
+ end
173
+
174
+ def light
175
+ create_bright_variant(:light)
176
+ end
177
+
178
+ private
179
+
180
+ def create_bright_variant(variant_name)
181
+ raise "Cannot create a #{name} variant of a style list (#{inspect})" if @list
182
+ new_name = ("#{variant_name}_"+@name.to_s).to_sym
183
+ new_rgb = @rgb == [0,0,0] ? [128, 128, 128] : @rgb.map {|color| color==0 ? 0 : [color+128,255].min }
184
+
185
+ find_style(new_name) or variant(new_name, :increment=>60, :rgb=>new_rgb)
186
+ end
187
+
188
+ def find_style(name)
189
+ self.class.list[name]
179
190
  end
180
191
  end
181
192
  end
@@ -223,11 +223,20 @@ class HighLine
223
223
  # A Unix savvy method using stty to fetch the console columns, and rows.
224
224
  # ... stty does not work in JRuby
225
225
  def terminal_size
226
+ begin
227
+ require "io/console"
228
+ winsize = IO.console.winsize rescue nil
229
+ return winsize if winsize
230
+ rescue LoadError
231
+ end
232
+
226
233
  if /solaris/ =~ RUBY_PLATFORM and
227
234
  `stty` =~ /\brows = (\d+).*\bcolumns = (\d+)/
228
235
  [$2, $1].map { |c| x.to_i }
236
+ elsif `stty size` =~ /^(\d+)\s(\d+)$/
237
+ [$2.to_i, $1.to_i]
229
238
  else
230
- `stty size`.split.map { |x| x.to_i }.reverse
239
+ [ 80, 24 ]
231
240
  end
232
241
  end
233
242
  end
@@ -0,0 +1,4 @@
1
+ class HighLine
2
+ # The version of the installed library.
3
+ VERSION = "1.7.1".freeze
4
+ end
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  # tc_highline.rb
2
3
  #
3
4
  # Created by James Edward Gray II on 2005-04-26.
@@ -9,6 +10,8 @@ require "test/unit"
9
10
 
10
11
  require "highline"
11
12
  require "stringio"
13
+ require "readline"
14
+ require "tempfile"
12
15
 
13
16
  if HighLine::CHARACTER_MODE == "Win32API"
14
17
  class HighLine
@@ -224,7 +227,95 @@ class TestHighLine < Test::Unit::TestCase
224
227
  assert_equal("", answer)
225
228
  assert_equal("Please enter your password: \n", @output.string)
226
229
  end
227
-
230
+
231
+ def test_after_some_chars_backspace_does_not_enter_prompt_when_ascii
232
+ @input << "apple\b\b\b\b\b\b\b\b\b\b"
233
+ @input.rewind
234
+ answer = @terminal.ask("Please enter your password: ") do |q|
235
+ q.echo = "*"
236
+ end
237
+ assert_equal("", answer)
238
+ assert_equal("apple".size, @output.string.count("\b"))
239
+ end
240
+
241
+ def test_after_some_chars_backspace_does_not_enter_prompt_when_utf8
242
+ @input << "maçã\b\b\b\b\b\b\b\b"
243
+ @input.rewind
244
+ answer = @terminal.ask("Please enter your password: ") do |q|
245
+ q.echo = "*"
246
+ end
247
+ assert_equal("", answer)
248
+ assert_equal("maçã".size, @output.string.count("\b"))
249
+ end
250
+
251
+ def test_readline_mode
252
+ # Rubinius seems to be ignoring Readline input
253
+ # and output assignments. This ruins testing.
254
+ # but it doesn't mean readline is not working
255
+ # properly on rubinius.
256
+
257
+ return if RUBY_ENGINE == "rbx"
258
+
259
+ # Creating Tempfiles here because Readline.input
260
+ # and Readline.output only accepts a File object
261
+ # as argument (not any duck type as StringIO)
262
+
263
+ temp_stdin = Tempfile.new "temp_stdin"
264
+ temp_stdout = Tempfile.new "temp_stdout"
265
+
266
+ Readline.input = @input = File.open(temp_stdin.path, 'w+')
267
+ Readline.output = @output = File.open(temp_stdout.path, 'w+')
268
+
269
+ @terminal = HighLine.new(@input, @output)
270
+
271
+ @input << "any input\n"
272
+ @input.rewind
273
+
274
+ answer = @terminal.ask("Prompt: ") do |q|
275
+ q.readline = true
276
+ end
277
+
278
+ @output.rewind
279
+ output = @output.read
280
+
281
+ assert_equal "any input", answer
282
+ assert_match "Prompt: any input\n", output
283
+
284
+ @input.close
285
+ @output.close
286
+ Readline.input = STDIN
287
+ Readline.output = STDOUT
288
+ end
289
+
290
+ def test_readline_mode_with_limit_set
291
+ temp_stdin = Tempfile.new "temp_stdin"
292
+ temp_stdout = Tempfile.new "temp_stdout"
293
+
294
+ Readline.input = @input = File.open(temp_stdin.path, 'w+')
295
+ Readline.output = @output = File.open(temp_stdout.path, 'w+')
296
+
297
+ @terminal = HighLine.new(@input, @output)
298
+
299
+ @input << "any input\n"
300
+ @input.rewind
301
+
302
+ answer = @terminal.ask("Prompt: ") do |q|
303
+ q.limit = 50
304
+ q.readline = true
305
+ end
306
+
307
+ @output.rewind
308
+ output = @output.read
309
+
310
+ assert_equal "any input", answer
311
+ assert_equal "Prompt: any input\n", output
312
+
313
+ @input.close
314
+ @output.close
315
+ Readline.input = STDIN
316
+ Readline.output = STDOUT
317
+ end
318
+
228
319
  def test_readline_on_non_echo_question_has_prompt
229
320
  @input << "you can't see me"
230
321
  @input.rewind
@@ -327,6 +418,30 @@ class TestHighLine < Test::Unit::TestCase
327
418
  @terminal.uncolor("This should be \e[38;5;137mrgb_906030\e[0m!\n")
328
419
  )
329
420
  end
421
+
422
+ def test_grey_is_the_same_of_gray
423
+ @terminal.say("<%= GRAY %>")
424
+ gray_code = @output.string.dup
425
+ @output.truncate(@output.rewind)
426
+
427
+ @terminal.say("<%= GREY %>")
428
+ grey_code = @output.string.dup
429
+ @output.truncate(@output.rewind)
430
+
431
+ assert_equal gray_code, grey_code
432
+ end
433
+
434
+ def test_light_is_the_same_as_bright
435
+ @terminal.say("<%= BRIGHT_BLUE %>")
436
+ bright_blue_code = @output.string.dup
437
+ @output.truncate(@output.rewind)
438
+
439
+ @terminal.say("<%= LIGHT_BLUE %>")
440
+ light_blue_code = @output.string.dup
441
+ @output.truncate(@output.rewind)
442
+
443
+ assert_equal bright_blue_code, light_blue_code
444
+ end
330
445
 
331
446
  def test_confirm
332
447
  @input << "junk.txt\nno\nsave.txt\ny\n"
@@ -380,6 +495,51 @@ class TestHighLine < Test::Unit::TestCase
380
495
  @output.string )
381
496
  end
382
497
 
498
+ def test_default_with_String
499
+ @input << "\n"
500
+ @input.rewind
501
+
502
+ answer = @terminal.ask("Question: ") do |q|
503
+ q.default = "string"
504
+ end
505
+
506
+ assert_equal "string", answer
507
+ assert_equal "Question: |string| ", @output.string
508
+ end
509
+
510
+ def test_default_with_Symbol
511
+ # With a Symbol, it should show up the String version
512
+ # at prompt, but return the Symbol as answer
513
+
514
+ @input << "\n"
515
+ @input.rewind
516
+
517
+ answer = @terminal.ask("Question: ") do |q|
518
+ q.default = :string
519
+ end
520
+
521
+ assert_equal :string, answer
522
+ assert_equal "Question: |string| ", @output.string
523
+ end
524
+
525
+ def test_default_with_non_String_objects
526
+ # With a non-string object, it should not show
527
+ # any 'default' at prompt line. And should
528
+ # return the "default" object, without conversion.
529
+
530
+ @input << "\n"
531
+ @input.rewind
532
+
533
+ default_non_string_object = Object.new
534
+
535
+ answer = @terminal.ask("Question: ") do |q|
536
+ q.default = default_non_string_object
537
+ end
538
+
539
+ assert_equal default_non_string_object, answer
540
+ assert_equal "Question: ", @output.string
541
+ end
542
+
383
543
  def test_string_preservation
384
544
  @input << "Maybe\nYes\n"
385
545
  @input.rewind
@@ -427,7 +587,7 @@ class TestHighLine < Test::Unit::TestCase
427
587
  q.glob = "*.rb"
428
588
  end
429
589
  assert_instance_of(File, file)
430
- assert_equal("# tc_highline.rb\n", file.gets)
590
+ assert_equal("# encoding: utf-8\n", file.gets)
431
591
  file.close
432
592
 
433
593
  @input.rewind
@@ -755,6 +915,54 @@ class TestHighLine < Test::Unit::TestCase
755
915
  assert_equal("Pick a letter or number: \n", @output.string)
756
916
  end
757
917
 
918
+ def test_correct_string_encoding_when_echo_false
919
+ @input << "ação\r" # An UTF-8 portuguese word for 'action'
920
+ @input.rewind
921
+
922
+ answer = @terminal.ask("Please enter your password: ") do |q|
923
+ q.echo = false
924
+ end
925
+
926
+ assert_equal "ação", answer
927
+ assert_equal Encoding::default_external, answer.encoding
928
+ end
929
+
930
+ def test_backspace_with_ascii_when_echo_false
931
+ @input << "password\b\r"
932
+ @input.rewind
933
+
934
+ answer = @terminal.ask("Please enter your password: ") do |q|
935
+ q.echo = false
936
+ end
937
+
938
+ assert_not_equal("password", answer)
939
+ assert_equal("passwor", answer)
940
+ end
941
+
942
+ def test_backspace_with_utf8_when_echo_false
943
+ @input << "maçã\b\r"
944
+ @input.rewind
945
+
946
+ answer = @terminal.ask("Please enter your password: ") do |q|
947
+ q.echo = false
948
+ end
949
+
950
+ assert_not_equal("maçã", answer)
951
+ assert_equal("maç", answer)
952
+ end
953
+
954
+ def test_echoing_with_utf8_when_echo_is_star
955
+ @input << "maçã\r"
956
+ @input.rewind
957
+
958
+ answer = @terminal.ask("Type: ") do |q|
959
+ q.echo = "*"
960
+ end
961
+
962
+ assert_equal("Type: ****\n", @output.string)
963
+ assert_equal("maçã", answer)
964
+ end
965
+
758
966
  def test_paging
759
967
  @terminal.page_at = 22
760
968
 
@@ -933,6 +1141,24 @@ class TestHighLine < Test::Unit::TestCase
933
1141
  colorized = @terminal.color("This will have a newline.", :green)
934
1142
  @terminal.say(colorized)
935
1143
  assert_equal("\e[32mThis will have a newline.\e[0m\n", @output.string)
1144
+
1145
+ @output.truncate(@output.rewind)
1146
+
1147
+ assert_nothing_raised { @terminal.say(nil) }
1148
+ assert_equal("", @output.string)
1149
+ end
1150
+
1151
+ def test_say_handles_non_string_argument
1152
+ integer = 10
1153
+ hash = { :a => 20 }
1154
+
1155
+ assert_nothing_raised { @terminal.say(integer) }
1156
+ assert_equal String(integer), @output.string.chomp
1157
+
1158
+ @output.truncate(@output.rewind)
1159
+
1160
+ assert_nothing_raised { @terminal.say(hash) }
1161
+ assert_equal String(hash), @output.string.chomp
936
1162
  end
937
1163
 
938
1164
  def test_terminal_size