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 +17 -0
- data/LICENSE +2 -2
- data/Rakefile +11 -1
- data/TODO +1 -7
- data/examples/asking_for_arrays.rb +18 -0
- data/examples/menus.rb +3 -3
- data/examples/using_readline.rb +17 -0
- data/lib/highline.rb +95 -7
- data/lib/highline/menu.rb +49 -7
- data/lib/highline/question.rb +85 -6
- data/test/tc_highline.rb +62 -3
- data/test/tc_import.rb +0 -3
- data/test/tc_menu.rb +34 -4
- data/test/ts_all.rb +0 -3
- metadata +4 -2
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.
|
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
|
-
*
|
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
|
data/examples/menus.rb
CHANGED
@@ -55,12 +55,12 @@ loop do
|
|
55
55
|
menu.shell = true
|
56
56
|
menu.case = :capitalize
|
57
57
|
|
58
|
-
menu.choice
|
58
|
+
menu.choice(:Load, "Load a file.") do |command, details|
|
59
59
|
say("Loading file with options: #{details}...")
|
60
60
|
end
|
61
|
-
menu.choice
|
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
|
data/lib/highline.rb
CHANGED
@@ -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
|
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
|
-
|
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.
|
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")
|
data/lib/highline/menu.rb
CHANGED
@@ -23,12 +23,13 @@ class HighLine
|
|
23
23
|
#
|
24
24
|
def initialize( )
|
25
25
|
#
|
26
|
-
# Initialize Question objects with ignored
|
26
|
+
# Initialize Question objects with ignored values, we'll
|
27
27
|
# adjust ours as needed.
|
28
28
|
#
|
29
|
-
super("Ignored", [ ], &nil) # avoiding passing
|
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
|
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.
|
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
|
data/lib/highline/question.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
236
|
-
|
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
|
-
|
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( )
|
data/test/tc_highline.rb
CHANGED
@@ -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
|
|
data/test/tc_import.rb
CHANGED
@@ -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"
|
data/test/tc_menu.rb
CHANGED
@@ -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
|
324
|
+
answer = @terminal.choose do |menu|
|
295
325
|
menu.choices(:load, :quit)
|
296
326
|
menu.choice(:save) do |command, details|
|
297
327
|
selected = command
|
data/test/ts_all.rb
CHANGED
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.
|
7
|
-
date: 2005-
|
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
|