scout-gear 1.1.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +4 -0
- data/.vimproject +604 -1
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/bin/scout +28 -0
- data/lib/scout/indiferent_hash.rb +0 -30
- data/lib/scout/log/progress/report.rb +1 -1
- data/lib/scout/log/progress/util.rb +0 -1
- data/lib/scout/log.rb +1 -1
- data/lib/scout/meta_extension.rb +15 -1
- data/lib/scout/misc/format.rb +227 -0
- data/lib/scout/misc.rb +14 -0
- data/lib/scout/path/find.rb +88 -33
- data/lib/scout/path/util.rb +51 -0
- data/lib/scout/path.rb +23 -10
- data/lib/scout/simple_opt/accessor.rb +54 -0
- data/lib/scout/simple_opt/doc.rb +120 -0
- data/lib/scout/simple_opt/get.rb +57 -0
- data/lib/scout/simple_opt/parse.rb +66 -0
- data/lib/scout/simple_opt/setup.rb +26 -0
- data/lib/scout/simple_opt.rb +5 -0
- data/lib/scout/tmpfile.rb +2 -6
- data/lib/scout-gear.rb +2 -0
- data/scout-gear.gemspec +19 -3
- data/test/scout/indiferent_hash/test_case_insensitive.rb +16 -0
- data/test/scout/path/test_find.rb +42 -1
- data/test/scout/path/test_util.rb +22 -0
- data/test/scout/simple_opt/test_get.rb +11 -0
- data/test/scout/simple_opt/test_parse.rb +10 -0
- data/test/scout/simple_opt/test_setup.rb +77 -0
- data/test/scout/test_meta_extension.rb +16 -2
- data/test/scout/test_misc.rb +13 -0
- data/test/scout/test_path.rb +16 -0
- metadata +18 -2
data/lib/scout/log.rb
CHANGED
data/lib/scout/meta_extension.rb
CHANGED
@@ -13,9 +13,23 @@ module MetaExtension
|
|
13
13
|
|
14
14
|
meta.define_method(:setup) do |obj,*rest|
|
15
15
|
obj.extend base
|
16
|
-
self.class_variable_get("@@extension_attrs")
|
16
|
+
attrs = self.class_variable_get("@@extension_attrs")
|
17
|
+
|
18
|
+
return if attrs.nil? || attrs.empty?
|
19
|
+
|
20
|
+
if rest.length == 1 && Hash === (rlast = rest.last) &&
|
21
|
+
! (rlkey = rlast.keys.first).nil? &&
|
22
|
+
attrs.include?(rlkey.to_sym)
|
23
|
+
|
24
|
+
pairs = rlast
|
25
|
+
else
|
26
|
+
pairs = attrs.zip(rest)
|
27
|
+
end
|
28
|
+
|
29
|
+
pairs.each do |name,value|
|
17
30
|
obj.instance_variable_set("@#{name}", value)
|
18
31
|
end
|
32
|
+
|
19
33
|
obj
|
20
34
|
end
|
21
35
|
|
@@ -0,0 +1,227 @@
|
|
1
|
+
module Misc
|
2
|
+
COLOR_LIST = %w(#BC80BD #CCEBC5 #FFED6F #8DD3C7 #FFFFB3 #BEBADA #FB8072 #80B1D3 #FDB462 #B3DE69 #FCCDE5 #D9D9D9)
|
3
|
+
|
4
|
+
def self.colors_for(list)
|
5
|
+
unused = COLOR_LIST.dup
|
6
|
+
|
7
|
+
used = {}
|
8
|
+
colors = list.collect do |elem|
|
9
|
+
if used.include? elem
|
10
|
+
used[elem]
|
11
|
+
else
|
12
|
+
color = unused.shift
|
13
|
+
used[elem]=color
|
14
|
+
color
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
[colors, used]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.format_seconds(time, extended = false)
|
22
|
+
seconds = time.to_i
|
23
|
+
str = [seconds/3600, seconds/60 % 60, seconds % 60].map{|t| "%02i" % t }.join(':')
|
24
|
+
str << ".%02i" % ((time - seconds) * 100) if extended
|
25
|
+
str
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.format_paragraph(text, size = 80, indent = 0, offset = 0)
|
29
|
+
i = 0
|
30
|
+
size = size + offset + indent
|
31
|
+
re = /((?:\n\s*\n\s*)|(?:\n\s*(?=\*)))/
|
32
|
+
text.split(re).collect do |paragraph|
|
33
|
+
i += 1
|
34
|
+
str = if i % 2 == 1
|
35
|
+
words = paragraph.gsub(/\s+/, "\s").split(" ")
|
36
|
+
lines = []
|
37
|
+
line = " "*offset
|
38
|
+
word = words.shift
|
39
|
+
while word
|
40
|
+
word = word[0..size-indent-offset-4] + '...' if word.length >= size - indent - offset
|
41
|
+
while word and Log.uncolor(line).length + Log.uncolor(word).length <= size - indent
|
42
|
+
line << word << " "
|
43
|
+
word = words.shift
|
44
|
+
end
|
45
|
+
offset = 0
|
46
|
+
lines << ((" " * indent) << line[0..-2])
|
47
|
+
line = ""
|
48
|
+
end
|
49
|
+
(lines * "\n")
|
50
|
+
else
|
51
|
+
paragraph
|
52
|
+
end
|
53
|
+
offset = 0
|
54
|
+
str
|
55
|
+
end*""
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.format_definition_list_item(dt, dd, size = 80, indent = 20, color = :yellow)
|
59
|
+
dd = "" if dd.nil?
|
60
|
+
dt = Log.color color, dt if color
|
61
|
+
dt = dt.to_s unless dd.empty?
|
62
|
+
len = Log.uncolor(dt).length
|
63
|
+
|
64
|
+
if indent < 0
|
65
|
+
text = format_paragraph(dd, size, indent.abs-1, 0)
|
66
|
+
text = dt << "\n" << text
|
67
|
+
else
|
68
|
+
offset = len - indent
|
69
|
+
offset = 0 if offset < 0
|
70
|
+
text = format_paragraph(dd, size, indent.abs+1, offset)
|
71
|
+
text[0..len-1] = dt
|
72
|
+
end
|
73
|
+
text
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.format_definition_list(defs, size = 80, indent = 20, color = :yellow, sep = "\n\n")
|
77
|
+
entries = []
|
78
|
+
defs.each do |dt,dd|
|
79
|
+
text = format_definition_list_item(dt,dd,size,indent,color)
|
80
|
+
entries << text
|
81
|
+
end
|
82
|
+
entries * sep
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.camel_case(string)
|
86
|
+
return string if string !~ /_/ && string =~ /[A-Z]+.*/
|
87
|
+
string.split(/_|(\d+)/).map{|e|
|
88
|
+
(e =~ /^[A-Z]{2,}$/ ? e : e.capitalize)
|
89
|
+
}.join
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.camel_case_lower(string)
|
93
|
+
string.split('_').inject([]){ |buffer,e|
|
94
|
+
buffer.push(buffer.empty? ? e.downcase : (e =~ /^[A-Z]{2,}$/ ? e : e.capitalize))
|
95
|
+
}.join
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.snake_case(string)
|
99
|
+
return nil if string.nil?
|
100
|
+
string = string.to_s if Symbol === string
|
101
|
+
string.
|
102
|
+
gsub(/([A-Z]{2,})([A-Z][a-z])/,'\1_\2').
|
103
|
+
gsub(/([a-z])([A-Z])/,'\1_\2').
|
104
|
+
gsub(/\s/,'_').gsub(/[^\w_]/, '').
|
105
|
+
split("_").collect{|p| p.match(/[A-Z]{2,}/) ? p : p.downcase } * "_"
|
106
|
+
end
|
107
|
+
|
108
|
+
# source: https://gist.github.com/ekdevdes/2450285
|
109
|
+
# author: Ethan Kramer (https://github.com/ekdevdes)
|
110
|
+
def self.humanize(value, options = {})
|
111
|
+
if options.empty?
|
112
|
+
options[:format] = :sentence
|
113
|
+
end
|
114
|
+
|
115
|
+
values = value.to_s.split('_')
|
116
|
+
values.each_index do |index|
|
117
|
+
# lower case each item in array
|
118
|
+
# Miguel Vazquez edit: Except for acronyms
|
119
|
+
values[index].downcase! unless values[index].match(/[a-zA-Z][A-Z]/)
|
120
|
+
end
|
121
|
+
if options[:format] == :allcaps
|
122
|
+
values.each do |value|
|
123
|
+
value.capitalize!
|
124
|
+
end
|
125
|
+
|
126
|
+
if options.empty?
|
127
|
+
options[:seperator] = " "
|
128
|
+
end
|
129
|
+
|
130
|
+
return values.join " "
|
131
|
+
end
|
132
|
+
|
133
|
+
if options[:format] == :class
|
134
|
+
values.each do |value|
|
135
|
+
value.capitalize!
|
136
|
+
end
|
137
|
+
|
138
|
+
return values.join ""
|
139
|
+
end
|
140
|
+
|
141
|
+
if options[:format] == :sentence
|
142
|
+
values[0].capitalize! unless values[0].match(/[a-zA-Z][A-Z]/)
|
143
|
+
|
144
|
+
return values.join " "
|
145
|
+
end
|
146
|
+
|
147
|
+
if options[:format] == :nocaps
|
148
|
+
return values.join " "
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.fixascii(string)
|
153
|
+
if string.respond_to?(:encode)
|
154
|
+
self.fixutf8(string).encode("ASCII-8BIT")
|
155
|
+
else
|
156
|
+
string
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.to_utf8(string)
|
161
|
+
string.encode("UTF-16BE", :invalid => :replace, :undef => :replace, :replace => "?").encode('UTF-8')
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.fixutf8(string)
|
165
|
+
return nil if string.nil?
|
166
|
+
return string if string.respond_to?(:encoding) && string.encoding.to_s == "UTF-8" && (string.respond_to?(:valid_encoding?) && string.valid_encoding?) ||
|
167
|
+
(string.respond_to?(:valid_encoding) && string.valid_encoding)
|
168
|
+
|
169
|
+
if string.respond_to?(:encode)
|
170
|
+
string.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
|
171
|
+
else
|
172
|
+
require 'iconv'
|
173
|
+
@@ic ||= Iconv.new('UTF-8//IGNORE', 'UTF-8')
|
174
|
+
@@ic.iconv(string)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def self.humanize_list(list)
|
179
|
+
return "" if list.empty?
|
180
|
+
if list.length == 1
|
181
|
+
list.first
|
182
|
+
else
|
183
|
+
list[0..-2].collect{|e| e.to_s} * ", " << " and " << list[-1].to_s
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def self.parse_sql_values(txt)
|
188
|
+
io = StringIO.new txt.strip
|
189
|
+
|
190
|
+
values = []
|
191
|
+
fields = []
|
192
|
+
current = nil
|
193
|
+
quoted = false
|
194
|
+
while c = io.getc
|
195
|
+
if quoted
|
196
|
+
if c == "'"
|
197
|
+
quoted = false
|
198
|
+
else
|
199
|
+
current << c
|
200
|
+
end
|
201
|
+
else
|
202
|
+
case c
|
203
|
+
when "("
|
204
|
+
current = ""
|
205
|
+
when ")"
|
206
|
+
fields << current
|
207
|
+
values << fields
|
208
|
+
fields = []
|
209
|
+
current = nil
|
210
|
+
when ','
|
211
|
+
if not current.nil?
|
212
|
+
fields << current
|
213
|
+
current = ""
|
214
|
+
end
|
215
|
+
when "'"
|
216
|
+
quoted = true
|
217
|
+
when ";"
|
218
|
+
break
|
219
|
+
else
|
220
|
+
current << c
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
values
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
data/lib/scout/misc.rb
ADDED
data/lib/scout/path/find.rb
CHANGED
@@ -1,65 +1,120 @@
|
|
1
|
+
require_relative '../indiferent_hash'
|
1
2
|
module Path
|
3
|
+
|
2
4
|
def _parts
|
3
5
|
@_parts ||= self.split("/")
|
4
6
|
end
|
5
7
|
|
6
8
|
def _subpath
|
7
|
-
@subpath ||= _parts.length > 1 ? _parts[1..-1] * "/" : _parts[0]
|
9
|
+
@subpath ||= _parts.length > 1 ? _parts[1..-1] * "/" : _parts[0] || ""
|
8
10
|
end
|
9
11
|
|
10
12
|
def _toplevel
|
11
|
-
@toplevel ||= _parts.length > 1 ? _parts[0] :
|
13
|
+
@toplevel ||= _parts.length > 1 ? _parts[0] : ""
|
12
14
|
end
|
13
15
|
|
14
16
|
def self.follow(path, map)
|
15
|
-
map.sub('{PKGDIR}', path.pkgdir).
|
16
|
-
sub('{RESOURCE}', path.to_s).
|
17
|
+
map.sub('{PKGDIR}', path.pkgdir.respond_to?(:subdir) ? path.pkgdir.pkgdir : path.pkgdir || Path.default_pkgdir).
|
18
|
+
sub('{RESOURCE}', path.pkgdir.to_s).
|
17
19
|
sub('{PWD}', FileUtils.pwd).
|
18
20
|
sub('{TOPLEVEL}', path._toplevel).
|
19
21
|
sub('{SUBPATH}', path._subpath).
|
20
22
|
sub('{BASENAME}', File.basename(path)).
|
21
23
|
sub('{PATH}', path).
|
22
|
-
sub('{LIBDIR}', path.libdir).
|
24
|
+
sub('{LIBDIR}', path.libdir || (path.pkgdir.respond_to?(:libdir) && path.pkgdir.libdir) || Path.caller_lib_dir).
|
23
25
|
sub('{REMOVE}/', '').
|
24
26
|
sub('{REMOVE}', '').gsub(/\/+/,'/')
|
25
27
|
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def
|
44
|
-
|
29
|
+
def self.path_maps
|
30
|
+
@@path_maps ||= IndiferentHash.setup({
|
31
|
+
:current => File.join("{PWD}", "{TOPLEVEL}", "{SUBPATH}"),
|
32
|
+
:user => File.join(ENV['HOME'], ".{PKGDIR}", "{TOPLEVEL}", "{SUBPATH}"),
|
33
|
+
:global => File.join('/', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
34
|
+
:usr => File.join('/usr/', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
35
|
+
:local => File.join('/usr/local', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
36
|
+
:fast => File.join('/fast', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
37
|
+
:cache => File.join('/cache', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
38
|
+
:bulk => File.join('/bulk', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
39
|
+
:lib => File.join('{LIBDIR}', "{TOPLEVEL}", "{SUBPATH}"),
|
40
|
+
:base => File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}", "{SUBPATH}"),
|
41
|
+
:default => :user
|
42
|
+
})
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.map_search
|
46
|
+
@@map_search ||= %w(current workflow user local global lib fast cache bulk)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.search_order
|
50
|
+
@@search_order ||= (path_maps.keys & map_search) + (path_maps.keys - map_search)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.add_path(name, map)
|
54
|
+
@@path_maps[name] = map
|
55
|
+
@@search_order = nil
|
56
|
+
end
|
57
|
+
|
58
|
+
SLASH = "/"[0]
|
59
|
+
DOT = "."[0]
|
60
|
+
def located?
|
61
|
+
# OPEN RESOURCE
|
62
|
+
self.slice(0,1) == SLASH || (self.slice(0,1) == DOT && self.slice(1,2) == SLASH) # || (resource != Rbbt && (Open.remote?(self) || Open.ssh?(self)))
|
63
|
+
end
|
64
|
+
|
65
|
+
def annotate_found_where(found, where)
|
66
|
+
self.annotate(found).tap{|p|
|
67
|
+
p.instance_variable_set("@where", where)
|
68
|
+
p.instance_variable_set("@original", self.dup)
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def where
|
73
|
+
@where
|
74
|
+
end
|
75
|
+
|
76
|
+
def original
|
77
|
+
@original
|
78
|
+
end
|
79
|
+
|
80
|
+
def follow(map_name = :default, annotate = true)
|
81
|
+
map = Path.path_maps[map_name]
|
45
82
|
while Symbol === map
|
46
|
-
|
83
|
+
map_name = map
|
84
|
+
map = Path.path_maps[map_name]
|
47
85
|
end
|
48
|
-
Path.follow(self, map)
|
86
|
+
found = Path.follow(self, map)
|
87
|
+
|
88
|
+
annotate_found_where(found, map_name) if annotate
|
89
|
+
|
90
|
+
found
|
49
91
|
end
|
50
92
|
|
51
93
|
def find(where = nil)
|
52
|
-
return
|
94
|
+
return self if located?
|
95
|
+
return find_all if where == 'all' || where == :all
|
96
|
+
return follow(where) if where
|
53
97
|
|
54
|
-
|
55
|
-
|
98
|
+
Path.search_order.each do |map_name|
|
99
|
+
found = follow(map_name, false)
|
56
100
|
|
57
|
-
|
58
|
-
map = PATH_MAPS[name]
|
59
|
-
real_path = _follow(map)
|
60
|
-
return real_path if File.exists?(real_path)
|
101
|
+
return annotate_found_where(found, map_name) if File.exist?(found) || File.directory?(found)
|
61
102
|
end
|
62
103
|
|
63
|
-
return
|
104
|
+
return follow(:default)
|
105
|
+
end
|
106
|
+
|
107
|
+
def exist?
|
108
|
+
# OPEN
|
109
|
+
found = self.find
|
110
|
+
File.exist?(found) || File.directory?(found)
|
111
|
+
end
|
112
|
+
|
113
|
+
alias exists? exist?
|
114
|
+
|
115
|
+
def find_all(caller_lib = nil, search_paths = nil)
|
116
|
+
Path.search_order
|
117
|
+
.collect{|where| find(where) }
|
118
|
+
.select{|file| file.exist? }.uniq
|
64
119
|
end
|
65
120
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Path
|
2
|
+
def directory?
|
3
|
+
return nil unless self.exist?
|
4
|
+
File.directory?(self.find)
|
5
|
+
end
|
6
|
+
|
7
|
+
def dirname
|
8
|
+
self.annotate(File.dirname(self))
|
9
|
+
end
|
10
|
+
|
11
|
+
def basename
|
12
|
+
self.annotate(File.basename(self))
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def glob(pattern = '*')
|
17
|
+
if self.include? "*"
|
18
|
+
self.glob_all
|
19
|
+
else
|
20
|
+
return [] unless self.exist?
|
21
|
+
found = self.find
|
22
|
+
exp = File.join(found, pattern)
|
23
|
+
paths = Dir.glob(exp).collect{|f| self.annotate(f) }
|
24
|
+
|
25
|
+
paths.each do |p|
|
26
|
+
p.original = File.join(found.original, p.sub(/^#{found}/, ''))
|
27
|
+
end if found.original
|
28
|
+
|
29
|
+
paths
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def glob_all(pattern = nil, caller_lib = nil, search_paths = nil)
|
34
|
+
search_paths ||= Path.path_maps
|
35
|
+
search_paths = search_paths.dup
|
36
|
+
|
37
|
+
search_paths.keys.collect do |where|
|
38
|
+
found = find(where)
|
39
|
+
paths = pattern ? Dir.glob(File.join(found, pattern)) : Dir.glob(found)
|
40
|
+
|
41
|
+
paths = paths.collect{|p| self.annotate p }
|
42
|
+
|
43
|
+
paths = paths.each do |p|
|
44
|
+
p.original = File.join(found.original, p.sub(/^#{found}/, ''))
|
45
|
+
p.where = where
|
46
|
+
end if found.original and pattern
|
47
|
+
|
48
|
+
paths
|
49
|
+
end.flatten.uniq
|
50
|
+
end
|
51
|
+
end
|
data/lib/scout/path.rb
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
require_relative 'meta_extension'
|
2
|
+
require_relative 'path/find'
|
3
|
+
require_relative 'path/util'
|
2
4
|
|
3
5
|
module Path
|
4
6
|
extend MetaExtension
|
5
|
-
extension_attr :pkgdir, :libdir
|
7
|
+
extension_attr :pkgdir, :libdir, :path_maps
|
6
8
|
|
7
9
|
def self.caller_lib_dir(file = nil, relative_to = ['lib', 'bin'])
|
8
10
|
|
9
11
|
if file.nil?
|
10
12
|
caller_dup = caller.dup
|
11
13
|
while file = caller_dup.shift
|
12
|
-
break unless file =~ /scout\/(?:resource\.rb|workflow\.rb)/ or
|
13
|
-
file =~ /scout\/path\.rb/ or
|
14
|
-
file =~ /scout\/
|
14
|
+
break unless file =~ /(?:scout|rbbt)\/(?:resource\.rb|workflow\.rb)/ or
|
15
|
+
file =~ /(?:scout|rbbt)\/(?:.*\/)?path\.rb/ or
|
16
|
+
file =~ /(?:scout|rbbt)\/(?:.*\/)?path\/(?:find|refactor|util)\.rb/ or
|
17
|
+
file =~ /(?:scout|rbbt)\/persist.rb/
|
15
18
|
end
|
16
19
|
file = file.sub(/\.rb[^\w].*/,'.rb')
|
17
20
|
end
|
@@ -31,11 +34,21 @@ module Path
|
|
31
34
|
return nil
|
32
35
|
end
|
33
36
|
|
34
|
-
def self.
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
def self.default_pkgdir
|
38
|
+
@@default_pkgdir ||= 'scout'
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.default_pkgdir=(pkgdir)
|
42
|
+
@@default_pkgdir = pkgdir
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def pkgdir
|
47
|
+
@pkgdir ||= Path.default_pkgdir
|
48
|
+
end
|
49
|
+
|
50
|
+
def libdir
|
51
|
+
@libdir
|
39
52
|
end
|
40
53
|
|
41
54
|
def join(subpath, prevpath = nil)
|
@@ -43,7 +56,7 @@ module Path
|
|
43
56
|
prevpath = prevpath.to_s if Symbol === prevpath
|
44
57
|
|
45
58
|
subpath = File.join(prevpath.to_s, subpath) if prevpath
|
46
|
-
new = File.join(self, subpath)
|
59
|
+
new = self.empty? ? subpath : File.join(self, subpath)
|
47
60
|
self.annotate(new)
|
48
61
|
new
|
49
62
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module SOPT
|
2
|
+
class << self
|
3
|
+
attr_accessor :inputs, :input_shortcuts, :input_types, :input_descriptions, :input_defaults
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.all
|
7
|
+
@all ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.shortcuts
|
11
|
+
@shortcuts ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.inputs
|
15
|
+
@inputs ||= []
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.input_shortcuts
|
19
|
+
@input_shortcuts ||= {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.input_types
|
23
|
+
@input_types ||= {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.input_descriptions
|
27
|
+
@input_descriptions ||= {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.input_defaults
|
31
|
+
@input_defaults ||= {}
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.reset
|
35
|
+
@shortcuts = {}
|
36
|
+
@all = {}
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.delete_inputs(inputs)
|
40
|
+
inputs.each do |input|
|
41
|
+
input = input.to_s
|
42
|
+
self.shortcuts.delete self.input_shortcuts.delete(input)
|
43
|
+
self.inputs.delete input
|
44
|
+
self.input_types.delete input
|
45
|
+
self.input_defaults.delete input
|
46
|
+
self.input_descriptions.delete input
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.usage
|
51
|
+
puts SOPT.doc
|
52
|
+
exit 0
|
53
|
+
end
|
54
|
+
end
|