highline 1.6.21 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
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