Skip to content

Commit 57efe01

Browse files
committed
Updated readme
1 parent 2888648 commit 57efe01

8 files changed

+187
-153
lines changed

README.md

+36-37
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,26 @@ After installing the **Commandable** gem require it somewhere that gets loaded b
4848

4949
Extend your class with the **Commandable** module:
5050

51-
class Widget
51+
require 'commandable'
52+
53+
class Foo
5254
extend Commandable
55+
56+
end
5357

5458
Then put `command` and a description above the method you want to make accessible. The description is optional but can be helpful
5559
since it's used when automatically building your help/usage instructions.
5660

57-
command "create a new widget"
58-
def new(name)
59-
...
61+
require 'commandable'
62+
63+
class Foo
64+
extend Commandable
65+
66+
command "Explain what the command does"
67+
def bar
68+
puts "Foo::bar"
6069
end
70+
end
6171

6272
### The "`command`" command and its options
6373

@@ -201,8 +211,7 @@ A typical help output looks something like this:
201211
readme : displays the readme file (default)
202212
v : <xor> Application Version
203213
version : <xor> Application Version
204-
help : you're looking at it now
205-
214+
help : you're looking at it now
206215

207216

208217
### Complete demonstration app and some example classes ###
@@ -237,6 +246,16 @@ If set to true help instructions will include the default values in the paramete
237246
# Will print:
238247
command arg1 [arg2]
239248

249+
###Screen Clearing Options
250+
251+
**Commandable.clear\_screen**
252+
_default = false_
253+
Set to true to enable clearing the screen when printing help/usage instructions.
254+
255+
**Commandable.color\clear\_screen\_code**
256+
_default = "\e[H\e[2J"
257+
The escape codes used to clear the screen.
258+
240259
### Colorized Output Options
241260

242261
The help information can be colored using the standard ANSI escape commands found in the `term-ansicolor` gem. The `term-ansicolor` gem is installed as a dependency but just in case you have problems you can install it yourself by running:
@@ -263,8 +282,8 @@ Then you can do something like this:
263282
###Color options
264283

265284
**Commandable.color\_output**
266-
_default = true_
267-
Set to false to disable colorized help/usage instructions. You might find the colors really, really annoying...
285+
_default = false_
286+
Set to true to enable colorized help/usage instructions.
268287

269288
**Commandable.color\_app\_info**
270289
_default = intense\_white_ + bold
@@ -302,13 +321,8 @@ The color the friendly name of the error will be in error messages
302321
\_default = intense\_black_ + bold
303322
The color the error description will be in error messages
304323

305-
**Commandable.color\screen\_clear_code**
306-
_default = "\e[H\e[2J"
307-
The color the error description will be in error messages
308-
309324
The best way to see what all this means it just type `commandable help` and you'll see the help instructions in color.
310325

311-
312326
### Executing the Command Line
313327

314328
There are two ways of using **Commandable** to run your methods. You can use its built in execute method to automatically run whatever is entered on the command line or you can have **Commandable** build an array of procs that you can execute yourself. This allows you to have finer grain control over the execution of the commands as you can deal with the return values as you run each command.
@@ -380,7 +394,6 @@ You just need to configure your bin file with the app settings and then run `Com
380394

381395
# Make sure you require your app after Commandable, or use
382396
# a configuration file to load the settings then your app
383-
# See the Widget app for an example of this.
384397
require 'yourappname'
385398
Commandable.execute(ARGV)
386399

@@ -390,9 +403,7 @@ You just need to configure your bin file with the app settings and then run `Com
390403
# Commandable.execute(ARGV, :silent)
391404

392405

393-
I actually prefer to create a separate file for my **Commandable** configuration and load it in my main app file in the `lib` directory. Again, take a look at `Widget` to see what I mean.
394-
395-
You can get a copy of widget by running `commandable widget [path]` and it will copy the example app to the directory you specify.
406+
I actually prefer to create a separate file for my **Commandable** configuration and load it in my main app file in the `lib` directory.
396407

397408
## In closing... ##
398409

@@ -409,20 +420,17 @@ Most of all it should be simple to use so if you have any problems please drop m
409420

410421
2012-01-20 - Version: 0.3.0
411422

423+
* All features are off by default to make Commandable more friendly across platforms.
412424
* Added ability to disable screen clearing and to set your own screen clear escape code. (Based on [John Sumsion](https://github.com/jdsumsion)'s idea)
413425
* Decoupled screen clearing from coloring; you can have either or both.
414426
* Fixed bug that disabled help output in silent mode. (fixed by [John Sumsion](https://github.com/jdsumsion))
415427
* Fixed bug that didn't label the default method if screen colors were off.
416428
* Removed monkey patch from FileUtils. It was more philosophical than necessary.
417429
* Changed terminal coloring gem back to official the term-ansicolor from my own fork now that my changes have been pulled into it.
418430
* Code clean up. While mostly not a real refactor I've separated out the code into functional groups (aka files).
419-
* Removed Widget example - it was making the examples too tightly coupled to HashModel.
431+
* Removed Widget gem example - it was making the examples too tightly coupled to HashModel.
420432
* Removed Cucumber features.
421433

422-
To do
423-
424-
* Added some more examples.
425-
* Updated docs to reflect changes.
426434

427435
2011-09-27 - Version: 0.2.3
428436

@@ -444,28 +452,19 @@ To do
444452

445453
* First public release. It's 0.2.0 because 0.1.0, going by the name of Cloptions, wasn't released.
446454

447-
## To Do
448-
449-
Add ability to easily use nested argument trees without hard-coding case blocks. For instance a command that takes set of commands like `foo remote set "ftp_svr" 10.250.1.100` or `foo remote delete "ftp_svr"`.
450-
451-
### Next major version:
455+
### Possible future upgrades/improvements
452456

457+
* See if there's a elegant way to add nested argument trees without case blocks. e.g. a command that takes set of commands like `foo remote set "ftp_svr" 10.250.1.100` and `foo remote delete "ftp_svr"`.
453458
* Add a way to use or discover version numbers. Might have to force standardization and not allow configuration since it should be DRY.
454-
* Needs a massive refactoring.
455459
* Add a generator to automatically add Commandable support to your app.
456-
* Reorganize docs to be more logical and less the result of my scribblings as I develop.
457-
* Try to figure out how to trap `alias` so I don't you don't have to use an additional `command`.
458-
* Better formatting of help/usage instructions, the existing one is fairly ugly.
459-
* Use comments below `command` as the description text so you don't have to repeat yourself to get RDoc to give you docs for your functions.
460+
* Try to figure out how to trap `alias` so you don't have to use an additional `command`.
461+
* Use comments below `command` as the description text so you don't have to repeat yourself when documenting your code.
460462
* Clean up RSpecs. I'm doing too many ugly tests instead of specifying behavior.
461-
* Allow sorting of commands alphabetically or by priority
462-
463-
###Future versions:
464-
465-
* Accepting your suggestions...
463+
* Allow sorting of commands alphabetically or by priority in the help output
466464
* Make the help/usage directions format available to programmers without having to hack the code.
467465
* More edge case testing.
468466
* Allow optional parameters values to be reloaded so changing things like verbose_parameters makes the command list change. (**very** low priority)
467+
* Accepting your suggestions...
469468

470469

471470
.

bin/commandable

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
33
require 'commandable'
44
Commandable.color_output = true
5+
Commandable.clear_screen = true
56
Commandable.verbose_parameters = false
67
Commandable.app_exe = "commandable"
78
Commandable.app_info =

commandable.gemspec

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ EOF
2222
s.add_dependency("term-ansicolor", "~>1.0.7")
2323

2424
s.add_development_dependency("rspec", "~>2.5")
25-
#buns.add_development_dependency("aruba", "~>0.3")
2625

2726
s.files = `git ls-files`.split("\n")
2827
s.test_files = `git ls-files -- {spec,autotest}/*`.split("\n")

lib/commandable.rb

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# This library allows you to incredibly easily make
22
# your methods directly available from the command line.
33
#
4-
# Author:: Mike Bethany (mailto:mikbe.tk@gmail.com)
5-
# Copyright:: Copyright (c) 2012 Mike Bethany
6-
# License:: Distributed under the MIT licence (See LICENCE file)
7-
4+
# Author:: Mike Bethany (mailto:mikbe.tk@gmail.com)
5+
# Copyright:: Copyright (c) 2012 Mike Bethany
6+
# License:: Distributed under the MIT licence (See LICENCE file)
7+
# website:: http://mikbe.kt
88

99
require 'commandable/version'
1010
require 'commandable/exceptions'
@@ -13,4 +13,5 @@
1313
require 'commandable/coloring'
1414
require 'commandable/help_text'
1515
require 'commandable/command_parser'
16+
require 'commandable/execution_controller'
1617
require 'commandable/controller'

lib/commandable/command_parser.rb

-111
Original file line numberDiff line numberDiff line change
@@ -36,117 +36,6 @@ def each(&block)
3636
yield key => value
3737
end
3838
end
39-
40-
# A wrapper for the execution_queue that runs the queue and traps errors.
41-
# If an error occurs inside this method it will print out a complete list
42-
# of availavle methods with usage instructions and exit gracefully.
43-
#
44-
# If you do not want the output from your methods to be printed out automatically
45-
# run the execute command with silent set to anything other than false or nil.
46-
def execute(argv, silent=false)
47-
begin
48-
command_queue = execution_queue(argv)
49-
command_queue.each do |com|
50-
return_value = com[:proc].call
51-
puts return_value if !silent || com[:method] == :help
52-
end
53-
rescue SystemExit => kernel_exit
54-
Kernel.exit kernel_exit.status
55-
rescue Exception => exception
56-
if exception.respond_to?(:friendly_name)
57-
set_colors
58-
puts help("\n #{@c_error_word}Error:#{@c_reset} #{@c_error_name}#{exception.friendly_name}#{@c_reset}\n #{@c_error_description}#{exception.message}#{@c_reset}\n\n")
59-
else
60-
puts exception.inspect
61-
puts exception.backtrace.collect{|line| " #{line}"}
62-
end
63-
end
64-
end
65-
66-
# Returns an array of executable procs based on the given array of commands and parameters
67-
# Normally this would come from the command line parameters in the ARGV array.
68-
def execution_queue(argv)
69-
arguments = argv.dup
70-
method_hash = {}
71-
last_method = nil
72-
73-
if arguments.empty?
74-
arguments << @@default_method.keys[0] if @@default_method and !@@default_method.values[0][:parameters].flatten.include?(:req)
75-
end
76-
arguments << "help" if arguments.empty?
77-
78-
# Parse the command line into methods and their parameters
79-
80-
arguments.each do |arg|
81-
if Commandable[arg]
82-
last_method = arg.to_sym
83-
method_hash.merge!(last_method=>[])
84-
else
85-
unless last_method
86-
default = find_by_subkey(:default)
87-
88-
# Raise an error if there is no default method and the first item isn't a method
89-
raise UnknownCommandError, arguments.first if default.empty?
90-
91-
# Raise an error if there is a default method but it doesn't take any parameters
92-
raise UnknownCommandError, (arguments.first) if default.values[0][:argument_list] == ""
93-
94-
last_method = default.keys.first
95-
method_hash.merge!(last_method=>[])
96-
end
97-
method_hash[last_method] << arg
98-
end
99-
# Test for missing required switches
100-
@@commands.select do |key, value|
101-
if value[:required] and method_hash[key].nil?
102-
# If the required switch is also a default have the error be a missing parameter instead of a missing command
103-
if value[:default]
104-
method_hash.merge!(key=>[])
105-
else
106-
raise MissingRequiredCommandError, key
107-
end
108-
end
109-
end
110-
end
111-
#puts "method_hash: #{method_hash}" if method_hash.to_s.include?("required_default")
112-
113-
# Build an array of procs to be called for each method and its given parameters
114-
proc_array = []
115-
method_hash.each do |meth, params|
116-
command = @@commands[meth]
117-
118-
if command[:parameters] && !command[:parameters].empty?
119-
120-
#Change the method name for attr_writers
121-
meth = "#{meth}=" if command[:parameters][0][0] == :writer
122-
123-
# Get a list of required parameters and make sure all of them were provided
124-
required = command[:parameters].select{|param| [:req, :writer].include?(param[0])}
125-
required.shift(params.count)
126-
raise MissingRequiredParameterError, {:method=>meth, :parameters=>required.collect!{|meth| meth[1]}.to_s[1...-1].gsub(":",""), :default=>command[:default]} unless required.empty?
127-
end
128-
129-
# Test for duplicate XORs
130-
proc_array.select{|x| x[:xor] and x[:xor]==command[:xor] }.each {|bad| raise ExclusiveMethodClashError, "#{meth}, #{bad[:method]}"}
131-
132-
klass = Object
133-
command[:class].split(/::/).each { |name| klass = klass.const_get(name) }
134-
## Look for class in class cache
135-
unless command[:class_method]
136-
klass = (@@class_cache[klass.name] ||= klass.new)
137-
end
138-
proc_array << {:method=>meth, :xor=>command[:xor], :parameters=>params, :priority=>command[:priority], :proc=>lambda{klass.send(meth, *params)}}
139-
end
140-
proc_array.sort{|a,b| a[:priority] <=> b[:priority]}.reverse
141-
142-
end
143-
144-
private
145-
146-
# Look through commands for a specific subkey
147-
def find_by_subkey(key, value=true)
148-
@@commands.select {|meth, meth_value| meth_value[key]==value}
149-
end
15039

15140
end
15241

0 commit comments

Comments
 (0)