aargvark 0.0.14

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