ark-cli 0.5.0 → 0.6.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.
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