highline 1.0.4 → 1.2.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,14 @@
2
2
 
3
3
  Below is a complete listing of changes for each revision of HighLine.
4
4
 
5
+ == 1.2.0
6
+
7
+ * Improved RubyForge and gem spec project descriptions.
8
+ * Added basic examples to README.
9
+ * Added a VERSION constant.
10
+ * Added support for hidden menu commands.
11
+ * Added Object.or_ask() when using highline/import.
12
+
5
13
  == 1.0.4
6
14
 
7
15
  * Moved the HighLine project to Subversion.
data/README CHANGED
@@ -19,7 +19,39 @@ See HighLine and HighLine::Question for documentation.
19
19
 
20
20
  == Examples
21
21
 
22
- See the examples/ directory of this project for code examples.
22
+ Basic usage:
23
+
24
+ ask("Company? ") { |q| q.default = "none" }
25
+
26
+ Validation:
27
+
28
+ ask("Age? ", Integer) { |q| q.in = 0..105 }
29
+ ask("Name? (last, first) ") { |q| q.validate = /\A\w+, ?\w+\Z/ }
30
+
31
+ Type conversion for answers:
32
+
33
+ ask("Birthday? ", Date)
34
+ ask("Interests? (comma sep list) ", lambda { |str| str.split(/,\s*/) })
35
+
36
+ Reading passwords:
37
+
38
+ ask("Enter your password: ") { |q| q.echo = false }
39
+ ask("Enter your password: ") { |q| q.echo = "x" }
40
+
41
+ ERb based output (with HighLine's ANSI color tools):
42
+
43
+ say("This should be <%= color('bold', BOLD) %>!")
44
+
45
+ Menus:
46
+
47
+ choose do |menu|
48
+ menu.prompt = "Please choose your favorite programming language? "
49
+
50
+ menu.choice(:ruby) { say("Good choice!") }
51
+ menu.choices(:python, :perl) { say("Not from around here, are you?") }
52
+ end
53
+
54
+ For more examples see the examples/ directory of this project.
23
55
 
24
56
  == Installing
25
57
 
data/Rakefile CHANGED
@@ -32,9 +32,9 @@ end
32
32
 
33
33
  spec = Gem::Specification.new do |spec|
34
34
  spec.name = "highline"
35
- spec.version = "1.0.4"
35
+ spec.version = "1.2.0"
36
36
  spec.platform = Gem::Platform::RUBY
37
- spec.summary = "HighLine is a high-level line oriented console interface."
37
+ spec.summary = "HighLine is a high-level command-line IO library."
38
38
  spec.files = Dir.glob("{examples,lib,test}/**/*.rb").
39
39
  delete_if { |item| item.include?("CVS") } +
40
40
  ["Rakefile", "setup.rb"]
@@ -55,9 +55,10 @@ spec = Gem::Specification.new do |spec|
55
55
  spec.rubyforge_project = "highline"
56
56
  spec.homepage = "http://highline.rubyforge.org"
57
57
  spec.description = <<END_DESC
58
- A "high-level line oriented" input/output library that grew out of my solution
59
- to Ruby Quiz #29. This library attempts to make standard console input and
60
- output robust and painless.
58
+ A high-level IO library that provides validation, type conversion, and more for
59
+ command-line interfaces. HighLine also includes a complete menu system that can
60
+ crank out anything from simple list selection to complete shells with just
61
+ minutes of work.
61
62
  END_DESC
62
63
  end
63
64
 
@@ -26,6 +26,9 @@ require "abbrev"
26
26
  # checking, convert types, etc.
27
27
  #
28
28
  class HighLine
29
+ # The version of the installed library.
30
+ VERSION = "1.2.0".freeze
31
+
29
32
  # An internal HighLine error. User code does not need to trap this.
30
33
  class QuestionError < StandardError
31
34
  # do nothing, just creating a unique error type
@@ -581,9 +584,13 @@ class HighLine
581
584
  # Character input will be returned as a single character String,
582
585
  # not an Integer.
583
586
  #
587
+ # This question's _first_answer_ will be returned instead of input, if set.
588
+ #
584
589
  # Raises EOFError if input is exhausted.
585
590
  #
586
591
  def get_response( )
592
+ return @question.first_answer if @question.first_answer?
593
+
587
594
  if @question.character.nil?
588
595
  if @question.echo == true and @question.limit.nil?
589
596
  get_line
@@ -25,3 +25,19 @@ module Kernel
25
25
  extend Forwardable
26
26
  def_delegators :$terminal, :agree, :ask, :choose, :say
27
27
  end
28
+
29
+ class Object
30
+ #
31
+ # Tries this object as a _first_answer_ for a HighLine::Question. See that
32
+ # attribute for details.
33
+ #
34
+ # *Warning*: This Object will be passed to String() before set.
35
+ #
36
+ def or_ask( *args, &details )
37
+ ask(*args) do |question|
38
+ question.first_answer = String(self) unless nil?
39
+
40
+ details.call(question) unless details.nil?
41
+ end
42
+ end
43
+ end
@@ -31,6 +31,7 @@ class HighLine
31
31
  super("Ignored", [ ], &nil) # avoiding passing the block along
32
32
 
33
33
  @items = [ ]
34
+ @hidden_items = [ ]
34
35
  @help = Hash.new("There's no help for that topic.")
35
36
 
36
37
  @index = :number
@@ -150,6 +151,13 @@ class HighLine
150
151
  def choices( *names, &action )
151
152
  names.each { |n| choice(n, &action) }
152
153
  end
154
+
155
+ # Identical to choice(), but the item will not be listed for the user.
156
+ def hidden( name, help = nil, &action )
157
+ @hidden_items << [name, action]
158
+
159
+ @help[name.to_s.downcase] = help unless help.nil?
160
+ end
153
161
 
154
162
  #
155
163
  # Sets the indexing style for this Menu object. Indexes are appended to
@@ -255,6 +263,9 @@ class HighLine
255
263
  # on the settings of _index_ and _select_by_.
256
264
  #
257
265
  def options( )
266
+ # add in any hidden menu commands
267
+ @items.concat(@hidden_items)
268
+
258
269
  by_index = if @index == :letter
259
270
  l_index = "`"
260
271
  @items.map { "#{l_index.succ!}" }
@@ -271,6 +282,9 @@ class HighLine
271
282
  else
272
283
  by_index + by_name
273
284
  end
285
+ ensure
286
+ # make sure the hidden items are removed, before we return
287
+ @items.slice!(@items.size - @hidden_items.size, @hidden_items.size)
274
288
  end
275
289
 
276
290
  #
@@ -279,6 +293,9 @@ class HighLine
279
293
  # selection, it will be executed as described in Menu.choice().
280
294
  #
281
295
  def select( highline_context, selection, details = nil )
296
+ # add in any hidden menu commands
297
+ @items.concat(@hidden_items)
298
+
282
299
  # Find the selected action.
283
300
  name, action = if selection =~ /^\d+$/
284
301
  @items[selection.to_i - 1]
@@ -301,6 +318,9 @@ class HighLine
301
318
  else
302
319
  nil
303
320
  end
321
+ ensure
322
+ # make sure the hidden items are removed, before we return
323
+ @items.slice!(@items.size - @hidden_items.size, @hidden_items.size)
304
324
  end
305
325
 
306
326
  #
@@ -49,6 +49,7 @@ class HighLine
49
49
  @in = nil
50
50
  @confirm = nil
51
51
  @gather = false
52
+ @first_answer = nil
52
53
  @directory = Pathname.new(File.expand_path(File.dirname($0)))
53
54
  @glob = "*"
54
55
  @responses = Hash.new
@@ -144,6 +145,13 @@ class HighLine
144
145
  # question is evaluated, so you can use it in your question.
145
146
  #
146
147
  attr_accessor :gather
148
+ #
149
+ # When set to a non *nil* value, this will be tried as an answer to the
150
+ # question. If this answer passes validations, it will become the result
151
+ # without the user ever being prompted. Otherwise this value is discarded,
152
+ # and this Question is resolved as a normal call to HighLine.ask().
153
+ #
154
+ attr_writer :first_answer
147
155
  #
148
156
  # The directory from which a user will be allowed to select files, when
149
157
  # File or Pathname is specified as an _answer_type_. Initially set to
@@ -323,6 +331,18 @@ class HighLine
323
331
  else expected[0..-2].join(", ") + ", and #{expected.last}"
324
332
  end
325
333
  end
334
+
335
+ # Returns _first_answer_, which will be unset following this call.
336
+ def first_answer( )
337
+ @first_answer
338
+ ensure
339
+ @first_answer = nil
340
+ end
341
+
342
+ # Returns true if _first_answer_ is set.
343
+ def first_answer?( )
344
+ not @first_answer.nil?
345
+ end
326
346
 
327
347
  #
328
348
  # Returns +true+ if the _answer_object_ is greater than the _above_
@@ -763,4 +763,11 @@ class TestHighLine < Test::Unit::TestCase
763
763
  @terminal.say("-=" * 50)
764
764
  assert_equal(("-=" * 40 + "\n") + ("-=" * 10 + "\n"), @output.string)
765
765
  end
766
+
767
+ def test_version
768
+ assert_not_nil(HighLine::VERSION)
769
+ assert_instance_of(String, HighLine::VERSION)
770
+ assert(HighLine::VERSION.frozen?)
771
+ assert_match(/\A\d\.\d\.\d\Z/, HighLine::VERSION)
772
+ end
766
773
  end
@@ -20,9 +20,35 @@ class TestImport < Test::Unit::TestCase
20
20
  assert_respond_to(self, :say)
21
21
  end
22
22
 
23
+ def test_or_ask
24
+ old_terminal = $terminal
25
+
26
+ input = StringIO.new
27
+ output = StringIO.new
28
+ $terminal = HighLine.new(input, output)
29
+
30
+ input << "10\n"
31
+ input.rewind
32
+
33
+ assert_equal(10, nil.or_ask("How much? ", Integer))
34
+
35
+ input.rewind
36
+
37
+ assert_equal(20, "20".or_ask("How much? ", Integer))
38
+ assert_equal(20, 20.or_ask("How much? ", Integer))
39
+
40
+ assert_equal(10, 20.or_ask("How much? ", Integer) { |q| q.in = 1..10 })
41
+ ensure
42
+ $terminal = old_terminal
43
+ end
44
+
23
45
  def test_redirection
46
+ old_terminal = $terminal
47
+
24
48
  $terminal = HighLine.new(nil, (output = StringIO.new))
25
49
  say("Testing...")
26
50
  assert_equal("Testing...\n", output.string)
51
+ ensure
52
+ $terminal = old_terminal
27
53
  end
28
54
  end
@@ -304,6 +304,46 @@ class TestMenu < Test::Unit::TestCase
304
304
  assert_equal("Sample1", selected)
305
305
  end
306
306
 
307
+ def test_hidden
308
+ @input << "Hidden\n4\n"
309
+ @input.rewind
310
+
311
+ selected = @terminal.choose do |menu|
312
+ menu.choice "Sample1"
313
+ menu.choice "Sample2"
314
+ menu.choice "Sample3"
315
+ menu.hidden "Hidden!"
316
+ end
317
+ assert_equal("Hidden!", selected)
318
+ assert_equal("1. Sample1\n2. Sample2\n3. Sample3\n? ", @output.string)
319
+
320
+ @input.rewind
321
+
322
+ selected = @terminal.choose do |menu|
323
+ menu.select_by = :index
324
+
325
+ menu.choice "Sample1"
326
+ menu.choice "Sample2"
327
+ menu.choice "Sample3"
328
+ menu.hidden "Hidden!"
329
+ end
330
+ assert_equal("Hidden!", selected)
331
+
332
+ @input.rewind
333
+
334
+ selected = @terminal.choose do |menu|
335
+ menu.select_by = :name
336
+
337
+ menu.choice "Sample1"
338
+ menu.choice "Sample2"
339
+ menu.choice "Sample3"
340
+ menu.hidden "Hidden!"
341
+ end
342
+ assert_equal("Hidden!", selected)
343
+
344
+ @input.rewind
345
+ end
346
+
307
347
  def test_select_by_letter
308
348
  @input << "b\n"
309
349
  @input.rewind
metadata CHANGED
@@ -3,15 +3,15 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: highline
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.4
7
- date: 2006-02-26 00:00:00 -06:00
8
- summary: HighLine is a high-level line oriented console interface.
6
+ version: 1.2.0
7
+ date: 2006-03-22 00:00:00 -06:00
8
+ summary: HighLine is a high-level command-line IO library.
9
9
  require_paths:
10
10
  - lib
11
11
  email: james@grayproductions.net
12
12
  homepage: http://highline.rubyforge.org
13
13
  rubyforge_project: highline
14
- description: "A \"high-level line oriented\" input/output library that grew out of my solution to Ruby Quiz #29. This library attempts to make standard console input and output robust and painless."
14
+ description: A high-level IO library that provides validation, type conversion, and more for command-line interfaces. HighLine also includes a complete menu system that can crank out anything from simple list selection to complete shells with just minutes of work.
15
15
  autorequire: highline
16
16
  default_executable:
17
17
  bindir: bin