clive 0.6.2 → 0.7.0

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/README.md CHANGED
@@ -12,190 +12,193 @@ Install with:
12
12
 
13
13
  ## How To
14
14
 
15
- A simple example to start:
16
-
15
+ Simply include `Clive::Parser` to start using.
16
+ A simple example:
17
+
18
+ # test.rb
17
19
  require 'clive'
18
20
 
19
- opts = {}
20
- c = Clive.new do
21
- switch(:v, :verbose, "Run verbosely") {opts[:verbose] = true}
21
+ class CLI
22
+ include Clive::Parser
23
+ option_hash :config
24
+
25
+ desc 'Run verbosely'
26
+ switch :v, :verbose do
27
+ config[:verbose] = true
28
+ end
29
+
22
30
  end
23
- c.parse(ARGV)
24
- p opts
31
+ CLI.parse(ARGV)
32
+ p CLI.config
25
33
 
26
34
  This creates a very simple interface which can have one switch, you can then use the
27
35
  long or short form to call the block.
28
36
 
29
- my_file -v
37
+ test.rb -v
30
38
  #=> {:verbose => true}
31
- my_file --verbose
39
+ test.rb --verbose
32
40
  #=> {:verbose => true}
33
41
 
34
42
 
35
43
  ### Switches
36
44
 
37
- As we've seen above switches are created using #switch. You can provide as little
38
- information as you want. `switch(:v) {}` creates a switch that responds only to
39
- `-v`, or `switch(:verbose) {}` creates a switch that only responds to `--verbose`.
40
-
41
- ### Boolean
42
-
43
- Boolean switches allow you to accept arguments like `--no-verbose` and `--verbose`,
44
- and deal with both situations in the same block.
45
+ The most basic options. When they are called by either name the block is run. To create
46
+ a switch use `#switch`.
45
47
 
46
- c = Clive.new do
47
- bool(:v, :verbose) {|i| p i}
48
+ switch :s do
49
+ # code
48
50
  end
49
- c.parse(ARGV)
51
+ # Called with '-s'
50
52
 
51
- ####
53
+ switch :long do
54
+ # code
55
+ end
56
+ # Called with '--long'
52
57
 
53
- my_file --verbose
54
- #=> true
55
- my_file -v
56
- #=> true
57
- my_file --no-verbose
58
- #=> false
58
+ switch :b, :both do
59
+ # code
60
+ end
61
+ # Called with '-b' or '--both'
62
+
63
+
64
+ ### Booleans
65
+
66
+ Boolean switches allow you to easily create a pair of switches, eg. `--force` and
67
+ `--no-force`. The block given is passed either true or false depending on which was
68
+ used.
69
+
70
+ bool :f, :force do |truth|
71
+ p truth
72
+ end
73
+ # '-f' returns true
74
+ # '--force' returns true
75
+ # '--no-force' returns false
76
+
77
+ You must provide a long name, a short name is optional.
59
78
 
60
- As you can see the true case can be triggered with the short or long form, the false
61
- case can be triggered by appending "no-" to the long form, and it can't be triggered
62
- with a short form.
63
79
 
64
80
  ### Flags
65
81
 
66
- Flags are like switches but also take an argument:
82
+ Flags are like switches but take one or more arguments, these are then passed to the
83
+ block.
67
84
 
68
- c = Clive.new do
69
- flag(:p, :print, "ARG", "Print ARG") do |i|
70
- p i
71
- end
85
+ # Creates a flag with a mandatory argument
86
+ flag :with, :args => "ARG" do |arg|
87
+ puts arg
72
88
  end
73
- c.parse(ARGV)
74
-
75
- ####
76
-
77
- my_file --print=hello
78
- #=> "hello"
79
- my_file --print equalsless
80
- #=> "equalsless"
81
- my_file -p short
82
- #=> "short"
83
-
84
- The argument is then passed into the block. As you can see you can use short, long,
85
- equals, or no equals to call flags. As with switches you can call `flag(:p) {|i| ...}`
86
- which responds to `-p ...`, `flag(:print) {|i| ...}` which responds to `--print ...`
87
- or `--print=...`. Flags can have default values, for that situation put square brackets
88
- round the argument name.
89
-
90
- flag(:p, :print, "[ARG]", "Print ARG or "hey" by default) do |i|
91
- i ||= "hey"
92
- p i
89
+
90
+ # Creates a flag with an optional argument, by using []
91
+ flag :with, :args => "[ARG]" do |arg|
92
+ puts arg
93
+ end
94
+
95
+ # Creates a flag with multiple arguments
96
+ flag :with, :args => "FIRST [OPTIONAL]" do |i, j|
97
+ puts i, j
93
98
  end
94
99
 
95
- ### Commands
96
-
97
- Commands work like in git, here's an example:
100
+ You can also provide a list of options to select from.
98
101
 
99
- opts = {}
100
- c = Clive.new do
101
- command(:add) do
102
- opts[:add] = {}
103
- flag(:r, :require, "Require a library") {|i| opts[:add][:lib] = i}
104
- end
102
+ flag :choose, :args => %w(small med large) do |choice|
103
+ puts choice
105
104
  end
106
- c.parse(ARGV)
107
- p opts
108
105
 
109
- ####
106
+ flag :number, :args => 1..5 do |num|
107
+ puts num
108
+ end
110
109
 
111
- my_file add -r Clive
112
- #=> {:add => {:lib => "Clive"}}
113
110
 
114
- Commands make it easy to group flags, switches and even other commands. The block for
115
- the command is executed on finding the command, this allows you to put other code within
116
- the block specific for the command, as shown above.
111
+ ### Commands
117
112
 
113
+ Commands allow you to group a collection of options (or more commands) under a keyword.
114
+ The block provided is run when one of the names for the command is encountered, but the
115
+ blocks of the options in it are only ran when they are found.
116
+
117
+ command :init, :create do
118
+ bool :force do |truth|
119
+ puts "Force"
120
+ end
121
+ end
122
+ # 'init --force'
123
+
118
124
 
119
125
  ### Arguments
120
126
 
121
- Anything that isn't a command, switch or flag is taken as an argument. These are returned
122
- by #parse as an array.
123
-
124
- opts = {}
125
- c = Clive.new do
126
- flag(:size) {|i| opts[:size] = i}
127
+ Anything that is not captured as a command, option or argument of a flag, is returned by
128
+ #parse in an array.
129
+
130
+ class Args
131
+ include Clive::Parser
132
+
133
+ switch(:hey) { puts "Hey" }
127
134
  end
128
- args = c.parse(ARGV)
135
+ args = Args.parse(ARGV)
129
136
  p args
130
137
 
131
- ####
132
-
133
- my_file --size big /usr/bin
134
- #=> ["/usr/bin"]
138
+ # `file --hey argument "A string"`
139
+ #=> ['argument', 'A string']
135
140
 
136
141
 
137
- ### Error Handling
142
+ ### Option Handling
138
143
 
139
144
  You are able to intercept errors when an option does not exist in a similar way to
140
145
  `method_missing`.
141
146
 
142
- c = Clive.new do
147
+ class Missing
143
148
  option_missing do |name|
144
149
  puts "#{name} was used but not defined"
145
150
  end
146
151
  end
147
- c.parse("--hey")
152
+ Missing.parse %w(--hey)
148
153
  #=> hey was used but not defined
149
154
 
150
- I was hoping to provide a similar way of intercepting commands as well but these could
151
- also be arguments which means it could result in unexpected results. For this reason I
152
- will not be implementing `command_missing`.
153
155
 
154
- ### Putting It All Together
156
+ ### Help Formatting
155
157
 
156
- require 'clive'
157
-
158
- opts = {}
159
- c = Clive.new do
160
- bool(:v, :verbose, "Run verbosely") {|i| opts[:verbose] = i}
161
-
162
- command(:add, "Add a new project") do
163
- opts[:add] = {}
164
-
165
- switch(:force, "Force overwrite") {opts[:add][:force] = true}
166
- flag(:framework, "Add framework") do |i|
167
- opts[:add][:framework] ||= []
168
- opts[:add][:framework] << i
169
- end
170
-
171
- command(:init, "Initialize the project after creating") do
172
- switch(:m, :minimum, "Use minimum settings") {opts[:add][:min] = true}
173
- flag(:w, :width) {|i| opts[:add][:width] = i.to_i}
174
- end
175
-
176
- end
177
-
178
- switch(:version, "Show version") do
179
- puts "1.0.0"
180
- exit
158
+ There are two built in help formats the default, with colour, and a pure white one. To
159
+ change the formatter call `#help_formatter` with :default, or :white.
160
+
161
+ Optionally you can create your own formatter, like so:
162
+
163
+ class CLI
164
+ help_formatter do |h|
165
+ h.switch "{prepend}{names.join(', ')} {spaces}# {desc}"
166
+ h.bool "{prepend}{names.join(', ')} {spaces}# {desc}"
167
+ h.flag "{prepend}{names.join(', ')} {args.join(' ')} {spaces}# {desc}" <<
168
+ "{options.join('(', ', ', ')')}"
169
+ h.command "{prepend}{names.join(', ')} {spaces}# {desc}"
181
170
  end
182
171
  end
183
- args = c.parse(ARGV)
184
- p opts
185
- p args
186
-
187
- ####
172
+
173
+ Which would look like:
174
+
175
+ Usage: my_app [command] [options]
188
176
 
189
- my_file --version
190
- #=> 1.0.0
191
- my_file -v add --framework=blueprint init -m -w 200 ~/Desktop/new_thing ~/Desktop/another_thing
192
- #=> {:verbose => true, :add => {:framework => ["blueprint"], :min => true, :width => 200}}
193
- #=> ["~/Desktop/new_thing", "~/Desktop/another_thing"]
177
+ Commands:
178
+ test # A command
179
+
180
+ Options:
181
+ -h, --help # Display help
182
+ --[no-]force # Force build
183
+
184
+ You have access to the variables:
185
+
186
+ * prepend - a string of spaces as specified when `#help_formatter` is called
187
+ * names - an array of names for the option
188
+ * spaces - a string of spaces to align the descriptions properly
189
+ * desc - a string of the description for the option
190
+
191
+ And for flags you have access to:
192
+
193
+ * args - an array of arguments for the flag
194
+ * options - an array of options to choose from
195
+
196
+ Inside the { and } you can put any ruby, so feel free to use joins on the array.
194
197
 
195
198
 
196
199
  ## Clive::Output
197
200
 
198
- This is a new bit that allows you to colorize output from the command line, by patching a
201
+ This is a new bit that allows you to colourise output from the command line, by patching a
199
202
  few methods onto String.
200
203
 
201
204
  require 'clive/output'
@@ -1,137 +1,48 @@
1
1
  require 'clive/parser'
2
- require 'clive/output'
3
2
 
4
3
  # Clive is a simple dsl for creating command line interfaces
5
4
  #
6
5
  # @example Simple Example
7
6
  #
8
- # opts = {}
9
- # c = Clive.new do
10
- # switch(:v, :verbose, "Run verbosely") {
11
- # opts[:verbose] = true
12
- # }
13
- # end
14
- # c.parse(ARGV)
15
- # # app -v
16
- # #=> {:verbose => true}
17
- #
18
- # @example Class Style with Inheritence
19
- #
20
- # opts = {}
21
- # class BasicCommands < Clive
22
- # switch :basic do
23
- # p "basic"
7
+ # class CLI
8
+ # include Clive::Parser
9
+ #
10
+ # desc 'A switch'
11
+ # switch :s, :switch do
12
+ # puts "You used a switch"
24
13
  # end
25
- # end
26
- #
27
- # class SubCommands < BasicCommands
28
- # switch :sub do
29
- # p "sub"
14
+ #
15
+ # desc 'A flag'
16
+ # flag :hello, :args => "NAME" do |name|
17
+ # puts "Hello, #{name}"
30
18
  # end
31
- # end
32
- #
33
- # SubCommands.parse(ARGV)
34
- # # app --basic --sub
35
- # #=> "basic"
36
- # #=> "sub"
37
- #
38
- # @example Non-simple Example
39
- #
40
- # opts = {}
41
- # c = Clive.new do
42
- # bool(:v, :verbose, "Run verbosely") {|i| opts[:verbose] = i}
43
19
  #
44
- # command :add, "Add a new project" do
45
- # opts[:add] = {}
46
- #
47
- # switch(:force, "Force overwrite") {opts[:add][:force] = true}
48
- # flag :framework, "Add framework" do |i|
49
- # opts[:add][:framework] ||= []
50
- # opts[:add][:framework] << i
20
+ # desc 'True or false'
21
+ # bool :which do |which|
22
+ # case which
23
+ # when true
24
+ # puts "true, yay"
25
+ # when false
26
+ # puts "false, not yay"
27
+ # end
28
+ # end
29
+ #
30
+ # option_list :purchases
31
+ #
32
+ # command :new, :buy do
33
+ # switch :toaster do
34
+ # purchases << :toaster
51
35
  # end
52
36
  #
53
- # command :init, "Initialize the project after creating" do
54
- # switch(:m, :minimum, "Use minimum settings") {opts[:add][:min] = true}
55
- # flag(:w, :width) {|i| opts[:add][:width] = i.to_i}
37
+ # switch :tv do
38
+ # purchases << :tv
56
39
  # end
57
- #
58
40
  # end
59
41
  #
60
- # switch :version, "Show version" do
61
- # puts "1.0.0"
62
- # exit
63
- # end
64
42
  # end
65
- # ARGV = c.parse(ARGV)
66
- # # app add framework=blueprint --force --verbose
67
- # #=> {:add => {:framework => ['blueprint'], :force => true}, :verbose => true}
68
43
  #
69
- class Clive
70
-
71
- # This is the base command, the only way it differs from a normal command
72
- # is that it has no name and it's block is executed immediately on creation.
73
- #
74
- # @return [Command] the base command
75
- #
76
- attr_accessor :base
77
-
78
- def initialize(&block)
79
- @base = Command.new(true, &block)
80
- end
81
-
82
- # Parse the base command
83
- def parse(argv)
84
- @base.run(argv)
85
- end
86
-
87
- # @group Base Proxy Methods
88
-
89
- # @see Command#switches
90
- # @return [Array] switches in +base+
91
- def switches
92
- @base.switches
93
- end
94
-
95
- # @see Command#commands
96
- # @return [Array] commands in +base+
97
- def commands
98
- @base.commands
99
- end
100
-
101
- # @see Command#flags
102
- # @return [Array] flags in +base+
103
- def flags
104
- @base.flags
105
- end
106
-
107
- # @see Command#bools
108
- # @return [Array] bools in +base+
109
- def bools
110
- @base.bools
111
- end
112
-
113
- # @group Clive Class Methods
114
-
115
- @@base = Clive::Command.new(true)
116
-
117
- def self.flag(*args, &block)
118
- @@base.flag(*args, &block)
119
- end
120
-
121
- def self.switch(*args, &block)
122
- @@base.switch(*args, &block)
123
- end
124
-
125
- def self.command(*args, &block)
126
- @@base.command(*args, &block)
127
- end
128
-
129
- def self.bool(*args, &block)
130
- @@base.bool(*args, &block)
131
- end
132
-
133
- def self.parse(argv)
134
- @@base.run(argv)
135
- end
44
+ # CLI.parse(ARGV)
45
+ #
46
+ module Clive
136
47
 
137
48
  end