ragol 0.0.3
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.
- data/lib/ragol/args.rb +77 -0
- data/lib/ragol/argslist.rb +60 -0
- data/lib/ragol/boolean_option.rb +15 -0
- data/lib/ragol/doc.rb +79 -0
- data/lib/ragol/exception.rb +7 -0
- data/lib/ragol/fixnum_option.rb +19 -0
- data/lib/ragol/float_option.rb +19 -0
- data/lib/ragol/hash.rb +16 -0
- data/lib/ragol/matcher.rb +48 -0
- data/lib/ragol/matchers.rb +64 -0
- data/lib/ragol/option.rb +168 -0
- data/lib/ragol/optproc/optproc.rb +4 -0
- data/lib/ragol/optproc/optset.rb +19 -0
- data/lib/ragol/optset.rb +197 -0
- data/lib/ragol/regexp_option.rb +17 -0
- data/lib/ragol/results.rb +69 -0
- data/lib/ragol/string_option.rb +14 -0
- data/lib/ragol/synoption/args.rb +26 -0
- data/lib/ragol/synoption/boolean_option.rb +22 -0
- data/lib/ragol/synoption/fixnum_option.rb +12 -0
- data/lib/ragol/synoption/float_option.rb +12 -0
- data/lib/ragol/synoption/option.rb +27 -0
- data/lib/ragol/synoption/optset.rb +9 -0
- metadata +83 -0
data/lib/ragol/args.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'ragol/hash'
|
5
|
+
|
6
|
+
module Ragol
|
7
|
+
class OptionArguments < Hash
|
8
|
+
VAR_TYPES = {
|
9
|
+
:boolean => :boolean,
|
10
|
+
:string => :string,
|
11
|
+
:float => :float,
|
12
|
+
:integer => :fixnum,
|
13
|
+
:fixnum => :fixnum,
|
14
|
+
:regexp => :regexp,
|
15
|
+
}
|
16
|
+
|
17
|
+
OLD_OPTIONS = {
|
18
|
+
:regexps => [ Regexp.new('--fo+'), Regexp.new('--ba*r') ],
|
19
|
+
:tags => [ '--foo', '-b' ],
|
20
|
+
:arg => [ [ :boolean, :string, :float, :integer, :fixnum, :regexp ], [ :optional, :required, :none ] ],
|
21
|
+
:set => Proc.new { },
|
22
|
+
:rcnames => [ "foo" ],
|
23
|
+
:rc => [ ]
|
24
|
+
}
|
25
|
+
|
26
|
+
NEW_OPTIONS = {
|
27
|
+
:regexps => [ Regexp.new('--fo+'), Regexp.new('--ba*r') ],
|
28
|
+
:tags => [ '--foo', '-b' ],
|
29
|
+
:rcnames => [ 'foo', 'foobar' ],
|
30
|
+
:takesvalue => [ true, :optional, false ],
|
31
|
+
:valuetype => [ :boolean, :string, :float, :integer, :fixnum, :regexp ],
|
32
|
+
:valueregexp => Regexp.new('(one|two|three)'),
|
33
|
+
:default => nil,
|
34
|
+
:process => Proc.new { |val| },
|
35
|
+
:postproc => Proc.new { |optset, results, unprocessed| },
|
36
|
+
:description => "a description"
|
37
|
+
}
|
38
|
+
|
39
|
+
def initialize origargs = Hash.new
|
40
|
+
super()
|
41
|
+
|
42
|
+
if origargs[:arg]
|
43
|
+
if re = origargs[:arg].find { |x| x.kind_of?(Regexp) }
|
44
|
+
self[:valueregexp] = re
|
45
|
+
self[:valuetype] = :regexp
|
46
|
+
else
|
47
|
+
self[:valuetype] = Ragol::HashUtil.hash_array_value VAR_TYPES, origargs[:arg]
|
48
|
+
end
|
49
|
+
|
50
|
+
self[:takesvalue] = if self[:valuetype] == :boolean
|
51
|
+
false
|
52
|
+
else
|
53
|
+
hasvaluetype = self[:valuetype] != nil
|
54
|
+
takes = { :optional => :optional, :required => true, :none => hasvaluetype, nil => hasvaluetype }
|
55
|
+
Ragol::HashUtil.hash_array_value takes, origargs[:arg]
|
56
|
+
end
|
57
|
+
else
|
58
|
+
Ragol::HashUtil.copy_hash self, origargs, [ [ :takesvalue, :valuereq ], [ :valuetype ], [ :valueregexp ] ]
|
59
|
+
if self[:valuetype]
|
60
|
+
self[:takesvalue] ||= true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
fields = [
|
65
|
+
[ :regexps, :regexp, :res, :re ],
|
66
|
+
[ :tags ],
|
67
|
+
[ :process, :set ],
|
68
|
+
[ :postproc ],
|
69
|
+
[ :rcnames, :rcname, :rc ],
|
70
|
+
[ :default ],
|
71
|
+
[ :unsets, :unset ],
|
72
|
+
[ :description ],
|
73
|
+
]
|
74
|
+
Ragol::HashUtil.copy_hash self, origargs, fields
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
module Ragol
|
5
|
+
class ArgsList
|
6
|
+
attr_accessor :args
|
7
|
+
|
8
|
+
def initialize args = Array.new
|
9
|
+
@args = args
|
10
|
+
end
|
11
|
+
|
12
|
+
def next_arg
|
13
|
+
curr = @args.shift
|
14
|
+
re = Regexp.new('^- (?:(\d+)(\D+) | ([a-zA-Z])(\w+) )', Regexp::EXTENDED)
|
15
|
+
|
16
|
+
if md = re.match(curr)
|
17
|
+
mi = md[1] ? 1 : 3
|
18
|
+
arg, newarg = ('-' + md[mi]), ('-' + md[mi + 1])
|
19
|
+
@args.unshift newarg
|
20
|
+
arg
|
21
|
+
else
|
22
|
+
curr
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def shift_arg
|
27
|
+
@args.shift
|
28
|
+
end
|
29
|
+
|
30
|
+
def args_empty?
|
31
|
+
@args.empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
def empty?
|
35
|
+
@args.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
def current_arg
|
39
|
+
curr = @args[0]
|
40
|
+
re = Regexp.new('^-(?:\d+|\w)')
|
41
|
+
if md = re.match(curr)
|
42
|
+
md[0]
|
43
|
+
else
|
44
|
+
curr
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def eql? args
|
49
|
+
@args == args
|
50
|
+
end
|
51
|
+
|
52
|
+
def [] idx
|
53
|
+
@args[idx]
|
54
|
+
end
|
55
|
+
|
56
|
+
def end_of_options?
|
57
|
+
current_arg == '--'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'ragol/option'
|
5
|
+
|
6
|
+
module Ragol
|
7
|
+
# a boolean option maps to a single tag, not a tag and value. For example,
|
8
|
+
# "-v" (verbose) is a boolean option, but "-r 3444" (revision) is a option
|
9
|
+
# with a value.
|
10
|
+
class BooleanOption < Option
|
11
|
+
def takes_value?
|
12
|
+
false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/ragol/doc.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'logue/loggable'
|
5
|
+
|
6
|
+
module Ragol
|
7
|
+
# documentation for an option.
|
8
|
+
class Doc
|
9
|
+
include Logue::Loggable
|
10
|
+
|
11
|
+
def initialize option
|
12
|
+
@option = option
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_doc_tag
|
16
|
+
tags = @option.matchers.tags.elements
|
17
|
+
longopts, shortopts = tags.partition { |tag| tag[0 .. 1] == '--' }
|
18
|
+
tagline = [ shortopts, longopts ].flatten.join ', '
|
19
|
+
if @option.takes_value?
|
20
|
+
tagline << " ARG"
|
21
|
+
end
|
22
|
+
tagline
|
23
|
+
end
|
24
|
+
|
25
|
+
# returns an option regexp as a 'cleaner' string
|
26
|
+
def re_to_string re
|
27
|
+
re.source.gsub(%r{\\d\+?}, 'N').gsub(%r{[\^\?\$\\\(\)]}, '')
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_doc_negate
|
31
|
+
doc = nil
|
32
|
+
@option.matchers.negatives.elements.each do |neg|
|
33
|
+
str = if neg.kind_of? Regexp
|
34
|
+
str = re_to_string neg
|
35
|
+
else
|
36
|
+
str = neg
|
37
|
+
end
|
38
|
+
|
39
|
+
if doc
|
40
|
+
doc << " [#{str}]"
|
41
|
+
else
|
42
|
+
doc = str
|
43
|
+
end
|
44
|
+
end
|
45
|
+
doc
|
46
|
+
end
|
47
|
+
|
48
|
+
# -g [--use-merge-history] : use/display additional information from merge
|
49
|
+
# 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
50
|
+
# 0 1 2 3 4 5 6
|
51
|
+
|
52
|
+
def to_doc_line lhs, rhs, sep = ""
|
53
|
+
fmt = " %-24s %1s %s"
|
54
|
+
sprintf fmt, lhs, sep, rhs
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_doc io
|
58
|
+
# wrap optdesc?
|
59
|
+
|
60
|
+
[ @option.description ].flatten.each_with_index do |descline, idx|
|
61
|
+
lhs = idx == 0 ? to_doc_tag : ""
|
62
|
+
io.puts to_doc_line lhs, descline, idx == 0 ? ":" : ""
|
63
|
+
end
|
64
|
+
|
65
|
+
if defval = @option.default
|
66
|
+
io.puts to_doc_line "", " default: #{defval}"
|
67
|
+
end
|
68
|
+
|
69
|
+
if re = @option.matchers.regexps
|
70
|
+
io.puts to_doc_line re_to_string(re), "same as above", ":"
|
71
|
+
end
|
72
|
+
|
73
|
+
if @option.matchers.negatives
|
74
|
+
lhs = to_doc_negate
|
75
|
+
io.puts to_doc_line lhs, "", ""
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'ragol/option'
|
5
|
+
|
6
|
+
module Ragol
|
7
|
+
class FixnumOption < Option
|
8
|
+
REGEXP = Regexp.new '^ ([\-\+]?\d+) $ ', Regexp::EXTENDED
|
9
|
+
|
10
|
+
def value_regexp
|
11
|
+
REGEXP
|
12
|
+
end
|
13
|
+
|
14
|
+
def convert md
|
15
|
+
return unless val = md && md[-1]
|
16
|
+
val.to_i
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'ragol/option'
|
5
|
+
|
6
|
+
module Ragol
|
7
|
+
class FloatOption < Option
|
8
|
+
REGEXP = Regexp.new '^ ([\-\+]?\d* (?:\.\d+)?) $ ', Regexp::EXTENDED
|
9
|
+
|
10
|
+
def value_regexp
|
11
|
+
REGEXP
|
12
|
+
end
|
13
|
+
|
14
|
+
def convert md
|
15
|
+
return unless val = md && md[-1]
|
16
|
+
val.to_f
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/ragol/hash.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
module Ragol
|
5
|
+
module HashUtil
|
6
|
+
def self.copy_hash to_hash, from_hash, fields = Array.new
|
7
|
+
fields.each do |fieldnames|
|
8
|
+
to_hash[fieldnames.first] = from_hash[fieldnames.find { |x| from_hash[x] }]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.hash_array_value hash, array
|
13
|
+
hash[(array & hash.keys)[0]]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'logue/loggable'
|
5
|
+
|
6
|
+
module Ragol
|
7
|
+
class Matcher
|
8
|
+
include Logue::Loggable
|
9
|
+
|
10
|
+
attr_reader :elements
|
11
|
+
|
12
|
+
def initialize tags
|
13
|
+
@elements = [ tags ].flatten.compact
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_match opt
|
17
|
+
tag = opt.split('=', 2)[0] || opt
|
18
|
+
|
19
|
+
@elements.each do |elmt|
|
20
|
+
if elmt.kind_of?(Regexp)
|
21
|
+
if md = elmt.match(tag)
|
22
|
+
return [ :regexp, md ]
|
23
|
+
end
|
24
|
+
elsif tag.length > elmt.length
|
25
|
+
next
|
26
|
+
elsif elmt.index(tag) == 0
|
27
|
+
score = tag.length == elmt.length ? 1.0 : tag.length * 0.01
|
28
|
+
return [ :string, score ]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def match? opt
|
35
|
+
type, val = find_match(opt)
|
36
|
+
type && val
|
37
|
+
end
|
38
|
+
|
39
|
+
def score opt
|
40
|
+
type, val = find_match(opt)
|
41
|
+
type && (type == :regexp ? 1.0 : val)
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_s
|
45
|
+
@elements.join(', ')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'logue/loggable'
|
5
|
+
require 'ragol/matcher'
|
6
|
+
|
7
|
+
module Ragol
|
8
|
+
class Matchers
|
9
|
+
include Logue::Loggable
|
10
|
+
|
11
|
+
attr_reader :tags
|
12
|
+
attr_reader :negatives
|
13
|
+
attr_reader :regexps
|
14
|
+
|
15
|
+
def initialize tags, negate, regexp
|
16
|
+
@tags = tags
|
17
|
+
@negatives = negate
|
18
|
+
@regexps = regexp
|
19
|
+
end
|
20
|
+
|
21
|
+
def tag_match? arg
|
22
|
+
@tags and @tags.match? arg
|
23
|
+
end
|
24
|
+
|
25
|
+
def negative_match? arg
|
26
|
+
@negatives and @negatives.match? arg
|
27
|
+
end
|
28
|
+
|
29
|
+
def regexp_match? arg
|
30
|
+
@regexps and @regexps.match? arg
|
31
|
+
end
|
32
|
+
|
33
|
+
def match_type? arg
|
34
|
+
case
|
35
|
+
when tm = tag_match?(arg)
|
36
|
+
[ :tag_match, tm ]
|
37
|
+
when nm = negative_match?(arg)
|
38
|
+
[ :negative_match, nm ]
|
39
|
+
when rm = regexp_match?(arg)
|
40
|
+
[ :regexp_match, rm ]
|
41
|
+
else
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def name
|
47
|
+
@name ||= begin
|
48
|
+
if @tags
|
49
|
+
if longtag = @tags.elements.find { |t| t[0, 2] == '--' }
|
50
|
+
longtag.sub(%r{^--}, '')
|
51
|
+
else
|
52
|
+
@tags.elements[0][1 .. -1]
|
53
|
+
end
|
54
|
+
elsif @regexps
|
55
|
+
@regexps.elements[0].to_s
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
[ @tags, @regexps ].compact.collect { |x| x.to_s }.join(' ')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/ragol/option.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'logue/loggable'
|
5
|
+
require 'ragol/matcher'
|
6
|
+
require 'ragol/matchers'
|
7
|
+
require 'ragol/doc'
|
8
|
+
|
9
|
+
module Ragol
|
10
|
+
class Option
|
11
|
+
include Logue::Loggable
|
12
|
+
|
13
|
+
attr_reader :matchers
|
14
|
+
|
15
|
+
attr_accessor :name
|
16
|
+
attr_accessor :default
|
17
|
+
attr_accessor :description
|
18
|
+
attr_accessor :tags
|
19
|
+
attr_accessor :negates
|
20
|
+
attr_accessor :regexps
|
21
|
+
|
22
|
+
def initialize options = Hash.new, &blk
|
23
|
+
@tags = nil
|
24
|
+
@negates = nil
|
25
|
+
@regexps = nil
|
26
|
+
@name = nil
|
27
|
+
@default = nil
|
28
|
+
@unsets = nil
|
29
|
+
@process = nil
|
30
|
+
@takesvalue = nil
|
31
|
+
@rcnames = nil
|
32
|
+
@description = nil
|
33
|
+
|
34
|
+
if blk
|
35
|
+
blk.call self
|
36
|
+
end
|
37
|
+
|
38
|
+
tagsmatch = to_matcher(@tags || options[:tags])
|
39
|
+
negatesmatch = to_matcher(@negates || options[:negates])
|
40
|
+
regexpsmatch = to_matcher(@regexps || options[:regexps])
|
41
|
+
|
42
|
+
@matchers = Ragol::Matchers.new tagsmatch, negatesmatch, regexpsmatch
|
43
|
+
|
44
|
+
@name ||= options[:name] || @matchers.name
|
45
|
+
|
46
|
+
@default ||= options[:default]
|
47
|
+
@unsets ||= options[:unsets]
|
48
|
+
@process ||= options[:process]
|
49
|
+
@takesvalue ||= options[:takesvalue]
|
50
|
+
@rcnames ||= [ options[:rcnames] ].flatten
|
51
|
+
@description ||= options[:description]
|
52
|
+
end
|
53
|
+
|
54
|
+
def match_rc? field
|
55
|
+
@rcnames.include?(field)
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_matcher elements
|
59
|
+
elements && Ragol::Matcher.new(elements)
|
60
|
+
end
|
61
|
+
|
62
|
+
def takes_value?
|
63
|
+
@takesvalue
|
64
|
+
end
|
65
|
+
|
66
|
+
def post_process option_set, results, unprocessed
|
67
|
+
resolve_value option_set, results, unprocessed
|
68
|
+
|
69
|
+
if @unsets
|
70
|
+
option_set.unset results, @unsets
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def resolve_value option_set, results, unprocessed
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_s
|
78
|
+
@matchers.to_s
|
79
|
+
end
|
80
|
+
|
81
|
+
def value_regexp
|
82
|
+
end
|
83
|
+
|
84
|
+
def convert md
|
85
|
+
md.kind_of?(MatchData) ? md[-1] : md
|
86
|
+
end
|
87
|
+
|
88
|
+
def do_match val
|
89
|
+
if valuere = value_regexp
|
90
|
+
unless md = valuere.match(val)
|
91
|
+
raise "invalid argument '#{val}' for option: #{self}"
|
92
|
+
end
|
93
|
+
md
|
94
|
+
else
|
95
|
+
val
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def take_eq_value opt
|
100
|
+
val = opt.split('=', 2)[1]
|
101
|
+
val && do_match(val)
|
102
|
+
end
|
103
|
+
|
104
|
+
def argument_missing
|
105
|
+
if takes_value? == true
|
106
|
+
raise "value expected for option: #{self}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def match_next_value_required results
|
111
|
+
val = results.shift_arg
|
112
|
+
val && do_match(val)
|
113
|
+
end
|
114
|
+
|
115
|
+
def match_next_value_optional results
|
116
|
+
return unless val = results.current_arg
|
117
|
+
return true if val[0] == '-'
|
118
|
+
return results.shift_arg unless valuere = value_regexp
|
119
|
+
|
120
|
+
if md = valuere.match(results.current_arg)
|
121
|
+
results.shift_arg
|
122
|
+
md
|
123
|
+
else
|
124
|
+
true
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def match_next_value results
|
129
|
+
if takes_value? == true
|
130
|
+
match_next_value_required results
|
131
|
+
else
|
132
|
+
match_next_value_optional results
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def set_value_for_tag results, arg
|
137
|
+
md = if takes_value?
|
138
|
+
take_eq_value(arg) || match_next_value(results) || argument_missing
|
139
|
+
else
|
140
|
+
true
|
141
|
+
end
|
142
|
+
set_option_value md, arg, results
|
143
|
+
end
|
144
|
+
|
145
|
+
def set_value_negative results, arg
|
146
|
+
set_option_value false, arg, results
|
147
|
+
end
|
148
|
+
|
149
|
+
def set_value_regexp results, arg
|
150
|
+
md = @matchers.regexp_match? arg
|
151
|
+
set_option_value md, arg, results
|
152
|
+
end
|
153
|
+
|
154
|
+
def set_option_value md, arg, results
|
155
|
+
value = md == true ? true : convert(md)
|
156
|
+
if @process
|
157
|
+
setargs = [ value, arg, results.unprocessed ][0 ... @process.arity]
|
158
|
+
@process.call(*setargs)
|
159
|
+
end
|
160
|
+
results.set_value name, value
|
161
|
+
end
|
162
|
+
|
163
|
+
def to_doc io
|
164
|
+
doc = Ragol::Doc.new self
|
165
|
+
doc.to_doc io
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'ragol/optset'
|
5
|
+
|
6
|
+
module OptProc
|
7
|
+
class OptionSet < Ragol::OptionSet
|
8
|
+
include Logue::Loggable
|
9
|
+
|
10
|
+
def initialize data
|
11
|
+
super :data => data
|
12
|
+
end
|
13
|
+
|
14
|
+
# this is a legacy method; process should be used instead.
|
15
|
+
def process_option argslist
|
16
|
+
set_option argslist
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/ragol/optset.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'logue/loggable'
|
5
|
+
require 'ragol/results'
|
6
|
+
require 'ragol/exception'
|
7
|
+
require 'ragol/args'
|
8
|
+
|
9
|
+
module Ragol
|
10
|
+
class OptionSet
|
11
|
+
include Logue::Loggable
|
12
|
+
|
13
|
+
# maps from an OptionSet class to the valid options for that class.
|
14
|
+
@@options_for_class = Hash.new { |h, k| h[k] = Array.new }
|
15
|
+
|
16
|
+
def self.has_option optcls, optargs = Hash.new
|
17
|
+
@@options_for_class[self] << { :class => optcls, :args => optargs }
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.options_for_class cls
|
21
|
+
@@options_for_class[cls]
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :options
|
25
|
+
|
26
|
+
def initialize(*options)
|
27
|
+
# puts "options: #{options.inspect}"
|
28
|
+
if options[0] && options[0].kind_of?(Hash)
|
29
|
+
data = options[0][:data]
|
30
|
+
options = data.collect do |optdata|
|
31
|
+
optargs = OptionArguments.new(optdata)
|
32
|
+
|
33
|
+
opttype = optargs[:valuetype]
|
34
|
+
clstype = OptionArguments::VAR_TYPES[opttype]
|
35
|
+
|
36
|
+
if clstype
|
37
|
+
clsstr = clstype.to_s
|
38
|
+
require 'ragol/' + clsstr + '_option'
|
39
|
+
clssym = (clsstr.capitalize + 'Option').to_sym
|
40
|
+
optcls = ::Ragol.const_get(clssym)
|
41
|
+
optcls.new(optargs)
|
42
|
+
else
|
43
|
+
Ragol::Option.new(optargs)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
@options = options
|
49
|
+
|
50
|
+
cls = self.class
|
51
|
+
while cls <= OptionSet
|
52
|
+
opts = self.class.options_for_class(cls)
|
53
|
+
|
54
|
+
opts.each do |option|
|
55
|
+
args = option[:args]
|
56
|
+
opt = option[:class].new(*args)
|
57
|
+
|
58
|
+
add opt
|
59
|
+
end
|
60
|
+
|
61
|
+
cls = cls.superclass
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def name
|
66
|
+
@name ||= self.class.to_s.sub(%r{.*?(\w+)OptionSet}, '\1').downcase
|
67
|
+
end
|
68
|
+
|
69
|
+
def inspect
|
70
|
+
@options.collect { |opt| opt.inspect }.join("\n")
|
71
|
+
end
|
72
|
+
|
73
|
+
def find_by_name name
|
74
|
+
@options.find { |opt| opt.name == name }
|
75
|
+
end
|
76
|
+
|
77
|
+
def << option
|
78
|
+
add option
|
79
|
+
end
|
80
|
+
|
81
|
+
def add option
|
82
|
+
@options << option
|
83
|
+
option
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_best_match results
|
87
|
+
tag_matches = Hash.new { |h, k| h[k] = Array.new }
|
88
|
+
negative_match = nil
|
89
|
+
regexp_match = nil
|
90
|
+
|
91
|
+
options.each do |opt|
|
92
|
+
if mt = opt.matchers.match_type?(results.current_arg)
|
93
|
+
case mt[0]
|
94
|
+
when :tag_match
|
95
|
+
tag_matches[mt[1]] << opt
|
96
|
+
when :negative_match
|
97
|
+
negative_match = opt
|
98
|
+
when :regexp_match
|
99
|
+
regexp_match = opt
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if tag_matches.keys.any?
|
105
|
+
highest = tag_matches.keys.sort[-1]
|
106
|
+
opts = tag_matches[highest]
|
107
|
+
if opts.size > 1
|
108
|
+
optstr = opts.collect { |opt| '(' + opt.to_s + ')' }.join(', ')
|
109
|
+
raise "ambiguous match of '#{results.current_arg}'; matches options: #{optstr}"
|
110
|
+
end
|
111
|
+
[ :tag_match, opts.first ]
|
112
|
+
elsif negative_match
|
113
|
+
[ :negative_match, negative_match ]
|
114
|
+
elsif regexp_match
|
115
|
+
[ :regexp_match, regexp_match ]
|
116
|
+
else
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def find_matching_option results
|
122
|
+
type, opt = get_best_match(results)
|
123
|
+
|
124
|
+
unless type
|
125
|
+
raise OptionException.new "#{name}: invalid option '#{results.current_arg}'"
|
126
|
+
end
|
127
|
+
|
128
|
+
[ type, opt ]
|
129
|
+
end
|
130
|
+
|
131
|
+
def set_option results
|
132
|
+
type, opt = find_matching_option(results)
|
133
|
+
|
134
|
+
case type
|
135
|
+
when :tag_match
|
136
|
+
arg = results.next_arg
|
137
|
+
opt.set_value_for_tag results, arg
|
138
|
+
when :negative_match
|
139
|
+
arg = results.next_arg
|
140
|
+
opt.set_value_negative results, arg
|
141
|
+
when :regexp_match
|
142
|
+
arg = results.next_arg
|
143
|
+
opt.set_value_regexp results, arg
|
144
|
+
end
|
145
|
+
|
146
|
+
opt
|
147
|
+
end
|
148
|
+
|
149
|
+
def process args, results = Ragol::Results.new(options, args)
|
150
|
+
options_processed = Array.new
|
151
|
+
|
152
|
+
while !results.args_empty?
|
153
|
+
if results.end_of_options?
|
154
|
+
results.shift_arg
|
155
|
+
break
|
156
|
+
elsif results.current_arg[0] != '-'
|
157
|
+
break
|
158
|
+
end
|
159
|
+
|
160
|
+
option = set_option(results)
|
161
|
+
if option
|
162
|
+
options_processed << option
|
163
|
+
else
|
164
|
+
break
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
options_processed.each do |opt|
|
169
|
+
opt.post_process self, results, results.args
|
170
|
+
end
|
171
|
+
|
172
|
+
results
|
173
|
+
end
|
174
|
+
|
175
|
+
def unset results, key
|
176
|
+
if opt = find_by_name(key)
|
177
|
+
results.unset_value opt.name
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def read_rclines lines, results = Ragol::Results.new(options, nil)
|
182
|
+
options_processed = Array.new
|
183
|
+
|
184
|
+
lines.each do |line|
|
185
|
+
line.sub!(%r{\#.*}, '')
|
186
|
+
next if line.empty?
|
187
|
+
name, val = line.split(%r{\s*:\s*})
|
188
|
+
opt = @options.detect { |op| op.match_rc? name }
|
189
|
+
if opt
|
190
|
+
opt.set_option_value val, name, results
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
results
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'logue/loggable'
|
5
|
+
require 'ragol/option'
|
6
|
+
require 'ragol/argslist'
|
7
|
+
|
8
|
+
module Ragol
|
9
|
+
class Results
|
10
|
+
include Logue::Loggable
|
11
|
+
|
12
|
+
attr_reader :options
|
13
|
+
|
14
|
+
def initialize options, args = Array.new
|
15
|
+
@argslist = Ragol::ArgsList.new(args)
|
16
|
+
@values = Hash.new
|
17
|
+
|
18
|
+
options.each do |option|
|
19
|
+
@values[option.name] = option.default
|
20
|
+
|
21
|
+
define_singleton_method option.name do
|
22
|
+
instance_eval do
|
23
|
+
@values[option.name]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def value optname
|
30
|
+
@values[optname]
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_value optname, value
|
34
|
+
@values[optname] = value
|
35
|
+
end
|
36
|
+
|
37
|
+
def unset_value optname
|
38
|
+
@values.delete optname
|
39
|
+
end
|
40
|
+
|
41
|
+
def unprocessed
|
42
|
+
@argslist
|
43
|
+
end
|
44
|
+
|
45
|
+
def end_of_options?
|
46
|
+
@argslist.end_of_options?
|
47
|
+
end
|
48
|
+
|
49
|
+
def args
|
50
|
+
@argslist.args
|
51
|
+
end
|
52
|
+
|
53
|
+
def next_arg
|
54
|
+
@argslist.next_arg
|
55
|
+
end
|
56
|
+
|
57
|
+
def shift_arg
|
58
|
+
@argslist.shift_arg
|
59
|
+
end
|
60
|
+
|
61
|
+
def args_empty?
|
62
|
+
@argslist.args_empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
def current_arg
|
66
|
+
@argslist.current_arg
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
module Synoption
|
5
|
+
class OptionArguments < Hash
|
6
|
+
def initialize name, tag, description, default, origargs
|
7
|
+
super()
|
8
|
+
|
9
|
+
merge! origargs.dup
|
10
|
+
|
11
|
+
takesvalue = if origargs.has_key?(:takesvalue)
|
12
|
+
origargs[:takesvalue]
|
13
|
+
else
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
self[:takesvalue] = takesvalue
|
18
|
+
self[:regexps] ||= origargs[:regexp]
|
19
|
+
self[:negates] ||= origargs[:negate]
|
20
|
+
self[:tags] = [ tag, '--' + name.to_s.gsub('_', '-') ]
|
21
|
+
self[:description] = description
|
22
|
+
self[:name] = name
|
23
|
+
self[:default] = default
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'ragol/boolean_option'
|
5
|
+
require 'ragol/synoption/option'
|
6
|
+
|
7
|
+
module Synoption
|
8
|
+
# a boolean option maps to a single tag, not a tag and value. For example,
|
9
|
+
# "-v" (verbose) is a boolean option, but "-r 3444" (revision) is a option
|
10
|
+
# with a value.
|
11
|
+
class BooleanOption < Ragol::Option
|
12
|
+
include OptionInit
|
13
|
+
|
14
|
+
def default_value
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
def takes_value?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'ragol/fixnum_option'
|
5
|
+
require 'ragol/synoption/option'
|
6
|
+
|
7
|
+
module Synoption
|
8
|
+
# An option that has a fixnum (integer) as its value.
|
9
|
+
class FixnumOption < Ragol::FixnumOption
|
10
|
+
include Synoption::OptionInit
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'ragol/option'
|
5
|
+
require 'ragol/synoption/args'
|
6
|
+
|
7
|
+
module Synoption
|
8
|
+
module OptionInit
|
9
|
+
def initialize(*args, &blk)
|
10
|
+
name, tag, description, deflt, options = *args
|
11
|
+
options ||= Hash.new
|
12
|
+
deflt ||= default_value
|
13
|
+
args = OptionArguments.new name, tag, description, deflt, options
|
14
|
+
super args, &blk
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_value
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Synoption
|
24
|
+
class Option < Ragol::Option
|
25
|
+
include OptionInit
|
26
|
+
end
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ragol
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jeff Pace
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: logue
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.0.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.0.1
|
30
|
+
description: Another implementation of an option processor.
|
31
|
+
email: jeugenepace@gmail.com
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- lib/ragol/args.rb
|
37
|
+
- lib/ragol/argslist.rb
|
38
|
+
- lib/ragol/boolean_option.rb
|
39
|
+
- lib/ragol/doc.rb
|
40
|
+
- lib/ragol/exception.rb
|
41
|
+
- lib/ragol/fixnum_option.rb
|
42
|
+
- lib/ragol/float_option.rb
|
43
|
+
- lib/ragol/hash.rb
|
44
|
+
- lib/ragol/matcher.rb
|
45
|
+
- lib/ragol/matchers.rb
|
46
|
+
- lib/ragol/option.rb
|
47
|
+
- lib/ragol/optproc/optproc.rb
|
48
|
+
- lib/ragol/optproc/optset.rb
|
49
|
+
- lib/ragol/optset.rb
|
50
|
+
- lib/ragol/regexp_option.rb
|
51
|
+
- lib/ragol/results.rb
|
52
|
+
- lib/ragol/string_option.rb
|
53
|
+
- lib/ragol/synoption/args.rb
|
54
|
+
- lib/ragol/synoption/boolean_option.rb
|
55
|
+
- lib/ragol/synoption/fixnum_option.rb
|
56
|
+
- lib/ragol/synoption/float_option.rb
|
57
|
+
- lib/ragol/synoption/option.rb
|
58
|
+
- lib/ragol/synoption/optset.rb
|
59
|
+
homepage: http://github.com/jpace/ragol
|
60
|
+
licenses: []
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 1.8.23
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: ! 'Ragol: Another GetOpt Library.'
|
83
|
+
test_files: []
|