command-set 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/GUIDED_TOUR +24 -0
- data/doc/Specifications +1 -1
- data/lib/command-set/arguments.rb +15 -1
- data/lib/command-set/command-set.rb +18 -1
- data/lib/command-set/dsl.rb +60 -30
- data/lib/command-set/text-interpreter.rb +43 -10
- metadata +5 -6
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.
|
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
|
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
|
data/lib/command-set/dsl.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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::
|
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.
|
7
|
-
date: 2007-
|
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.
|
59
|
+
- command-set-0.8.1 RDoc
|
59
60
|
extra_rdoc_files:
|
60
|
-
-
|
61
|
-
- doc/Specifications
|
62
|
-
- doc/argumentDSL
|
61
|
+
- GUIDED_TOUR
|
63
62
|
executables: []
|
64
63
|
|
65
64
|
extensions: []
|