cmdline 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/cmdline.rb ADDED
@@ -0,0 +1,251 @@
1
+
2
+
3
+ class CommandLine
4
+
5
+ FLAG_1=0
6
+ FLAG_2=1
7
+ ACCESSOR=2
8
+ DISP_NAME=3
9
+ REQUIRED=4
10
+ DEFAULT=5
11
+ DOC=6
12
+ CHECK=7
13
+
14
+ @@add_help=true
15
+
16
+
17
+
18
+ def self.add_help= bool
19
+ @@add_help=bool
20
+ end
21
+
22
+
23
+
24
+ # definition
25
+ # [ :command, nil, <accessor>, <display name>, <required?>, <default>, <doc>, <check allowed commands> ]
26
+ # command is a subcommand, cf. `svn help`,
27
+ # [ <flag1>, <flag2/nil>, <accessor>, <display name>, <required?>, <default>, <doc>, <check: optional> ]
28
+ #
29
+ # commandline taking arguments, e.g. `mv src target` are specified like this:
30
+ # [ :args, nil, <accessor>, <display name>, <required>, <default>, <doc>, <check: optional> ]
31
+ # the entire rest of the commandline arg array after the first unrecognized options
32
+ # will then be available under `cmdline.<accessor>` the check proc will either be able to check the entire
33
+ # array or, if that fails with an exception, will test each element individually.
34
+ def initialize definition
35
+ self.definition= definition
36
+ @output_io ||= STDERR
37
+ @exit_on_usage=true
38
+
39
+ end
40
+
41
+ def output= io
42
+ @output_io = io
43
+ end
44
+
45
+ # whether `exit` will be called to terminate the program if `usage` is
46
+ # called. Default behaviour is to call `exit`
47
+ # If this behaviour is turned off, a call to usage will result in an exception
48
+ # instead.
49
+ def exit_on_usage= bool
50
+ @exit_on_usage= bool
51
+ end
52
+
53
+ def definition= definition
54
+ definition.push(["-h", "--help", :help, false, false, nil, "print this message"]) if @@add_help
55
+ cl = class << self; self; end
56
+ # add an accessor to self for each definition.
57
+ cl.instance_eval { attr_accessor *definition.map{|arg_def| arg_def[ACCESSOR]} }
58
+
59
+
60
+ definition.each {|arg_def|
61
+ #check if cmdline takes a command
62
+ if arg_def[FLAG_1]==:command
63
+ @has_command = true
64
+ end
65
+ #set default values
66
+ set arg_def[ACCESSOR], arg_def[DEFAULT]
67
+ }
68
+
69
+ @definition=definition
70
+
71
+ class << @definition
72
+ def retrieve_flag flag
73
+ find { |arg|
74
+ arg[FLAG_1]==flag || arg[FLAG_2]==flag
75
+ }
76
+ end
77
+ end
78
+
79
+ end # definition
80
+
81
+ def usage mes=""
82
+ raise mes unless @exit_on_usage
83
+
84
+
85
+ # put together usage information for flags.
86
+ max = 0 #max flag length for formatting
87
+ has_required=false
88
+ has_options=false
89
+ us = @definition.map {|arg_def|
90
+ if arg_def[FLAG_1] == :command
91
+ flag=:command
92
+ elsif arg_def[FLAG_1] == :args
93
+ flag=:args
94
+ else
95
+ # create a usage string of the form:
96
+ # -f/-flag <value>* must start with a number
97
+ # for each definition. (commands and args are treated seperately)
98
+ flag = "#{arg_def[FLAG_1]}"
99
+ flag << "/#{arg_def[FLAG_2]}" if arg_def[FLAG_2]
100
+ flag << " <#{arg_def[DISP_NAME]}>" if arg_def[DISP_NAME]
101
+ flag << "*" if arg_def[REQUIRED]
102
+ has_required = true if arg_def[REQUIRED]
103
+ has_options = true
104
+ max = max > flag.length ? max : flag.length
105
+ end
106
+ [flag, arg_def[DOC]]
107
+ }
108
+
109
+ usage = "usage: #{$0}"
110
+
111
+ if command=@definition.retrieve_flag(:command)
112
+ fmt = command[REQUIRED] ? " %s" : " [%s]"
113
+ usage << sprintf(fmt,command[DISP_NAME])
114
+ end
115
+
116
+ if has_options
117
+ usage << (has_required ? " options" : " [options]")
118
+ end
119
+
120
+ args_doc=false
121
+ if command=@definition.retrieve_flag(:args)
122
+ fmt = command[REQUIRED] ? " %s" : " [%s]"
123
+ usage << sprintf(fmt,command[DISP_NAME])
124
+ args_doc = "#{command[DISP_NAME]}: #{command[DOC]}"
125
+ end
126
+ usage << "\n"
127
+
128
+ us.each { |arg_def|
129
+ if arg_def[0].kind_of? String
130
+ usage << sprintf(" %-#{max}s %s\n", arg_def[0], arg_def[1])
131
+ elsif arg_def[0] == :command
132
+ # command
133
+ usage << arg_def[1] if arg_def[1]
134
+ end
135
+
136
+ }
137
+ @output_io.puts usage
138
+ @output_io.puts "* required flags" if has_required
139
+ @output_io.puts "\n#{args_doc}" if args_doc
140
+ @output_io.puts
141
+ @output_io.puts mes
142
+ exit
143
+ end
144
+
145
+ def parse args=ARGV
146
+ @found = []
147
+ i=0
148
+ # handle svn like command
149
+ if definition = @definition.retrieve_flag(:command)
150
+
151
+ if definition[REQUIRED] && args.length==0
152
+ usage "missing mandatory command"
153
+ elsif test_def = @definition.retrieve_flag(args[i])
154
+ usage "missing mandatory command" if definition[REQUIRED]
155
+ else
156
+
157
+ check definition, args[i]
158
+ set definition[ACCESSOR], args[i]
159
+
160
+ i+=1
161
+ end
162
+
163
+ end
164
+
165
+ while i<args.length do
166
+ @found.push args[i]
167
+ if definition = @definition.retrieve_flag(args[i]) # is there a definition for this flag?
168
+ if definition[DISP_NAME]
169
+ # takes a parameter
170
+ check definition, args[i+=1]
171
+ set definition[ACCESSOR], args[i]
172
+ else
173
+ # plain flag
174
+ set definition[ACCESSOR], true
175
+ end
176
+ else # are unknown flags ok? i.e. is there an :args definition.
177
+ if definition = @definition.retrieve_flag(:args)
178
+ check_args definition, args[i, args.length-1]
179
+ set definition[ACCESSOR], args[i, args.length-1]
180
+ break
181
+ end
182
+ usage "unknown flag: #{args[i]}"
183
+ end
184
+ i+=1
185
+ end
186
+
187
+ if definition = @definition.retrieve_flag(:args) # are :args required?
188
+ if definition[REQUIRED]
189
+ args = self.send definition[ACCESSOR]
190
+ usage "missing mandatory args" unless args && args.length>1
191
+ end
192
+ end
193
+
194
+ usage if self.help # call usage if the -h/--help flag was set.
195
+
196
+ # check all mandatory args are present.
197
+ @definition.each {|definition|
198
+
199
+ if definition[REQUIRED] && !([:command, :args].include? definition[FLAG_1])
200
+ usage "missing mandatory flag #{definition [FLAG_1]?definition[FLAG_1]:definition[FLAG_2]}" unless ((@found.include? definition[FLAG_1]) || (@found.include? definition[FLAG_2]))
201
+ end
202
+ }
203
+ end
204
+
205
+ private
206
+
207
+ def set sym, value
208
+ self.send((sym.to_s+"=").to_sym, value)
209
+ end
210
+
211
+ #
212
+ # check the argument's value against allowed values,
213
+ # check may be a Regexp, an Array or a Proc taking the value.
214
+ #
215
+ def check definition, val
216
+ check=definition[CHECK]
217
+ return true unless check
218
+ if check.kind_of? Regexp
219
+ if !check.match val
220
+ usage "illegal value: #{val} for: #{definition[FLAG_1]}"
221
+ end
222
+ elsif check.kind_of? Proc
223
+ usage "illegal value: #{val} for: #{definition[FLAG1]}" unless definition[CHECK].call val
224
+ elsif check.kind_of? Array
225
+ usage "illegal value: #{val} for: #{definition[FLAG1]}" unless definition[CHECK].include? val
226
+ end
227
+
228
+ return true
229
+ end
230
+
231
+ def check_args definition, arr
232
+ ret = false
233
+ # might be a proc to check the entire array
234
+ if definition[CHECK].kind_of? Proc
235
+ begin
236
+ return definition[CHECK].call(arr)
237
+ rescue
238
+ end
239
+ end
240
+ # or something else to check each arg against
241
+ unless ret
242
+ arr.each {|val|
243
+ ret= check definition, val
244
+ return false unless ret
245
+ }
246
+ end
247
+ return ret
248
+ end
249
+
250
+ end
251
+
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: cmdline
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.0
7
+ date: 2007-05-10 00:00:00 +02:00
8
+ summary: "cmdline: Yet Another Command Line Tool"
9
+ require_paths:
10
+ - lib
11
+ email:
12
+ homepage:
13
+ rubyforge_project:
14
+ description: Library used to handle command line arguments.
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors: []
30
+
31
+ files:
32
+ - lib/cmdline.rb
33
+ - examples/example.rb
34
+ - examples/long_example.rb
35
+ - examples/plain_args_example.rb
36
+ - examples/regexp_example.rb
37
+ - examples/subcommand_example.rb
38
+ - AUTHORS
39
+ - CHANGELOG
40
+ - COPYING
41
+ - LICENSE
42
+ - Rakefile
43
+ - README
44
+ test_files: []
45
+
46
+ rdoc_options: []
47
+
48
+ extra_rdoc_files: []
49
+
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ requirements:
55
+ - none
56
+ dependencies: []
57
+