main 0.0.2 → 2.0.0
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 +136 -25
- data/README.tmpl +126 -9
- data/TODO +2 -0
- data/a.rb +26 -0
- data/gemspec.rb +1 -1
- data/gen_readme.rb +4 -0
- data/lib/arrayfields.rb +434 -0
- data/lib/main.rb +46 -17
- data/lib/main/arrayfields.rb +190 -103
- data/lib/main/attributes.rb +84 -25
- data/lib/main/base.rb +146 -23
- data/lib/main/factories.rb +12 -8
- data/lib/main/mode.rb +42 -0
- data/lib/main/parameter.rb +77 -38
- data/lib/main/pervasives.rb +52 -0
- data/lib/main/softspoken.rb +12 -0
- data/lib/main/stdext.rb +18 -0
- data/lib/main/usage.rb +21 -3
- data/samples/e.rb +18 -0
- data/samples/f.rb +27 -0
- data/test/main.rb +156 -30
- metadata +25 -17
- data/lib/main/proxy.rb +0 -54
@@ -0,0 +1,52 @@
|
|
1
|
+
module Pervasives
|
2
|
+
VERSION = "1.1.0"
|
3
|
+
def self.version() VERSION end
|
4
|
+
|
5
|
+
Methods = Hash.new{|h,k| h[k] = {}}
|
6
|
+
|
7
|
+
[Class, Module, Object].each do |type|
|
8
|
+
type.instance_methods.each do |m|
|
9
|
+
Methods[type]["#{ m }"] = type.instance_method m
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.call o, m, *a, &b
|
14
|
+
list =
|
15
|
+
case o
|
16
|
+
when Class then [Class, Module, Object]
|
17
|
+
when Module then [Module, Object]
|
18
|
+
when Object then [Object]
|
19
|
+
end
|
20
|
+
type = list.detect{|type| Methods[type]["#{ m }"]}
|
21
|
+
m = Methods[type]["#{ m }"]
|
22
|
+
( m ).bind( o ).call( *a, &b )
|
23
|
+
end
|
24
|
+
|
25
|
+
class ::Object
|
26
|
+
def __pervasive__ m, *a, &b
|
27
|
+
Pervasives.call self, m, *a, &b
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Proxy
|
32
|
+
instance_methods.each{|m| undef_method m unless m[%r/__/]}
|
33
|
+
|
34
|
+
def initialize obj
|
35
|
+
@obj = obj
|
36
|
+
end
|
37
|
+
|
38
|
+
def method_missing m, *a, &b
|
39
|
+
Pervasives.call @obj, m, *a, &b
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.new *a, &b
|
44
|
+
Proxy.new *a, &b
|
45
|
+
end
|
46
|
+
|
47
|
+
class ::Object
|
48
|
+
def Pervasives *a, &b
|
49
|
+
Proxy.new *a, &b
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/main/stdext.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class ::Logger
|
2
|
+
def device
|
3
|
+
@logdev.instance_eval{ @dev }
|
4
|
+
end
|
5
|
+
def tty?
|
6
|
+
device.respond_to?('tty?') and device.tty?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Object
|
11
|
+
def singleton_class object = self, &block
|
12
|
+
sc =
|
13
|
+
class << object
|
14
|
+
self
|
15
|
+
end
|
16
|
+
block ? sc.module_eval(&block) : sc
|
17
|
+
end
|
18
|
+
end
|
data/lib/main/usage.rb
CHANGED
@@ -26,8 +26,20 @@ module Main
|
|
26
26
|
alias_method 'delete', 'delete_at'
|
27
27
|
|
28
28
|
def self.default_synopsis main
|
29
|
+
# build up synopsis
|
29
30
|
s = "#{ main.name }"
|
30
31
|
|
32
|
+
# mode info
|
33
|
+
if main.mode_name != 'main'
|
34
|
+
s << " #{ main.fully_qualified_mode.join ' ' }"
|
35
|
+
end
|
36
|
+
|
37
|
+
unless main.modes.empty?
|
38
|
+
modes = main.modes.keys.join('|')
|
39
|
+
s << " (#{ modes })"
|
40
|
+
end
|
41
|
+
|
42
|
+
# argument info
|
31
43
|
main.parameters.each do |p|
|
32
44
|
if p.type == :argument
|
33
45
|
if p.required?
|
@@ -38,6 +50,7 @@ module Main
|
|
38
50
|
end
|
39
51
|
end
|
40
52
|
|
53
|
+
# keyword info
|
41
54
|
main.parameters.each do |p|
|
42
55
|
if p.type == :keyword
|
43
56
|
if p.required?
|
@@ -48,6 +61,7 @@ module Main
|
|
48
61
|
end
|
49
62
|
end
|
50
63
|
|
64
|
+
# option info
|
51
65
|
n = 0
|
52
66
|
main.parameters.each do |p|
|
53
67
|
if p.type == :option
|
@@ -103,12 +117,16 @@ module Main
|
|
103
117
|
s =
|
104
118
|
parameters.map do |p|
|
105
119
|
ps = ''
|
106
|
-
ps << Util.columnize("
|
107
|
-
ps << "
|
120
|
+
ps << Util.columnize("#{ p.synopsis }", :indent => 2, :width => 78)
|
121
|
+
#ps << Util.columnize("* #{ p.synopsis }", :indent => 2, :width => 78)
|
122
|
+
#ps << "\n"
|
108
123
|
if p.description?
|
109
|
-
ps << Util.columnize(p.description, :indent => 6, :width => 78)
|
110
124
|
ps << "\n"
|
125
|
+
ps << Util.columnize("#{ p.description }", :indent => 6, :width => 78)
|
126
|
+
#ps << Util.columnize(p.description, :indent => 6, :width => 78)
|
127
|
+
#ps << "\n"
|
111
128
|
end
|
129
|
+
#ps << "\n"
|
112
130
|
ps
|
113
131
|
end.join("\n")
|
114
132
|
usage['parameters'] = s
|
data/samples/e.rb
ADDED
data/samples/f.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'main'
|
2
|
+
|
3
|
+
Main {
|
4
|
+
argument('directory'){ description 'the directory to operate on' }
|
5
|
+
|
6
|
+
option('force'){ description 'use a bigger hammer' }
|
7
|
+
|
8
|
+
def run
|
9
|
+
puts 'this is how we run when no mode is specified'
|
10
|
+
end
|
11
|
+
|
12
|
+
mode 'compress' do
|
13
|
+
option('bzip'){ description 'use bzip compression' }
|
14
|
+
|
15
|
+
def run
|
16
|
+
puts 'this is how we run in compress mode'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
mode 'uncompress' do
|
21
|
+
option('delete-after'){ description 'delete orginal file after uncompressing' }
|
22
|
+
|
23
|
+
def run
|
24
|
+
puts 'this is how we run in un-compress mode'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
}
|
data/test/main.rb
CHANGED
@@ -8,10 +8,12 @@ require 'test/unit'
|
|
8
8
|
require 'main'
|
9
9
|
|
10
10
|
class T < Test::Unit::TestCase
|
11
|
-
|
11
|
+
attribute 'status'
|
12
|
+
attribute 'logger'
|
13
|
+
attribute 'error'
|
12
14
|
|
13
15
|
def setup
|
14
|
-
@status = nil
|
16
|
+
@status = nil
|
15
17
|
@logger = Logger.new StringIO.new
|
16
18
|
@error = nil
|
17
19
|
end
|
@@ -21,22 +23,36 @@ class T < Test::Unit::TestCase
|
|
21
23
|
|
22
24
|
def main argv=[], env={}, &b
|
23
25
|
at_exit{ exit! }
|
26
|
+
|
24
27
|
$VERBOSE=nil
|
25
28
|
ARGV.replace argv
|
26
29
|
ENV.clear
|
27
30
|
env.each{|k,v| ENV[k.to_s]=v.to_s}
|
28
|
-
|
31
|
+
|
32
|
+
this = self
|
33
|
+
|
34
|
+
klass = ::Main.create do
|
35
|
+
module_eval &b if b
|
36
|
+
|
37
|
+
define_method :handle_exception do |e|
|
38
|
+
if e.respond_to? :status
|
39
|
+
this.status = e.status
|
40
|
+
else
|
41
|
+
raise
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
main = klass.new argv, env
|
47
|
+
|
48
|
+
main.logger = @logger
|
49
|
+
|
29
50
|
begin
|
30
|
-
main = Object::Main.new(&b)
|
31
|
-
main.logger = @logger
|
32
51
|
main.run
|
33
|
-
|
34
|
-
|
35
|
-
@status = e.status
|
36
|
-
else
|
37
|
-
raise
|
38
|
-
end
|
52
|
+
ensure
|
53
|
+
this.status ||= main.exit_status
|
39
54
|
end
|
55
|
+
|
40
56
|
main
|
41
57
|
end
|
42
58
|
|
@@ -92,10 +108,10 @@ class T < Test::Unit::TestCase
|
|
92
108
|
def test_0050
|
93
109
|
assert_nothing_raised{
|
94
110
|
main{
|
95
|
-
def run()
|
111
|
+
def run() exit 42 end
|
96
112
|
}
|
97
113
|
}
|
98
|
-
assert status ==
|
114
|
+
assert status == 42
|
99
115
|
end
|
100
116
|
def test_0060
|
101
117
|
assert_nothing_raised{
|
@@ -106,7 +122,7 @@ class T < Test::Unit::TestCase
|
|
106
122
|
assert status == 1
|
107
123
|
end
|
108
124
|
def test_0060
|
109
|
-
|
125
|
+
assert_raises(RuntimeError){
|
110
126
|
main{
|
111
127
|
def run() exit_status 42; raise end
|
112
128
|
}
|
@@ -114,7 +130,7 @@ class T < Test::Unit::TestCase
|
|
114
130
|
assert status == 42
|
115
131
|
end
|
116
132
|
def test_0070
|
117
|
-
|
133
|
+
assert_raises(ArgumentError){
|
118
134
|
main{
|
119
135
|
def run() exit_status 42; raise ArgumentError end
|
120
136
|
}
|
@@ -124,18 +140,6 @@ class T < Test::Unit::TestCase
|
|
124
140
|
#
|
125
141
|
# parameter parsing
|
126
142
|
#
|
127
|
-
def test_0080
|
128
|
-
p = nil
|
129
|
-
argv = %w[ 42 ]
|
130
|
-
assert_nothing_raised{
|
131
|
-
main(argv){
|
132
|
-
parameter('foo'){ type :argument }
|
133
|
-
define_method('run'){ p = param['foo'] }
|
134
|
-
}
|
135
|
-
}
|
136
|
-
assert p.value == argv.first
|
137
|
-
assert p.values == argv
|
138
|
-
end
|
139
143
|
def test_0080
|
140
144
|
p = nil
|
141
145
|
assert_raises(Main::Parameter::NotGiven){
|
@@ -147,17 +151,19 @@ class T < Test::Unit::TestCase
|
|
147
151
|
end
|
148
152
|
def test_0090
|
149
153
|
p = nil
|
154
|
+
m = nil
|
150
155
|
argv = %w[ 42 ]
|
151
156
|
given = nil
|
152
157
|
assert_nothing_raised{
|
153
|
-
main(argv){
|
158
|
+
main(argv.dup){
|
154
159
|
argument 'foo'
|
155
|
-
define_method('run'){ p = param['foo'] }
|
160
|
+
define_method('run'){ m = self; p = param['foo'] }
|
156
161
|
}
|
157
162
|
}
|
158
163
|
assert p.value == argv.first
|
159
164
|
assert p.values == argv
|
160
165
|
assert p.given?
|
166
|
+
assert m.argv.empty?
|
161
167
|
end
|
162
168
|
def test_0100
|
163
169
|
p = nil
|
@@ -467,7 +473,7 @@ class T < Test::Unit::TestCase
|
|
467
473
|
end
|
468
474
|
def test_0290
|
469
475
|
assert_nothing_raised{
|
470
|
-
u = Main::Usage.default
|
476
|
+
u = Main::Usage.default Main.create
|
471
477
|
}
|
472
478
|
end
|
473
479
|
def test_0300
|
@@ -633,6 +639,126 @@ class T < Test::Unit::TestCase
|
|
633
639
|
assert argv == $argv
|
634
640
|
end
|
635
641
|
|
642
|
+
#
|
643
|
+
# negative/globbing arity
|
644
|
+
#
|
645
|
+
def test_4000
|
646
|
+
m = nil
|
647
|
+
argv = %w( a b c )
|
648
|
+
assert_nothing_raised{
|
649
|
+
main(argv.dup) {
|
650
|
+
argument('zero_or_more'){ arity -1 }
|
651
|
+
run{ m = self }
|
652
|
+
}
|
653
|
+
}
|
654
|
+
assert m.param['zero_or_more'].values == argv
|
655
|
+
end
|
656
|
+
def test_4010
|
657
|
+
m = nil
|
658
|
+
argv = %w( a b c )
|
659
|
+
assert_nothing_raised{
|
660
|
+
main(argv.dup) {
|
661
|
+
argument('zero_or_more'){ arity '*' }
|
662
|
+
run{ m = self }
|
663
|
+
}
|
664
|
+
}
|
665
|
+
assert m.param['zero_or_more'].values == argv
|
666
|
+
end
|
667
|
+
def test_4020
|
668
|
+
m = nil
|
669
|
+
argv = %w( a b c )
|
670
|
+
assert_nothing_raised{
|
671
|
+
main(argv.dup) {
|
672
|
+
argument('one_or_more'){ arity -2 }
|
673
|
+
run{ m = self }
|
674
|
+
}
|
675
|
+
}
|
676
|
+
assert m.param['one_or_more'].values == argv
|
677
|
+
end
|
678
|
+
def test_4030
|
679
|
+
m = nil
|
680
|
+
argv = %w( a b c )
|
681
|
+
assert_nothing_raised{
|
682
|
+
main(argv.dup) {
|
683
|
+
argument('two_or_more'){ arity -3 }
|
684
|
+
run{ m = self }
|
685
|
+
}
|
686
|
+
}
|
687
|
+
assert m.param['two_or_more'].values == argv
|
688
|
+
end
|
689
|
+
def test_4040
|
690
|
+
m = nil
|
691
|
+
argv = %w()
|
692
|
+
assert_nothing_raised{
|
693
|
+
main(argv.dup) {
|
694
|
+
argument('zero_or_more'){ arity -1 }
|
695
|
+
run{ m = self }
|
696
|
+
}
|
697
|
+
}
|
698
|
+
assert m.param['zero_or_more'].values == argv
|
699
|
+
end
|
700
|
+
def test_4050
|
701
|
+
m = nil
|
702
|
+
argv = %w()
|
703
|
+
assert_raises(Main::Parameter::NotGiven){
|
704
|
+
main(argv.dup) {
|
705
|
+
argument('one_or_more'){ arity -2 }
|
706
|
+
run{ m = self }
|
707
|
+
}
|
708
|
+
}
|
709
|
+
end
|
710
|
+
def test_4060
|
711
|
+
m = nil
|
712
|
+
argv = %w( a )
|
713
|
+
assert_raises(Main::Parameter::Arity){
|
714
|
+
main(argv.dup) {
|
715
|
+
argument('two_or_more'){ arity -3 }
|
716
|
+
run{ m = self }
|
717
|
+
}
|
718
|
+
}
|
719
|
+
end
|
720
|
+
def test_4070
|
721
|
+
m = nil
|
722
|
+
argv = %w( a )
|
723
|
+
assert_raises(Main::Parameter::Arity){
|
724
|
+
main(argv.dup) {
|
725
|
+
argument('two_or_more'){ arity -4 }
|
726
|
+
run{ m = self }
|
727
|
+
}
|
728
|
+
}
|
729
|
+
end
|
730
|
+
#
|
731
|
+
# sub-command/mode functionality
|
732
|
+
#
|
733
|
+
def test_4080
|
734
|
+
m = nil
|
735
|
+
argv = %w( a b )
|
736
|
+
assert_nothing_raised{
|
737
|
+
main(argv.dup) {
|
738
|
+
mode 'a' do
|
739
|
+
argument 'b'
|
740
|
+
run{ m = self }
|
741
|
+
end
|
742
|
+
}
|
743
|
+
}
|
744
|
+
assert m.param['b'].value == 'b'
|
745
|
+
end
|
746
|
+
def test_4090
|
747
|
+
m = nil
|
748
|
+
argv = %w( a b c )
|
749
|
+
assert_nothing_raised{
|
750
|
+
main(argv.dup) {
|
751
|
+
mode 'a' do
|
752
|
+
mode 'b' do
|
753
|
+
argument 'c'
|
754
|
+
run{ m = self }
|
755
|
+
end
|
756
|
+
end
|
757
|
+
}
|
758
|
+
}
|
759
|
+
assert m.param['c'].value == 'c'
|
760
|
+
end
|
761
|
+
|
636
762
|
end
|
637
763
|
|
638
764
|
|