main 0.0.1
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/README +343 -0
- data/README.tmpl +154 -0
- data/a.rb +33 -0
- data/gemspec.rb +27 -0
- data/gen_readme.rb +38 -0
- data/install.rb +210 -0
- data/lib/main.rb +25 -0
- data/lib/main/base.rb +150 -0
- data/lib/main/cast.rb +74 -0
- data/lib/main/factories.rb +15 -0
- data/lib/main/getoptlong.rb +470 -0
- data/lib/main/parameter.rb +496 -0
- data/lib/main/usage.rb +138 -0
- data/lib/main/util.rb +91 -0
- data/main-0.0.1.gem +0 -0
- data/samples/a.rb +17 -0
- data/samples/b.rb +17 -0
- data/samples/c.rb +21 -0
- data/samples/d.rb +26 -0
- data/test/main.rb +523 -0
- metadata +69 -0
data/a.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'main'
|
2
|
+
|
3
|
+
ENV['BARFOO'] = 'true,false,false'
|
4
|
+
ARGV.replace %w( 42 bar=40 bar=2 --foobar=a )
|
5
|
+
|
6
|
+
Main {
|
7
|
+
argument('foo'){
|
8
|
+
cast :int
|
9
|
+
}
|
10
|
+
|
11
|
+
keyword('bar'){
|
12
|
+
arity 2
|
13
|
+
cast :float
|
14
|
+
defaults 0.0, 1.0
|
15
|
+
}
|
16
|
+
|
17
|
+
option('foobar'){
|
18
|
+
argument :optional
|
19
|
+
description 'the foobar option is very handy'
|
20
|
+
}
|
21
|
+
|
22
|
+
environment('BARFOO'){
|
23
|
+
cast :list_of_bool
|
24
|
+
synopsis 'export barfoo=value'
|
25
|
+
}
|
26
|
+
|
27
|
+
def run
|
28
|
+
p params['foo'].value
|
29
|
+
p params['bar'].values
|
30
|
+
p params['foobar'].value
|
31
|
+
p params['BARFOO'].value
|
32
|
+
end
|
33
|
+
}
|
data/gemspec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
|
6
|
+
Gem::Specification::new do |spec|
|
7
|
+
$VERBOSE = nil
|
8
|
+
spec.name = lib
|
9
|
+
spec.version = version
|
10
|
+
spec.platform = Gem::Platform::RUBY
|
11
|
+
spec.summary = lib
|
12
|
+
|
13
|
+
spec.files = Dir::glob "**/**"
|
14
|
+
spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
|
15
|
+
|
16
|
+
spec.require_path = "lib"
|
17
|
+
spec.autorequire = lib
|
18
|
+
|
19
|
+
spec.has_rdoc = File::exist? "doc"
|
20
|
+
spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
|
21
|
+
|
22
|
+
spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
|
23
|
+
|
24
|
+
spec.author = "Ara T. Howard"
|
25
|
+
spec.email = "ara.t.howard@noaa.gov"
|
26
|
+
spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
|
27
|
+
end
|
data/gen_readme.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
$VERBOSE=nil
|
4
|
+
|
5
|
+
def indent s, n = 2
|
6
|
+
ws = ' ' * n
|
7
|
+
s.gsub %r/^/, ws
|
8
|
+
end
|
9
|
+
|
10
|
+
template = IO::read 'README.tmpl'
|
11
|
+
|
12
|
+
samples = ''
|
13
|
+
prompt = '~ > '
|
14
|
+
|
15
|
+
Dir['sample*/*'].sort.each do |sample|
|
16
|
+
samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
|
17
|
+
|
18
|
+
cmd = "cat #{ sample }"
|
19
|
+
samples << indent(prompt + cmd, 2) << "\n\n"
|
20
|
+
samples << indent(`#{ cmd }`, 4) << "\n"
|
21
|
+
|
22
|
+
cmd = "ruby #{ sample }"
|
23
|
+
samples << indent(prompt + cmd, 2) << "\n\n"
|
24
|
+
|
25
|
+
cmd = "ruby -Ilib #{ sample }"
|
26
|
+
samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
|
27
|
+
|
28
|
+
cmd = "ruby #{ sample } --help"
|
29
|
+
samples << indent(prompt + cmd, 2) << "\n\n"
|
30
|
+
|
31
|
+
cmd = "ruby -Ilib #{ sample } --help"
|
32
|
+
samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
|
33
|
+
end
|
34
|
+
|
35
|
+
#samples.gsub! %r/^/, ' '
|
36
|
+
|
37
|
+
readme = template.gsub %r/^\s*@samples\s*$/, samples
|
38
|
+
print readme
|
data/install.rb
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'find'
|
4
|
+
require 'ftools'
|
5
|
+
require 'tempfile'
|
6
|
+
include Config
|
7
|
+
|
8
|
+
LIBDIR = "lib"
|
9
|
+
LIBDIR_MODE = 0644
|
10
|
+
|
11
|
+
BINDIR = "bin"
|
12
|
+
BINDIR_MODE = 0755
|
13
|
+
|
14
|
+
|
15
|
+
$srcdir = CONFIG["srcdir"]
|
16
|
+
$version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
|
17
|
+
$libdir = File.join(CONFIG["libdir"], "ruby", $version)
|
18
|
+
$archdir = File.join($libdir, CONFIG["arch"])
|
19
|
+
$site_libdir = $:.find {|x| x =~ /site_ruby$/}
|
20
|
+
$bindir = CONFIG["bindir"] || CONFIG['BINDIR']
|
21
|
+
$ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
|
22
|
+
$ruby_ext = CONFIG['EXEEXT'] || ''
|
23
|
+
$ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
|
24
|
+
|
25
|
+
if !$site_libdir
|
26
|
+
$site_libdir = File.join($libdir, "site_ruby")
|
27
|
+
elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
|
28
|
+
$site_libdir = File.join($site_libdir, $version)
|
29
|
+
end
|
30
|
+
|
31
|
+
def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
|
32
|
+
#{{{
|
33
|
+
path = []
|
34
|
+
dir = []
|
35
|
+
Find.find(srcdir) do |f|
|
36
|
+
next unless FileTest.file?(f)
|
37
|
+
next if (f = f[srcdir.length+1..-1]) == nil
|
38
|
+
next if (/CVS$/ =~ File.dirname(f))
|
39
|
+
next if f =~ %r/\.lnk/
|
40
|
+
path.push f
|
41
|
+
dir |= [File.dirname(f)]
|
42
|
+
end
|
43
|
+
for f in dir
|
44
|
+
next if f == "."
|
45
|
+
next if f == "CVS"
|
46
|
+
File::makedirs(File.join(destdir, f))
|
47
|
+
end
|
48
|
+
for f in path
|
49
|
+
next if (/\~$/ =~ f)
|
50
|
+
next if (/^\./ =~ File.basename(f))
|
51
|
+
unless bin
|
52
|
+
File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
|
53
|
+
else
|
54
|
+
from = File.join(srcdir, f)
|
55
|
+
to = File.join(destdir, f)
|
56
|
+
shebangify(from) do |sf|
|
57
|
+
$deferr.print from, " -> ", File::catname(from, to), "\n"
|
58
|
+
$deferr.printf "chmod %04o %s\n", mode, to
|
59
|
+
File::install(sf, to, mode, false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
#}}}
|
64
|
+
end
|
65
|
+
def shebangify f
|
66
|
+
#{{{
|
67
|
+
open(f) do |fd|
|
68
|
+
buf = fd.read 42
|
69
|
+
if buf =~ %r/^\s*#\s*!.*ruby/o
|
70
|
+
ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
|
71
|
+
begin
|
72
|
+
fd.rewind
|
73
|
+
ftmp.puts "#!#{ $ruby }"
|
74
|
+
while((buf = fd.read(8192)))
|
75
|
+
ftmp.write buf
|
76
|
+
end
|
77
|
+
ftmp.close
|
78
|
+
yield ftmp.path
|
79
|
+
ensure
|
80
|
+
ftmp.close!
|
81
|
+
end
|
82
|
+
else
|
83
|
+
yield f
|
84
|
+
end
|
85
|
+
end
|
86
|
+
#}}}
|
87
|
+
end
|
88
|
+
def ARGV.switch
|
89
|
+
#{{{
|
90
|
+
return nil if self.empty?
|
91
|
+
arg = self.shift
|
92
|
+
return nil if arg == '--'
|
93
|
+
if arg =~ /^-(.)(.*)/
|
94
|
+
return arg if $1 == '-'
|
95
|
+
raise 'unknown switch "-"' if $2.index('-')
|
96
|
+
self.unshift "-#{$2}" if $2.size > 0
|
97
|
+
"-#{$1}"
|
98
|
+
else
|
99
|
+
self.unshift arg
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
#}}}
|
103
|
+
end
|
104
|
+
def ARGV.req_arg
|
105
|
+
#{{{
|
106
|
+
self.shift || raise('missing argument')
|
107
|
+
#}}}
|
108
|
+
end
|
109
|
+
def linkify d, linked = []
|
110
|
+
#--{{{
|
111
|
+
if test ?d, d
|
112
|
+
versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
|
113
|
+
versioned.each do |v|
|
114
|
+
src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
|
115
|
+
lnk = nil
|
116
|
+
begin
|
117
|
+
if test ?l, dst
|
118
|
+
lnk = "#{ dst }.lnk"
|
119
|
+
puts "#{ dst } -> #{ lnk }"
|
120
|
+
File::rename dst, lnk
|
121
|
+
end
|
122
|
+
unless test ?e, dst
|
123
|
+
puts "#{ src } -> #{ dst }"
|
124
|
+
File::copy src, dst
|
125
|
+
linked << dst
|
126
|
+
end
|
127
|
+
ensure
|
128
|
+
if lnk
|
129
|
+
at_exit do
|
130
|
+
puts "#{ lnk } -> #{ dst }"
|
131
|
+
File::rename lnk, dst
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
linked
|
138
|
+
#--}}}
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
#
|
143
|
+
# main program
|
144
|
+
#
|
145
|
+
|
146
|
+
libdir = $site_libdir
|
147
|
+
bindir = $bindir
|
148
|
+
no_linkify = false
|
149
|
+
linked = nil
|
150
|
+
help = false
|
151
|
+
|
152
|
+
usage = <<-usage
|
153
|
+
#{ File::basename $0 }
|
154
|
+
-d, --destdir <destdir>
|
155
|
+
-l, --libdir <libdir>
|
156
|
+
-b, --bindir <bindir>
|
157
|
+
-r, --ruby <ruby>
|
158
|
+
-n, --no_linkify
|
159
|
+
-s, --sudo
|
160
|
+
-h, --help
|
161
|
+
usage
|
162
|
+
|
163
|
+
begin
|
164
|
+
while switch = ARGV.switch
|
165
|
+
case switch
|
166
|
+
when '-d', '--destdir'
|
167
|
+
libdir = ARGV.req_arg
|
168
|
+
when '-l', '--libdir'
|
169
|
+
libdir = ARGV.req_arg
|
170
|
+
when '-b', '--bindir'
|
171
|
+
bindir = ARGV.req_arg
|
172
|
+
when '-r', '--ruby'
|
173
|
+
$ruby = ARGV.req_arg
|
174
|
+
when '-n', '--no_linkify'
|
175
|
+
no_linkify = true
|
176
|
+
when '-s', '--sudo'
|
177
|
+
sudo = 'sudo'
|
178
|
+
when '-h', '--help'
|
179
|
+
help = true
|
180
|
+
else
|
181
|
+
raise "unknown switch #{switch.dump}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
rescue
|
185
|
+
STDERR.puts $!.to_s
|
186
|
+
STDERR.puts usage
|
187
|
+
exit 1
|
188
|
+
end
|
189
|
+
|
190
|
+
if help
|
191
|
+
STDOUT.puts usage
|
192
|
+
exit
|
193
|
+
end
|
194
|
+
|
195
|
+
system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
|
196
|
+
|
197
|
+
unless no_linkify
|
198
|
+
linked = linkify('lib') + linkify('bin')
|
199
|
+
end
|
200
|
+
|
201
|
+
system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
|
202
|
+
|
203
|
+
install_rb(LIBDIR, libdir, LIBDIR_MODE)
|
204
|
+
install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
|
205
|
+
|
206
|
+
if linked
|
207
|
+
linked.each{|path| File::rm_f path}
|
208
|
+
end
|
209
|
+
|
210
|
+
system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
|
data/lib/main.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Main
|
2
|
+
VERSION = '0.0.1'
|
3
|
+
|
4
|
+
LIBDIR = File.join(File.dirname(File.expand_path(__FILE__)), self.name.downcase, '')
|
5
|
+
|
6
|
+
require 'logger'
|
7
|
+
require 'enumerator'
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'rubygems'
|
11
|
+
rescue LoadError
|
12
|
+
end
|
13
|
+
# TODO - inline these
|
14
|
+
require 'attributes'
|
15
|
+
require 'arrayfields'
|
16
|
+
|
17
|
+
require LIBDIR + 'util'
|
18
|
+
require LIBDIR + 'usage'
|
19
|
+
require LIBDIR + 'cast'
|
20
|
+
require LIBDIR + 'parameter'
|
21
|
+
require LIBDIR + 'getoptlong'
|
22
|
+
require LIBDIR + 'base'
|
23
|
+
require LIBDIR + 'factories'
|
24
|
+
end
|
25
|
+
|
data/lib/main/base.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
module Main
|
2
|
+
class Base
|
3
|
+
EXIT_SUCCESS = 0
|
4
|
+
EXIT_FAILURE = 1
|
5
|
+
EXIT_OK = 42
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attribute( 'program' ){ File.basename $0 }
|
9
|
+
attribute( 'name' ){ File.basename $0 }
|
10
|
+
attribute( 'synopsis' ){ Usage.default_synopsis self }
|
11
|
+
attribute( 'description' )
|
12
|
+
attribute( 'author' )
|
13
|
+
attribute( 'version' )
|
14
|
+
attribute( 'logger' ){ STDERR }
|
15
|
+
attribute( 'exit_status' ){ EXIT_SUCCESS }
|
16
|
+
attribute( 'exit_success' ){ EXIT_SUCCESS }
|
17
|
+
attribute( 'exit_failure' ){ EXIT_FAILURE }
|
18
|
+
attribute( 'exit_ok' ){ EXIT_OK }
|
19
|
+
attribute( 'usage' ){ Usage.default_usage self }
|
20
|
+
|
21
|
+
def new *a, &b
|
22
|
+
obj = allocate
|
23
|
+
obj.__initialize__
|
24
|
+
obj.instance_eval{ initialize *a, &b }
|
25
|
+
obj
|
26
|
+
end
|
27
|
+
|
28
|
+
def parameters
|
29
|
+
@parameters ||= Parameter::List[]
|
30
|
+
end
|
31
|
+
|
32
|
+
def parameter *a, &b
|
33
|
+
parameters << Parameter.new(*a, &b)
|
34
|
+
end
|
35
|
+
|
36
|
+
def option *a, &b
|
37
|
+
(parameters << Parameter.create(:option, *a, &b)).last
|
38
|
+
end
|
39
|
+
alias_method 'opt', 'option'
|
40
|
+
alias_method 'switch', 'option'
|
41
|
+
|
42
|
+
def default_options!
|
43
|
+
option 'help', 'h'
|
44
|
+
end
|
45
|
+
|
46
|
+
def argument *a, &b
|
47
|
+
(parameters << Parameter.create(:argument, *a, &b)).last
|
48
|
+
end
|
49
|
+
alias_method 'arg', 'argument'
|
50
|
+
|
51
|
+
def keyword *a, &b
|
52
|
+
(parameters << Parameter.create(:keyword, *a, &b)).last
|
53
|
+
end
|
54
|
+
alias_method 'kw', 'keyword'
|
55
|
+
|
56
|
+
def environment *a, &b
|
57
|
+
(parameters << Parameter.create(:environment, *a, &b)).last
|
58
|
+
end
|
59
|
+
alias_method 'env', 'environment'
|
60
|
+
|
61
|
+
def run *a, &b
|
62
|
+
define_method 'run' &b
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
attribute 'argv'
|
67
|
+
attribute 'env'
|
68
|
+
attribute 'params'
|
69
|
+
attribute 'logger'
|
70
|
+
|
71
|
+
%w(
|
72
|
+
program name synopsis description author version
|
73
|
+
exit_status exit_success exit_failure exit_ok
|
74
|
+
usage
|
75
|
+
).each{|a| attribute(a){ self.class.send a}}
|
76
|
+
|
77
|
+
%w( parameters param ).each do |dst|
|
78
|
+
alias_method "#{ dst }", "params"
|
79
|
+
alias_method "#{ dst }=", "params="
|
80
|
+
alias_method "#{ dst }?", "params?"
|
81
|
+
end
|
82
|
+
|
83
|
+
%w( exit_success! exit_failure! exit_ok! ).each do |code|
|
84
|
+
module_eval <<-code
|
85
|
+
def #{ code } *a, &b
|
86
|
+
exit #{ code.chop }
|
87
|
+
end
|
88
|
+
code
|
89
|
+
end
|
90
|
+
|
91
|
+
%w( debug info warn fatal error ).each do |m|
|
92
|
+
module_eval <<-code
|
93
|
+
def #{ m } *a, &b
|
94
|
+
logger.#{ m } *a, &b
|
95
|
+
end
|
96
|
+
code
|
97
|
+
end
|
98
|
+
|
99
|
+
def __initialize__ argv = ARGV, env = ENV
|
100
|
+
@argv, @env = argv, env
|
101
|
+
|
102
|
+
log = self.class.logger
|
103
|
+
|
104
|
+
@logger =
|
105
|
+
case log
|
106
|
+
when Logger
|
107
|
+
log
|
108
|
+
when IO, StringIO
|
109
|
+
Logger.new log
|
110
|
+
else
|
111
|
+
Logger.new *log
|
112
|
+
end
|
113
|
+
|
114
|
+
__parse_parameters__
|
115
|
+
end
|
116
|
+
|
117
|
+
def __parse_parameters__
|
118
|
+
self.class.parameters.parse @argv, @env
|
119
|
+
#(@params = []).fields = []
|
120
|
+
@params = Parameter::Table.new
|
121
|
+
self.class.parameters.each do |p|
|
122
|
+
@params[p.name.to_s] = p
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def __run__
|
127
|
+
if @params['help'] and @params['help'].given?
|
128
|
+
print usage.to_s
|
129
|
+
exit
|
130
|
+
end
|
131
|
+
|
132
|
+
begin
|
133
|
+
run
|
134
|
+
rescue Exception => e
|
135
|
+
if SystemExit === e
|
136
|
+
exit_status e.status
|
137
|
+
else
|
138
|
+
fatal{ e }
|
139
|
+
exit_status EXIT_FAILURE if exit_status == EXIT_SUCCESS
|
140
|
+
end
|
141
|
+
end
|
142
|
+
status = Integer(exit_status) rescue(exit_status ? 0 : 1)
|
143
|
+
exit status
|
144
|
+
end
|
145
|
+
|
146
|
+
def run
|
147
|
+
raise NotImplementedError, 'run not defined'
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|