highline 0.6.1 → 1.0.0

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/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