command-set 0.8.1 → 0.8.2

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/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