command-set 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
data/doc/argumentDSL CHANGED
@@ -21,16 +21,17 @@ Decorator methods, and the classes they add:
21
21
 
22
22
  The shorthand argument methods are:
23
23
 
24
- +regexp_argument+:: RegexpArgument
25
- +multiword_argument+:: MultiArgument
24
+ +any_argument+:: StringArgument
26
25
  +array_argument+:: ArrayArgument
27
- +string_argument+:: StringArgument
26
+ +choose_argument+:: ArrayArgument
28
27
  +file_argument+:: FileArgument
29
- +any_argument+:: StringArgument
28
+ +multiword_argument+:: MultiArgument
30
29
  +nonvalidating_proc_argument+:: NoValidateProcArgument
31
30
  +number_argument+:: NumberArgument
32
- +choose_argument+:: ArrayArgument
33
31
  +proc_argument+:: ProcArgument
34
32
  +regex_argument+:: RegexpArgument
33
+ +regexp_argument+:: RegexpArgument
34
+ +rest_argument+:: RestOfLineArgument
35
+ +string_argument+:: StringArgument
35
36
 
36
37
  Don't forget about #alternating_argument and #argument itself!
@@ -119,6 +119,7 @@ module Command
119
119
  end
120
120
  end
121
121
 
122
+ #Input has to be a number, in the range passed to create the argument
122
123
  class NumberArgument < Argument
123
124
  register "number", Range
124
125
 
@@ -146,6 +147,7 @@ module Command
146
147
  end
147
148
  end
148
149
 
150
+ #Input must match the regular expression passed to create this Argument
149
151
  class RegexpArgument < Argument
150
152
  register "regexp", Regexp
151
153
  register "regex"
@@ -164,6 +166,7 @@ module Command
164
166
  end
165
167
  end
166
168
 
169
+ #File access. Completes paths, validates file options.
167
170
  class FileArgument < Argument
168
171
  register "file"
169
172
  Defaults = {
@@ -174,6 +177,18 @@ module Command
174
177
  end
175
178
  }
176
179
 
180
+ #You create a FileArgument either with an optional hash of options, or
181
+ #a block that evaluates whether or not a path is acceptable.
182
+ #
183
+ #The default options hash looks like:
184
+ #
185
+ # :prune_patterns => [/^\./], #regexs of paths to eliminate from
186
+ # #completion
187
+ # :dirs => [ENV['PWD']], #essentially the PATH env variable
188
+ # :acceptor => proc do |path| #Is a good path?
189
+ # return (File.exists?(path) and not File.directory?(path))
190
+ # end #The default wants existent non-dirs
191
+ #
177
192
  def initialize(name, options={})
178
193
  super(name)
179
194
  options ||= {}
@@ -264,6 +279,9 @@ module Command
264
279
  end
265
280
  end
266
281
 
282
+ #Using FiddlyArguments is sometimes unavoidable, but it kind of stinks.
283
+ #You assign blocks that validate, complete and parse the input. You're
284
+ #probably better off subclassing Argument.
267
285
  class FiddlyArgument < Argument
268
286
  def initialize(name, &block)
269
287
  super(name)
@@ -288,6 +306,7 @@ module Command
288
306
  end
289
307
  end
290
308
 
309
+ #Created with an array of options to choose from
291
310
  class ArrayArgument < Argument
292
311
  register "array", Array
293
312
  register "choose"
@@ -306,6 +325,7 @@ module Command
306
325
  end
307
326
  end
308
327
 
328
+ #Liberally accepts any string as input
309
329
  class StringArgument < Argument
310
330
  register "string", String
311
331
  register "any"
@@ -324,6 +344,8 @@ module Command
324
344
  end
325
345
  end
326
346
 
347
+ #Consumes the rest of the line as a space separated string.
348
+ #Useful for commands with sentences as their arguments.
327
349
  class RestOfLineArgument < StringArgument
328
350
  register "rest"
329
351
 
@@ -337,6 +359,14 @@ module Command
337
359
  end
338
360
  end
339
361
 
362
+ #Created with a two argument block, a proc_argument validates it's input
363
+ #by passing it to the block. It also uses the block to validate.
364
+ #
365
+ #As a result, the block should return a list of acceptable completions,
366
+ #given a prefix and the current subject.
367
+ #
368
+ #Ideally, use proc_arguments to prototype new argument types before
369
+ #creating whole classes for them.
340
370
  class ProcArgument < Argument
341
371
  register "proc", Proc
342
372
 
@@ -355,6 +385,7 @@ module Command
355
385
  end
356
386
  end
357
387
 
388
+ #Like ProcArgument, but performs to validation on the input.
358
389
  class NoValidateProcArgument < ProcArgument
359
390
  register "nonvalidating_proc"
360
391
 
@@ -413,6 +444,9 @@ module Command
413
444
  end
414
445
 
415
446
 
447
+ #Consumes multiple words as dictated by the block used to create the
448
+ #argument. A little complex, but powerful. For use, see
449
+ #StandardCommands::Set
416
450
  class MultiArgument < Argument
417
451
  register "multiword"
418
452
 
@@ -165,9 +165,9 @@ module Command
165
165
  #creating the command set. You can even call
166
166
  #DSL::CommandSetDefinition#define_commands on the set that's returned
167
167
  #in order to add one-off commands or fold in other command sets.
168
- def require_commands(file, mod, cmd_path=[])
168
+ def require_commands(mod, file, cmd_path=[])
169
169
  set = self.new
170
- set.require_commands(file, mod, cmd_path)
170
+ set.require_commands(mod, file, cmd_path)
171
171
  return set
172
172
  end
173
173
  end
@@ -45,8 +45,8 @@ Action:: utility functions within the command action block
45
45
  #+define_commands+ on a specific Module, pick out a specific
46
46
  #subcommand (by passing a path), and then including specific commands
47
47
  #from it.
48
- def require_commands(file, module_name, path = [], *commands)
49
- require file
48
+ def require_commands(module_name, file = nil, path = [], *commands)
49
+ require file rescue nil
50
50
  module_path = module_name.to_s.split("::")
51
51
  mod = Object
52
52
  module_path.each do |part|
@@ -258,7 +258,7 @@ Action:: utility functions within the command action block
258
258
  #module's documentation. Also useful if you want to document your own
259
259
  #argument class' contributions. Try something like:
260
260
  #
261
- # > ruby -r"lib/command-set/arguments.rb" -e "Command::DSL::Argument::document"
261
+ # > ruby -r"lib/command-set/arguments.rb" -e "puts Command::DSL::Argument::document"
262
262
  def self.document
263
263
  docs = <<-EOD
264
264
  There are two kinds of methods available for #{self.name}.
@@ -289,7 +289,7 @@ Action:: utility functions within the command action block
289
289
 
290
290
  EOD
291
291
 
292
- @@shorthand_map.each_pair do |method, klass|
292
+ @@shorthand_map.to_a.sort.each do |method, klass|
293
293
  docs += "+#{method}+:: #{klass.name.sub("Command::","")}\n"
294
294
  end
295
295
 
@@ -301,7 +301,7 @@ Action:: utility functions within the command action block
301
301
  indent = /^\s+/.match(docs)[0]
302
302
  docs.gsub!(/^#{indent}/, "")
303
303
 
304
- puts docs
304
+ return docs
305
305
  end
306
306
 
307
307
  def self.argument_typemap #:nodoc:
@@ -26,7 +26,237 @@ module Command
26
26
  defined
27
27
  end
28
28
  end
29
+ end
30
+
31
+ module StdCmd
32
+ module Help
33
+ @@set = nil
34
+ def self.define_commands
35
+ return @@set ||= Command::CommandSet.define_commands do
36
+ command("help") do
37
+ optional.multiword_argument(:terms) do |terms,subject|
38
+ prefix = terms.pop
39
+ subject.command_set.completion_list(terms, prefix, subject)
40
+ end
41
+
42
+ subject_methods :interpreter_behavior, :command_set
43
+
44
+ action do
45
+ width = (subject.interpreter_behavior)[:screen_width]
46
+ puts
47
+ if(terms.nil? || terms.empty?)
48
+ subject.command_set.documentation(width).each do |docline|
49
+ puts docline
50
+ end
51
+ else
52
+ command,remains = subject.command_set.find_command(*terms)
53
+ docs = command.documentation(width)
54
+ docs.each do |docline|
55
+ puts docline
56
+ end
57
+ end
58
+ puts
59
+ end
60
+
61
+ doesnt_undo
62
+
63
+ document <<-EOH
64
+ Returns a hopefully helpful description of the command indicated
65
+ EOH
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ #Resume is very rarely used in user-facing command sets, but can be
72
+ #handy to chain in as a synthetic command
73
+ module Resume
74
+ @@set = nil
75
+ def self.define_commands
76
+ return @@set ||= Command::CommandSet.define_commands do
77
+ command Command::StandardCommand::Resume
78
+ end
79
+ end
29
80
 
81
+ end
82
+
83
+ module Quit
84
+ @@set = nil
85
+ def self.define_commands
86
+ return @@set ||= Command::CommandSet.define_commands do
87
+ command Command::StandardCommand::Quit
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ module Undo
94
+ @@set = nil
95
+ def self.define_commands
96
+ return @@set ||= Command::CommandSet.define_commands do
97
+ command("undo") do
98
+ doesnt_undo
99
+ action do
100
+ command=subject.undo_stack.get_undo
101
+ command.undo
102
+ end
103
+
104
+ subject_methods :undo_stack
105
+
106
+ document <<-EOH
107
+ Undoes the most recently used command, if possible.
108
+ EOH
109
+ end
110
+
111
+ command("redo") do
112
+ doesnt_undo
113
+ action do
114
+ command=subject.undo_stack.get_redo
115
+ command.execute
116
+ end
117
+
118
+ document <<-EOH
119
+ Redoes the most recently used command, if possible.
120
+ EOH
121
+ end
122
+ end
123
+ end
124
+
125
+ end
126
+
127
+ module Mode
128
+ @@set = nil
129
+ def self.define_commands
130
+ return @@set ||= Command::CommandSet.define_commands do
131
+ root_command do
132
+ argument(Command::FiddlyArgument.new(:mode) do |argument|
133
+ argument.completion do |t,s|
134
+ []
135
+ end
136
+
137
+ argument.validation do |term,s|
138
+ Command::CommandSet === term
139
+ end
140
+ end)
141
+ subject_methods :interpreter
142
+ doesnt_undo
143
+
144
+ action do
145
+ subject.interpreter.push_mode(mode)
146
+ end
147
+ end
148
+
149
+ command(:exit) do
150
+ subject_methods :interpreter
151
+ doesnt_undo
152
+
153
+ action do
154
+ subject.interpreter.pop_mode
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ module Set
162
+ @@set = nil
163
+ def self.define_commands
164
+ return @@set ||= Command::CommandSet.define_commands do
165
+ command(:set) do
166
+ optional.multiword_argument(:address) do |terms, subject|
167
+ last_word = terms.pop
168
+ hash = value_set(terms, subject)
169
+ if(Hash === hash)
170
+ return hash.keys.grep(%r{^#{last_word}.*})
171
+ else
172
+ return []
173
+ end
174
+ end
175
+
176
+ optional.argument(:value, "VALUE")
177
+
178
+ def value_set(terms, subject)
179
+ knobs = subject.knobs
180
+ return [] if knobs.nil?
181
+
182
+ terms.each do |term|
183
+ unless knobs.respond_to? :[]
184
+ raise Command::CommandError, "can't find settings under #{term}"
185
+ end
186
+ knobs = knobs[term]
187
+ end
188
+
189
+ return knobs
190
+ end
191
+
192
+ define_method :value_set do |terms, subject|
193
+ self.class.value_set(terms, subject)
194
+ end
195
+
196
+ subject_methods :knobs
197
+
198
+ #TODO: This is a big mess in here
199
+ #AFAICT, there should be an address, followed by an optional name
200
+ #followed by an optional value...
201
+
202
+ action do
203
+ if address.nil?
204
+ dont_undo
205
+ puts subject.knobs.keys.sort.join("\n")
206
+ return
207
+ else
208
+ @knob_name = address.pop
209
+ @knobs = value_set(address, subject)
210
+ end
211
+
212
+ if Hash === @knobs[@knob_name]
213
+ dont_undo
214
+ puts @knobs[@knob_name].keys.sort.join("\n")
215
+ return
216
+ elsif @knobs.has_key? @knob_name
217
+ if value.nil?
218
+ dont_undo
219
+ puts "#@knob_name: #{@knobs[@knob_name].inspect}"
220
+ else
221
+ @original_value = @knobs[@knob_name]
222
+ @knobs[@knob_name]=value
223
+ #I'm only keeping this because I trust you meant something
224
+ #@knobs[@knob_name]=convert_value(@original_value, value)
225
+ end
226
+ end
227
+ end
228
+
229
+ undo do
230
+ @knobs[@knob_name] = @original_value
231
+ end
232
+
233
+ document <<-EOH
234
+ Without arugments, lists the available variables.
235
+
236
+ With one argument, prints the value of the variable <name>.
237
+
238
+ Sets <name> to <value>. Most settings should be obvious. But
239
+ some important ones probably won't be.
240
+ EOH
241
+ end
242
+ end
243
+ end
244
+ end
245
+
246
+ #Includes quit, undo/redo and help.
247
+ module Basics
248
+ @@set = nil
249
+ def self.define_commands
250
+ return @@set ||= Command::CommandSet.define_commands do
251
+ include_commands Quit
252
+ include_commands Undo
253
+ include_commands Help
254
+ end
255
+ end
256
+ end
257
+ end
258
+
259
+ module Command
30
260
  #This is a collection of useful commands that are often useful to add to
31
261
  #DSL::CommandSetDefinition#include_commands
32
262
  #
@@ -38,6 +268,14 @@ module Command
38
268
  # include_commands Command::StandardCommands::Help
39
269
  # end
40
270
  #
271
+ #Or you could use Command::DSL::require_commands, like so
272
+ #
273
+ # set = CommandSet::define_commands do
274
+ # require_commands "StdCmd::Quit", "command-set/standard_commands",
275
+ # require_commands "StdCmd::Undo"
276
+ # require_commands "StdCmd::Help"
277
+ # end
278
+ #
41
279
  #Some notes:
42
280
  #
43
281
  #0. Resume is usually handy for use in +chain+ calls, not as something to
@@ -52,192 +290,16 @@ module Command
52
290
  # the current value, +set+ +optionname+ +value+ sets the value of
53
291
  # +optionname+
54
292
  module StandardCommands
55
- help = CommandSet.define_commands do
56
- command("help") do
57
- optional.multiword_argument(:terms) do |terms,subject|
58
- prefix = terms.pop
59
- subject.command_set.completion_list(terms, prefix, subject)
60
- end
61
-
62
- subject_methods :interpreter_behavior, :command_set
63
-
64
- action do
65
- width = (subject.interpreter_behavior)[:screen_width]
66
- puts
67
- if(terms.nil? || terms.empty?)
68
- subject.command_set.documentation(width).each do |docline|
69
- puts docline
70
- end
71
- else
72
- command,remains = subject.command_set.find_command(*terms)
73
- docs = command.documentation(width)
74
- docs.each do |docline|
75
- puts docline
76
- end
77
- end
78
- puts
79
- end
80
-
81
- doesnt_undo
82
-
83
- document <<-EOH
84
- Returns a hopefully helpful description of the command indicated
85
- EOH
86
- end
87
- end
88
- Help = help
89
-
90
- #Resume is very rarely used in user-facing command sets, but can be handy to chain in
91
- #as a synthetic command
92
- resume = CommandSet.define_commands do
93
- command StandardCommand::Resume
94
- end
95
- Resume = resume
96
-
97
- quit = CommandSet.define_commands do
98
- command StandardCommand::Quit
99
- end
100
- Quit = quit
101
-
102
- undo_redo = CommandSet.define_commands do
103
- command("undo") do
104
- doesnt_undo
105
- action do
106
- command=subject.undo_stack.get_undo
107
- command.undo
108
- end
293
+ Help = StdCmd::Help.define_commands()
109
294
 
110
- subject_methods :undo_stack
295
+ Resume = StdCmd::Resume.define_commands()
111
296
 
112
- document <<-EOH
113
- Undoes the most recently used command, if possible.
114
- EOH
115
- end
116
-
117
- command("redo") do
118
- doesnt_undo
119
- action do
120
- command=subject.undo_stack.get_redo
121
- command.execute
122
- end
297
+ Quit = StdCmd::Quit.define_commands()
123
298
 
124
- document <<-EOH
125
- Redoes the most recently used command, if possible.
126
- EOH
127
- end
128
- end
129
- Undo = undo_redo
130
-
131
- mode_exit = CommandSet.define_commands do
132
- root_command do
133
- argument(FiddlyArgument.new(:mode) do |argument|
134
- argument.completion do |t,s|
135
- []
136
- end
137
-
138
- argument.validation do |term,s|
139
- CommandSet === term
140
- end
141
- end)
142
- subject_methods :interpreter
143
- doesnt_undo
144
-
145
- action do
146
- subject.interpreter.push_mode(mode)
147
- end
148
- end
299
+ Undo = StdCmd::Undo.define_commands()
149
300
 
150
- command(:exit) do
151
- subject_methods :interpreter
152
- doesnt_undo
301
+ Mode = StdCmd::Mode.define_commands()
153
302
 
154
- action do
155
- subject.interpreter.pop_mode
156
- end
157
- end
158
- end
159
- Mode = mode_exit
160
-
161
-
162
- set = CommandSet.define_commands do
163
- command(:set) do
164
- optional.multiword_argument(:address) do |terms, subject|
165
- last_word = terms.pop
166
- hash = value_set(terms, subject)
167
- if(Hash === hash)
168
- return hash.keys.grep(%r{^#{last_word}.*})
169
- else
170
- return []
171
- end
172
- end
173
-
174
- optional.argument(:value, "VALUE")
175
-
176
- def value_set(terms, subject)
177
- knobs = subject.knobs
178
- return [] if knobs.nil?
179
-
180
- terms.each do |term|
181
- unless knobs.respond_to? :[]
182
- raise CommandError, "can't find settings under #{term}"
183
- end
184
- knobs = knobs[term]
185
- end
186
-
187
- return knobs
188
- end
189
-
190
- define_method :value_set do |terms, subject|
191
- self.class.value_set(terms, subject)
192
- end
193
-
194
- subject_methods :knobs
195
-
196
- #TODO: This is a big mess in here
197
- #AFAICT, there should be an address, followed by an optional name
198
- #followed by an optional value...
199
-
200
- action do
201
- if address.nil?
202
- dont_undo
203
- puts subject.knobs.keys.sort.join("\n")
204
- return
205
- else
206
- @knob_name = address.pop
207
- @knobs = value_set(address, subject)
208
- end
209
-
210
- if Hash === @knobs[@knob_name]
211
- dont_undo
212
- puts @knobs[@knob_name].keys.sort.join("\n")
213
- return
214
- elsif @knobs.has_key? @knob_name
215
- if value.nil?
216
- dont_undo
217
- puts "#@knob_name: #{@knobs[@knob_name].inspect}"
218
- else
219
- @original_value = @knobs[@knob_name]
220
- @knobs[@knob_name]=value
221
- #I'm only keeping this because I trust you meant something
222
- #@knobs[@knob_name]=convert_value(@original_value, value)
223
- end
224
- end
225
- end
226
-
227
- undo do
228
- @knobs[@knob_name] = @original_value
229
- end
230
-
231
- document <<-EOH
232
- Without arugments, lists the available variables.
233
-
234
- With one argument, prints the value of the variable <name>.
235
-
236
- Sets <name> to <value>. Most settings should be obvious. But
237
- some important ones probably won't be.
238
- EOH
239
- end
240
- end
241
- Set = set
303
+ Set = StdCmd::Set.define_commands()
242
304
  end
243
305
  end
metadata CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: command-set
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.8.1
6
+ version: 0.8.2
7
7
  date: 2007-12-13 00:00:00 -08:00
8
8
  summary: Framework for interactive programs focused around a DSL for commands
9
9
  require_paths:
@@ -47,7 +47,6 @@ files:
47
47
  - doc/README
48
48
  - doc/Specifications
49
49
  - doc/argumentDSL
50
- - GUIDED_TOUR
51
50
  test_files: []
52
51
 
53
52
  rdoc_options:
@@ -56,9 +55,9 @@ rdoc_options:
56
55
  - --main
57
56
  - Command
58
57
  - --title
59
- - command-set-0.8.1 RDoc
58
+ - command-set-0.8.2 RDoc
60
59
  extra_rdoc_files:
61
- - GUIDED_TOUR
60
+ - doc/argumentDSL
62
61
  executables: []
63
62
 
64
63
  extensions: []
data/GUIDED_TOUR DELETED
@@ -1,24 +0,0 @@
1
- The quickest way to get a handle on what CommandSet can do for you is to
2
- look at the various pieces and get a handle on how they work together.
3
-
4
- The rough sketch is that you enumerate a series of commands, which you then
5
- feed to an interpreter. The interpreter will set you up with a template for
6
- your porgram's subject, which you fill in with some defaults. Then, give
7
- the filled in subject back to the interpreter and let it run.
8
-
9
- Here's the appropriate places to get started:
10
-
11
- 0. DSL (Read thoroughly - especially the sub modules)
12
- 0. BaseInterpreter#subject_template
13
- 0. BaseInterpreter#subject=
14
- 0. TextInterpreter#go
15
-
16
- A couple of handy tricks can be found at
17
-
18
- 0. BaseInterpreter#process_input
19
- 0. StandardCommands
20
- 0. QuickInterpreter
21
-
22
- More advanced stuff that worth learning once your app is off the ground:
23
-
24
- 0. Results