clio 0.0.1 → 0.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.
Files changed (181) hide show
  1. data/CHANGES +66 -0
  2. data/MANIFEST +48 -169
  3. data/README +13 -17
  4. data/RELEASE +8 -0
  5. data/VERSION +1 -0
  6. data/lib/clio/buffer.rb +93 -0
  7. data/lib/clio/commandable.rb +71 -69
  8. data/lib/clio/commandline.rb +429 -230
  9. data/lib/clio/consoleutils.rb +0 -16
  10. data/lib/clio/facets/kernel.rb +13 -0
  11. data/lib/clio/facets/string.rb +25 -0
  12. data/lib/clio/layout.rb +14 -0
  13. data/lib/clio/layout/flow.rb +1 -0
  14. data/lib/clio/layout/line.rb +23 -0
  15. data/lib/clio/layout/list.rb +33 -0
  16. data/lib/clio/layout/split.rb +122 -0
  17. data/lib/clio/layout/stack.rb +17 -0
  18. data/lib/clio/layout/table.rb +46 -0
  19. data/lib/clio/progressbar.rb +189 -210
  20. data/lib/clio/string.rb +116 -109
  21. data/lib/clio/usage.rb +184 -0
  22. data/lib/clio/usage/argument.rb +84 -0
  23. data/lib/clio/usage/command.rb +440 -0
  24. data/lib/clio/usage/interface.rb +122 -0
  25. data/lib/clio/usage/main.rb +165 -0
  26. data/lib/clio/usage/option.rb +251 -0
  27. data/lib/clio/usage/parser.rb +191 -0
  28. data/lib/clio/usage/signature.rb +55 -0
  29. data/meta/abstract +3 -0
  30. data/meta/authors +1 -0
  31. data/meta/created +1 -0
  32. data/meta/homepage +1 -0
  33. data/meta/license +1 -0
  34. data/meta/repository +1 -0
  35. data/meta/summary +1 -0
  36. data/spec/commandline/autousage.rd +56 -0
  37. data/spec/commandline/bracket.rd +64 -0
  38. data/spec/commandline/completion.rd +38 -0
  39. data/spec/commandline/define.rd +44 -0
  40. data/spec/commandline/method.rd +60 -0
  41. data/spec/commandline/parse.rd +72 -0
  42. data/spec/commandline/scenario.rd +81 -0
  43. data/spec/commandline/subclass.rd +54 -0
  44. data/spec/string/unit.rd +58 -0
  45. data/spec/usage/define.rd +44 -0
  46. data/spec/usage/parse.rd +47 -0
  47. metadata +65 -196
  48. data/HISTORY +0 -11
  49. data/METADATA +0 -18
  50. data/NEWS +0 -10
  51. data/admin/config/reap.yaml +0 -30
  52. data/admin/depot/commandline.rb +0 -219
  53. data/admin/depot/multicommand.rb +0 -403
  54. data/admin/depot/test_multicommand.rb +0 -40
  55. data/admin/log/notes.xml +0 -28
  56. data/admin/log/stats.html +0 -25
  57. data/admin/log/syntax.log +0 -0
  58. data/admin/log/testunit.log +0 -16
  59. data/admin/pack/clio-0.0.1.gem +0 -0
  60. data/admin/share/reap/example.rb +0 -7
  61. data/admin/temps/lib/clio/about.rb.erb +0 -4
  62. data/lib/clio/command.rb +0 -296
  63. data/lib/clio/option.rb +0 -36
  64. data/lib/clio/runmode.rb +0 -126
  65. data/test/test_command.rb +0 -42
  66. data/test/test_commandline.rb +0 -83
  67. data/vendor/Console/Console.cpp +0 -1203
  68. data/vendor/Console/Console.rdoc +0 -690
  69. data/vendor/Console/Console_ANSI.rdoc +0 -302
  70. data/vendor/Console/HISTORY.txt +0 -7
  71. data/vendor/Console/INSTALL.txt +0 -18
  72. data/vendor/Console/Makefile +0 -162
  73. data/vendor/Console/README.txt +0 -26
  74. data/vendor/Console/doc/classes/Win32.html +0 -115
  75. data/vendor/Console/doc/classes/Win32/Console.html +0 -650
  76. data/vendor/Console/doc/classes/Win32/Console.src/M000001.html +0 -31
  77. data/vendor/Console/doc/classes/Win32/Console.src/M000002.html +0 -23
  78. data/vendor/Console/doc/classes/Win32/Console.src/M000003.html +0 -23
  79. data/vendor/Console/doc/classes/Win32/Console.src/M000004.html +0 -27
  80. data/vendor/Console/doc/classes/Win32/Console.src/M000005.html +0 -23
  81. data/vendor/Console/doc/classes/Win32/Console.src/M000006.html +0 -28
  82. data/vendor/Console/doc/classes/Win32/Console.src/M000007.html +0 -23
  83. data/vendor/Console/doc/classes/Win32/Console.src/M000008.html +0 -24
  84. data/vendor/Console/doc/classes/Win32/Console.src/M000009.html +0 -44
  85. data/vendor/Console/doc/classes/Win32/Console.src/M000010.html +0 -23
  86. data/vendor/Console/doc/classes/Win32/Console.src/M000011.html +0 -33
  87. data/vendor/Console/doc/classes/Win32/Console.src/M000012.html +0 -26
  88. data/vendor/Console/doc/classes/Win32/Console.src/M000013.html +0 -27
  89. data/vendor/Console/doc/classes/Win32/Console.src/M000014.html +0 -28
  90. data/vendor/Console/doc/classes/Win32/Console.src/M000015.html +0 -23
  91. data/vendor/Console/doc/classes/Win32/Console.src/M000016.html +0 -23
  92. data/vendor/Console/doc/classes/Win32/Console.src/M000017.html +0 -23
  93. data/vendor/Console/doc/classes/Win32/Console.src/M000018.html +0 -29
  94. data/vendor/Console/doc/classes/Win32/Console.src/M000019.html +0 -23
  95. data/vendor/Console/doc/classes/Win32/Console.src/M000020.html +0 -23
  96. data/vendor/Console/doc/classes/Win32/Console.src/M000021.html +0 -28
  97. data/vendor/Console/doc/classes/Win32/Console.src/M000022.html +0 -23
  98. data/vendor/Console/doc/classes/Win32/Console.src/M000023.html +0 -28
  99. data/vendor/Console/doc/classes/Win32/Console.src/M000024.html +0 -35
  100. data/vendor/Console/doc/classes/Win32/Console.src/M000025.html +0 -28
  101. data/vendor/Console/doc/classes/Win32/Console.src/M000026.html +0 -28
  102. data/vendor/Console/doc/classes/Win32/Console.src/M000027.html +0 -28
  103. data/vendor/Console/doc/classes/Win32/Console.src/M000028.html +0 -31
  104. data/vendor/Console/doc/classes/Win32/Console.src/M000029.html +0 -23
  105. data/vendor/Console/doc/classes/Win32/Console.src/M000030.html +0 -23
  106. data/vendor/Console/doc/classes/Win32/Console.src/M000031.html +0 -23
  107. data/vendor/Console/doc/classes/Win32/Console.src/M000032.html +0 -27
  108. data/vendor/Console/doc/classes/Win32/Console.src/M000033.html +0 -27
  109. data/vendor/Console/doc/classes/Win32/Console.src/M000034.html +0 -25
  110. data/vendor/Console/doc/classes/Win32/Console/ANSI.html +0 -103
  111. data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.html +0 -220
  112. data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000035.html +0 -32
  113. data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000036.html +0 -205
  114. data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000037.html +0 -40
  115. data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000038.html +0 -25
  116. data/vendor/Console/doc/classes/Win32/Console/API.html +0 -758
  117. data/vendor/Console/doc/classes/Win32/Console/API.src/M000039.html +0 -27
  118. data/vendor/Console/doc/classes/Win32/Console/API.src/M000040.html +0 -27
  119. data/vendor/Console/doc/classes/Win32/Console/API.src/M000041.html +0 -27
  120. data/vendor/Console/doc/classes/Win32/Console/API.src/M000042.html +0 -32
  121. data/vendor/Console/doc/classes/Win32/Console/API.src/M000043.html +0 -32
  122. data/vendor/Console/doc/classes/Win32/Console/API.src/M000044.html +0 -28
  123. data/vendor/Console/doc/classes/Win32/Console/API.src/M000045.html +0 -26
  124. data/vendor/Console/doc/classes/Win32/Console/API.src/M000046.html +0 -26
  125. data/vendor/Console/doc/classes/Win32/Console/API.src/M000047.html +0 -27
  126. data/vendor/Console/doc/classes/Win32/Console/API.src/M000048.html +0 -30
  127. data/vendor/Console/doc/classes/Win32/Console/API.src/M000049.html +0 -29
  128. data/vendor/Console/doc/classes/Win32/Console/API.src/M000050.html +0 -27
  129. data/vendor/Console/doc/classes/Win32/Console/API.src/M000051.html +0 -28
  130. data/vendor/Console/doc/classes/Win32/Console/API.src/M000052.html +0 -30
  131. data/vendor/Console/doc/classes/Win32/Console/API.src/M000053.html +0 -27
  132. data/vendor/Console/doc/classes/Win32/Console/API.src/M000054.html +0 -29
  133. data/vendor/Console/doc/classes/Win32/Console/API.src/M000055.html +0 -29
  134. data/vendor/Console/doc/classes/Win32/Console/API.src/M000056.html +0 -28
  135. data/vendor/Console/doc/classes/Win32/Console/API.src/M000057.html +0 -27
  136. data/vendor/Console/doc/classes/Win32/Console/API.src/M000058.html +0 -47
  137. data/vendor/Console/doc/classes/Win32/Console/API.src/M000059.html +0 -32
  138. data/vendor/Console/doc/classes/Win32/Console/API.src/M000060.html +0 -47
  139. data/vendor/Console/doc/classes/Win32/Console/API.src/M000061.html +0 -34
  140. data/vendor/Console/doc/classes/Win32/Console/API.src/M000062.html +0 -32
  141. data/vendor/Console/doc/classes/Win32/Console/API.src/M000063.html +0 -32
  142. data/vendor/Console/doc/classes/Win32/Console/API.src/M000064.html +0 -35
  143. data/vendor/Console/doc/classes/Win32/Console/API.src/M000065.html +0 -26
  144. data/vendor/Console/doc/classes/Win32/Console/API.src/M000066.html +0 -27
  145. data/vendor/Console/doc/classes/Win32/Console/API.src/M000067.html +0 -29
  146. data/vendor/Console/doc/classes/Win32/Console/API.src/M000068.html +0 -27
  147. data/vendor/Console/doc/classes/Win32/Console/API.src/M000069.html +0 -27
  148. data/vendor/Console/doc/classes/Win32/Console/API.src/M000070.html +0 -28
  149. data/vendor/Console/doc/classes/Win32/Console/API.src/M000071.html +0 -27
  150. data/vendor/Console/doc/classes/Win32/Console/API.src/M000072.html +0 -26
  151. data/vendor/Console/doc/classes/Win32/Console/API.src/M000073.html +0 -27
  152. data/vendor/Console/doc/classes/Win32/Console/API.src/M000074.html +0 -31
  153. data/vendor/Console/doc/classes/Win32/Console/API.src/M000075.html +0 -27
  154. data/vendor/Console/doc/classes/Win32/Console/API.src/M000076.html +0 -32
  155. data/vendor/Console/doc/classes/Win32/Console/API.src/M000077.html +0 -27
  156. data/vendor/Console/doc/classes/Win32/Console/API.src/M000078.html +0 -32
  157. data/vendor/Console/doc/classes/Win32/Console/API.src/M000079.html +0 -32
  158. data/vendor/Console/doc/classes/Win32/Console/API.src/M000080.html +0 -32
  159. data/vendor/Console/doc/classes/Win32/Console/Constants.html +0 -360
  160. data/vendor/Console/doc/created.rid +0 -1
  161. data/vendor/Console/doc/files/Console_ANSI_rdoc.html +0 -407
  162. data/vendor/Console/doc/files/Console_cpp.html +0 -104
  163. data/vendor/Console/doc/files/Console_rdoc.html +0 -964
  164. data/vendor/Console/doc/files/lib/Win32/Console/ANSI_rb.html +0 -123
  165. data/vendor/Console/doc/files/lib/Win32/Console_rb.html +0 -297
  166. data/vendor/Console/doc/fr_class_index.html +0 -32
  167. data/vendor/Console/doc/fr_file_index.html +0 -31
  168. data/vendor/Console/doc/fr_method_index.html +0 -106
  169. data/vendor/Console/doc/index.html +0 -24
  170. data/vendor/Console/doc/rdoc-style.css +0 -172
  171. data/vendor/Console/extconf.rb +0 -18
  172. data/vendor/Console/lib/Term/ansicolor.rb +0 -76
  173. data/vendor/Console/lib/Win32/Console.rb +0 -970
  174. data/vendor/Console/lib/Win32/Console/ANSI.rb +0 -305
  175. data/vendor/Console/test/test_cursor.rb +0 -9
  176. data/vendor/Console/test/test_mouse.rb +0 -6
  177. data/vendor/Console/test/test_readinput.rb +0 -62
  178. data/vendor/Console/test/test_readoutput.rb +0 -52
  179. data/vendor/Console/test/test_sendevent.rb +0 -17
  180. data/vendor/Console/test/test_title.rb +0 -14
  181. data/vendor/Console/test/test_write.rb +0 -36
data/lib/clio/string.rb CHANGED
@@ -1,147 +1,154 @@
1
- #require 'facets/rope'
2
1
  require 'clio/ansicode'
3
- require 'facets/string/mask'
2
+ require 'clio/layout/split'
3
+ require 'clio/facets/string'
4
4
 
5
5
  module Clio
6
6
 
7
- # = Clio String class.
7
+ def self.string(str)
8
+ String.new(str)
9
+ end
10
+
11
+ # Clio Strings stores a regular string (@text) and
12
+ # a Hash mapping character index to ansicodes (@marks).
13
+ # For example is we has the string:
14
+ #
15
+ # "Big Apple"
16
+ #
17
+ # And applied the color red to it, the marks hash would be:
18
+ #
19
+ # { 0=>[:red] , 9=>[:clear] }
8
20
  #
9
21
  class String
10
22
 
11
- ESC_RE = /\e\[[0-9]*\w/
12
-
13
- private
14
-
15
- def initialize(text, ansi=nil)
16
- @text = text.to_s
17
- @ansi = ansi || text.to_s
18
- end
19
-
20
- public
21
-
22
23
  attr :text
24
+ attr :marks
23
25
 
24
- attr :ansi
25
-
26
- #
27
- def to_s ; ansi ; end
28
-
29
- #def to_str ; text ; end
30
-
31
- #
32
- def +(append)
33
- case append
34
- when Symbol
35
- t = text
36
- a = ansi + ANSICode.send(append)
37
- when self.class
38
- t = text + append.text
39
- a = ansi + append.ansi
40
- else
41
- t = text + append
42
- a = ansi + append
43
- end
44
- self.class.new(t, a)
26
+ def initialize(text=nil, marks=nil)
27
+ @text = text || ''
28
+ @marks = marks || Hash.new{ |h,k| h[k]=[] }
45
29
  end
46
30
 
47
- #
48
- def <<(append)
49
- case append
50
- when Symbol
51
- @ansi << ANSICode.send(append)
52
- when self.class
53
- @text << append.text
54
- @ansi << append.ansi
55
- else
56
- @text << append
57
- @ansi << append
31
+ def to_s
32
+ s = text.dup
33
+ m = marks.sort{ |a,b| b[0] <=> a[0] }
34
+ m.each do |index, codes|
35
+ codes.each do |code|
36
+ s.insert(index, ANSICode.send(code))
37
+ end
58
38
  end
39
+ s
59
40
  end
60
41
 
61
- #
62
42
  def size ; text.size ; end
63
- alias_method(:length, :size)
64
43
 
65
- # Give the string a color.
66
- def color(ansicolor=nil)
67
- self.class.new(text, ANSICode.send(ansicolor){ansi})
44
+ ###
45
+ def color!(ansicolor)
46
+ marks[0] << ansicolor
47
+ marks[size] << :clear
68
48
  end
69
49
 
70
- # Give the string a color.
71
- def color!(ansicolor=nil)
72
- @ansi = ANSICode.send(ansicolor){ansi}
50
+ ###
51
+ def color(ansicolor)
52
+ m = marks.dup
53
+ m[0] << ansicolor
54
+ m[size] << :clear
55
+ self.class.new(text, m)
73
56
  end
74
57
 
75
- #--
76
- # TODO: No doubt the delegation will need to be made more robust.
77
- #++
78
-
79
- INPLACE_DELEGATE_METHODS = /(\[\]=|replace|!$)/
80
- EXCLUDE_DELEGATE_METHODS = /(split|^to_)/
81
-
82
- # Delegate to underlying text/ansi.
83
- def method_missing(s, *a, &b)
84
- case s.to_s
85
- when EXCLUDE_DELEGATE_METHODS
86
- super
87
- when INPLACE_DELEGATE_METHODS
88
- text.send(s, *a, &b)
89
- m = ansi.to_mask
90
- e = ansi.to_mask(ESC_RE)
91
- n = (e - m)
92
- e.instance_delegate.send(s,*a, &b)
93
- r = e + n
94
- @ansi = r.to_s
58
+ ###
59
+ def upcase ; self.class.new(text.upcase, marks) ; end
60
+ def upcase! ; text.upcase! ; end
61
+
62
+ ###
63
+ def downcase ; self.class.new(text.upcase, marks) ; end
64
+ def downcase! ; text.upcase! ; end
65
+
66
+ ###
67
+ def +(other)
68
+ case other
69
+ when String
70
+ ntext = text + other.text
71
+ nmarks = marks.dup
72
+ other.marks.each{ |i, c| m[i] << c }
95
73
  else
96
- apply(s, *a, &b)
74
+ ntext = text + other.to_s
75
+ nmarks = marks.dup
97
76
  end
77
+ self.class.new(ntext, nmarks)
98
78
  end
99
79
 
100
- private
101
-
102
- #
103
- def apply(s, *a, &b)
104
- t = text.send(s, *a, &b)
105
- m = ansi.to_mask
106
- e = ansi.to_mask(ESC_RE)
107
- n = (e - m)
108
- x = e.apply(s,*a, &b)
109
- r = x + n
110
- self.class.new(t, r.to_s)
80
+ def |(other)
81
+ Split.new(self, other)
111
82
  end
112
83
 
113
- end
114
-
115
- end
116
-
117
-
118
- =begin SPECIFICATION
119
-
120
- require 'quarry/spec'
84
+ def lr(other, options={})
85
+ Split.new(self, other, options)
86
+ end
121
87
 
122
- Quarry.spec "Clio::String" do
88
+ ### slice
89
+ def slice(*args)
90
+ if args.size == 2
91
+ index, len = *args
92
+ endex = index+len
93
+ new_text = text[index, len]
94
+ new_marks = {}
95
+ marks.each do |i, v|
96
+ new_marks[i] = v if i >= index && i < endex
97
+ end
98
+ self.class.new(new_text, new_marks)
99
+ elsif args.size == 1
100
+ rng = args.first
101
+ case rng
102
+ when Range
103
+ index, endex = rng.begin, rng.end
104
+ new_text = text[rng]
105
+ new_marks = {}
106
+ marks.each do |i, v|
107
+ new_marks[i] = v if i >= index && i < endex
108
+ end
109
+ self.class.new(new_text, new_marks)
110
+ else
111
+ self.class.new(text[rng,1], {rng=>marks[rng]})
112
+ end
113
+ else
114
+ raise ArgumentError
115
+ end
116
+ end
123
117
 
124
- s1 = Clio::String.new("Hi how are you.")
125
- s2 = Clio::String.new("Fine thanks.")
118
+ alias_method :[], :slice
126
119
 
127
- verify "color" do
128
- r = s1.color(:red)
129
- e = Clio::ANSICode.red(s1.text)
130
- e.assert == r.to_s
120
+ # TODO: block support and \1, \2 support.
121
+ def sub(pattern,replacement)
122
+ if md = pattern.match(@text)
123
+ delta = replacement.size - md.size
124
+ marks2 = shift_marks(md.end, delta)
125
+ text2 = text.sub(pattern,replacement)
126
+ self.class.new(text2, marks2)
127
+ else
128
+ self.class.new(text, marks)
129
+ end
131
130
  end
132
131
 
133
- verify "non-in-place delegation" do
134
- r = s1.upcase
135
- e = s1.text.upcase
136
- e.assert == r.to_s
132
+ #
133
+ def gsub
137
134
  end
138
135
 
139
- verify "string addition" do
140
- r = s1 + s2
141
- e = s1.text + s2.text
136
+ private
137
+
138
+ def shift_marks(index, delta)
139
+ new_marks = {}
140
+ marks.each do |i, v|
141
+ case i <=> index
142
+ when 0, -1
143
+ new_marks[i] = v
144
+ when 1
145
+ new_marks[i+delta] = v
146
+ end
147
+ end
148
+ new_marks
142
149
  end
143
150
 
144
151
  end
145
152
 
146
- =end
153
+ end
147
154
 
data/lib/clio/usage.rb ADDED
@@ -0,0 +1,184 @@
1
+ require 'clio/usage/main'
2
+ require 'clio/usage/parser'
3
+
4
+ module Clio
5
+
6
+ # = Usage
7
+ #
8
+ # Uasge provides a verstile but easy to use system of describing
9
+ # a commandline interface.
10
+ #
11
+ # == Underlying Fluent and Block Notation
12
+ #
13
+ # Underlying all usage is a fluent interface for decalaring
14
+ # a commandline's structure. Here is an example of using
15
+ # this DSL, albeit rather brutely.
16
+ #
17
+ # usage = Clio::Usage.new
18
+ # usage.command(:document).help('generate documentation')
19
+ # usage.command(:document).option(:output, :o).type('FILE')
20
+ # usage.command(:document).option(:output).help('output directory')
21
+ # usage.option(:verbose, :V).help('verbose output')
22
+ # usage.option(:quiet, :q).help('run silently').xor(:V)
23
+ #
24
+ # The example defines a subcommand 'document' that can take an
25
+ # 'output' option, and two mutually excluive universal options,
26
+ # 'verbose' and 'quiet', with respective one-letter aliases.
27
+ #
28
+ # As you might expect the fluent notation can be broken down into
29
+ # block notation which is easier to read.
30
+ #
31
+ # usage = Usage.new
32
+ # usage do
33
+ # option(:verbose, :v) do
34
+ # help('verbose output')
35
+ # end
36
+ # option(:quiet, :q) do
37
+ # help('run silently')
38
+ # xor(:V)
39
+ # end
40
+ # command(:document) do
41
+ # help('generate documentation')
42
+ # option(:output, :o) do
43
+ # type('FILE')
44
+ # help('output directory')
45
+ # end
46
+ # argument('files') do
47
+ # multiple
48
+ # end
49
+ # end
50
+ # end
51
+ #
52
+ # Clearly block notation is DRY and more elegant the the previous fluent
53
+ # version, but fluent notation is important because it allows the usage
54
+ # object to be easily passed around and augmented as needed.
55
+ #
56
+ #--
57
+ # == Abbriviated Notation
58
+ #
59
+ # While comprehensble, the core Usage DSL can be a somewhat verbose.
60
+ # So abbriviated forms of these methods are provided. These methods
61
+ # go one step further as well, and allow for some additional arguments.
62
+ #
63
+ # cli.usage do
64
+ # opt('verbose -v', 'verbose output') |
65
+ # opt('quiet -q' , 'run silently')
66
+ # cmd('document', 'generate documentation') do
67
+ # opt('output=FILE -o', 'output directory')
68
+ # arg('FILE*')
69
+ # end
70
+ # end
71
+ #
72
+ # Notice the use of '|'. This allows us to define mutual exclusion
73
+ # without resorting to #xor as was done in the first example.
74
+ #++
75
+ #
76
+ # = Method Notation
77
+ #
78
+ # This notation is very elegant, but slightly more limited in scope.
79
+ # For instance, subcommands that use non-letter characters, such as ':',
80
+ # can not be described with this notation.
81
+ #
82
+ # usage.document('<file*>', '--output=FILE -o')
83
+ # usage('--verbose -V','--quiet -q')
84
+ #
85
+ # usage.help(
86
+ # 'document' , 'generate documentation',
87
+ # 'validate' , 'run tests or specifications',
88
+ # '--verbose' , 'verbose output',
89
+ # '--quiet' , 'run siltently'
90
+ # )
91
+ #
92
+ # usage.document.help(
93
+ # '--output', 'output directory'
94
+ # 'file*', 'files to document'
95
+ # )
96
+ #
97
+ # This notation is slightly more limited in scope... so...
98
+ #
99
+ # usage.command(:document, '--output=FILE -o', '<file*>')
100
+ #
101
+ # == Bracket Shorthand Notation
102
+ #
103
+ # The core notation can be somewhat verbose. As a further convenience
104
+ # commandline usage can be defined with a brief <i>bracket shorthand</i>.
105
+ # This is especailly useful when the usage is simple and statically defined.
106
+ #
107
+ # usage['document']['--output=FILE -o']['FILE*']
108
+ #
109
+ # Using a little creativity to improve readabilty we can convert the
110
+ # whole example from above using this notation.
111
+ #
112
+ # usage['--verbose -V', 'verbose output' ] \
113
+ # ['--quiet -q', 'run silently' ] \
114
+ # ['document', 'generate documention' ] \
115
+ # [ '--output=FILE -o', 'output directory' ] \
116
+ # [ 'FILE*', 'files to document' ]
117
+ #
118
+ # Alternately the help information can be left out and defined in
119
+ # a seprate set of usage calls.
120
+ #
121
+ # usage['--verbose -V']['--quiet -q'] \
122
+ # ['document']['--output=FILE -o']['FILE*']
123
+ #
124
+ # usage.help(
125
+ # 'document' , 'generate documentation',
126
+ # 'validate' , 'run tests or specifications',
127
+ # '--verbose' , 'verbose output',
128
+ # '--quiet' , 'run siltently'
129
+ # )
130
+ #
131
+ # usage['document'].help(
132
+ # '--output', 'output directory'
133
+ # 'FILE', 'files to docment'
134
+ # )
135
+ #
136
+ # A little more verbose, but a bit more intutive.
137
+ #
138
+ # == "Alien" Notation
139
+ #
140
+ # As a side note, it is easy enough to alias #[] to #_, so alternatively
141
+ # one code create a variant shorthand written as:
142
+ #
143
+ # usage do
144
+ # _ '--verbose -V', 'verbose output'
145
+ # _ '--quiet -q', 'run silently'
146
+ # _ 'document', 'generate documentation' do
147
+ # _ '--output=FILE -o', 'output directory'
148
+ # _ 'FILE*', 'files to document'
149
+ # end
150
+ # end
151
+ #
152
+ # To demonsrtate it's equvalence to bracket shorthand, it can be chained as well.
153
+ #
154
+ # usage._('document')._('--output=FILE -o')._('FILE*')
155
+ #
156
+ # This notation is not supported by default, but if it is more your style
157
+ # it is easy enough to implement by extending Clio::Usage::Command like this:
158
+ #
159
+ # class Clio::Usage::Command
160
+ # alias_method :_, :[]
161
+ # end
162
+ #
163
+ # == Combining Notations
164
+ #
165
+ # Since the various notations all translate to same underlying
166
+ # structures, they can be mixed and matched as suites ones taste.
167
+ # For example we could mix Method Notation and Bracket Notation.
168
+ #
169
+ # usage.document['--output=FILE -o']['file*']
170
+ # usage['--verbose -V']['--quiet -q']
171
+ #
172
+ # The important thing to keep in mind when doing this is what is
173
+ # returned by each type of usage call.
174
+ #
175
+ module Usage
176
+
177
+ def self.new(name=nil, &block)
178
+ Main.new(name, &block)
179
+ end
180
+
181
+ end#module Usage
182
+
183
+ end#module Clio
184
+
@@ -0,0 +1,84 @@
1
+ module Clio
2
+
3
+ module Usage #:nodoc:
4
+
5
+ # = Usage Argument
6
+ #
7
+ class Argument
8
+ #attr :parent
9
+ attr :name
10
+ attr :type
11
+ attr :help
12
+ attr :splat
13
+
14
+ # New Argument.
15
+ #def initialize(name, parent=nil, &block)
16
+ def initialize(name, &block)
17
+ @name = name.to_s
18
+ @type = name.upcase
19
+ #@parent = parent
20
+ @splat = false
21
+ @help = ''
22
+ instance_eval(&block) if block
23
+ end
24
+
25
+ #
26
+ def initialize_copy(o)
27
+ @name = o.name.dup
28
+ @type = o.type.dup
29
+ @help = o.help.dup
30
+ end
31
+
32
+ # Same as +name+ but given as a symbol.
33
+ def key
34
+ name.to_sym
35
+ end
36
+
37
+ # Specify the type of the argument.
38
+ # This is an arbitrary description of the type.
39
+ # The value given is converted to uppercase.
40
+ #
41
+ # arg.type('file')
42
+ # arg.type #=> 'FILE'
43
+ #
44
+ def type(string=nil)
45
+ return @type unless string
46
+ @type = string.to_s.upcase
47
+ self
48
+ end
49
+
50
+ #
51
+ def splat(true_or_false=nil)
52
+ return @splat if true_or_false.nil?
53
+ @splat = true_or_false
54
+ end
55
+
56
+ # Specify help text for argument.
57
+ def help(string=nil)
58
+ @help.replace(string.to_s) if string
59
+ @help
60
+ end
61
+
62
+ def to_s
63
+ if name.upcase == type
64
+ s = "<#{name}"
65
+ else
66
+ s = "<#{name}:#{type}"
67
+ end
68
+ s << (splat ? "...>" : ">")
69
+ s
70
+ end
71
+
72
+ def inspect
73
+ s = "<#{name}"
74
+ s << ":#{type.inspect}" if type
75
+ s << ">"
76
+ s
77
+ end
78
+
79
+ end #class Argument
80
+
81
+ end #module Usage
82
+
83
+ end #module Clio
84
+