rprogram 0.0.9
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/History.txt +8 -0
- data/Manifest.txt +19 -0
- data/README.txt +46 -0
- data/Rakefile +17 -0
- data/lib/rprogram/compat.rb +58 -0
- data/lib/rprogram/exceptions/program_not_found.rb +4 -0
- data/lib/rprogram/exceptions.rb +1 -0
- data/lib/rprogram/extensions/meta/object.rb +24 -0
- data/lib/rprogram/extensions/meta.rb +1 -0
- data/lib/rprogram/extensions.rb +1 -0
- data/lib/rprogram/nameable.rb +67 -0
- data/lib/rprogram/non_option.rb +41 -0
- data/lib/rprogram/option.rb +59 -0
- data/lib/rprogram/options.rb +83 -0
- data/lib/rprogram/program.rb +105 -0
- data/lib/rprogram/task.rb +233 -0
- data/lib/rprogram/version.rb +3 -0
- data/lib/rprogram.rb +0 -0
- data/test/test_rprogram.rb +0 -0
- metadata +75 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
lib/rprogram.rb
|
6
|
+
lib/rprogram/version.rb
|
7
|
+
lib/rprogram/compat.rb
|
8
|
+
lib/rprogram/exceptions/program_not_found.rb
|
9
|
+
lib/rprogram/exceptions.rb
|
10
|
+
lib/rprogram/extensions/meta/object.rb
|
11
|
+
lib/rprogram/extensions/meta.rb
|
12
|
+
lib/rprogram/extensions.rb
|
13
|
+
lib/rprogram/option.rb
|
14
|
+
lib/rprogram/non_option.rb
|
15
|
+
lib/rprogram/options.rb
|
16
|
+
lib/rprogram/task.rb
|
17
|
+
lib/rprogram/nameable.rb
|
18
|
+
lib/rprogram/program.rb
|
19
|
+
test/test_rprogram.rb
|
data/README.txt
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
RProgram
|
2
|
+
by Postmodern Modulus III
|
3
|
+
http://rubyforge.org/projects/rprogram/
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
RProgram is a library for creating wrappers around command-line programs.
|
8
|
+
RProgram provides a Rubyful interface to programs and all their options
|
9
|
+
or non-options. RProgram can also search for programs installed on a
|
10
|
+
system.
|
11
|
+
|
12
|
+
== FEATURES/PROBLEMS:
|
13
|
+
|
14
|
+
* Provides cross-platform access to the PATH variable.
|
15
|
+
* Supports leading/tailing non-options.
|
16
|
+
* Supports long-options and short-options.
|
17
|
+
* Supports custom formating of options.
|
18
|
+
|
19
|
+
== INSTALL:
|
20
|
+
|
21
|
+
$ sudo gem install rprogram
|
22
|
+
|
23
|
+
== LICENSE:
|
24
|
+
|
25
|
+
The MIT License
|
26
|
+
|
27
|
+
Copyright (c) 2008 Hal Brodigan
|
28
|
+
|
29
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
30
|
+
a copy of this software and associated documentation files (the
|
31
|
+
'Software'), to deal in the Software without restriction, including
|
32
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
33
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
34
|
+
permit persons to whom the Software is furnished to do so, subject to
|
35
|
+
the following conditions:
|
36
|
+
|
37
|
+
The above copyright notice and this permission notice shall be
|
38
|
+
included in all copies or substantial portions of the Software.
|
39
|
+
|
40
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
41
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
42
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
43
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
44
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
45
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
46
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/rprogram/version.rb'
|
6
|
+
|
7
|
+
Hoe.new('rprogram', RProgram::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'rprogram'
|
9
|
+
p.author = 'Postmodern Modulus III'
|
10
|
+
p.email = 'postmodern.mod3@gmail.com'
|
11
|
+
p.summary = 'RProgram is a library for creating ruby wrappers around command-line programs'
|
12
|
+
p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
|
13
|
+
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
|
14
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
# vim: syntax=Ruby
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module RProgram
|
2
|
+
module Compat
|
3
|
+
#
|
4
|
+
# Returns the native _platform_.
|
5
|
+
#
|
6
|
+
# Compat.arch #=> "linux"
|
7
|
+
#
|
8
|
+
def self.platform
|
9
|
+
RUBY_PLATFORM.split('-').last
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# Returns an array representing the +PATH+ environment variable.
|
14
|
+
# If the +PATH+ environment variable is not setup, an empty array will
|
15
|
+
# be returned.
|
16
|
+
#
|
17
|
+
# Compat.PATH #=> ["/bin", "/usr/bin"]
|
18
|
+
#
|
19
|
+
def self.PATH
|
20
|
+
# return an empty array in case
|
21
|
+
# the PATH variable does not exist
|
22
|
+
return [] unless ENV['PATH']
|
23
|
+
|
24
|
+
if self.platform =~ /mswin32/
|
25
|
+
return ENV['PATH'].split(';')
|
26
|
+
else
|
27
|
+
return ENV['PATH'].split(':')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Finds the program matching _name_ and returns it's full path.
|
33
|
+
# If the program was not found, +nil+ will be returned.
|
34
|
+
#
|
35
|
+
# Compat.find_program('as') #=> "/usr/bin/as"
|
36
|
+
#
|
37
|
+
def self.find_program(name)
|
38
|
+
self.PATH.each do |dir|
|
39
|
+
full_path = File.expand_path(File.join(dir,name))
|
40
|
+
|
41
|
+
return full_path if File.file?(full_path)
|
42
|
+
end
|
43
|
+
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Finds the program matching one of the names within _names_ and
|
49
|
+
# returns it's full path. If no program was found matching any of
|
50
|
+
# the names, the +nil+ will be returned.
|
51
|
+
#
|
52
|
+
# Compat.find_program_by_names("gas","as") #=> "/usr/bin/as"
|
53
|
+
#
|
54
|
+
def self.find_program_by_names(*names)
|
55
|
+
names.map { |name| self.find_program(name) }.compact.first
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rprogram/exceptions/program_not_found'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# metaprogramming assistant -- metaid.rb
|
2
|
+
class Object # :nodoc:
|
3
|
+
# The hidden singleton lurks behind everyone
|
4
|
+
def metaclass; class << self; self; end; end
|
5
|
+
def meta_eval(&blk); metaclass.instance_eval(&blk); end
|
6
|
+
|
7
|
+
# A class_eval version of meta_eval
|
8
|
+
def metaclass_eval(&blk); metaclass.class_eval(&blk); end
|
9
|
+
|
10
|
+
# Adds methods to a metaclass
|
11
|
+
def meta_def(name, &blk)
|
12
|
+
meta_eval { define_method(name, &blk) }
|
13
|
+
end
|
14
|
+
|
15
|
+
# Adds class methods to a metaclass
|
16
|
+
def metaclass_def(name, &blk)
|
17
|
+
metaclass_eval { define_method(name, &blk) }
|
18
|
+
end
|
19
|
+
|
20
|
+
# Defines an instance method within a class
|
21
|
+
def class_def(name, &blk)
|
22
|
+
class_eval { define_method(name, &blk) }
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rprogram/extensions/meta/object.rb'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rprogram/extensions/meta'
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rprogram/extensions/meta'
|
2
|
+
require 'rprogram/compat'
|
3
|
+
|
4
|
+
module RProgram
|
5
|
+
module Nameable
|
6
|
+
def self.included(base)
|
7
|
+
base.metaclass_eval do
|
8
|
+
def program_name
|
9
|
+
@program_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def program_name=(name)
|
13
|
+
@program_name = name.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def program_aliases
|
17
|
+
@program_aliases ||= []
|
18
|
+
end
|
19
|
+
|
20
|
+
def program_aliases=(aliases)
|
21
|
+
@program_aliases = aliases.to_a.map { |name| name.to_s }
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_program
|
25
|
+
names = self.program_aliases
|
26
|
+
names.unshift(self.program_name) if self.program_name
|
27
|
+
|
28
|
+
return Compat.find_program_by_names(*names)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Returns the program name of a class.
|
35
|
+
#
|
36
|
+
def program_name
|
37
|
+
self.class.program_name
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Returns the program aliases.
|
42
|
+
#
|
43
|
+
def program_aliases
|
44
|
+
self.class.program_aliases
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
#
|
50
|
+
# Sets the program name for a class to the specified _name_.
|
51
|
+
#
|
52
|
+
# name_program 'ls'
|
53
|
+
#
|
54
|
+
def Object.name_program(name)
|
55
|
+
self.program_name = name
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Sets the program aliases for a class to the specified _aliases_.
|
60
|
+
#
|
61
|
+
# name_program 'vim', 'vi'
|
62
|
+
#
|
63
|
+
def Object.alias_program(*aliases)
|
64
|
+
self.program_aliases = aliases
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module RProgram
|
2
|
+
class NonOption
|
3
|
+
|
4
|
+
# Name of the argument(s)
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
# Is the argument a leading argument(s)
|
8
|
+
attr_reader :leading
|
9
|
+
|
10
|
+
# Is the argument a tailing argument(s)
|
11
|
+
attr_reader :tailing
|
12
|
+
|
13
|
+
# Can the argument be specified multiple times
|
14
|
+
attr_reader :multiple
|
15
|
+
|
16
|
+
def initialize(opts={:name => nil, :leading => false, :tailing => false, :multiple => false})
|
17
|
+
@name = opts[:name]
|
18
|
+
|
19
|
+
@leading = opts[:leading] || false
|
20
|
+
@tailing = opts[:tailing] || true
|
21
|
+
@multiple = opts[:multiple] || false
|
22
|
+
end
|
23
|
+
|
24
|
+
def arguments(value)
|
25
|
+
return [] if (value==nil || value==false)
|
26
|
+
|
27
|
+
if value.kind_of?(Hash)
|
28
|
+
return value.map { |name,value| "#{name}=#{value}" }
|
29
|
+
elsif value.kind_of?(Array)
|
30
|
+
if @multiple
|
31
|
+
return value.compact
|
32
|
+
else
|
33
|
+
return value.join
|
34
|
+
end
|
35
|
+
else
|
36
|
+
return [value]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module RProgram
|
2
|
+
class Option
|
3
|
+
|
4
|
+
# Flag of the option
|
5
|
+
attr_reader :flag
|
6
|
+
|
7
|
+
# Is the option in equals format
|
8
|
+
attr_reader :equals
|
9
|
+
|
10
|
+
# Can the option be specified multiple times
|
11
|
+
attr_reader :multiple
|
12
|
+
|
13
|
+
def initialize(opts={:flag => nil, :equals => false, :multiple => false},&block)
|
14
|
+
@flag = opts[:flag]
|
15
|
+
|
16
|
+
@equals = opts[:equals] || false
|
17
|
+
@multiple = opts[:multiple] || false
|
18
|
+
|
19
|
+
@formating = block
|
20
|
+
end
|
21
|
+
|
22
|
+
def arguments(value)
|
23
|
+
return [@flag] if value==true
|
24
|
+
return [] if (value==nil || value==false)
|
25
|
+
|
26
|
+
if value.kind_of?(Hash)
|
27
|
+
value = value.map { |name,value| "#{name}=#{value}" }
|
28
|
+
elsif value.kind_of?(Array)
|
29
|
+
value = value.compact
|
30
|
+
end
|
31
|
+
|
32
|
+
if @multiple
|
33
|
+
args = []
|
34
|
+
|
35
|
+
value.each { |arg| args += format(arg) }
|
36
|
+
return args
|
37
|
+
else
|
38
|
+
return format(value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def default_format(value)
|
45
|
+
return [@flag] + value if value.kind_of?(Array)
|
46
|
+
return ["#{flag}=#{value}"] if @equals
|
47
|
+
return [@flag, value]
|
48
|
+
end
|
49
|
+
|
50
|
+
def format(value)
|
51
|
+
if @formating
|
52
|
+
return @formating.call(@flag,value).to_a
|
53
|
+
else
|
54
|
+
return default_format(value)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'rprogram/extensions/meta'
|
2
|
+
require 'rprogram/non_option'
|
3
|
+
require 'rprogram/option'
|
4
|
+
|
5
|
+
module RProgram
|
6
|
+
module Options
|
7
|
+
def self.included(base)
|
8
|
+
base.metaclass_eval do
|
9
|
+
def non_options
|
10
|
+
@non_options ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def has_non_option?(name)
|
14
|
+
name = name.to_sym
|
15
|
+
|
16
|
+
ancestors.each do |base|
|
17
|
+
if base.include?(Options)
|
18
|
+
return true if base.non_options.include?(name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_non_option(name)
|
26
|
+
name = name.to_sym
|
27
|
+
|
28
|
+
ancestors.each do |base|
|
29
|
+
if base.include?(Options)
|
30
|
+
return base.non_options[name] if base.non_options.has_key?(name)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
return nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def options
|
38
|
+
@options ||= {}
|
39
|
+
end
|
40
|
+
|
41
|
+
def has_option?(name)
|
42
|
+
name = name.to_sym
|
43
|
+
|
44
|
+
ancestors.each do |base|
|
45
|
+
if base.include?(Options)
|
46
|
+
return true if base.options.has_key?(name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_option(name)
|
54
|
+
name = name.to_sym
|
55
|
+
|
56
|
+
ancestors.each do |base|
|
57
|
+
if base.include?(Options)
|
58
|
+
return base.options[name] if base.options.has_key?(name)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
return nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def has_non_option?(name)
|
68
|
+
self.class.has_non_option?(name)
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_non_option(name)
|
72
|
+
self.class.get_non_option(name)
|
73
|
+
end
|
74
|
+
|
75
|
+
def has_option?(name)
|
76
|
+
self.class.has_option?(name)
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_option(name)
|
80
|
+
self.class.get_option(name)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'rprogram/compat'
|
2
|
+
require 'rprogram/task'
|
3
|
+
require 'rprogram/exceptions/program_not_found'
|
4
|
+
|
5
|
+
module RProgram
|
6
|
+
class Program
|
7
|
+
|
8
|
+
# Path to the program
|
9
|
+
attr_reader :path
|
10
|
+
|
11
|
+
# Name of the program
|
12
|
+
attr_reader :name
|
13
|
+
|
14
|
+
#
|
15
|
+
# Creates a new Program object from _path_. If _block_ is given, it will
|
16
|
+
# be passed the newly created Program.
|
17
|
+
#
|
18
|
+
# Program.new('/usr/bin/ls')
|
19
|
+
#
|
20
|
+
def initialize(path,&block)
|
21
|
+
@path = File.expand_path(path)
|
22
|
+
@name = File.basename(@path)
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Finds the program with the specified _name_ and returns a new
|
27
|
+
# Program object. If no programs could be found with the matching _name_,
|
28
|
+
# a ProramNotFound exception will be raised.
|
29
|
+
#
|
30
|
+
# Program.find_by_name('cat') # => Program
|
31
|
+
#
|
32
|
+
def self.find_by_name(name)
|
33
|
+
path = Compat.find_program(name)
|
34
|
+
unless path
|
35
|
+
raise(ProgramNotFound,"program '#{name}' could not be found",caller)
|
36
|
+
end
|
37
|
+
|
38
|
+
return self.new(path)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.find_by_names(*names)
|
42
|
+
path = Compat.find_program_by_names(*names)
|
43
|
+
|
44
|
+
unless path
|
45
|
+
names = names.map { |name| name.dump }.join(', ')
|
46
|
+
|
47
|
+
raise(ProgramNotFound,"programs #{names} were not be found",caller)
|
48
|
+
end
|
49
|
+
|
50
|
+
return self.new(path)
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Creates a new Program object with the specified _path_,
|
55
|
+
# if _path_ is a valid file.
|
56
|
+
#
|
57
|
+
# Program.create_from_path('/bin/cd') # => Program
|
58
|
+
#
|
59
|
+
# Program.create_from_path('/obviously/fake') # => nil
|
60
|
+
#
|
61
|
+
def self.create_from_path(path)
|
62
|
+
return self.new(path) if File.file?(path)
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.create_from_paths(*paths)
|
66
|
+
paths.each do |path|
|
67
|
+
return self.new(path) if File.file?(path)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# Runs the program with the specified _args_ and returns
|
73
|
+
# an Array of the programs output.
|
74
|
+
#
|
75
|
+
# echo = Program.find_by_name('echo')
|
76
|
+
# echo.run("hello") # => ["hello\n"]
|
77
|
+
#
|
78
|
+
def run(*args)
|
79
|
+
command = [@path] + args
|
80
|
+
|
81
|
+
IO.popen(command.join(' ')) do |process|
|
82
|
+
return process.readlines
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Runs the program with the specified _task_ object.
|
88
|
+
#
|
89
|
+
def run_task(task)
|
90
|
+
run(*(task.arguments))
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# Returns the path of the program.
|
95
|
+
#
|
96
|
+
# puts Program.find_by_name('echo')
|
97
|
+
# /usr/bin/echo
|
98
|
+
# # => nil
|
99
|
+
#
|
100
|
+
def to_s
|
101
|
+
@path.to_s
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,233 @@
|
|
1
|
+
require 'rprogram/options'
|
2
|
+
|
3
|
+
module RProgram
|
4
|
+
class Task
|
5
|
+
|
6
|
+
include Options
|
7
|
+
|
8
|
+
#
|
9
|
+
# Creates a new Task object with the given _options_. If a block is
|
10
|
+
# given, it is passed the newly created Task object.
|
11
|
+
#
|
12
|
+
# Task.new(:test => 'example', :count => 2, :verbose => true)
|
13
|
+
# Task.new(:help => true) { |task| ... }
|
14
|
+
#
|
15
|
+
def initialize(options={},&block)
|
16
|
+
@subtasks = {}
|
17
|
+
@options = options
|
18
|
+
|
19
|
+
block.call(self) if block
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Returns the compiled _arguments_ from a Task object created
|
24
|
+
# with the given _options_ and _block_.
|
25
|
+
#
|
26
|
+
# MyTask.arguments(:verbose => true, :count => 2)
|
27
|
+
#
|
28
|
+
# MyTask.arguments do |task|
|
29
|
+
# task.verbose = true
|
30
|
+
# task.file = 'output.txt'
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
def self.arguments(options={},&block)
|
34
|
+
self.new(options,&block).arguments
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Returns an array of _arguments_ generated from all the leading
|
39
|
+
# non-options of the task and it's sub-tasks.
|
40
|
+
#
|
41
|
+
def leading_non_options
|
42
|
+
args = []
|
43
|
+
|
44
|
+
# add the task leading non-options
|
45
|
+
@options.each do |name,value|
|
46
|
+
non_opt = get_non_option(name)
|
47
|
+
|
48
|
+
if (non_opt && non_opt.leading)
|
49
|
+
args += non_opt.arguments(value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# add all leading subtask non-options
|
54
|
+
@subtasks.each_value do |task|
|
55
|
+
args += task.leading_non_options
|
56
|
+
end
|
57
|
+
|
58
|
+
return args
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Returns an array of _arguments_ generated from all the options
|
63
|
+
# of the task and it's sub-tasks.
|
64
|
+
#
|
65
|
+
def options
|
66
|
+
args = []
|
67
|
+
|
68
|
+
# add all subtask options
|
69
|
+
@subtasks.each_value do |task|
|
70
|
+
args += task.arguments
|
71
|
+
end
|
72
|
+
|
73
|
+
# add the task options
|
74
|
+
@options.each do |name,value|
|
75
|
+
opt = get_option(name)
|
76
|
+
args += opt.arguments(value) if opt
|
77
|
+
end
|
78
|
+
|
79
|
+
return args
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Returns an array of _arguments_ generated from all the tailing
|
84
|
+
# non-options of the task and it's sub-tasks.
|
85
|
+
#
|
86
|
+
def tailing_non_options
|
87
|
+
args = []
|
88
|
+
|
89
|
+
# add all tailing subtask non-options
|
90
|
+
@subtasks.each_value do |task|
|
91
|
+
args += task.tailing_non_options
|
92
|
+
end
|
93
|
+
|
94
|
+
# add the task tailing non-options
|
95
|
+
@options.each do |name,value|
|
96
|
+
non_opt = get_non_option(name)
|
97
|
+
|
98
|
+
if (non_opt && non_opt.tailing)
|
99
|
+
args += non_opt.arguments(value)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
return args
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Returns an array of _arguments_ compiled from the _arguments_ of
|
108
|
+
# the tasks leading non_options, options and tailing non-options.
|
109
|
+
#
|
110
|
+
def arguments
|
111
|
+
leading_non_options + options + ['--'] + tailing_non_options
|
112
|
+
end
|
113
|
+
|
114
|
+
protected
|
115
|
+
|
116
|
+
#
|
117
|
+
# Defines a sub-task of _name_ and class of _task_.
|
118
|
+
#
|
119
|
+
# subtask :extra, ExtraTask
|
120
|
+
#
|
121
|
+
def Object.subtask(name,task)
|
122
|
+
class_eval %{
|
123
|
+
def #{name}(options={},&block)
|
124
|
+
if @subtasks[#{name.dump}]
|
125
|
+
@subtasks[#{name.dump}].options.merge!(options)
|
126
|
+
|
127
|
+
block.call(@subtasks[#{name.dump}]) if block
|
128
|
+
else
|
129
|
+
@subtasks[#{name.dump}] = #{task}.new(options,&block)
|
130
|
+
end
|
131
|
+
|
132
|
+
return @subtasks[#{name.dump}]
|
133
|
+
end
|
134
|
+
}
|
135
|
+
end
|
136
|
+
|
137
|
+
#
|
138
|
+
# Defines a non-option with the given _opts_.
|
139
|
+
#
|
140
|
+
# non_option :name => 'input_file', :tailing => true
|
141
|
+
#
|
142
|
+
# non_option :name => 'file', :tailing => true, :multiple => true
|
143
|
+
#
|
144
|
+
def Object.non_option(opts={})
|
145
|
+
name = opts[:name].to_sym
|
146
|
+
|
147
|
+
self.non_options[name] = NonOption.new(opts)
|
148
|
+
|
149
|
+
class_def(name) do
|
150
|
+
if opts[:multiple]
|
151
|
+
@options[name] ||= []
|
152
|
+
else
|
153
|
+
@options[name]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class_def("#{name}=") do |value|
|
158
|
+
@options[name] = value
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# Defines a long-option with the given _opts_.
|
164
|
+
#
|
165
|
+
# long_option :flag => '--output'
|
166
|
+
#
|
167
|
+
# long_option :flag => '-f', :name => :file
|
168
|
+
#
|
169
|
+
def Object.long_option(opts={},&block)
|
170
|
+
flag = opts[:flag].to_s
|
171
|
+
method_name = (opts[:name] || Task.flag_namify(flag)).to_sym
|
172
|
+
|
173
|
+
self.options[method_name] = Option.new(opts,&block)
|
174
|
+
|
175
|
+
class_def(method_name) do
|
176
|
+
if opts[:multiple]
|
177
|
+
@options[method_name] ||= []
|
178
|
+
else
|
179
|
+
@options[method_name]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class_def("#{method_name}=") do |value|
|
184
|
+
@options[method_name] = value
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
#
|
189
|
+
# Defines a short_option with the given _opts_.
|
190
|
+
#
|
191
|
+
# short_option :flag => '-c', :name => :count
|
192
|
+
#
|
193
|
+
def Object.short_option(opts={},&block)
|
194
|
+
method_name = opts[:name].to_sym
|
195
|
+
|
196
|
+
self.options[method_name] = Option.new(opts,&block)
|
197
|
+
|
198
|
+
class_def(method_name) do
|
199
|
+
if opts[:multiple]
|
200
|
+
@options[method_name] ||= []
|
201
|
+
else
|
202
|
+
@options[method_name]
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
class_def("#{method_name}=") do |value|
|
207
|
+
@options[method_name] = value
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
#
|
212
|
+
# Converts a long-option flag to a Ruby method name.
|
213
|
+
#
|
214
|
+
# Task.flag_namify('--output-file') #=> "output_files"
|
215
|
+
#
|
216
|
+
def Task.flag_namify(flag)
|
217
|
+
flag = flag.to_s
|
218
|
+
|
219
|
+
# remove leading dashes
|
220
|
+
if flag =~ /^--/
|
221
|
+
method_name = flag[2..-1]
|
222
|
+
elsif flag =~ /^-/
|
223
|
+
method_name = flag[1..-1]
|
224
|
+
else
|
225
|
+
method_name = flag
|
226
|
+
end
|
227
|
+
|
228
|
+
# replace remaining dashes with underscores
|
229
|
+
return method_name.gsub(/[-.]/,'_')
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
end
|
data/lib/rprogram.rb
ADDED
File without changes
|
File without changes
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: rprogram
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.9
|
7
|
+
date: 2008-01-09 00:00:00 -08:00
|
8
|
+
summary: RProgram is a library for creating ruby wrappers around command-line programs
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: postmodern.mod3@gmail.com
|
12
|
+
homepage: " by Postmodern Modulus III"
|
13
|
+
rubyforge_project: rprogram
|
14
|
+
description: "== FEATURES/PROBLEMS: * Provides cross-platform access to the PATH variable. * Supports leading/tailing non-options. * Supports long-options and short-options. * Supports custom formating of options. == INSTALL: $ sudo gem install rprogram == LICENSE:"
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Postmodern Modulus III
|
31
|
+
files:
|
32
|
+
- History.txt
|
33
|
+
- Manifest.txt
|
34
|
+
- README.txt
|
35
|
+
- Rakefile
|
36
|
+
- lib/rprogram.rb
|
37
|
+
- lib/rprogram/version.rb
|
38
|
+
- lib/rprogram/compat.rb
|
39
|
+
- lib/rprogram/exceptions/program_not_found.rb
|
40
|
+
- lib/rprogram/exceptions.rb
|
41
|
+
- lib/rprogram/extensions/meta/object.rb
|
42
|
+
- lib/rprogram/extensions/meta.rb
|
43
|
+
- lib/rprogram/extensions.rb
|
44
|
+
- lib/rprogram/option.rb
|
45
|
+
- lib/rprogram/non_option.rb
|
46
|
+
- lib/rprogram/options.rb
|
47
|
+
- lib/rprogram/task.rb
|
48
|
+
- lib/rprogram/nameable.rb
|
49
|
+
- lib/rprogram/program.rb
|
50
|
+
- test/test_rprogram.rb
|
51
|
+
test_files:
|
52
|
+
- test/test_rprogram.rb
|
53
|
+
rdoc_options:
|
54
|
+
- --main
|
55
|
+
- README.txt
|
56
|
+
extra_rdoc_files:
|
57
|
+
- History.txt
|
58
|
+
- Manifest.txt
|
59
|
+
- README.txt
|
60
|
+
executables: []
|
61
|
+
|
62
|
+
extensions: []
|
63
|
+
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
dependencies:
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: hoe
|
69
|
+
version_requirement:
|
70
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 1.4.0
|
75
|
+
version:
|