clive 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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