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.
- data/CHANGES +66 -0
- data/MANIFEST +48 -169
- data/README +13 -17
- data/RELEASE +8 -0
- data/VERSION +1 -0
- data/lib/clio/buffer.rb +93 -0
- data/lib/clio/commandable.rb +71 -69
- data/lib/clio/commandline.rb +429 -230
- data/lib/clio/consoleutils.rb +0 -16
- data/lib/clio/facets/kernel.rb +13 -0
- data/lib/clio/facets/string.rb +25 -0
- data/lib/clio/layout.rb +14 -0
- data/lib/clio/layout/flow.rb +1 -0
- data/lib/clio/layout/line.rb +23 -0
- data/lib/clio/layout/list.rb +33 -0
- data/lib/clio/layout/split.rb +122 -0
- data/lib/clio/layout/stack.rb +17 -0
- data/lib/clio/layout/table.rb +46 -0
- data/lib/clio/progressbar.rb +189 -210
- data/lib/clio/string.rb +116 -109
- data/lib/clio/usage.rb +184 -0
- data/lib/clio/usage/argument.rb +84 -0
- data/lib/clio/usage/command.rb +440 -0
- data/lib/clio/usage/interface.rb +122 -0
- data/lib/clio/usage/main.rb +165 -0
- data/lib/clio/usage/option.rb +251 -0
- data/lib/clio/usage/parser.rb +191 -0
- data/lib/clio/usage/signature.rb +55 -0
- data/meta/abstract +3 -0
- data/meta/authors +1 -0
- data/meta/created +1 -0
- data/meta/homepage +1 -0
- data/meta/license +1 -0
- data/meta/repository +1 -0
- data/meta/summary +1 -0
- data/spec/commandline/autousage.rd +56 -0
- data/spec/commandline/bracket.rd +64 -0
- data/spec/commandline/completion.rd +38 -0
- data/spec/commandline/define.rd +44 -0
- data/spec/commandline/method.rd +60 -0
- data/spec/commandline/parse.rd +72 -0
- data/spec/commandline/scenario.rd +81 -0
- data/spec/commandline/subclass.rd +54 -0
- data/spec/string/unit.rd +58 -0
- data/spec/usage/define.rd +44 -0
- data/spec/usage/parse.rd +47 -0
- metadata +65 -196
- data/HISTORY +0 -11
- data/METADATA +0 -18
- data/NEWS +0 -10
- data/admin/config/reap.yaml +0 -30
- data/admin/depot/commandline.rb +0 -219
- data/admin/depot/multicommand.rb +0 -403
- data/admin/depot/test_multicommand.rb +0 -40
- data/admin/log/notes.xml +0 -28
- data/admin/log/stats.html +0 -25
- data/admin/log/syntax.log +0 -0
- data/admin/log/testunit.log +0 -16
- data/admin/pack/clio-0.0.1.gem +0 -0
- data/admin/share/reap/example.rb +0 -7
- data/admin/temps/lib/clio/about.rb.erb +0 -4
- data/lib/clio/command.rb +0 -296
- data/lib/clio/option.rb +0 -36
- data/lib/clio/runmode.rb +0 -126
- data/test/test_command.rb +0 -42
- data/test/test_commandline.rb +0 -83
- data/vendor/Console/Console.cpp +0 -1203
- data/vendor/Console/Console.rdoc +0 -690
- data/vendor/Console/Console_ANSI.rdoc +0 -302
- data/vendor/Console/HISTORY.txt +0 -7
- data/vendor/Console/INSTALL.txt +0 -18
- data/vendor/Console/Makefile +0 -162
- data/vendor/Console/README.txt +0 -26
- data/vendor/Console/doc/classes/Win32.html +0 -115
- data/vendor/Console/doc/classes/Win32/Console.html +0 -650
- data/vendor/Console/doc/classes/Win32/Console.src/M000001.html +0 -31
- data/vendor/Console/doc/classes/Win32/Console.src/M000002.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000003.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000004.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console.src/M000005.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000006.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console.src/M000007.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000008.html +0 -24
- data/vendor/Console/doc/classes/Win32/Console.src/M000009.html +0 -44
- data/vendor/Console/doc/classes/Win32/Console.src/M000010.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000011.html +0 -33
- data/vendor/Console/doc/classes/Win32/Console.src/M000012.html +0 -26
- data/vendor/Console/doc/classes/Win32/Console.src/M000013.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console.src/M000014.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console.src/M000015.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000016.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000017.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000018.html +0 -29
- data/vendor/Console/doc/classes/Win32/Console.src/M000019.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000020.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000021.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console.src/M000022.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000023.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console.src/M000024.html +0 -35
- data/vendor/Console/doc/classes/Win32/Console.src/M000025.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console.src/M000026.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console.src/M000027.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console.src/M000028.html +0 -31
- data/vendor/Console/doc/classes/Win32/Console.src/M000029.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000030.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000031.html +0 -23
- data/vendor/Console/doc/classes/Win32/Console.src/M000032.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console.src/M000033.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console.src/M000034.html +0 -25
- data/vendor/Console/doc/classes/Win32/Console/ANSI.html +0 -103
- data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.html +0 -220
- data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000035.html +0 -32
- data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000036.html +0 -205
- data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000037.html +0 -40
- data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000038.html +0 -25
- data/vendor/Console/doc/classes/Win32/Console/API.html +0 -758
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000039.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000040.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000041.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000042.html +0 -32
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000043.html +0 -32
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000044.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000045.html +0 -26
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000046.html +0 -26
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000047.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000048.html +0 -30
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000049.html +0 -29
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000050.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000051.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000052.html +0 -30
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000053.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000054.html +0 -29
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000055.html +0 -29
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000056.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000057.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000058.html +0 -47
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000059.html +0 -32
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000060.html +0 -47
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000061.html +0 -34
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000062.html +0 -32
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000063.html +0 -32
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000064.html +0 -35
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000065.html +0 -26
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000066.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000067.html +0 -29
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000068.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000069.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000070.html +0 -28
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000071.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000072.html +0 -26
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000073.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000074.html +0 -31
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000075.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000076.html +0 -32
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000077.html +0 -27
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000078.html +0 -32
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000079.html +0 -32
- data/vendor/Console/doc/classes/Win32/Console/API.src/M000080.html +0 -32
- data/vendor/Console/doc/classes/Win32/Console/Constants.html +0 -360
- data/vendor/Console/doc/created.rid +0 -1
- data/vendor/Console/doc/files/Console_ANSI_rdoc.html +0 -407
- data/vendor/Console/doc/files/Console_cpp.html +0 -104
- data/vendor/Console/doc/files/Console_rdoc.html +0 -964
- data/vendor/Console/doc/files/lib/Win32/Console/ANSI_rb.html +0 -123
- data/vendor/Console/doc/files/lib/Win32/Console_rb.html +0 -297
- data/vendor/Console/doc/fr_class_index.html +0 -32
- data/vendor/Console/doc/fr_file_index.html +0 -31
- data/vendor/Console/doc/fr_method_index.html +0 -106
- data/vendor/Console/doc/index.html +0 -24
- data/vendor/Console/doc/rdoc-style.css +0 -172
- data/vendor/Console/extconf.rb +0 -18
- data/vendor/Console/lib/Term/ansicolor.rb +0 -76
- data/vendor/Console/lib/Win32/Console.rb +0 -970
- data/vendor/Console/lib/Win32/Console/ANSI.rb +0 -305
- data/vendor/Console/test/test_cursor.rb +0 -9
- data/vendor/Console/test/test_mouse.rb +0 -6
- data/vendor/Console/test/test_readinput.rb +0 -62
- data/vendor/Console/test/test_readoutput.rb +0 -52
- data/vendor/Console/test/test_sendevent.rb +0 -17
- data/vendor/Console/test/test_title.rb +0 -14
- 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 '
|
|
2
|
+
require 'clio/layout/split'
|
|
3
|
+
require 'clio/facets/string'
|
|
4
4
|
|
|
5
5
|
module Clio
|
|
6
6
|
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
66
|
-
def color(ansicolor
|
|
67
|
-
|
|
44
|
+
###
|
|
45
|
+
def color!(ansicolor)
|
|
46
|
+
marks[0] << ansicolor
|
|
47
|
+
marks[size] << :clear
|
|
68
48
|
end
|
|
69
49
|
|
|
70
|
-
|
|
71
|
-
def color
|
|
72
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
m
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
125
|
-
s2 = Clio::String.new("Fine thanks.")
|
|
118
|
+
alias_method :[], :slice
|
|
126
119
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
e = s1.text.upcase
|
|
136
|
-
e.assert == r.to_s
|
|
132
|
+
#
|
|
133
|
+
def gsub
|
|
137
134
|
end
|
|
138
135
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
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
|
+
|