aargvark 0.0.14

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.
Files changed (5) hide show
  1. data/LICENSE +16 -0
  2. data/README +180 -0
  3. data/Rakefile +47 -0
  4. data/lib/aargvark.rb +284 -0
  5. metadata +61 -0
data/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ Aargvark, a simple, powerful argument parser for the Ruby programming language.
2
+ Copyright (C) 2009 Mike Zazaian
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or
7
+ (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
data/README ADDED
@@ -0,0 +1,180 @@
1
+
2
+ #=Aargvark
3
+ # Version 0.0.14
4
+ # Updated 2009-05-12
5
+ #
6
+ # Maintainer: Mike Zazaian, mike@zop.io, http://zop.io
7
+ # License: This file is placed in the public domain.
8
+ #
9
+ #
10
+ #=OVERVIEW
11
+ #
12
+ # Aargvark is a utility written in Ruby to process arguments for command-line
13
+ # scripts and applications. It allows you to define a simple structure for your
14
+ # script's arguments, then compares them against the ARGV array that's produced
15
+ # by Ruby when your script is called from a command line, such as:
16
+ #
17
+ # ruby myscript.rb -a -b -c --example-alias inputfile.txt outputfile.txt
18
+ #
19
+ #
20
+ #=INSTALL
21
+ #
22
+ # To install Aargvark, either install Aargvark as a Rubygem, like this:
23
+ #
24
+ # gem install --remote aargvark
25
+ #
26
+ # Or just put lib/aargvark.rb in your own script's lib/ directory, and add the path
27
+ # to the LOAD_PATH global like this:
28
+ #
29
+ # $LOAD_PATH << "/path/to/aargvark/directory"
30
+ #
31
+ # This assumes that /path/to/aargvark/directory is whichever directory in
32
+ # which the aargvark.rb file is located.
33
+ #
34
+ # Once you've got aargvark in place, you can import it into your script with
35
+ # *require*, such as:
36
+ #
37
+ # require 'aargbark'
38
+ #
39
+ #
40
+ #=CREATING AN AARGVARK
41
+ #
42
+ # Once you've required Aargvark into your script, you can use it catch arguments
43
+ # called from a command line like this:
44
+ #
45
+ # processed_arguments = Aargvark.new(called_arguments, argument_structure)
46
+ #
47
+ #
48
+ # There are three important parts to this equation, being:
49
+ #
50
+ #
51
+ #==*THE CALLED ARGUMENTS ARRAY* An array of arguments called by the
52
+ # script's user that are passed into the script. In this example it's intended
53
+ # to be Ruby's ARGV array, which automatically passes arguments called from the
54
+ # commandline into the Ruby script. However, "called_arguments" can be any
55
+ # array within your script that contains called arguments.
56
+ #
57
+ #==*THE ARGUMENT STRUCTURE ARRAY* This array represents the structure of how the
58
+ # script will process and recognize available and required arguments.
59
+ #
60
+ # This array contains one or more _SUB-ARRAYS_, each of which represent an argument
61
+ # that CAN or MUST be passed into the script. An example of basic _SUB-ARRAY_
62
+ # structure is:
63
+ #
64
+ # ["-a", "--alias", :required, [true, :string], [false, :integer], ...]
65
+ #
66
+ # |-a| *ARGUMENT.* Used to call the argument from the command line. Must
67
+ # be a single letter [A-Za-z] preceded by a single hyphen "-".
68
+ #
69
+ # This is the only value that MUST be included regardless of whether or
70
+ # not an ALIAS is provided. If both an ARGUMENT and an ALIAS are
71
+ # set in the structure array, only ONE of the can be called from
72
+ # the commandline when invoking the script, otherwise an error will
73
+ # be thrown.
74
+ #
75
+ # |--alias| *ALIAS.* Must be a series of uppercase, lowercase letters and
76
+ # hyphens [A-Za-z\-] preceded by two hyphens "--".
77
+ #
78
+ # Can be used in substitute of the argument to call the argument
79
+ # from the commandline, but cannot be called simultaneously with the
80
+ # argument. May be OMITTED.
81
+ #
82
+ # |:required| *REQUIREMENT.* Determines whether this argument (or its alias) is
83
+ # required to be called when running the script. This may be set as
84
+ # either :required, or OMITTED.
85
+ #
86
+ #|[true, :string]| *SUB-ARGUMENT.* The first value (true||false) indicates whether the
87
+ # sub-argument must be called along with the argument. The second
88
+ # value (:string||:integer||:float), determines what type of
89
+ # information must be passed in this place. May be OMITTED.
90
+ #
91
+ # |...| *PLACEHOLDER FOR MORE SUB-ARGUMENTS.* May be as few or as many as
92
+ # you need, or may be OMITTED.
93
+ #
94
+ # To break this down a bit, this sub-array represents ONE ARGUMENT that can be
95
+ # called with the letter "-a", OR its alias "--alias". The :required symbol after
96
+ # the alias indicates that this argument must be called when running the parent
97
+ # script. So that's the first part of the sub-array.
98
+ #
99
+ # The remaining arrays represent *SUB-ARGUMENTS*, arguments that can or must be
100
+ # called along with the primary argument. The first value in the *SUB-ARGUMENT*
101
+ # array is boolean (true||false) indicating whether or not the sub-argument is
102
+ # required, and the second value is a symbol (:string|:integer|:float) indicating
103
+ # the type of data that the subargument must contain.
104
+ #
105
+ #
106
+ #===EXAMPLES OF VALID SUB-ARRAYS
107
+ #
108
+ # An argument that is called with the letter -r that has the alias "--recursive":
109
+ #
110
+ # ["-r", "--recursive"]
111
+ #
112
+ # An argument that is called with the letter -b, that has no alias, but is required
113
+ # and has two sub-arguments that are strings and are also required.
114
+ #
115
+ # ["-b", :required, [true, :string], [true, :string]]
116
+ #
117
+ # An argument called with the letter -z that has the alias "--zip-me-up", is
118
+ # required, has one integer sub-argument that is required, and one float
119
+ # sub-argument that isn't required.
120
+ #
121
+ # ["-z", "--zip-me-up", :required, [true, :integer], [false, :float]]
122
+ #
123
+ # An argument that is only called with the letter -c, has no alias or
124
+ # sub-arguments, and is not required.
125
+ #
126
+ # ["-c"]
127
+ #
128
+ #
129
+ #===THE NO-ARGUMENT SUB-ARRAY
130
+ #
131
+ # Sometimes you may want to include an argument that isn't called with a letter or
132
+ # an alias. For this you use the [:noarg] array.
133
+ #
134
+ # The [:noarg] array, or, if it's required, the [:noarg, :required] array, can be
135
+ # included at the end of the *ARGUMENT STRUCTURE ARRAY*, after all *ARGUMENT
136
+ # SUB-ARRAYS* are called.
137
+ #
138
+ #
139
+ #===AN EXAMPLE OF A FULL ARGUMENT-STRUCTURE ARRAY
140
+ #
141
+ # Here's an example of a full *ARGUMENT-STRUCTURE ARRAY*. Note that the order of
142
+ # the sub-arrays doesn't matter ("-e" can be called after "-c"), except for the
143
+ # fact that all [:noarg] arguments must be placed at the end of the array.
144
+ #
145
+ # argument structure = []
146
+ # argument_structure << ["-a", "--alias", :required]
147
+ # argument_structure << ["-e"]
148
+ # argument_structure << ["-c", :required, [true, :string]]
149
+ # argument_structure << [:noarg, :required]
150
+ # argument_structure << [:noarg]
151
+ #
152
+ # OR
153
+ #
154
+ # argument_structure = [["-a", "--alias", :required], ["-e"], ["-c", :required, [true, :string]], [:noarg, :required], [:noarg]]
155
+ #
156
+ #
157
+ #== THE PROCESSED ARGUMENTS ARRAY
158
+ #
159
+ # The result of comparing the *CALLED ARGUMENTS ARRAY* (ARGV, etc.) against the
160
+ # *ARGUMENT STRUCTURE ARRAY* (such as the one seen above).
161
+ #
162
+ # If the *ARGUMENT-STRUCTURE ARRAY* is of the correct format, and all of the
163
+ # arguments passed in from the *CALLED ARGUMENTS ARRAY* fit that structure, this
164
+ # array will spit out a single-level array with all of the *ARGUMENT* and
165
+ # SUB-ARGUMENT values that have been passed into the script.
166
+ #
167
+ #
168
+ #===AN EXAMPLE OF A PROCESSED ARGUMENTS ARRAY
169
+ #
170
+ # Suppose you passed arguments into the script according to the *ARGUMENT-STRUCTURE
171
+ # ARRAY* seen immediately above. The resulting array, which would be identical to
172
+ # the incoming ARGV array, might look something like this:
173
+ #
174
+ # ["-a", "-c", "file_name.txt", "output_file.txt"]
175
+ #
176
+ # Note that this array contains only four values, as only four are required by the
177
+ # above *ARGUMENT-STRUCTURE ARRAY*, but this include as many as SIX values if the
178
+ # argument "-e" were called, along with a value for the second [:noarg].
179
+ #
180
+ #
@@ -0,0 +1,47 @@
1
+
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rake/rdoctask'
5
+ require 'rake/gempackagetask'
6
+
7
+ spec = Gem::Specification.new do |s|
8
+ s.name = "aargvark"
9
+ s.version = "0.0.14"
10
+ s.author = "Mike Zazaian"
11
+ s.email = "zazaian@gmail.com"
12
+ s.homepage = "aargvark.rubyforge.org"
13
+ s.platform = Gem::Platform::RUBY
14
+ s.rubyforge_project = "aargvark"
15
+
16
+ s.summary = "A simple, powerful argument parser for Ruby."
17
+ s.description = <<-EOL
18
+ Prawn is a fast, tiny, and nimble PDF generator for Ruby
19
+ EOL
20
+
21
+ s.files = %[ lib/aargvark.rb ]
22
+ s.files = Dir.glob("{lib}/**/**/*") + ["Rakefile"]
23
+ s.rdoc_options << '--title' << 'Aargvark Documentation' <<
24
+ '--main' << 'README' << '-q'
25
+ s.require_path = "lib"
26
+ s.has_rdoc = true
27
+ s.extra_rdoc_files = %w[ README LICENSE ]
28
+ end
29
+
30
+ desc "genrates documentation"
31
+ Rake::RDocTask.new do |rdoc|
32
+ rdoc.rdoc_files.include( "README", "LICENSE", "lib/" )
33
+ rdoc.main = "README"
34
+ rdoc.rdoc_dir = "doc/html"
35
+ rdoc.title = "Aargvark Documentation"
36
+ end
37
+
38
+ Rake::GemPackageTask.new(spec) do |pkg|
39
+ pkg.need_tar = true
40
+ pkg.need_zip = true
41
+ end
42
+
43
+ task :default => "pkg/#{spec.name}-#{spec.version}.gem" do
44
+ puts "Generated #{spec.name}-#{spec.version}.gem (latest version) in ./pkg directory."
45
+ end
46
+
47
+ # EOF
@@ -0,0 +1,284 @@
1
+ #!/usr/bin/ruby1.8
2
+
3
+
4
+ class Aargvark
5
+ attr_accessor :argument_pool, :letter_array, :noarg_count, :matches, :aliens
6
+
7
+ def initialize(argv, all_args)
8
+ @argv = argv
9
+ @argument_pool = []
10
+ @letter_array = []
11
+ @matches = []
12
+
13
+ all_args.each {|i| @argument_pool << Argument.new(i)}
14
+ @noarg_count = [0,0,0]
15
+ @argument_pool.each do |i|
16
+ if i.noarg
17
+ @noarg_count[0] += 1 if i.required
18
+ @noarg_count[1] += 1
19
+ end
20
+ end
21
+ get_matches
22
+ end
23
+
24
+ def get_matches
25
+ # Add all present argument letters and aliases to the letter_array array
26
+ @argument_pool.each do |arg|
27
+ @letter_array << arg.letter
28
+ if arg.alias
29
+ @letter_array << arg.alias
30
+ end
31
+ end
32
+
33
+ @argv.each do |s|
34
+ if s.is_arg? || s.is_alias?
35
+ unless @letter_array.index(s)
36
+ type = s.is_arg? ? "Argument" : "Alias"
37
+ raise ArgumentError, "#{type} #{s} was entered, but is not valid."
38
+ end
39
+ end
40
+ end
41
+
42
+ @argument_pool.each do |arg|
43
+
44
+ if arg.letter
45
+ letter_pos = @argv.index(arg.letter)
46
+ if letter_pos
47
+ subarg_pos = letter_pos + 1
48
+ end
49
+ end
50
+
51
+ if arg.alias
52
+ alias_pos = @argv.index(arg.alias)
53
+ if alias_pos
54
+ subarg_pos = alias_pos + 1
55
+ end
56
+ end
57
+
58
+ if ! letter_pos && ! alias_pos && ! arg.noarg && arg.required
59
+ error = "The use of argument \"#{arg.letter}\" "
60
+ error += arg.alias ? "or its alias \"#{arg.alias}\" are" : "is"
61
+ error += " required when running this script.\nPlease make sure that "
62
+ error += arg.alias ? "either of these are" : "this is"
63
+ error += " called when running the script from the commandline."
64
+
65
+ raise ArgumentError, error
66
+ end
67
+
68
+ #need script to input the values for the :noarg arguments based on the end of
69
+ #the sub-arguments for the last argument in the argv array
70
+ if arg.noarg
71
+ last_arg = @argv.collect {|e| e.scan(/^-[a-z]$|^--[a-z\-]+$/)}.flatten.pop
72
+ arg_obj = spit_argument(last_arg)
73
+ last_arg_pos = @argv.rindex(last_arg)
74
+ diff = @argv.size - last_arg_pos
75
+ end
76
+
77
+ if letter_pos || alias_pos
78
+ if @argv.rindex(arg.letter) != letter_pos || @argv.rindex(arg.alias) != alias_pos
79
+ raise ArgumentError, "Argument \"#{arg.letter}\" was called twice from the commandline. "+
80
+ "Each argument should only be called once."
81
+ end
82
+
83
+ # Raise an error if both an argument and its alias are called from the
84
+ # command line
85
+ if letter_pos && alias_pos
86
+ raise ArgumentError, "Argument \"#{arg.letter}\" and alias \"#{arg.alias}\" were both" +
87
+ " called from the command line. Please use only the letter" +
88
+ " argument or the alias, not both."
89
+ end
90
+
91
+ alien_pos = subarg_pos
92
+ alien_count = 0
93
+ if @argv[alien_pos] != nil
94
+ while ! @argv[alien_pos].is_arg? && ! @argv[alien_pos].is_alias?
95
+ argv_diff = @argv.size - alien_pos
96
+ break if @noarg_count[0] <= argv_diff && argv_diff <= @noarg_count[1]
97
+ alien_pos += 1
98
+ alien_count += 1
99
+ break if ! @argv[alien_pos]
100
+ end
101
+ end
102
+
103
+ min = arg.subarg_range[0]
104
+ max = arg.subarg_range[1]
105
+ if alien_count < min || max < alien_count
106
+ error = "#{alien_count} sub-arguments have been given for argument #{arg.letter}.\n" +
107
+ "The current parameters for #{arg.letter} specify that you use "
108
+ error += min == max ? "exactly #{min}" : "between #{min} and #{max}"
109
+ error += " sub-arguments. \nPlease double-check your " +
110
+ "input array and ensure the correct number of sub-arguments."
111
+
112
+ raise ArgumentError, error
113
+ end
114
+
115
+ @matches << arg.letter
116
+ if arg.sub_args
117
+ arg.sub_args.each do |subarg_array|
118
+ required = subarg_array[0]
119
+ type = subarg_array[1]
120
+ if required == false
121
+ if @argv[subarg_pos].class.to_s == type.to_s.capitalize && @letter_array.index(@argv[subarg_pos]) == nil
122
+ @matches << @argv[subarg_pos]
123
+ end
124
+ elsif required == true
125
+ if @argv[subarg_pos].class.to_s == type.to_s.capitalize && @letter_array.index(@argv[subarg_pos]) == nil
126
+ @matches << @argv[subarg_pos]
127
+ else
128
+ raise ArgumentError, "\"#{@argv[subarg_pos]}\" is not a valid sub-argument for argument #{arg.letter}.\n" +
129
+ "A valid sub-argument of type #{type.to_s.capitalize} must be entered in this position."
130
+ end
131
+ end
132
+ subarg_pos += 1
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ def spit_argument(in_arg)
140
+ if ! in_arg.is_arg? && ! in_arg.is_alias?
141
+ raise ArgumentError, "#{in_arg} is not a valid argument request for spit_argument. The \"letter\" " +
142
+ "variable should be either an argument or an alias."
143
+ end
144
+ @argument_pool.each do |a|
145
+ return a if a.letter == in_arg || a.alias == in_arg
146
+ end
147
+ end
148
+
149
+ def matches
150
+ puts @matches
151
+ end
152
+
153
+ class Argument
154
+ attr_accessor :letter, :noarg, :alias, :required, :sub_args, :subarg_range
155
+
156
+ def initialize (arg_array)
157
+ @sub_args = []
158
+ @subarg_range = [0,0]
159
+
160
+ if arg_array.class != Array
161
+ if arg_array.class == String
162
+ if arg_array.is_arg?
163
+ @letter = arg_array
164
+ end
165
+ else
166
+ raise ArgumentError, "\"#{arg_array}\" is not a valid argument. Arguments and the details" +
167
+ " thereof must be entered as an Array in the format:" +
168
+ "[\"-n\", \"--argument-alias\", [true/false, :string/:integer/:float], etc...]"
169
+ end
170
+ else
171
+ if arg_array[0].is_arg?
172
+ @letter = arg_array[0]
173
+ elsif arg_array[0].is_noarg?
174
+ @noarg = true
175
+ else
176
+ raise ArgumentError, "The first item in each Argument array must be either a lowercase letter preceded by" +
177
+ " a hyphen or the symbol :noarg. Please go back and make sure that your argument arrays conform to" +
178
+ " these standards."
179
+ end
180
+ end
181
+
182
+ if arg_array.size > 1
183
+
184
+ #If the second item in an argument array is an alias, set the alias for the
185
+ #argument as that value.
186
+ if arg_array[1].is_alias?
187
+ @alias = arg_array[1]
188
+ end
189
+
190
+ if arg_array[1] == :required || arg_array[2] == :required
191
+ @required = true
192
+ else
193
+ @required = false
194
+ end
195
+
196
+ first_subarg = 1
197
+ if @alias
198
+ first_subarg += 1
199
+ end
200
+
201
+ if @required
202
+ first_subarg += 1
203
+ end
204
+
205
+ first_subarg.upto(arg_array.size - 1) do |x|
206
+ if arg_array[x].is_subarg?
207
+ @sub_args << arg_array[x]
208
+ end
209
+ end
210
+ end
211
+
212
+ @sub_args.each do |subarg|
213
+ @subarg_range[0] += 1 if subarg.to_s == "true"
214
+ @subarg_range[1] += 1
215
+ end
216
+
217
+ end
218
+ end
219
+ end
220
+
221
+
222
+ class String
223
+
224
+ def is_arg?
225
+ match(/^-[A-Za-z{1}]$/)
226
+ end
227
+
228
+ def is_alias?
229
+ match(/^--[A-Za-z\-]+$/)
230
+ end
231
+
232
+ def is_noarg?
233
+ return false
234
+ end
235
+
236
+ end
237
+
238
+ class Symbol
239
+
240
+ def is_arg?
241
+ return false
242
+ end
243
+
244
+ def is_alias?
245
+ return false
246
+ end
247
+
248
+ def is_noarg?
249
+ return self == :noarg ? true : false
250
+ end
251
+
252
+ end
253
+
254
+
255
+ public
256
+ def is_subarg?(throw_errors = true)
257
+ if self.class != Array
258
+ return false
259
+ if throw_errors
260
+ raise ArgumentError, "Sub-arguments must be entered as an array, in the format:"
261
+ + "[true/false, :string/:integer/:float]"
262
+ end
263
+ else
264
+ has_true_false = self[0].to_s.match(/^true|false$/)
265
+ result = self[1].to_s.match(/^string|integer|float$/)
266
+ has_subarg_type = result && self[1].class == Symbol ? true : false
267
+ if ! has_true_false
268
+ return false
269
+ if throw_errors
270
+ raise ArgumentError, "The first value in each sub-argument array must be either 'true' or 'false'"
271
+ end
272
+ elsif ! has_subarg_type
273
+ return false
274
+ if throw_errors
275
+ raise ArgumentError, "The second value in each sub-argument array must be either :string, :integer or :float"
276
+ end
277
+ else
278
+ return true
279
+ end
280
+ end
281
+ end
282
+
283
+
284
+
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aargvark
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.14
5
+ platform: ruby
6
+ authors:
7
+ - Mike Zazaian
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-20 00:00:00 +10:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Prawn is a fast, tiny, and nimble PDF generator for Ruby
17
+ email: zazaian@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - LICENSE
25
+ files:
26
+ - lib/aargvark.rb
27
+ - Rakefile
28
+ - README
29
+ - LICENSE
30
+ has_rdoc: true
31
+ homepage: aargvark.rubyforge.org
32
+ post_install_message:
33
+ rdoc_options:
34
+ - --title
35
+ - Aargvark Documentation
36
+ - --main
37
+ - README
38
+ - -q
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project: aargvark
56
+ rubygems_version: 1.2.0
57
+ signing_key:
58
+ specification_version: 2
59
+ summary: A simple, powerful argument parser for Ruby.
60
+ test_files: []
61
+