remi-simplecli 0.1.4

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.
Files changed (4) hide show
  1. data/README +118 -0
  2. data/examples/hello-cli +44 -0
  3. data/lib/simplecli.rb +180 -0
  4. metadata +56 -0
data/README ADDED
@@ -0,0 +1,118 @@
1
+ == SimpleCLI
2
+
3
+ Super Simple RubyGems-like CLI
4
+
5
+ SimpleCLI gives you a stupidly simple way to implement command-line
6
+ interfaces like that of RubyGems with a basic interface like:
7
+
8
+ gem command [options]
9
+
10
+ SimpleCLI gives you a way of defining your commands (or actions) so
11
+ they'll automatically show up when you run <tt>`yourapp commands`</tt>
12
+
13
+ SimpleCLI also makes it really easy to add documentation to each of
14
+ your commands (or actions)
15
+
16
+ === Example
17
+
18
+ Here's a super simple SimpleCLI example:
19
+
20
+ #! /usr/bin/env ruby
21
+
22
+ require File.dirname(__FILE__) + '/../lib/simplecli'
23
+
24
+ class Hello
25
+ include SimpleCLI
26
+
27
+ def usage
28
+ puts <<doco
29
+
30
+ Hello CLI
31
+
32
+ Usage:
33
+ #{ script_name } command [options]
34
+
35
+ Futher help:
36
+ #{ script_name } commands # list all available commands
37
+ #{ script_name } help <COMMAND> # show help for COMMAND
38
+ #{ script_name } help # show this help message
39
+
40
+ doco
41
+ end
42
+
43
+ def sayhello_help
44
+ <<doco
45
+ Usage: #{ script_name } sayhello [SAY]
46
+
47
+ Arguments:
48
+ SAY: Something to say (default 'Hello World!')
49
+
50
+ Summary:
51
+ Says hello!
52
+ doco
53
+ end
54
+ def sayhello *args
55
+ puts args.empty? ? "Hello World!" : args.join(' ')
56
+ end
57
+
58
+ end
59
+
60
+ # POSTAMBLE
61
+ if __FILE__ == $0
62
+ Hello.new( ARGV, :default => 'sayhello' ).run
63
+ end
64
+
65
+ Example usage:
66
+
67
+ <b><tt>$ ./hello-cli</b></tt>
68
+
69
+ Hello CLI
70
+
71
+ Usage:
72
+ hello-cli command [options]
73
+
74
+ Futher help:
75
+ hello-cli commands # list all available commands
76
+ hello-cli help <COMMAND> # show help for COMMAND
77
+ hello-cli help # show this help message
78
+
79
+ <b><tt>$ ./hello-cli commands</b></tt>
80
+
81
+ hello-cli commands are:
82
+
83
+ DEFAULT COMMAND sayhello
84
+
85
+ commands List all 'hello-cli' commands
86
+ help Provide help documentation for a command
87
+ sayhello Says hello!
88
+
89
+ For help on a particular command, use 'hello-cli help COMMAND'.
90
+
91
+ <b><tt>$ ./hello-cli help</b></tt>
92
+
93
+ Usage: hello-cli help COMMAND
94
+
95
+ Summary:
96
+ Provide help documentation for a command
97
+
98
+ <b><tt>$ ./hello-cli help sayhello</b></tt>
99
+
100
+ Usage: hello-cli sayhello [SAY]
101
+
102
+ Arguments:
103
+ SAY: Something to say (default 'Hello World!')
104
+
105
+ Summary:
106
+ Says hello!
107
+
108
+ <b><tt>$ ./hello-cli sayhello</b></tt>
109
+
110
+ Hello World!
111
+
112
+ <b><tt>$ ./hello-cli sayhello Hi There</b></tt>
113
+
114
+ Hi There
115
+
116
+ <b><tt>$ ./hello-cli Hi There</b></tt> <tt># this works because sayhello is configured as the default command</tt>
117
+
118
+ Hi There
@@ -0,0 +1,44 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/simplecli'
4
+
5
+ class Hello
6
+ include SimpleCLI
7
+
8
+ def usage
9
+ puts <<doco
10
+
11
+ Hello CLI
12
+
13
+ Usage:
14
+ #{ script_name } command [options]
15
+
16
+ Futher help:
17
+ #{ script_name } commands # list all available commands
18
+ #{ script_name } help <COMMAND> # show help for COMMAND
19
+ #{ script_name } help # show this help message
20
+
21
+ doco
22
+ end
23
+
24
+ def sayhello_help
25
+ <<doco
26
+ Usage: #{ script_name } sayhello [SAY]
27
+
28
+ Arguments:
29
+ SAY: Something to say (default 'Hello World!')
30
+
31
+ Summary:
32
+ Says hello!
33
+ doco
34
+ end
35
+ def sayhello *args
36
+ puts args.empty? ? "Hello World!" : args.join(' ')
37
+ end
38
+
39
+ end
40
+
41
+ # POSTAMBLE
42
+ if __FILE__ == $0
43
+ Hello.new( ARGV, :default => 'sayhello' ).run
44
+ end
data/lib/simplecli.rb ADDED
@@ -0,0 +1,180 @@
1
+ #
2
+ # Stupidly simple way to get a CLI that handles:
3
+ # myapp somecommand --blah=5 args --more stuff -y
4
+ #
5
+ # All it does is, if the "command" (or "action") passed
6
+ # has a method with the same name, the rest of the args
7
+ # are passed to the method.
8
+ #
9
+ # If you provide a command_help method that returns help
10
+ # info as a String, that'll be used when you call:
11
+ # myapp help somecommand
12
+ #
13
+ # If you provide a 'Summary:\n blah blah blah' bit in
14
+ # your help_somecommand, it'll be used as the command's
15
+ # summary and your command will show up when you:
16
+ # myapp commands
17
+ #
18
+ # To use, include in your class
19
+ #
20
+ # NOTE: if you use the 'default' command functionality,
21
+ # we don'e even bother to check to see if we respond_to?
22
+ # what you provide as a default command, incase it
23
+ # uses method missing or something. So it's *YOUR*
24
+ # responsibility to provide this method
25
+ #
26
+ # Conventionally, your 'default' method should simple pass
27
+ # along the arguments to another defined and documented command!
28
+ #
29
+ module SimpleCLI
30
+ attr_accessor :options
31
+ attr_reader :args, :command, :command_args
32
+
33
+ def initialize args = [], options = {}
34
+ @args = args
35
+ @options = options
36
+ parse!
37
+ end
38
+
39
+ # figure out what command to run, arguments to pass it, etc
40
+ #
41
+ # call #run afterwards, to run. or call parse! to parse and run
42
+ #
43
+ # typically, you shouldn't call this yourself. call parse when you
44
+ # want to RE-parse the arguments passed in, because initialize auto-parses
45
+ #
46
+ # typical:
47
+ # Bin.new( ARGV ).run
48
+ # Bin.new( ARGV, :default => 'some_default_method ).run
49
+ #
50
+ # use this is you want to ...
51
+ # bin = Bin.new ARGV
52
+ # bin.options[:default] = 'some_default_method'
53
+ # bin.instance_eval { 'do some custom stuff that might change the command to run, etc' }
54
+ # bin.parse!
55
+ # bin.run
56
+ #
57
+ def parse!
58
+ args = @args.clone
59
+
60
+ @default_command = @options[:default].to_s if @options.keys.include? :default
61
+ @commands = all_commands
62
+
63
+ if not args.empty? and @commands.map{|c|c.downcase}.include? args.first.downcase
64
+ @command = args.shift.downcase
65
+ else
66
+ @command = (args.empty?) ? 'usage' : ( @default_command || 'usage' )
67
+ end
68
+
69
+ @command_args = args
70
+ end
71
+
72
+ # run command determined by parse
73
+ def run
74
+ begin
75
+ self.send @command, *@command_args
76
+ rescue ArgumentError => ex
77
+ puts "'#{@command}' called with wrong number of arguments\n\n"
78
+ puts help_for( @command )
79
+ end
80
+ end
81
+
82
+ # returns names of all defined 'command' methods
83
+ #
84
+ # only returns methods with methodname_help sister methods,
85
+ # inotherwords: only returns DOCUMENTED methods
86
+ # ... this should get you to document that command!
87
+ def all_commands
88
+ self.methods.sort.grep( /_help/ ).collect{ |help_method| help_method.gsub( /(.*)_help/ , '\1' ) }
89
+ end
90
+
91
+ # returns help String for command
92
+ def help_for command
93
+ help_method = "#{ command }_help".to_sym
94
+ self.send( help_method ) if self.respond_to? help_method
95
+ end
96
+
97
+ # returns summary String for command (extracted from help_for command)
98
+ #
99
+ # Looks for
100
+ # Summary:
101
+ # some summary text here, on a new line after 'Summary:'
102
+ #
103
+ def summary_for command
104
+ doco = help_for command
105
+ if doco
106
+ match = /Summary:\n*(.*)/.match doco
107
+ if match and match.length > 1
108
+ match[1].strip
109
+ end
110
+ end
111
+ end
112
+
113
+ # default usage message, called if we can't figure out what command to run
114
+ #
115
+ # override in your app by re-defining - it should puts the message (or do whatever) itself!
116
+ # this method doesn't return a string, like blah_help methods (which are called by #help).
117
+ # usage is called, all by itself ... so it needs to print itself!
118
+ #
119
+ def usage *args
120
+ puts "default usage message. please define a 'usage' method returning a new message."
121
+ end
122
+
123
+ # shortcut to pretty file name of script, which can be used in your help doco
124
+ def script_name
125
+ File.basename $0
126
+ end
127
+
128
+ # HELP
129
+ def help_help
130
+ <<doco
131
+ Usage: #{ script_name } help COMMAND
132
+
133
+ Summary:
134
+ Provide help documentation for a command
135
+ doco
136
+ end
137
+ def help *args
138
+ command = args.shift
139
+ if command.nil?
140
+ puts help_for( :help )
141
+ elsif (doco = help_for command)
142
+ puts doco
143
+ else
144
+ puts "No documentation found for command: #{command}"
145
+ end
146
+ end
147
+
148
+ # COMMANDS
149
+ def commands_help
150
+ <<doco
151
+ Usage: #{ script_name } commands
152
+
153
+ Summary:
154
+ List all '#{ script_name }' commands
155
+ doco
156
+ end
157
+ def commands *no_args
158
+ before_spaces = 4
159
+ after_spaces = 18
160
+ text = all_commands.inject(''){ |all,cmd| all << "\n#{' ' * before_spaces}#{cmd}#{' ' * (after_spaces - cmd.length)}#{summary_for(cmd)}" }
161
+ puts <<doco
162
+ #{ script_name } commands are:
163
+
164
+ DEFAULT COMMAND #{ @default_command || 'not set' }
165
+ #{ text }
166
+
167
+ For help on a particular command, use '#{ script_name } help COMMAND'.
168
+ doco
169
+
170
+ #If you've made a command and it's not showing up here, you
171
+ #need to make help method named 'COMMAND_help' that returns
172
+ #your commands help documentation.
173
+ #
174
+ #[NOT YET IMPLEMENTED:]
175
+ #Commands may be abbreviated, so long as they are unumbiguous.
176
+ #e.g. 'snip h commands' is short for 'snip help commands'.
177
+ #doco
178
+ end
179
+
180
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: remi-simplecli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - remi Taylor
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-04-27 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: SimpleCLI gives you a stupidly simple way to implement command-line interfaces like that of RubyGems
17
+ email: remi@remitaylor.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README
26
+ - lib/simplecli.rb
27
+ - examples/hello-cli
28
+ has_rdoc: true
29
+ homepage: http://github.com/remi/simplecli
30
+ post_install_message:
31
+ rdoc_options:
32
+ - --main
33
+ - README
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ version:
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ requirements: []
49
+
50
+ rubyforge_project:
51
+ rubygems_version: 1.0.1
52
+ signing_key:
53
+ specification_version: 2
54
+ summary: Super Simple RubyGems-like CLI
55
+ test_files: []
56
+