ark-cli 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40d1e78d63af56864533187b51ab27bdf514cdcd
4
- data.tar.gz: 7cc02dba83f021e537314dfccc03bc77592e39c4
3
+ metadata.gz: a54741976deb70204c112ab5ee3ec996463ddaf6
4
+ data.tar.gz: bf135aed0b692a6d591dff1160773a83b896ad32
5
5
  SHA512:
6
- metadata.gz: b80df1a67863e975e5d46633e9128a6fd6392a2bd1233e0b905e09d5b1158c347185ec12987561a6cc16229a8fa947dbacf1b7e3fd7a501e191e248280d7329b
7
- data.tar.gz: c710c95aed57880c6a3f5cf01331f859ab766ef10850950466567725b1a14c36718ba0226ed08b30479fb86f78367df3b59ce75be726d265190e16906d92eccf
6
+ metadata.gz: b84c3e4562701df554ab07d821140ff4cb02c765c6aebe8d633f4a54f30e595b8d5f7eda3bf0c3b6046f2c4bca6c03eee032c790139cdcc5b431f7ef72207811
7
+ data.tar.gz: 819682f6427f6d4e0397a43f11ae91cb83ad54b6e4ef411dacded492c7384a6bfa43af917248cb9b1ff6f4fd8a57986f31ee3debb82f3ba59ad5242aa26b95c2
data/README.md CHANGED
@@ -32,9 +32,9 @@ r = Ark::CLI.report do |s|
32
32
  end
33
33
 
34
34
  r.args # Get all arguments received, including trailing args
35
- r.arg[:host] # Get the value of the `host` argument
36
- r.opt[:port] # Get the value of the `port` option
37
- r.count[:v] # Get the number of times an option was toggled
35
+ r.arg(:host) # Get the value of the `host` argument
36
+ r.opt(:port) # Get the value of the `port` option
37
+ r.count(:v) # Get the number of times an option was toggled
38
38
  ```
39
39
 
40
40
  The `CLI.report` method yields a `Spec` instance, which we'll call `s`. Calls to
@@ -72,7 +72,7 @@ Arguments with default values are optional - no error will be raised if they
72
72
  aren't given.
73
73
 
74
74
  ```ruby
75
- s.args 'file:~/.dcf'
75
+ s.args 'file:/tmp/foo'
76
76
  s.args 'host', 'port:22', "user:#{ENV['USER']}"
77
77
  ```
78
78
 
@@ -122,21 +122,21 @@ host, path = r.args
122
122
  Get the value of a named argument with the `r.arg` method:
123
123
 
124
124
  ```ruby
125
- host = r.arg[:host]
126
- path = r.arg[:path]
125
+ host = r.arg(:host)
126
+ path = r.arg(:path)
127
127
  ```
128
128
 
129
129
  Inspect the value of an option with `r.opt`:
130
130
 
131
131
  ```ruby
132
- verbose = r.opt[:v]
133
- port = r.opt[:port]
132
+ verbose = r.opt(:v)
133
+ port = r.opt(:port)
134
134
  ```
135
135
 
136
136
  Get a count of the number of times a flag was specified with `r.count`:
137
137
 
138
138
  ```ruby
139
- verbosity = r.count[:verbose]
139
+ verbosity = r.count(:verbose)
140
140
  ```
141
141
 
142
142
  Get an array of trailing arguments with `r.trailing`:
@@ -156,7 +156,7 @@ CLI declaration.
156
156
 
157
157
  Usage information for the above declaration would look like this:
158
158
 
159
- example [OPTION...] HOST PATH
159
+ example [-p --port NUMBER] [-v --verbose] [-h --help] HOST PATH
160
160
 
161
161
  An example demonstrating usage of ark-cli
162
162
 
data/lib/ark/cli.rb CHANGED
@@ -28,12 +28,14 @@ module Ark # :nodoc:
28
28
 
29
29
  # A library for handling options and arguments from the command line.
30
30
  #
31
- # Call #begin to define a new interface and parse the command line. See
31
+ # Call #report to define a new interface and parse the command line. See
32
32
  # +README.md+ or +example/hello.rb+ for more information.
33
33
  module CLI
34
- # Convenience method for interface declarations. Yields the CLI instance and
35
- # then returns it after parsing. Equivalent to instantiating a CLI instance
36
- # with #new, modifying it, and then calling #parse
34
+ # :call-seq:
35
+ # report(input=ARGV) { |spec| ... } => Report
36
+ #
37
+ # Convenience method for interface declarations. Yields a +Spec+ instance and
38
+ # returns a +Report+ instance for inspection.
37
39
  #
38
40
  # +args+ is an array of strings, which defaults to ARGV
39
41
  def self.report(args=ARGV, &block)
@@ -1,12 +1,21 @@
1
- module Ark
1
+ module Ark # :nodoc:
2
2
  module CLI
3
3
 
4
+ # Main class for ark-cli. Defines a +Spec+, parses the command line and returns
5
+ # +Report+ objects.
4
6
  class Interface
5
7
 
6
8
  # Raised when the command line is malformed
7
9
  class SyntaxError < ArgumentError
8
10
  end
9
11
 
12
+ # Raised when a required argument is not given
13
+ class InterfaceError < ArgumentError
14
+ end
15
+
16
+ # :call-seq:
17
+ # rebuild(input=ARGV) { |spec| ... } => Interface
18
+ #
10
19
  # Initialize an Interface instance.
11
20
  #
12
21
  # +args+ must be an array of strings, like ARGV
@@ -14,8 +23,11 @@ class Interface
14
23
  self.rebuild(args, &block)
15
24
  end
16
25
 
26
+ # The +Report+ object for this interface, for inspecting information parsed
27
+ # from the command line.
17
28
  attr_reader :report
18
29
 
30
+ # Rebuild the interface with a new spec and args
19
31
  def rebuild(input=ARGV, &block)
20
32
  @input = input
21
33
  @spec = Spec.new
@@ -30,7 +42,11 @@ class Interface
30
42
  last_opt = nil
31
43
  refargs = @spec.get_args.clone
32
44
 
33
- @report = Report.new()
45
+ args = []
46
+ trailing = []
47
+ named = {}
48
+ options = {}
49
+ counts = {}
34
50
 
35
51
  @input.each do |word|
36
52
  dbg "Parsing '#{word}'"
@@ -66,36 +82,47 @@ class Interface
66
82
  else
67
83
  dbg "Parsed output arg", 1
68
84
  taking_options = false
69
- @report.args << word
85
+ args << word
70
86
  key = refargs.shift
71
87
  if key
72
88
  if key == @spec.get_variad
73
- @report.arg[key] = []
74
- @report.arg[key] << word
89
+ named[key] = []
90
+ named[key] << word
75
91
  else
76
- @report.arg[key] = word
92
+ named[key] = word
77
93
  end
78
94
  elsif @spec.is_variadic?
79
- @report.arg[@spec.get_variad] << word
95
+ named[@spec.get_variad] << word
80
96
  else
81
- @report.trailing << word
97
+ trailing << word
82
98
  end
83
99
  end
84
100
  end
85
101
  end
102
+ if @spec.trailing_error && !trailing.empty?
103
+ raise InterfaceError, "Error: got trailing option(s): #{trailing.join(', ')}"
104
+ end
86
105
  @spec.get_opts.each do |name, opt|
87
- @report.opt[name] = opt.value
88
- @report.count[name] = opt.count
106
+ options[name] = opt.value
107
+ counts[name] = opt.count
89
108
  end
90
109
  @spec.get_args.each do |name|
91
- if @report.arg[name].nil?
110
+ if named[name].nil?
92
111
  if @spec.has_default?(name)
93
- @report.arg[name] = @spec.get_default(name)
94
- @report.args << @report.arg[name]
112
+ named[name] = @spec.get_default(name)
113
+ args << named[name]
114
+ else
115
+ unless @spec.is_variadic? && @spec.get_variad == name
116
+ raise InterfaceError, "Required argument '#{name.upcase}' was not given."
117
+ end
95
118
  end
96
119
  end
97
120
  end
98
- if @report.opt[:help]
121
+ if @spec.is_variadic?
122
+ named[@spec.get_variad] ||= []
123
+ end
124
+ @report = Report.new(args, named, trailing, options, counts)
125
+ if @report.opt(:help)
99
126
  self.print_usage()
100
127
  end
101
128
  end
@@ -166,7 +193,8 @@ class Interface
166
193
  puts self.usage
167
194
  exit 0
168
195
  end
169
- end
196
+
197
+ end # class Interface
170
198
 
171
199
  end # module CLI
172
200
  end # module Ark
@@ -9,14 +9,15 @@ class Option
9
9
  # [+keys+] A list of names this option will be identified by
10
10
  # [+args+] A list of argument named this option will expect
11
11
  # [+desc+] A short description of this option
12
- def initialize(long, short=nil, args=nil, desc=nil)
13
- @long = long
14
- @short = short
15
- @args = args || []
16
- @vals = []
17
- @flag = false
18
- @count = 0
19
- @desc = desc || ''
12
+ def initialize(long, short=nil, args=nil, defaults=nil, desc=nil)
13
+ @long = long
14
+ @short = short
15
+ @args = args || []
16
+ @defaults = defaults || {}
17
+ @vals = []
18
+ @flag = false
19
+ @count = 0
20
+ @desc = desc || ''
20
21
  end
21
22
 
22
23
  # A count of how many times this option has been given on the command line.
@@ -85,7 +86,11 @@ class Option
85
86
  elsif self.full?
86
87
  return @vals
87
88
  else
88
- return nil
89
+ if !@defaults.compact.empty?
90
+ return @defaults.length > 1 ? @defaults : @defaults.first
91
+ else
92
+ return nil
93
+ end
89
94
  end
90
95
  end
91
96
  end
@@ -1,29 +1,40 @@
1
- module Ark
1
+ module Ark # :nodoc:
2
2
  module CLI
3
3
 
4
+ # Stores information parsed from the command line for later inspection
4
5
  class Report
5
- def initialize()
6
- @args = []
7
- @named_args = {}
8
- @trailing_args = []
9
- @counts = {}
10
- @options = {}
6
+ # Initialize a bare +Report+ object
7
+ def initialize(args, named, trailing, options, counts)
8
+ @args = args
9
+ @named = named
10
+ @trailing = trailing
11
+ @options = options
12
+ @counts = counts
11
13
  end
12
14
 
15
+ # Return an array of all args parsed
13
16
  def args
14
17
  return @args
15
18
  end
16
- def arg
17
- return @named_args
19
+
20
+ # Get an argument by +name+
21
+ def arg(name)
22
+ return @named[name.to_s]
18
23
  end
24
+
25
+ # Return an array of any arguments without names
19
26
  def trailing
20
- return @trailing_args
27
+ return @trailing
21
28
  end
22
- def opt
23
- return @options
29
+
30
+ # Get the value of an option by +name+
31
+ def opt(name)
32
+ return @options[name.to_s]
24
33
  end
25
- def count
26
- return @counts
34
+
35
+ # Get the toggle count for an option by +name+
36
+ def count(name)
37
+ return @counts[name.to_s]
27
38
  end
28
39
  end
29
40
 
data/lib/ark/cli/spec.rb CHANGED
@@ -1,6 +1,10 @@
1
- module Ark
1
+ module Ark # :nodoc:
2
2
  module CLI
3
3
 
4
+ # The +Spec+ class defines the properties of an interface, namely its expected
5
+ # arguments and option definitions, as well as the program name and
6
+ # description. The +Spec+ instance forms the DSL used for interface declarations
7
+ # with the methods +name+, +desc+, +args+, and +opt+.
4
8
  class Spec
5
9
 
6
10
  # Raised when a nonexistent option is received
@@ -11,7 +15,7 @@ class Spec
11
15
  class ArgumentSyntaxError < ArgumentError
12
16
  end
13
17
 
14
- # Initialize a bare interface spec
18
+ # Initialize a bare interface +Spec+
15
19
  def initialize()
16
20
  @args = []
17
21
  @options = {}
@@ -29,22 +33,28 @@ class Spec
29
33
 
30
34
  private
31
35
 
36
+ # Strip any special syntax from a given argument. Used when parsing arguments
32
37
  def strip(arg)
33
38
  return arg[/^(\S+?)(:|\.\.\.|$)/, 1]
34
39
  end
35
40
 
41
+ # Return +true+ if the given argument has a default value, like +'arg:defaultvalue'+
36
42
  def defaulted?(arg)
37
43
  return !arg[/^\S+?:.+/].nil?
38
44
  end
39
45
 
46
+ # Parse the default value from an arg with one
40
47
  def parse_default(arg)
41
48
  return arg[/^.+?:(.+)/, 1]
42
49
  end
43
50
 
51
+ # Return +true+ if the given argument is a glob, like +'arg...'+
44
52
  def variadic?(arg)
45
53
  return !arg[/\.\.\.$/].nil?
46
54
  end
47
55
 
56
+ # Parse a given argument, interpreting any special syntax, and storing
57
+ # argument information as needed
48
58
  def parse_arg(arg, default: nil, last: false)
49
59
  stripped = strip(arg)
50
60
  @args << stripped
@@ -64,55 +74,66 @@ class Spec
64
74
 
65
75
  public
66
76
 
77
+ # Get the name defined for this spec
67
78
  def get_name
68
79
  return @name
69
80
  end
70
81
 
82
+ # Get the description defined for this spec
71
83
  def get_desc
72
84
  return @desc
73
85
  end
74
86
 
87
+ # Get an array of argument names defined for this spec
75
88
  def get_args
76
89
  return @args
77
90
  end
78
91
 
92
+ # Return +true+ if this interface has any options defined for it
79
93
  def has_options?
80
94
  @options.values.uniq.length > 1
81
95
  end
82
96
 
97
+ # Get a hash of any options defined on this spec
83
98
  def get_opts
84
99
  return @options
85
100
  end
86
101
 
87
- # Get an Option object for the given option +name+
102
+ # Get an +Option+ object for the given option +name+
88
103
  def get_opt(name)
89
- name = name.to_sym
104
+ name = name.to_s
90
105
  if !@options.keys.member?(name)
91
106
  raise NoSuchOptionError, "Error, no such option: '#{name}'"
92
107
  end
93
108
  return @options[name]
94
109
  end
95
110
 
111
+ # Return +true+ if this interface is variadic
96
112
  def is_variadic?
97
113
  return @variadic
98
114
  end
99
115
 
116
+ # Return the argument name of the variadic argument
100
117
  def get_variad
101
118
  return @variad
102
119
  end
103
120
 
121
+ # Return +true+ if the given argument +arg+ has a default value
104
122
  def has_default?(arg)
105
123
  @defaults.key?(arg.to_s)
106
124
  end
107
125
 
126
+ # Return a hash of all default values
108
127
  def get_defaults
109
128
  return @defaults
110
129
  end
111
130
 
131
+ # Return the default value of the given argument +arg+
112
132
  def get_default(arg)
113
133
  @defaults[arg.to_s]
114
134
  end
115
135
 
136
+ # Return +true+ if this interface has any arguments defined
116
137
  def has_args?
117
138
  @args.length > 0
118
139
  end
@@ -143,6 +164,7 @@ class Spec
143
164
  @defaults = {}
144
165
 
145
166
  input.flatten.each_with_index do |item, i|
167
+ item = item.to_s
146
168
  last = (input.length - (i + 1)) == 0
147
169
  parse_arg(item, last: last)
148
170
  end
@@ -155,11 +177,23 @@ class Spec
155
177
  # [+args+] A list of arguments the option expects
156
178
  # [+desc+] A short description of the option, used to provide usage info
157
179
  def opt(long, short=nil, args: nil, desc: nil)
158
- long = long.to_sym
159
- short = short.to_sym if short
180
+ long = long.to_s
181
+ short = short.to_s if short
160
182
  args = [args] if args.is_a?(String)
161
- args.map!(&:to_sym) if args
162
- o = Option.new(long, short, args, desc)
183
+ defaults = []
184
+ if args
185
+ args.map! do |arg|
186
+ arg = arg.to_s
187
+ if defaulted?(arg)
188
+ defaults << parse_default(arg)
189
+ arg = strip(arg)
190
+ else
191
+ defaults << nil
192
+ end
193
+ arg
194
+ end
195
+ end
196
+ o = Option.new(long, short, args, defaults, desc)
163
197
  @options[long] = o
164
198
  @options[short] = o if short
165
199
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ark-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Macquarie Sharpless
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-07 00:00:00.000000000 Z
11
+ date: 2015-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ark-util