command-set 0.8.0 → 0.8.1

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/GUIDED_TOUR ADDED
@@ -0,0 +1,24 @@
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
data/doc/Specifications CHANGED
@@ -214,6 +214,6 @@ Command::Results::Presenter driving a Formatter
214
214
  Command::Results::Presenter driving a strict Formatter
215
215
  - should send notifications in correct order
216
216
 
217
- Finished in 0.174402 seconds
217
+ Finished in 0.24242 seconds
218
218
 
219
219
  137 examples, 0 failures
@@ -176,12 +176,13 @@ module Command
176
176
 
177
177
  def initialize(name, options={})
178
178
  super(name)
179
+ options ||= {}
179
180
  if Hash === options
180
181
  @options = Defaults.merge(options)
181
182
  @acceptor = @options[:acceptor]
182
183
  elsif Proc === options
183
184
  @options = Defaults.dup
184
- @acceptor = options
185
+ @acceptor = proc &options
185
186
  else
186
187
  raise "File argument needs hash or proc!"
187
188
  end
@@ -323,6 +324,19 @@ module Command
323
324
  end
324
325
  end
325
326
 
327
+ class RestOfLineArgument < StringArgument
328
+ register "rest"
329
+
330
+ def consume(subject, arguments)
331
+ term = arguments.join(" ")
332
+ arguments.clear
333
+ unless validate(term, subject)
334
+ raise ArgumentInvalidException, {@name => term}
335
+ end
336
+ return {@name => parse(subject, term)}
337
+ end
338
+ end
339
+
326
340
  class ProcArgument < Argument
327
341
  register "proc", Proc
328
342
 
@@ -42,7 +42,7 @@ Command::wrap_stdout
42
42
 
43
43
  #:startdoc:
44
44
 
45
- #Command::CommandSet is a tight little library that let's you clearly and
45
+ #Command::CommandSet is a tight little library that lets you clearly and
46
46
  #easily describe a set of commands for an interactive application. The
47
47
  #command set can then be handed to one of a number of interpreters that will
48
48
  #facilitate interaction with the user.
@@ -153,6 +153,23 @@ module Command
153
153
  set.define_commands(&block)
154
154
  return set
155
155
  end
156
+
157
+ #In driver code, it's often quickest to yank in commands from a file.
158
+ #To do that, create a code file with a module in it. The module needs
159
+ #a method of the form
160
+ #
161
+ # def self.define_commands()
162
+ #
163
+ #define_commands should return a CommandSet. Then, pass the require
164
+ #path and module name to require_commands, and it'll take care of
165
+ #creating the command set. You can even call
166
+ #DSL::CommandSetDefinition#define_commands on the set that's returned
167
+ #in order to add one-off commands or fold in other command sets.
168
+ def require_commands(file, mod, cmd_path=[])
169
+ set = self.new
170
+ set.require_commands(file, mod, cmd_path)
171
+ return set
172
+ end
156
173
  end
157
174
 
158
175
  include DSL::CommandSetDefinition
@@ -37,7 +37,31 @@ Action:: utility functions within the command action block
37
37
  @command_list[name] = command.dup
38
38
  @command_list[name].parent=self
39
39
  end
40
- #paths_update(command, name)
40
+ end
41
+ end
42
+
43
+ #If you've got a file dedicated to a set of commands, (and you really
44
+ #should) you can use require_commands to require it, call
45
+ #+define_commands+ on a specific Module, pick out a specific
46
+ #subcommand (by passing a path), and then including specific commands
47
+ #from it.
48
+ def require_commands(file, module_name, path = [], *commands)
49
+ require file
50
+ module_path = module_name.to_s.split("::")
51
+ mod = Object
52
+ module_path.each do |part|
53
+ mod = mod.const_get(part)
54
+ end
55
+
56
+ set = mod.define_commands
57
+ set = set.find_command(*path)
58
+
59
+ if CommandSet === set
60
+ include_commands(set, *commands)
61
+ elsif Class === set and Command > set
62
+ command(set)
63
+ else
64
+ raise RuntimeError,"#{set.inspect} isn't a CommandSet or a Command"
41
65
  end
42
66
  end
43
67
 
@@ -353,6 +377,40 @@ Action:: utility functions within the command action block
353
377
  end
354
378
  end
355
379
 
380
+ #The DSL for formatting. A lot of code will do just fine with the
381
+ #Kernel#puts #that Results intercepts. More involved output control
382
+ #starts by including CommandSet::DSL::Formatting, and using
383
+ #Formatting#list and Formatting#item to structure output for the
384
+ #formatters.
385
+ module Formatting
386
+ #To create lists and sublist of data, you can use #list to wrap code
387
+ #in a #begin_list / #end_list pair.
388
+ def list(name, options={}) #:yield:
389
+ begin_list(name, options)
390
+ yield if block_given?
391
+ end_list
392
+ end
393
+
394
+ #Tells the main collector to begin a list. Subsequent output will be
395
+ #gathered into that list. For more, check out Results::Collector
396
+ def begin_list(name, options={})
397
+ @main_collector.begin_list(name, options)
398
+ end
399
+
400
+ #Tells the main collector to end the current list. For more, check out
401
+ #Results::Collector
402
+ def end_list
403
+ @main_collector.end_list
404
+ end
405
+
406
+ #Clean way to create an item of output. Allows for various options to
407
+ #be added. The normal output method (#puts, #p, #write...) are all
408
+ #diverted within a command, and effectively create no-option items.
409
+ def item(name, options={})
410
+ @main_collector.item(name, options)
411
+ end
412
+ end
413
+
356
414
  #The methods available within the DSL::CommandDefinition#action method
357
415
  #
358
416
  #The trickiest thing to realize about writing Commands is that a
@@ -365,6 +423,7 @@ Action:: utility functions within the command action block
365
423
  #which will be local to the invocation of the command. This is
366
424
  #especially useful for undo and redo.
367
425
  module Action
426
+ include Formatting
368
427
 
369
428
  #:section: Basics
370
429
 
@@ -383,35 +442,6 @@ Action:: utility functions within the command action block
383
442
  @subject
384
443
  end
385
444
 
386
- #:section: Formatting
387
-
388
- #To create lists and sublist of data, you can use #list to wrap code
389
- #in a #begin_list / #end_list pair.
390
- def list(name, options={}) #:yield:
391
- begin_list(name, options)
392
- yield if block_given?
393
- end_list
394
- end
395
-
396
- #Tells the main collector to begin a list. Subsequent output will be
397
- #gathered into that list. For more, check out Results::Collector
398
- def begin_list(name, options={})
399
- @main_collector.begin_list(name, options)
400
- end
401
-
402
- #Tells the main collector to end the current list. For more, check out
403
- #Results::Collector
404
- def end_list
405
- @main_collector.end_list
406
- end
407
-
408
- #Clean way to create an item of output. Allows for various options to
409
- #be added. The normal output method (#puts, #p, #write...) are all
410
- #diverted within a command, and effectively create no-option items.
411
- def item(name, options={})
412
- @main_collector.item(name, options)
413
- end
414
-
415
445
  #:section: Pause and Resume
416
446
 
417
447
  #Stop here. Return control to the user. If several commands are
@@ -8,16 +8,49 @@ require 'command-set/interpreter'
8
8
  #platforms, I'm thinking. A more flexible way of doing this would rock,
9
9
  #regardless of length.
10
10
  module Readline
11
- extend DL::Importable
12
- dlload "/lib/libreadline.so"
13
- RLLB = symbol("rl_line_buffer")
14
- def self.line_buffer
15
- p = RLLB.ptr
16
- if p.nil?
17
- return p
18
- else
19
- return p.to_s
11
+ begin
12
+ extend DL::Importable
13
+ found_libreadline = false
14
+ ls_so_dirs = [
15
+ %w{lib},
16
+ %w{usr lib},
17
+ %w{usr local lib}
18
+ ].each{|path| path.unshift("")}
19
+
20
+ begin
21
+ File::open("/etc/ld.so.conf", "r") do |ld_so_conf|
22
+ ld_so_conf.each do |line|
23
+ unless /^#/ =~ line or /^%s*$/ =~ line
24
+ ls_so_dirs << line.chomp.split(File::Separator)
25
+ end
26
+ end
27
+ end
28
+ rescue Exception
20
29
  end
30
+
31
+ ls_so_dirs.each do |libreadline_location|
32
+ begin
33
+ dlload File::join(*(libreadline_location + ["libreadline.so"]))
34
+ RLLB = symbol("rl_line_buffer")
35
+ found_libreadline = true
36
+ break
37
+ rescue RuntimeError
38
+ end
39
+ end
40
+
41
+ raise RuntimeError,"couldn't find libreadline.so" unless found_libreadline
42
+
43
+ def self.line_buffer
44
+ p = RLLB.ptr
45
+ if p.nil?
46
+ return p
47
+ else
48
+ return p.to_s
49
+ end
50
+ end
51
+ rescue RuntimeError => rte
52
+ warn "Couldn't find libreadline - tab-completion will be unpredictable at best."
53
+ warn "The problem was: " + rte.message
21
54
  end
22
55
  end
23
56
 
@@ -147,7 +180,7 @@ module Command
147
180
  end
148
181
 
149
182
  def get_formatter
150
- return Results::TextFormatter.new(::Command::raw_stdout)
183
+ return Results::StrategyFormatter.new(::Command::raw_stdout)
151
184
  end
152
185
 
153
186
  def get_prompt
metadata CHANGED
@@ -3,8 +3,8 @@ 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.0
7
- date: 2007-11-27 00:00:00 -08:00
6
+ version: 0.8.1
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:
10
10
  - lib
@@ -47,6 +47,7 @@ files:
47
47
  - doc/README
48
48
  - doc/Specifications
49
49
  - doc/argumentDSL
50
+ - GUIDED_TOUR
50
51
  test_files: []
51
52
 
52
53
  rdoc_options:
@@ -55,11 +56,9 @@ rdoc_options:
55
56
  - --main
56
57
  - Command
57
58
  - --title
58
- - command-set-0.8.0 RDoc
59
+ - command-set-0.8.1 RDoc
59
60
  extra_rdoc_files:
60
- - doc/README
61
- - doc/Specifications
62
- - doc/argumentDSL
61
+ - GUIDED_TOUR
63
62
  executables: []
64
63
 
65
64
  extensions: []