highline 0.6.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  Below is a complete listing of changes for each revision of HighLine.
4
4
 
5
+ == 1.0.0
6
+
7
+ * Fixed documentation typo pointed out by Gavin Kistner.
8
+ * Added <tt>gather = ...</tt> option to question for fetching entire Arrays or
9
+ Hashes filled with answers. You can set +gather+ to a count of answers to
10
+ collect, a String or Regexp matching the end of input, or a Hash where each
11
+ key can be used in a new question.
12
+ * Added File support to HighLine.ask(). You can specify a _directory_ and a
13
+ _glob_ pattern that combine into a list of file choices the user can select
14
+ from. You can choose to receive the user's answer as an open filehandle or as
15
+ a Pathname object.
16
+ * Added Readline support for history and editing.
17
+ * Added tab completion for menu and file selection selection (requires
18
+ Readline).
19
+ * Added an optional character limit for input.
20
+ * Added a complete help system to HighLine's shell menu creation tools.
21
+
5
22
  == 0.6.1
6
23
 
7
24
  * Removed termios dependancy in gem, to fix Windows' install.
data/LICENSE CHANGED
@@ -1,7 +1,7 @@
1
1
  = License Terms
2
2
 
3
- Distributed under the
3
+ Distributed under the user's choice of the GPL[http://www.gnu.org/copyleft/gpl.html] (see COPYING for details) or the
4
4
  {Ruby software license}[http://www.ruby-lang.org/en/LICENSE.txt] by
5
- James Edward Gray II.
5
+ James Edward Gray II and Greg Brown.
6
6
 
7
7
  Please email James[mailto:james@grayproductions.net] with any questions.
data/Rakefile CHANGED
@@ -16,11 +16,13 @@ Rake::RDocTask.new do |rdoc|
16
16
  rdoc.main = "README"
17
17
  rdoc.rdoc_files.include( "README", "INSTALL",
18
18
  "TODO", "CHANGELOG",
19
+ "AUTHORS", "COPYING",
19
20
  "LICENSE", "lib/" )
20
21
  rdoc.rdoc_dir = "doc/html"
21
22
  rdoc.title = "HighLine Documentation"
22
23
  end
23
24
 
25
+ desc "Upload current documentation to Rubyforge"
24
26
  task :upload_docs => [:rdoc] do
25
27
  sh "scp -r site/* " +
26
28
  "bbazzarrakk@rubyforge.org:/var/www/gforge-projects/highline/"
@@ -30,7 +32,7 @@ end
30
32
 
31
33
  spec = Gem::Specification.new do |spec|
32
34
  spec.name = "highline"
33
- spec.version = "0.6.1"
35
+ spec.version = "1.0.0"
34
36
  spec.platform = Gem::Platform::RUBY
35
37
  spec.summary = "HighLine is a high-level line oriented console interface."
36
38
  spec.files = Dir.glob("{examples,lib,test}/**/*.rb").
@@ -62,3 +64,11 @@ Rake::GemPackageTask.new(spec) do |pkg|
62
64
  pkg.need_zip = true
63
65
  pkg.need_tar = true
64
66
  end
67
+
68
+ desc "Show library's code statistics"
69
+ task :stats do
70
+ require 'code_statistics'
71
+ CodeStatistics.new( ["HighLine", "lib"],
72
+ ["Functionals", "examples"],
73
+ ["Units", "test"] ).to_s
74
+ end
data/TODO CHANGED
@@ -3,10 +3,4 @@
3
3
  The following is a list of planned expansions for HighLine, in no particular
4
4
  order.
5
5
 
6
- * Support <tt>ask(..., Array)</tt>, better than the current
7
- <tt>ask(..., lambda { |arr| arr.split(",") })</tt> or similar.
8
- * Support <tt>ask(..., Hash)</tt>.
9
- * Support <tt>ask(..., File)</tt>.
10
- * Add readline support for history and editing.
11
- * Add an easy-access help system for menus.
12
- * Add tab completion for menu selection.
6
+ * This space for rent...
@@ -0,0 +1,18 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # asking_for_arrays.rb
4
+ #
5
+ # Created by James Edward Gray II on 2005-07-05.
6
+ # Copyright 2005 Gray Productions. All rights reserved.
7
+
8
+ require "rubygems"
9
+ require "highline/import"
10
+ require "pp"
11
+
12
+ grades = ask( "Enter test scores (or a blank line to quit):",
13
+ lambda { |ans| ans =~ /^-?\d+$/ ? Integer(ans) : ans} ) do |q|
14
+ q.gather = ""
15
+ end
16
+
17
+ say("Grades:")
18
+ pp grades
@@ -55,12 +55,12 @@ loop do
55
55
  menu.shell = true
56
56
  menu.case = :capitalize
57
57
 
58
- menu.choice :Load do |command, details|
58
+ menu.choice(:Load, "Load a file.") do |command, details|
59
59
  say("Loading file with options: #{details}...")
60
60
  end
61
- menu.choice :Save do |command, details|
61
+ menu.choice(:Save, "Save a file.") do |command, details|
62
62
  say("Saving file with options: #{details}...")
63
63
  end
64
- menu.choice(:Quit) { exit }
64
+ menu.choice(:Quit, "Exit program.") { exit }
65
65
  end
66
66
  end
@@ -0,0 +1,17 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # using_readline.rb
4
+ #
5
+ # Created by James Edward Gray II on 2005-07-06.
6
+ # Copyright 2005 Gray Productions. All rights reserved.
7
+
8
+ require "rubygems"
9
+ require "highline/import"
10
+
11
+ loop do
12
+ cmd = ask("Enter command: ", %w{save load reset quit}) do |q|
13
+ q.readline = true
14
+ end
15
+ say("Executing \"#{cmd}\"...")
16
+ break if cmd == "quit"
17
+ end
@@ -11,13 +11,15 @@ require "highline/question"
11
11
  require "highline/menu"
12
12
  require "erb"
13
13
  require "optparse"
14
+ require "stringio"
15
+ require "abbrev"
14
16
 
15
17
  #
16
18
  # A HighLine object is a "high-level line oriented" shell over an input and an
17
19
  # output stream. HighLine simplifies common console interaction, effectively
18
20
  # replacing puts() and gets(). User code can simply specify the question to ask
19
21
  # and any details about user interaction, then leave the rest of the work to
20
- # HighLine. When HighLine.ask() returns, you'll have to answer you requested,
22
+ # HighLine. When HighLine.ask() returns, you'll have the answer you requested,
21
23
  # even if HighLine had to ask many times, validate results, perform range
22
24
  # checking, convert types, etc.
23
25
  #
@@ -93,6 +95,15 @@ class HighLine
93
95
  @output = output
94
96
  @wrap_at = wrap_at
95
97
  @page_at = page_at
98
+
99
+ @question = nil
100
+ @answer = nil
101
+ @menu = nil
102
+ @header = nil
103
+ @prompt = nil
104
+ @gather = nil
105
+ @answers = nil
106
+ @key = nil
96
107
  end
97
108
 
98
109
  #
@@ -136,7 +147,10 @@ class HighLine
136
147
  def ask(question, answer_type = String, &details) # :yields: question
137
148
  @question ||= Question.new(question, answer_type, &details)
138
149
 
139
- say(@question)
150
+ return gather if @question.gather
151
+
152
+ # readline() needs to handle it's own output
153
+ say(@question) unless @question.readline
140
154
  begin
141
155
  @answer = @question.answer_or_default(get_response)
142
156
  unless @question.valid_answer?(@answer)
@@ -230,10 +244,10 @@ class HighLine
230
244
 
231
245
  if @menu.shell
232
246
  selected = ask("Ignored", @menu.answer_type)
233
- @menu.select(*selected)
247
+ @menu.select(self, *selected)
234
248
  else
235
249
  selected = ask("Ignored", @menu.answer_type)
236
- @menu.select(selected)
250
+ @menu.select(self, selected)
237
251
  end
238
252
  end
239
253
 
@@ -376,6 +390,51 @@ class HighLine
376
390
  end
377
391
  end
378
392
 
393
+ #
394
+ # Collects an Array/Hash full of answers as described in
395
+ # HighLine::Question.gather().
396
+ #
397
+ def gather( )
398
+ @gather = @question.gather
399
+ @answers = [ ]
400
+ original_question = @question
401
+
402
+ @question.gather = false
403
+
404
+ case @gather
405
+ when Integer
406
+ @answers << ask(@question)
407
+ @gather -= 1
408
+
409
+ original_question.question = ""
410
+ until @gather.zero?
411
+ @question = original_question
412
+ @answers << ask(@question)
413
+ @gather -= 1
414
+ end
415
+ when String, Regexp
416
+ @answers << ask(@question)
417
+
418
+ original_question.question = ""
419
+ until (@gather.is_a?(String) and @answers.last.to_s == @gather) or
420
+ (@gather.is_a?(Regexp) and @answers.last.to_s =~ @gather)
421
+ @question = original_question
422
+ @answers << ask(@question)
423
+ end
424
+
425
+ @answers.pop
426
+ when Hash
427
+ @answers = { }
428
+ @gather.keys.sort.each do |key|
429
+ @question = original_question
430
+ @key = key
431
+ @answers[key] = ask(@question)
432
+ end
433
+ end
434
+
435
+ @answers
436
+ end
437
+
379
438
  #
380
439
  # This section builds a character reading function to suit the proper
381
440
  # platform we're running on. Be warned: Here be dragons!
@@ -442,9 +501,37 @@ class HighLine
442
501
  #
443
502
  # Read a line of input from the input stream and process whitespace as
444
503
  # requested by the Question object.
504
+ #
505
+ # If Question's _readline_ property is set, that library will be used to
506
+ # fetch input. *WARNING*: This ignores the currently set input stream.
445
507
  #
446
508
  def get_line( )
447
- @question.change_case(@question.remove_whitespace(@input.gets))
509
+ if @question.readline
510
+ require "readline" # load only if needed
511
+
512
+ # capture say()'s work in a String to feed to readline()
513
+ old_output = @output
514
+ @output = StringIO.new
515
+ say(@question)
516
+ question = @output.string
517
+ @output = old_output
518
+
519
+ # prep auto-completion
520
+ completions = @question.selection.abbrev
521
+ Readline.completion_proc = lambda { |string| completions[string] }
522
+
523
+ # work-around ugly readline() warnings
524
+ old_verbose = $VERBOSE
525
+ $VERBOSE = nil
526
+ answer = @question.change_case(
527
+ @question.remove_whitespace(
528
+ Readline.readline(question, true) ) )
529
+ $VERBOSE = old_verbose
530
+
531
+ answer
532
+ else
533
+ @question.change_case(@question.remove_whitespace(@input.gets))
534
+ end
448
535
  end
449
536
 
450
537
  #
@@ -454,7 +541,7 @@ class HighLine
454
541
  #
455
542
  def get_response( )
456
543
  if @question.character.nil?
457
- if @question.echo == true
544
+ if @question.echo == true and @question.limit.nil?
458
545
  get_line
459
546
  else
460
547
  line = ""
@@ -462,7 +549,8 @@ class HighLine
462
549
  line << character.chr
463
550
  # looking for carriage return (decimal 13) or
464
551
  # newline (decimal 10) in raw input
465
- break if character == 13 or character == 10
552
+ break if character == 13 or character == 10 or
553
+ (@question.limit and line.size == @question.limit)
466
554
  @output.print(@question.echo) if @question.echo != false
467
555
  end
468
556
  say("\n")
@@ -23,12 +23,13 @@ class HighLine
23
23
  #
24
24
  def initialize( )
25
25
  #
26
- # Initialize Question objects with ignored valued, we'll
26
+ # Initialize Question objects with ignored values, we'll
27
27
  # adjust ours as needed.
28
28
  #
29
- super("Ignored", [ ], &nil) # avoiding passing to block along
29
+ super("Ignored", [ ], &nil) # avoiding passing the block along
30
30
 
31
31
  @items = [ ]
32
+ @help = Hash.new("There's no help for that topic.")
32
33
 
33
34
  @index = :number
34
35
  @index_suffix = ". "
@@ -41,12 +42,15 @@ class HighLine
41
42
  @shell = false
42
43
  @nil_on_handled = false
43
44
 
44
- # Override Questions repsonses, we'll set our own.
45
+ # Override Questions responses, we'll set our own.
45
46
  @responses = { }
47
+ # Context for action code.
48
+ @highline = nil
46
49
 
47
50
  yield self if block_given?
48
51
 
49
52
  update_responses # rebuild responses based on our settings
53
+ init_help if @shell and not @help.empty?
50
54
  end
51
55
 
52
56
  #
@@ -125,10 +129,14 @@ class HighLine
125
129
  # will be returned, unless _nil_on_handled_ is set (when you would get
126
130
  # +nil+ instead). In _shell_ mode, a provided block will be passed the
127
131
  # command chosen and any details that followed the command. Otherwise,
128
- # just the command is passed.
132
+ # just the command is passed. The <tt>@highline</tt> variable is set to
133
+ # the current HighLine context before the action code is called and can
134
+ # thus be used for adding output and the like.
129
135
  #
130
- def choice( name, &action )
136
+ def choice( name, help = nil, &action )
131
137
  @items << [name, action]
138
+
139
+ @help[name.to_s.downcase] = help unless help.nil?
132
140
  end
133
141
 
134
142
  #
@@ -166,6 +174,39 @@ class HighLine
166
174
  end
167
175
  end
168
176
 
177
+ #
178
+ # Initializes the help system by adding a <tt>:help</tt> choice, some
179
+ # action code, and the default help listing.
180
+ #
181
+ def init_help( )
182
+ return if @items.include?(:help)
183
+
184
+ topics = @help.keys.sort
185
+ help_help = @help.include?("help") ? @help["help"] :
186
+ "This command will display helpful messages about " +
187
+ "functionality, like this one. To see the help for " +
188
+ "a specific topic enter:\n\thelp [TOPIC]\nTry asking " +
189
+ "for help on any of the following:\n\n" +
190
+ "<%= list(#{topics.inspect}, :columns_across) %>"
191
+ choice(:help, help_help) do |command, topic|
192
+ topic.strip!
193
+ topic.downcase!
194
+ if topic.empty?
195
+ @highline.say(@help["help"])
196
+ else
197
+ @highline.say("= #{topic}\n\n#{@help[topic]}")
198
+ end
199
+ end
200
+ end
201
+
202
+ #
203
+ # Used to set help for arbitrary topics. Use the topic <tt>"help"</tt>
204
+ # to override the default message.
205
+ #
206
+ def help( topic, help )
207
+ @help[topic] = help
208
+ end
209
+
169
210
  #
170
211
  # Setting a _layout_ with this method also adjusts some other attributes
171
212
  # of the Menu object, to ideal defaults for the chosen _layout_. To
@@ -232,10 +273,10 @@ class HighLine
232
273
 
233
274
  #
234
275
  # This method processes the auto-completed user selection, based on the
235
- # rules for this Menu object. It an action was provided for the
276
+ # rules for this Menu object. If an action was provided for the
236
277
  # selection, it will be executed as described in Menu.choice().
237
278
  #
238
- def select( selection, details = nil )
279
+ def select( highline_context, selection, details = nil )
239
280
  # Find the selected action.
240
281
  name, action = if selection =~ /^\d+$/
241
282
  @items[selection.to_i - 1]
@@ -247,6 +288,7 @@ class HighLine
247
288
 
248
289
  # Run or return it.
249
290
  if not @nil_on_handled and not action.nil?
291
+ @highline = highline_context
250
292
  if @shell
251
293
  action.call(name, details)
252
294
  else
@@ -7,6 +7,7 @@
7
7
 
8
8
  require "optparse"
9
9
  require "date"
10
+ require "pathname"
10
11
 
11
12
  class HighLine
12
13
  #
@@ -34,7 +35,9 @@ class HighLine
34
35
  @answer_type = answer_type
35
36
 
36
37
  @character = nil
38
+ @limit = nil
37
39
  @echo = true
40
+ @readline = false
38
41
  @whitespace = :strip
39
42
  @case = nil
40
43
  @default = nil
@@ -43,6 +46,9 @@ class HighLine
43
46
  @below = nil
44
47
  @in = nil
45
48
  @confirm = nil
49
+ @gather = false
50
+ @directory = Pathname.new(File.expand_path(File.dirname($0)))
51
+ @glob = "*"
46
52
  @responses = Hash.new
47
53
 
48
54
  # allow block to override settings
@@ -52,6 +58,8 @@ class HighLine
52
58
  build_responses
53
59
  end
54
60
 
61
+ # The ERb template of the question to be asked.
62
+ attr_accessor :question
55
63
  # The type that will be used to convert this answer.
56
64
  attr_accessor :answer_type
57
65
  #
@@ -65,6 +73,12 @@ class HighLine
65
73
  #
66
74
  attr_accessor :character
67
75
  #
76
+ # Allows you to set a character limit for input.
77
+ #
78
+ # *WARNING*: This option forces a character by character read.
79
+ #
80
+ attr_accessor :limit
81
+ #
68
82
  # Can be set to +true+ or +false+ to control whether or not input will
69
83
  # be echoed back to the user. A setting of +true+ will cause echo to
70
84
  # match input, but any other true value will be treated as to String to
@@ -75,6 +89,16 @@ class HighLine
75
89
  #
76
90
  attr_accessor :echo
77
91
  #
92
+ # Use the Readline library to fetch input. This allows input editing as
93
+ # well as keeping a history. In addition, tab will auto-complete
94
+ # within an Array of choices or a file listing.
95
+ #
96
+ # *WARNING*: This option is incompatible with all of HighLine's
97
+ # character reading modes and it causes HighLine to ignore the
98
+ # specified _input_ stream.
99
+ #
100
+ attr_accessor :readline
101
+ #
78
102
  # Used to control whitespace processing for the answer to this question.
79
103
  # See HighLine::Question.remove_whitespace() for acceptable settings.
80
104
  #
@@ -105,6 +129,31 @@ class HighLine
105
129
  #
106
130
  attr_accessor :confirm
107
131
  #
132
+ # When set, the user will be prompted for multiple answers which will
133
+ # be collected into an Array or Hash and returned as the final answer.
134
+ #
135
+ # You can set _gather_ to an Integer to have an Array of exactly that
136
+ # many answers collected, or a String/Regexp to match an end input which
137
+ # will not be returned in the Array.
138
+ #
139
+ # Optionally _gather_ can be set to a Hash. In this case, the question
140
+ # will be asked once for each key and the answers will be returned in a
141
+ # Hash, mapped by key. The <tt>@key</tt> variable is set before each
142
+ # question is evaluated, so you can use it in your question.
143
+ #
144
+ attr_accessor :gather
145
+ #
146
+ # The directory from which a user will be allowed to select files, when
147
+ # File or Pathname is specified as an _answer_type_. Initially set to
148
+ # <tt>Pathname.new(File.expand_path(File.dirname($0)))</tt>.
149
+ #
150
+ attr_accessor :directory
151
+ #
152
+ # The glob pattern used to limit file selection when File or Pathname is
153
+ # specified as an _answer_type_. Initially set to <tt>"*"</tt>.
154
+ #
155
+ attr_accessor :glob
156
+ #
108
157
  # A Hash that stores the various responses used by HighLine to notify
109
158
  # the user. The currently used responses and their purpose are as
110
159
  # follows:
@@ -148,7 +197,7 @@ class HighLine
148
197
  #
149
198
  def build_responses( )
150
199
  ### WARNING: This code is quasi-duplicated in ###
151
- ### Menu.update_responses(). Check their too when ###
200
+ ### Menu.update_responses(). Check there too when ###
152
201
  ### making changes! ###
153
202
  append_default unless default.nil?
154
203
  @responses = { :ambiguous_completion =>
@@ -168,7 +217,7 @@ class HighLine
168
217
  "Your answer isn't valid (must match " +
169
218
  "#{@validate.inspect})." }.merge(@responses)
170
219
  ### WARNING: This code is quasi-duplicated in ###
171
- ### Menu.update_responses(). Check their too when ###
220
+ ### Menu.update_responses(). Check there too when ###
172
221
  ### making changes! ###
173
222
  end
174
223
 
@@ -208,9 +257,14 @@ class HighLine
208
257
  # <tt>lambda {...}</tt>:: Answer is passed to lambda for conversion.
209
258
  # Date:: Date.parse() is called with answer.
210
259
  # DateTime:: DateTime.parse() is called with answer.
260
+ # File:: The entered file name is auto-completed in
261
+ # terms of _directory_ + _glob_, opened, and
262
+ # returned.
211
263
  # Float:: Answer is converted with Kernel.Float().
212
264
  # Integer:: Answer is converted with Kernel.Integer().
213
265
  # +nil+:: Answer is left in String format. (Default.)
266
+ # Pathname:: Same as File, save that a Pathname object is
267
+ # returned.
214
268
  # String:: Answer is converted with Kernel.String().
215
269
  # Regexp:: Answer is fed to Regexp.new().
216
270
  # Symbol:: The method to_sym() is called on answer and
@@ -230,14 +284,22 @@ class HighLine
230
284
  answer_string.to_sym
231
285
  elsif @answer_type == Regexp
232
286
  Regexp.new(answer_string)
233
- elsif @answer_type.is_a?(Array)
287
+ elsif @answer_type.is_a?(Array) or
288
+ [File, Pathname].include?(@answer_type)
234
289
  # cheating, using OptionParser's Completion module
235
- @answer_type.extend(OptionParser::Completion)
236
- answer = @answer_type.complete(answer_string)
290
+ choices = selection
291
+ choices.extend(OptionParser::Completion)
292
+ answer = choices.complete(answer_string)
237
293
  if answer.nil?
238
294
  raise NoAutoCompleteMatch
239
295
  end
240
- answer.last
296
+ if @answer_type.is_a?(Array)
297
+ answer.last
298
+ elsif @answer_type == File
299
+ File.open(File.join(@directory.to_s, answer.last))
300
+ else
301
+ Pathname.new(File.join(@directory.to_s, answer.last))
302
+ end
241
303
  elsif [Date, DateTime].include?(@answer_type) or
242
304
  @answer_type.is_a?(Class)
243
305
  @answer_type.parse(answer_string)
@@ -310,6 +372,23 @@ class HighLine
310
372
  answer_string
311
373
  end
312
374
  end
375
+
376
+ #
377
+ # Returns an Array of valid answers to this question. These answers are
378
+ # only known when _answer_type_ is set to an Array of choices, File, or
379
+ # Pathname. Any other time, this method will return an empty Array.
380
+ #
381
+ def selection( )
382
+ if @answer_type.is_a?(Array)
383
+ @answer_type
384
+ elsif [File, Pathname].include?(@answer_type)
385
+ Dir[File.join(@directory.to_s, @glob)].map do |file|
386
+ File.basename(file)
387
+ end
388
+ else
389
+ [ ]
390
+ end
391
+ end
313
392
 
314
393
  # Stringifies the question to be asked.
315
394
  def to_str( )
@@ -5,9 +5,6 @@
5
5
  # Created by James Edward Gray II on 2005-04-26.
6
6
  # Copyright 2005 Gray Productions. All rights reserved.
7
7
 
8
- $test_lib_dir ||= File.join(File.dirname(__FILE__), "..", "lib")
9
- $:.unshift($test_lib_dir) unless $:.include?($test_lib_dir)
10
-
11
8
  require "test/unit"
12
9
 
13
10
  require "highline"
@@ -233,6 +230,68 @@ class TestHighLine < Test::Unit::TestCase
233
230
  @output.string )
234
231
  end
235
232
 
233
+ def test_files
234
+ @input << "#{File.basename(__FILE__)[0, 5]}\n"
235
+ @input.rewind
236
+
237
+ file = @terminal.ask("Select a file: ", File) do |q|
238
+ q.directory = File.expand_path(File.dirname(__FILE__))
239
+ q.glob = "*.rb"
240
+ end
241
+ assert_instance_of(File, file)
242
+ assert_equal("#!/usr/local/bin/ruby -w\n", file.gets)
243
+ assert_equal("\n", file.gets)
244
+ assert_equal("# tc_highline.rb\n", file.gets)
245
+ file.close
246
+
247
+ @input.rewind
248
+
249
+ pathname = @terminal.ask("Select a file: ", Pathname) do |q|
250
+ q.directory = File.expand_path(File.dirname(__FILE__))
251
+ q.glob = "*.rb"
252
+ end
253
+ assert_instance_of(Pathname, pathname)
254
+ assert_equal(File.size(__FILE__), pathname.size)
255
+ end
256
+
257
+ def test_gather
258
+ @input << "James\nDana\nStorm\nGypsy\n\n"
259
+ @input.rewind
260
+
261
+ answers = @terminal.ask("Enter four names:") do |q|
262
+ q.gather = 4
263
+ end
264
+ assert_equal(%w{James Dana Storm Gypsy}, answers)
265
+ assert_equal("\n", @input.gets)
266
+ assert_equal("Enter four names:\n", @output.string)
267
+
268
+ @input.rewind
269
+
270
+ answers = @terminal.ask("Enter four names:") do |q|
271
+ q.gather = ""
272
+ end
273
+ assert_equal(%w{James Dana Storm Gypsy}, answers)
274
+
275
+ @input.rewind
276
+
277
+ answers = @terminal.ask("Enter four names:") do |q|
278
+ q.gather = /^\s*$/
279
+ end
280
+ assert_equal(%w{James Dana Storm Gypsy}, answers)
281
+
282
+ @input.truncate(@input.rewind)
283
+ @input << "29\n49\n30\n"
284
+ @input.rewind
285
+ @output.truncate(@output.rewind)
286
+
287
+ answers = @terminal.ask("<%= @key %>: ", Integer) do |q|
288
+ q.gather = { "Age" => 0, "Wife's Age" => 0, "Father's Age" => 0}
289
+ end
290
+ assert_equal( { "Age" => 29, "Wife's Age" => 30, "Father's Age" => 49},
291
+ answers )
292
+ assert_equal("Age: Father's Age: Wife's Age: ", @output.string)
293
+ end
294
+
236
295
  def test_lists
237
296
  digits = %w{Zero One Two Three Four Five Six Seven Eight Nine}
238
297
 
@@ -5,9 +5,6 @@
5
5
  # Created by James Edward Gray II on 2005-04-26.
6
6
  # Copyright 2005 Gray Productions. All rights reserved.
7
7
 
8
- $test_lib_dir ||= File.join(File.dirname(__FILE__), "..", "lib")
9
- $:.unshift($test_lib_dir) unless $:.include?($test_lib_dir)
10
-
11
8
  require "test/unit"
12
9
 
13
10
  require "highline/import"
@@ -5,9 +5,6 @@
5
5
  # Created by Gregory Thomas Brown on 2005-05-10.
6
6
  # Copyright 2005 smtose.org. All rights reserved.
7
7
 
8
- $test_lib_dir ||= File.join(File.dirname(__FILE__), "..", "lib")
9
- $:.unshift($test_lib_dir) unless $:.include?($test_lib_dir)
10
-
11
8
  require "test/unit"
12
9
 
13
10
  require "highline"
@@ -69,6 +66,39 @@ class TestMenu < Test::Unit::TestCase
69
66
  assert_equal("Sample1, Sample2 or Sample3? ", @output.string)
70
67
  end
71
68
 
69
+ def test_help
70
+ @input << "help\nhelp load\nhelp rules\nhelp missing\n"
71
+ @input.rewind
72
+
73
+ 4.times do
74
+ @terminal.choose do |menu|
75
+ menu.shell = true
76
+
77
+ menu.choice(:load, "Load a file.")
78
+ menu.choice(:save, "Save data in file.")
79
+ menu.choice(:quit, "Exit program.")
80
+
81
+ menu.help("rules", "The rules of this system are as follows...")
82
+ end
83
+ end
84
+ assert_equal( "1. load\n2. save\n3. quit\n4. help\n? " +
85
+ "This command will display helpful messages about " +
86
+ "functionality, like this one. To see the help for a " +
87
+ "specific topic enter:\n" +
88
+ "\thelp [TOPIC]\n" +
89
+ "Try asking for help on any of the following:\n" +
90
+ "\nload quit rules save \n" +
91
+ "1. load\n2. save\n3. quit\n4. help\n? " +
92
+ "= load\n\n" +
93
+ "Load a file.\n" +
94
+ "1. load\n2. save\n3. quit\n4. help\n? " +
95
+ "= rules\n\n" +
96
+ "The rules of this system are as follows...\n" +
97
+ "1. load\n2. save\n3. quit\n4. help\n? " +
98
+ "= missing\n\n" +
99
+ "There's no help for that topic.\n", @output.string )
100
+ end
101
+
72
102
  def test_index
73
103
  @input << "Sample1\n"
74
104
  @input.rewind
@@ -291,7 +321,7 @@ class TestMenu < Test::Unit::TestCase
291
321
 
292
322
  selected = nil
293
323
  options = nil
294
- answer = @terminal.choose(:load, :save, :quit) do |menu|
324
+ answer = @terminal.choose do |menu|
295
325
  menu.choices(:load, :quit)
296
326
  menu.choice(:save) do |command, details|
297
327
  selected = command
@@ -5,9 +5,6 @@
5
5
  # Created by James Edward Gray II on 2005-04-26.
6
6
  # Copyright 2005 Gray Productions. All rights reserved.
7
7
 
8
- $test_dir ||= File.dirname(__FILE__)
9
- $:.unshift($test_dir) unless $:.include?($test_dir)
10
-
11
8
  require "test/unit"
12
9
 
13
10
  require "tc_highline"
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: highline
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.6.1
7
- date: 2005-05-23
6
+ version: 1.0.0
7
+ date: 2005-07-07
8
8
  summary: HighLine is a high-level line oriented console interface.
9
9
  require_paths:
10
10
  - lib
@@ -30,10 +30,12 @@ authors:
30
30
  - James Edward Gray II
31
31
  files:
32
32
  - examples/ansi_colors.rb
33
+ - examples/asking_for_arrays.rb
33
34
  - examples/basic_usage.rb
34
35
  - examples/menus.rb
35
36
  - examples/page_and_wrap.rb
36
37
  - examples/password.rb
38
+ - examples/using_readline.rb
37
39
  - lib/highline.rb
38
40
  - lib/highline/import.rb
39
41
  - lib/highline/menu.rb