gli 0.1.6 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,18 +1,32 @@
1
- This is a command line parser for a git-like command line client.
1
+ = Git-Like Interface Command Line Parser
2
2
 
3
- = Use
3
+ Author:: Dave Copeland (mailto:davetron5000 at g mail dot com)
4
+ Copyright:: Copyright (c) 2009 by Dave Copeland
5
+ License:: Distributes under the Apache License, see LICENSE.txt in the source distro
6
+
7
+ This is a DSL you can use to create a command line interface like git, gem or svn, in that the first argument is a command, and there are global and command specific flags.
8
+
9
+ == Use
10
+
11
+ Install if you need to:
12
+
13
+ sudo gem install gli
4
14
 
5
15
  The simplest way to get started is to create a scaffold project
6
16
 
7
17
  gli init my_proj command_name other_command_name
8
18
 
9
- This will create a (very) basic scaffold project in <tt>./my_proj</tt>, with a bare-bones
10
- main file in <tt>./my_proj/bin/my_proj</tt>. This file demonstrates most of what you need
11
- to describe your command line interface
19
+ This will create a basic scaffold project in <tt>./my_proj</tt> with:
12
20
 
13
- == More Detail
21
+ * executable in <tt>./my_proj/bin/my_proj</tt>. This file demonstrates most of what you need to describe your command line interface.
22
+ * an empty test in <tt>./my_proj/test/tc_nothing.rb</tt> that can bootstrap your tests
23
+ * a gemspec shell
24
+ * a README shell
25
+ * Rakefile that can generate RDoc, package your Gem and run tests
14
26
 
15
- This sets you up to use the DSL that GLI defines:
27
+ === Example
28
+
29
+ This example demonstrates most of the features of GLI
16
30
 
17
31
  #!/usr/bin/ruby
18
32
  $: << File.expand_path(File.dirname(__FILE__) + '/../lib')
@@ -21,27 +35,31 @@ This sets you up to use the DSL that GLI defines:
21
35
 
22
36
  include GLI
23
37
 
24
- This describes a command line switch "-n" that is global to all commands and specified before
25
- the command name on the command line.
38
+ This sets you up to use the DSL that GLI defines:
39
+
40
+
41
+ program_description 'Support program for bootstrapping GLI-based programs'
42
+
43
+ This sets a description of your program. This can be as long as you want.
44
+
26
45
 
27
46
  desc 'Dry run; don\'t change the disk'
28
47
  switch :n
29
48
 
49
+ This describes a command line switch "-n" that is global to all commands and specified before
50
+ the command name on the command line.
30
51
 
31
- This describes a command line flag that is global and has a default value of '<tt>.</tt>'. It also
32
- specifies a short description of its argument. This is used to print command line help. Note that we
33
- have specified two different aliases for this flag. <tt>-r</tt> (because it is listed first) is the default
34
- one and <tt>--root</tt> (note two-dash syntax) is also supported. This means that <tt>-r some_dir</tt> and <tt>--root=some_dir</tt> mean
35
- the same thing to the application.
36
52
 
37
53
  desc 'Root dir in which to create project'
38
54
  default_value '.'
39
55
  arg_name 'root_dir'
40
56
  flag [:r,:root]
41
57
 
42
- Here we specify a command. Inside the block we can use the same sorts of things as we did above to define flags
43
- and switches specific to the command. These must come after the command name. Also note that we use <tt>arg_name</tt>
44
- here to describe the arguments this command accepts.
58
+ The following describes a command line flag that is global and has a default value of '<tt>.</tt>'. It also
59
+ specifies a short description of its argument. This is used to print command line help. Note that we
60
+ have specified two different aliases for this flag. <tt>-r</tt> (because it is listed first) is the default
61
+ one and <tt>--root</tt> (note two-dash syntax) is also supported. This means that <tt>-r some_dir</tt> and <tt>--root=some_dir</tt> mean
62
+ the same thing to the application.
45
63
 
46
64
  desc 'Create a new GLI-based project'
47
65
  arg_name 'project_name [command[ command]*]'
@@ -53,18 +71,22 @@ here to describe the arguments this command accepts.
53
71
  c.desc 'Overwrite/ignore existing files and directories'
54
72
  c.switch [:force]
55
73
 
56
- Here we specify the actual actions to take when the command is executed. We define a block that
57
- will be given the global options (as a Hash), the command-specific options (as a hash) and the command
58
- line arguments
74
+ Here we specify a command. Inside the block we can use the same sorts of things as we did above to define flags
75
+ and switches specific to the command. These must come after the command name. Also note that we use <tt>arg_name</tt>
76
+ here to describe the arguments this command accepts.
59
77
 
60
78
  c.action do |global_options,options,args|
61
79
  if args.length < 1
62
- raise(MissingArgumentException,'You must specify the name of your project')
80
+ raise 'You must specify the name of your project'
63
81
  end
64
82
  Scaffold.create_scaffold(g[:r],!o[:notest],o[:e],args[0],args[1..-1],o[:force],g[:n])
65
83
  end
66
84
  end
67
85
 
86
+ Here we specify the actual actions to take when the command is executed. We define a block that
87
+ will be given the global options (as a Hash), the command-specific options (as a hash) and the command
88
+ line arguments
89
+
68
90
  You can also specify some global code to run before, after and on errors:
69
91
 
70
92
  pre do |global_options,command,options,args|
@@ -87,6 +109,8 @@ Now, we run the program using the arguments the user provided on the command lin
87
109
 
88
110
  run(ARGV)
89
111
 
112
+ Note that by using <tt>gli init</tt> you can create a shell with all of this already there.
113
+
90
114
  What this gives you:
91
115
 
92
116
  * A reasonably useful help system. <tt>your_program help</tt> will list all the global options and commands (along with command aliases) and <tt>your_program help command_name</tt> will list help for that given command.
@@ -99,8 +123,25 @@ What this doesn't give you:
99
123
  * A way to indicate required flags
100
124
  * A way to indicate a require argument or required number of arguments
101
125
  * A way to do default switches to 'true' and therefore accept things like <tt>--no-force</tt>
102
-
103
- = Interface Generated
126
+
127
+ == Reference
128
+
129
+
130
+ [+action+] Specify the action to take when a command is executed from the command line. This is only usable in a command block on the command object (e.g. <tt>c.action</tt>). This takes a block that yields three parameters: a hash of global options specified on the commandline, a hash of command-specific options specified on the command line, and an array of arguments parsed after the options were set on the command line. So, a command like <tt>git --git-dir=/tmp commit -a -m 'Foo bar' foo.c bar.c</tt> would result in the global hash containing <tt>:'git-dir' => '/tmp'</tt>, the options hash containing <tt>:a => true, :m => 'Foo bar'</tt> and the arguments array being <tt>['foo.c', 'bar.c']</tt>
131
+ [+arg_name+] Describe the name of the argument to the next flag or command. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.arg_name</tt>)
132
+ [+command+] Declare a command. This takes a symbol or array of symbols and a block. The block yields one argument, the command itself.
133
+ [+default_value+] Indicate the default value of the next flag. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.default_value</tt>)
134
+ [+desc+] Describe the next flag, switch, or command you will declare. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.desc</tt>)
135
+ [+flag+] Declare a flag, which is a command line switch that takes an argument. This takes either a symbol or an array of symbols. The first symbol decared is used in your program to determine the flag's value at runtime. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.flag</tt>)
136
+ [+long_desc+] Provide a more lengthy description of the next flag, switch, or command you will declare. This will appear in command line output for commands when you get help for a command. For flags and switches, this will only appear in the generated rdoc and *not* on the command line. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.long_desc</tt>)
137
+ [+on_error+] Declare an error handling routine that will be called if any command (or other GLI processing) encouters an exception. This is a block that will receive the exception that was caught. All exceptions are routed through this block. If the block evaluates to true, the built-in error handling will be called after, otherwise, nothing will happen.
138
+ [+post+] Declare code to run after every command that didn't experience an error. This is not available inside a command block. This takes a block that will receive four arguments: the global argument hash (as in <tt>action</tt>), the command (instance of Command), the command-specific options (as in <tt>action</tt>, and the parsed command line arguments (as in <tt>action</tt>).
139
+ [+pre+] Declare code to run before every command. This is not available inside a command block. This takes a block that will receive four arguments: the global argument hash (as in <tt>action</tt>), the command (instance of Command), the command-specific options (as in <tt>action</tt>, and the parsed command line arguments (as in <tt>action</tt>). If this block evaluates to false, the command will not be executed and the program will stop.
140
+ [+switch+] Declare a switch, which is a command-line switch taking no argument that indicates a boolean "true" when specified on the command line. This takes either a symbol or array of symbols. The first symbol declared is used in your program to determine if the switch was set. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.switch</tt>)
141
+
142
+ == Interface Generated
143
+
144
+ The command line interface that is created with the GLI DSL is:
104
145
 
105
146
  *executable* <i>global options and flags</i> *command* <i>command specific options and flags</i> `arguments`
106
147
 
@@ -109,7 +150,7 @@ What this doesn't give you:
109
150
  [command] the command to execute. The <tt>rebase</tt> in <tt>git rebase</tt>
110
151
  [arguments] Anything that's not a switch, flag, or command. The <tt>main.c</tt> in <tt>git add main.c</tt>
111
152
 
112
- == Switches
153
+ === Switches
113
154
 
114
155
  Switches can be specified one at a time in either a long or short format:
115
156
 
@@ -121,15 +162,22 @@ Switches can also be combined in their short form:
121
162
  ls -l -a
122
163
  ls -la
123
164
 
124
- == Flags
165
+ === Flags
125
166
 
126
167
  Flags can be specified in long or short form, and with or without an equals:
127
168
 
128
169
  git merge -s resolve
129
170
  git merge --strategy=resolve
130
171
 
131
- == Stop Switch
172
+ === Stop Switch
132
173
 
133
174
  A <tt>--</tt> at any time stops processing and sends the rest of the argument to the command as arguments, even if
134
175
  they start with a "--"
135
176
 
177
+ :include:gli.rdoc
178
+
179
+ == Links
180
+
181
+ * [http://davetron5000.github.com/gli] - RubyDoc
182
+ * [http://www.github.com/davetron5000/gli] - Source on GitHub
183
+
data/bin/gli CHANGED
@@ -5,20 +5,28 @@ require 'gli'
5
5
  require 'support/scaffold'
6
6
 
7
7
  include GLI
8
+
8
9
  desc 'Be verbose'
9
10
  switch :v
10
11
 
11
- desc 'Print version'
12
+ desc 'Show version'
12
13
  switch :version
13
14
 
14
- desc 'Dry run; don\'t change the disk'
15
+ desc 'Dry run; don''t change the disk'
15
16
  switch :n
16
17
 
17
18
  desc 'Root dir of project'
19
+ long_desc 'This is the directory where the project''s directory will be made, so if you specify a project name ''foo'' and the root dir of ''.'', the directory ''./foo'' will be created'
18
20
  default_value '.'
19
21
  flag [:r,:root]
20
22
 
21
23
  desc 'Create a new GLI-based project'
24
+ long_desc <<EOS
25
+ This will create a scaffold command line project that uses GLI
26
+ for command line processing. Specifically, this will create
27
+ an executable ready to go, as well as a lib and test directory, all
28
+ inside the directory named for your project
29
+ EOS
22
30
  arg_name 'project_name [command[ command]*]'
23
31
  command [:init,:scaffold] do |c|
24
32
 
@@ -33,7 +41,7 @@ command [:init,:scaffold] do |c|
33
41
 
34
42
  c.action do |g,o,args|
35
43
  if args.length < 1
36
- raise(MissingArgumentException,'You must specify the name of your project')
44
+ raise 'You must specify the name of your project'
37
45
  end
38
46
  Scaffold.create_scaffold(g[:r],!o[:notest],o[:e],args[0],args[1..-1],o[:force],g[:n])
39
47
  end
@@ -53,9 +61,4 @@ post do |global,command,options,args|
53
61
  puts "Executed #{command.name}" if global[:v]
54
62
  end
55
63
 
56
- #on_error do |global,command,options,args|
57
- # puts "Got an error" if global[:v]
58
- # true
59
- #end
60
-
61
64
  run(ARGV)
@@ -0,0 +1,45 @@
1
+ = <tt>gli</tt>
2
+
3
+ gli [global options] command_name [command-specific options] [--] arguments...
4
+
5
+ * Use the command +help+ to get a summary of commands
6
+ * Use the command <tt>help command_name</tt> to get a help for +command_name+
7
+ * Use <tt>--</tt> to stop command line argument processing; useful if your arguments have dashes in them
8
+
9
+ == Global Options
10
+ These options are available for any command and are specified before the name of the command
11
+
12
+ [<tt>-n</tt>] Dry run; dont change the disk
13
+ [<tt>-r, --root=arg</tt>] Root dir of project <i>( default: <tt>.</tt>)</i>
14
+
15
+ This is the directory where the projects directory will be made, so if you specify a project name foo and the root dir of ., the directory ./foo will be created
16
+
17
+ [<tt>-v</tt>] Be verbose
18
+ [<tt>--version</tt>] Show version
19
+ == Commands
20
+ [<tt>help</tt>] Shows list of commands or help for one command
21
+ [<tt>init</tt>] Create a new GLI-based project
22
+
23
+ === <tt>help [command]</tt>
24
+
25
+ Shows list of commands or help for one command
26
+
27
+ === <tt>init project_name [command[ command]*]</tt>
28
+
29
+ Create a new GLI-based project
30
+
31
+ *Aliases*
32
+ * <tt><b>scaffold</b></tt>
33
+
34
+ This will create a scaffold command line project that uses GLI
35
+ for command line processing. Specifically, this will create
36
+ an executable ready to go, as well as a lib and test directory, all
37
+ inside the directory named for your project
38
+
39
+
40
+ ==== Options
41
+ These options are specified *after* the command.
42
+
43
+ [<tt>-e, --ext</tt>] Create an ext dir
44
+ [<tt>--force</tt>] Overwrite/ignore existing files and directories
45
+ [<tt>--notest</tt>] Do not create a test dir
data/lib/gli.rb CHANGED
@@ -3,6 +3,7 @@ require 'gli/command.rb'
3
3
  require 'gli/switch.rb'
4
4
  require 'gli/flag.rb'
5
5
  require 'support/help.rb'
6
+ require 'support/rdoc.rb'
6
7
 
7
8
  # A means to define and parse a command line interface that works as
8
9
  # Git's does, in that you specify global options, a command name, command
@@ -10,7 +11,7 @@ require 'support/help.rb'
10
11
  module GLI
11
12
  extend self
12
13
 
13
- VERSION = '0.1.5'
14
+ VERSION = '0.2.1'
14
15
 
15
16
  @@program_name = $0.split(/\//)[-1]
16
17
  @@post_block = nil
@@ -25,8 +26,14 @@ module GLI
25
26
  clear_nexts
26
27
  end
27
28
 
28
- # describe the next switch, flag, or command
29
+ # describe the next switch, flag, or command. This should be a
30
+ # short, one-line description
29
31
  def desc(description); @@next_desc = description; end
32
+
33
+ # Provide a longer, more detailed description. This
34
+ # will be reformatted and wrapped to fit in 80 columns
35
+ def long_desc(long_desc); @@next_long_desc = long_desc; end
36
+
30
37
  # describe the argument name of the next flag
31
38
  def arg_name(name); @@next_arg_name = name; end
32
39
  # set the default value of the next flag
@@ -34,21 +41,21 @@ module GLI
34
41
 
35
42
  # Create a flag, which is a switch that takes an argument
36
43
  def flag(names)
37
- flag = Flag.new(names,@@next_desc,@@next_arg_name,@@next_default_value)
44
+ flag = Flag.new(names,@@next_desc,@@next_arg_name,@@next_default_value,@@next_long_desc)
38
45
  flags[flag.name] = flag
39
46
  clear_nexts
40
47
  end
41
48
 
42
49
  # Create a switch
43
50
  def switch(names)
44
- switch = Switch.new(names,@@next_desc)
51
+ switch = Switch.new(names,@@next_desc,@@next_long_desc)
45
52
  switches[switch.name] = switch
46
53
  clear_nexts
47
54
  end
48
55
 
49
56
  # Define a command.
50
57
  def command(names)
51
- command = Command.new(names,@@next_desc,@@next_arg_name)
58
+ command = Command.new(names,@@next_desc,@@next_arg_name,@@next_long_desc)
52
59
  commands[command.name] = command
53
60
  yield command
54
61
  clear_nexts
@@ -72,15 +79,18 @@ module GLI
72
79
  end
73
80
 
74
81
  # Define a block to run if an error occurs.
75
- # The block will receive the exception that was caught.
76
- # It should return false to avoid the built-in error handling
82
+ # The block will receive any Exception that was caught.
83
+ # It should return false to avoid the built-in error handling (which basically just
84
+ # prints out a message)
77
85
  def on_error(&a_proc)
78
86
  @@error_block = a_proc
79
87
  end
80
88
 
81
89
  # Runs whatever command is needed based on the arguments.
82
90
  def run(args)
83
- commands[:help] = DefaultHelpCommand.new if !commands[:help]
91
+ rdoc = RDocCommand.new
92
+ commands[:rdoc] = rdoc if !commands[:rdoc]
93
+ commands[:help] = DefaultHelpCommand.new(rdoc) if !commands[:help]
84
94
  begin
85
95
  global_options,command,options,arguments = parse_options(args)
86
96
  proceed = true
@@ -90,15 +100,12 @@ module GLI
90
100
  command.execute(global_options,options,arguments)
91
101
  @@post_block.call(global_options,command,options,arguments) if @@post_block
92
102
  end
93
- rescue UnknownCommandException, UnknownArgumentException, MissingArgumentException => ex
103
+ rescue Exception => ex
94
104
  regular_error_handling = true
95
105
  regular_error_handling = @@error_block.call(ex) if @@error_block
96
106
 
97
107
  if regular_error_handling
98
- puts "error: #{ex}"
99
- puts
100
- help = commands[:help]
101
- help.execute({},{},[])
108
+ puts "error: #{ex.message}"
102
109
  end
103
110
  end
104
111
  end
@@ -141,6 +148,7 @@ module GLI
141
148
  @@next_desc = nil
142
149
  @@next_arg_name = nil
143
150
  @@next_default_value = nil
151
+ @@next_long_desc = nil
144
152
  end
145
153
 
146
154
  clear_nexts
@@ -175,7 +183,7 @@ module GLI
175
183
  if !command
176
184
  command_name = args.shift
177
185
  command = find_command(command_name)
178
- raise(UnknownCommandException,"Unknown command '#{command_name}'") if !command
186
+ raise "Unknown command '#{command_name}'" if !command
179
187
  return parse_options_helper(args,global_options,command,command_options,arguments)
180
188
  else
181
189
  return global_options,command,command_options,arguments | args
@@ -225,16 +233,16 @@ module GLI
225
233
  try_me.delete arg
226
234
  break
227
235
  end
228
- raise(UnknownArgumentException,"Unknown argument #{arg}") if arg =~ /^\-/
236
+ raise "Unknown argument #{arg}" if arg =~ /^\-/
229
237
  end
230
238
  return [global_options,command,command_options,try_me | rest]
231
239
  else
232
240
  # Now we have our command name
233
241
  command_name = try_me.shift
234
- raise(UnknownArgumentException,"Unknown argument #{command_name}") if command_name =~ /^\-/
242
+ raise "Unknown argument #{command_name}" if command_name =~ /^\-/
235
243
 
236
244
  command = find_command(command_name)
237
- raise(UnknownCommandException,"Unknown command '#{command_name}'") if !command
245
+ raise "Unknown command '#{command_name}'" if !command
238
246
 
239
247
  return parse_options_helper(rest,global_options,command,command_options,arguments)
240
248
  end
@@ -252,14 +260,4 @@ module GLI
252
260
  nil
253
261
  end
254
262
 
255
- # Raise this if you get an argument you were not expecting
256
- class UnknownArgumentException < Exception
257
- end
258
-
259
- class UnknownCommandException < Exception
260
- end
261
-
262
- # Raise this if your command doesn't get the number of arguments you were expecting
263
- class MissingArgumentException < Exception
264
- end
265
263
  end
@@ -9,13 +9,16 @@ module GLI
9
9
  # [names] the name or names of this command (symbol or Array of symbols)
10
10
  # [description] description of this command
11
11
  # [arguments_name] description of the arguments, or nil if this command doesn't take arguments
12
+ # [long_desc] a longer description of the command, possibly with multiple lines and text formatting
12
13
  #
13
- def initialize(names,description,arguments_name=nil)
14
- super(names,description)
14
+ def initialize(names,description,arguments_name=nil,long_desc=nil)
15
+ super(names,description,long_desc)
15
16
  @arguments_description = arguments_name || ''
16
17
  clear_nexts
17
18
  end
18
19
 
20
+ def arguments_description; @arguments_description; end
21
+
19
22
  def names
20
23
  all_forms
21
24
  end
@@ -5,9 +5,11 @@ module GLI
5
5
  attr_reader :name
6
6
  attr_reader :aliases
7
7
  attr_reader :description
8
+ attr_reader :long_description
8
9
 
9
- def initialize(names,description)
10
+ def initialize(names,description,long_description=nil)
10
11
  @description = description
12
+ @long_description = long_description
11
13
  @name,@aliases,@names = parse_names(names)
12
14
  end
13
15
 
@@ -15,6 +17,10 @@ module GLI
15
17
  all_forms
16
18
  end
17
19
 
20
+ def <=>(other)
21
+ self.name.to_s <=> other.name.to_s
22
+ end
23
+
18
24
  private
19
25
  # Returns a string of all possible forms
20
26
  # of this flag. Mostly intended for printing
@@ -6,8 +6,8 @@ module GLI
6
6
 
7
7
  attr_reader :default_value
8
8
 
9
- def initialize(names,description,argument_name=nil,default=nil)
10
- super(names,description)
9
+ def initialize(names,description,argument_name=nil,default=nil,long_desc=nil)
10
+ super(names,description,long_desc)
11
11
  @argument_name = argument_name || "arg"
12
12
  @default_value = default
13
13
  end
@@ -24,7 +24,7 @@ module GLI
24
24
  args.delete_at index
25
25
  return value
26
26
  else
27
- raise(MissingArgumentException,"#{matched} requires an argument")
27
+ raise "#{matched} requires an argument"
28
28
  end
29
29
  else
30
30
  return value
@@ -38,7 +38,7 @@ module GLI
38
38
  if @names[arg]
39
39
  return [true,arg,nil] if arg.length == 2
40
40
  # This means we matched the long-form, but there's no argument
41
- raise(MissingArgumentException,"#{arg} requires an argument via #{arg}=argument")
41
+ raise "#{arg} requires an argument via #{arg}=argument"
42
42
  end
43
43
  @names.keys.each() do |name|
44
44
  match_string = "^#{name}=(.*)$"
@@ -4,8 +4,8 @@ module GLI
4
4
  # Defines a command line switch
5
5
  class Switch < CommandLineToken
6
6
 
7
- def initialize(names,description)
8
- super(names,description)
7
+ def initialize(names,description,long_desc=nil)
8
+ super(names,description,long_desc)
9
9
  end
10
10
 
11
11
  # Given the argument list, scans it looking for this switch
@@ -3,7 +3,8 @@ require 'gli/command'
3
3
 
4
4
  module GLI
5
5
  class DefaultHelpCommand < Command
6
- def initialize
6
+ def initialize(*omit_from_list)
7
+ @omit_from_list = omit_from_list
7
8
  super(:help,'Shows list of commands or help for one command','[command]')
8
9
  end
9
10
 
@@ -33,7 +34,8 @@ module GLI
33
34
 
34
35
  def list_commands
35
36
  puts 'Commands:'
36
- output_command_tokens_for_help(GLI.commands,:names)
37
+ commands_to_show = GLI.commands.reject{ |name,c| @omit_from_list.include?(c) }
38
+ output_command_tokens_for_help(commands_to_show,:names)
37
39
  end
38
40
 
39
41
  def list_one_command_help(command_name)
@@ -42,6 +44,10 @@ module GLI
42
44
  puts command.usage
43
45
  description = wrap(command.description,4)
44
46
  puts " #{description}"
47
+ if command.long_description
48
+ puts
49
+ puts " #{wrap(command.long_description,4)}"
50
+ end
45
51
  all_options = command.switches.merge(command.flags)
46
52
  if !all_options.empty?
47
53
  puts
@@ -0,0 +1,78 @@
1
+ require 'gli'
2
+ require 'fileutils'
3
+
4
+ module GLI
5
+ class RDocCommand < Command
6
+
7
+ def initialize
8
+ super(:rdoc,'Generates RDoc for your command line interface')
9
+ end
10
+
11
+ def execute(g,o,a)
12
+ File.open("#{GLI.program_name}.rdoc",'w') do |file|
13
+ file << "= <tt>#{GLI.program_name}</tt>\n\n"
14
+ file << " "
15
+ file << GLI.program_name
16
+ file << " "
17
+ global_options = GLI.switches.merge(GLI.flags)
18
+ if (global_options && global_options.length > 0)
19
+ file << "[global options] "
20
+ end
21
+ file << "command_name"
22
+ file << " [command-specific options]"
23
+ file << " [--] arguments...\n\n"
24
+ file << "* Use the command +help+ to get a summary of commands\n"
25
+ file << "* Use the command <tt>help command_name</tt> to get a help for +command_name+\n"
26
+ file << "* Use <tt>--</tt> to stop command line argument processing; useful if your arguments have dashes in them\n"
27
+ file << "\n"
28
+ if (global_options && global_options.length > 0)
29
+ file << "== Global Options\n"
30
+ file << "These options are available for any command and are specified before the name of the command\n\n"
31
+ output_flags(file,global_options)
32
+ end
33
+ file << "== Commands\n"
34
+ GLI.commands.values.sort.each do |command|
35
+ next if command == self
36
+ file << "[<tt>#{command.name}</tt>] #{command.description}\n"
37
+ end
38
+ file << "\n"
39
+
40
+ GLI.commands.values.sort.each do |command|
41
+ next if command == self
42
+ file << "=== <tt>#{command.name} #{command.arguments_description}</tt>\n\n"
43
+ file << "#{command.description}\n\n"
44
+ if command.aliases
45
+ file << "*Aliases*\n"
46
+ command.aliases.each do |al|
47
+ file << "* <tt><b>#{al}</b></tt>\n"
48
+ end
49
+ file << "\n"
50
+ end
51
+ all_options = command.switches.merge(command.flags)
52
+ if (all_options && all_options.length > 0)
53
+ file << "#{command.long_description}\n\n"
54
+ file << "==== Options\n"
55
+ file << "These options are specified *after* the command.\n\n"
56
+ output_flags(file,all_options)
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ def output_flags(file,flags)
63
+ flags.values.sort.each do |flag|
64
+ file << "[<tt>#{flag.usage}</tt>] #{flag.description}"
65
+ if flag.kind_of? Flag
66
+ file << " <i>( default: <tt>#{flag.default_value}</tt>)</i>" if flag.default_value
67
+ end
68
+ file << "\n"
69
+ if flag.long_description
70
+ file << "\n"
71
+ # 12 is 4 for tt, 5 for /tt, 2 for the brackets and 1 for spacing
72
+ (flag.usage.length + 12).times { file << " " }
73
+ file << "#{flag.long_description}\n\n"
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -12,6 +12,105 @@ module GLI
12
12
 
13
13
  if mkdirs(dirs,force,dry_run)
14
14
  mk_binfile(root_dir,create_ext_dir,force,dry_run,project_name,commands)
15
+ mk_readme(root_dir,dry_run,project_name)
16
+ mk_gemspec(root_dir,dry_run,project_name)
17
+ mk_rakefile(root_dir,dry_run,project_name,create_test_dir)
18
+ end
19
+ end
20
+
21
+ def self.mk_readme(root_dir,dry_run,project_name)
22
+ return if dry_run
23
+ File.open("#{root_dir}/#{project_name}/README.rdoc",'w') do |file|
24
+ file << "= #{project_name}\n\n"
25
+ file << "Describe your project here\n\n"
26
+ file << ":include:#{project_name}.rdoc\n\n"
27
+ end
28
+ File.open("#{root_dir}/#{project_name}/#{project_name}.rdoc",'w') do |file|
29
+ file << "= #{project_name}\n\n"
30
+ file << "Generate this with\n #{project_name} rdoc\nAfter you have described your command line interface"
31
+ end
32
+ end
33
+
34
+ def self.mk_gemspec(root_dir,dry_run,project_name)
35
+ return if dry_run
36
+ File.open("#{root_dir}/#{project_name}/#{project_name}.gemspec",'w') do |file|
37
+ file.puts <<EOS
38
+ spec = Gem::Specification.new do |s|
39
+ s.name = '#{project_name}'
40
+ s.version = '0.0.01'
41
+ s.author = 'Your Name Here'
42
+ s.email = 'your@email.address.com'
43
+ s.homepage = 'http://your.website.com'
44
+ s.platform = Gem::Platform::RUBY
45
+ s.summary = 'A description of your project'
46
+ # Add your other files here if you make them
47
+ s.files = %w(
48
+ bin/#{project_name}
49
+ )
50
+ s.require_paths << 'lib'
51
+ s.has_rdoc = true
52
+ s.extra_rdoc_files = ['README.rdoc','#{project_name}.rdoc']
53
+ s.rdoc_options << '--title' << 'Git Like Interface' << '--main' << 'README.rdoc' << '-ri'
54
+ s.bindir = 'bin'
55
+ s.executables << '#{project_name}'
56
+ end
57
+ EOS
58
+ end
59
+ end
60
+
61
+ def self.mk_rakefile(root_dir,dry_run,project_name,create_test_dir)
62
+ return if dry_run
63
+ File.open("#{root_dir}/#{project_name}/Rakefile",'w') do |file|
64
+ file.puts <<EOS
65
+ require 'rake/clean'
66
+ require 'rubygems'
67
+ require 'rake/gempackagetask'
68
+ require 'rake/rdoctask'
69
+
70
+ Rake::RDocTask.new do |rd|
71
+ rd.main = "README.rdoc"
72
+ rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
73
+ rd.title = 'Your application title'
74
+ end
75
+
76
+ spec = eval(File.read('#{project_name}.gemspec'))
77
+
78
+ Rake::GemPackageTask.new(spec) do |pkg|
79
+ end
80
+
81
+ EOS
82
+ if create_test_dir
83
+ file.puts <<EOS
84
+ require 'rake/testtask'
85
+ Rake::TestTask.new do |t|
86
+ t.libs << "test"
87
+ t.test_files = FileList['test/tc_*.rb']
88
+ end
89
+
90
+ task :default => :test
91
+ EOS
92
+ File.open("#{root_dir}/#{project_name}/test/tc_nothing.rb",'w') do |test_file|
93
+ test_file.puts <<EOS
94
+ require 'test/unit'
95
+ require 'test/unit/ui/console/testrunner'
96
+
97
+ class TC_testNothing < Test::Unit::TestCase
98
+
99
+ def setup
100
+ end
101
+
102
+ def teardown
103
+ end
104
+
105
+ def test_the_truth
106
+ assert true
107
+ end
108
+ end
109
+ EOS
110
+ end
111
+ else
112
+ file.puts "task :default => :package\n"
113
+ end
15
114
  end
16
115
  end
17
116
 
@@ -53,7 +152,11 @@ command :#{command} do |c|
53
152
  c.default_value 'default'
54
153
  c.flag :s
55
154
  c.action do |global_options,options,args|
155
+
56
156
  # Your command logic here
157
+
158
+ # If you have any errors, just raise them
159
+ # raise "that command made no sense"
57
160
  end
58
161
  end
59
162
  EOS
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Copeland
@@ -9,11 +9,11 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-19 00:00:00 -04:00
12
+ date: 2009-07-12 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
- description:
16
+ description: An application and API for describing command line interfaces that can be used to quickly create a shell for executing command-line tasks. The command line user interface is similar to Gits, in that it takes global options, a command, command-specific options, and arguments
17
17
  email: davidcopeland@naildrivin5.com
18
18
  executables:
19
19
  - gli
@@ -21,6 +21,7 @@ extensions: []
21
21
 
22
22
  extra_rdoc_files:
23
23
  - README.rdoc
24
+ - gli.rdoc
24
25
  files:
25
26
  - lib/gli/command.rb
26
27
  - lib/gli/command_line_token.rb
@@ -28,11 +29,15 @@ files:
28
29
  - lib/gli/switch.rb
29
30
  - lib/gli.rb
30
31
  - lib/support/help.rb
32
+ - lib/support/rdoc.rb
31
33
  - lib/support/scaffold.rb
32
34
  - bin/gli
33
35
  - README.rdoc
36
+ - gli.rdoc
34
37
  has_rdoc: true
35
38
  homepage: http://davetron5000.github.com/gli
39
+ licenses: []
40
+
36
41
  post_install_message:
37
42
  rdoc_options:
38
43
  - --title
@@ -58,9 +63,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
63
  requirements: []
59
64
 
60
65
  rubyforge_project: gli
61
- rubygems_version: 1.3.1
66
+ rubygems_version: 1.3.4
62
67
  signing_key:
63
- specification_version: 2
68
+ specification_version: 3
64
69
  summary: A Git Like Interface for building command line apps
65
70
  test_files: []
66
71