clio 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. data/COPYING +170 -0
  2. data/HISTORY +11 -0
  3. data/MANIFEST +181 -0
  4. data/METADATA +18 -0
  5. data/NEWS +10 -0
  6. data/README +52 -0
  7. data/admin/config/reap.yaml +30 -0
  8. data/admin/depot/commandline.rb +219 -0
  9. data/admin/depot/multicommand.rb +403 -0
  10. data/admin/depot/test_multicommand.rb +40 -0
  11. data/admin/log/notes.xml +28 -0
  12. data/admin/log/stats.html +25 -0
  13. data/admin/log/syntax.log +0 -0
  14. data/admin/log/testunit.log +16 -0
  15. data/admin/pack/clio-0.0.1.gem +0 -0
  16. data/admin/share/reap/example.rb +7 -0
  17. data/admin/temps/lib/clio/about.rb.erb +4 -0
  18. data/lib/clio/ansicode.rb +319 -0
  19. data/lib/clio/command.rb +296 -0
  20. data/lib/clio/commandable.rb +195 -0
  21. data/lib/clio/commandline.rb +275 -0
  22. data/lib/clio/consoleutils.rb +117 -0
  23. data/lib/clio/errors.rb +16 -0
  24. data/lib/clio/option.rb +36 -0
  25. data/lib/clio/progressbar.rb +253 -0
  26. data/lib/clio/runmode.rb +126 -0
  27. data/lib/clio/string.rb +147 -0
  28. data/test/test_command.rb +42 -0
  29. data/test/test_commandline.rb +83 -0
  30. data/vendor/Console/Console.cpp +1203 -0
  31. data/vendor/Console/Console.rdoc +690 -0
  32. data/vendor/Console/Console_ANSI.rdoc +302 -0
  33. data/vendor/Console/HISTORY.txt +7 -0
  34. data/vendor/Console/INSTALL.txt +18 -0
  35. data/vendor/Console/Makefile +162 -0
  36. data/vendor/Console/README.txt +26 -0
  37. data/vendor/Console/doc/classes/Win32.html +115 -0
  38. data/vendor/Console/doc/classes/Win32/Console.html +650 -0
  39. data/vendor/Console/doc/classes/Win32/Console.src/M000001.html +31 -0
  40. data/vendor/Console/doc/classes/Win32/Console.src/M000002.html +23 -0
  41. data/vendor/Console/doc/classes/Win32/Console.src/M000003.html +23 -0
  42. data/vendor/Console/doc/classes/Win32/Console.src/M000004.html +27 -0
  43. data/vendor/Console/doc/classes/Win32/Console.src/M000005.html +23 -0
  44. data/vendor/Console/doc/classes/Win32/Console.src/M000006.html +28 -0
  45. data/vendor/Console/doc/classes/Win32/Console.src/M000007.html +23 -0
  46. data/vendor/Console/doc/classes/Win32/Console.src/M000008.html +24 -0
  47. data/vendor/Console/doc/classes/Win32/Console.src/M000009.html +44 -0
  48. data/vendor/Console/doc/classes/Win32/Console.src/M000010.html +23 -0
  49. data/vendor/Console/doc/classes/Win32/Console.src/M000011.html +33 -0
  50. data/vendor/Console/doc/classes/Win32/Console.src/M000012.html +26 -0
  51. data/vendor/Console/doc/classes/Win32/Console.src/M000013.html +27 -0
  52. data/vendor/Console/doc/classes/Win32/Console.src/M000014.html +28 -0
  53. data/vendor/Console/doc/classes/Win32/Console.src/M000015.html +23 -0
  54. data/vendor/Console/doc/classes/Win32/Console.src/M000016.html +23 -0
  55. data/vendor/Console/doc/classes/Win32/Console.src/M000017.html +23 -0
  56. data/vendor/Console/doc/classes/Win32/Console.src/M000018.html +29 -0
  57. data/vendor/Console/doc/classes/Win32/Console.src/M000019.html +23 -0
  58. data/vendor/Console/doc/classes/Win32/Console.src/M000020.html +23 -0
  59. data/vendor/Console/doc/classes/Win32/Console.src/M000021.html +28 -0
  60. data/vendor/Console/doc/classes/Win32/Console.src/M000022.html +23 -0
  61. data/vendor/Console/doc/classes/Win32/Console.src/M000023.html +28 -0
  62. data/vendor/Console/doc/classes/Win32/Console.src/M000024.html +35 -0
  63. data/vendor/Console/doc/classes/Win32/Console.src/M000025.html +28 -0
  64. data/vendor/Console/doc/classes/Win32/Console.src/M000026.html +28 -0
  65. data/vendor/Console/doc/classes/Win32/Console.src/M000027.html +28 -0
  66. data/vendor/Console/doc/classes/Win32/Console.src/M000028.html +31 -0
  67. data/vendor/Console/doc/classes/Win32/Console.src/M000029.html +23 -0
  68. data/vendor/Console/doc/classes/Win32/Console.src/M000030.html +23 -0
  69. data/vendor/Console/doc/classes/Win32/Console.src/M000031.html +23 -0
  70. data/vendor/Console/doc/classes/Win32/Console.src/M000032.html +27 -0
  71. data/vendor/Console/doc/classes/Win32/Console.src/M000033.html +27 -0
  72. data/vendor/Console/doc/classes/Win32/Console.src/M000034.html +25 -0
  73. data/vendor/Console/doc/classes/Win32/Console/ANSI.html +103 -0
  74. data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.html +220 -0
  75. data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000035.html +32 -0
  76. data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000036.html +205 -0
  77. data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000037.html +40 -0
  78. data/vendor/Console/doc/classes/Win32/Console/ANSI/IO.src/M000038.html +25 -0
  79. data/vendor/Console/doc/classes/Win32/Console/API.html +758 -0
  80. data/vendor/Console/doc/classes/Win32/Console/API.src/M000039.html +27 -0
  81. data/vendor/Console/doc/classes/Win32/Console/API.src/M000040.html +27 -0
  82. data/vendor/Console/doc/classes/Win32/Console/API.src/M000041.html +27 -0
  83. data/vendor/Console/doc/classes/Win32/Console/API.src/M000042.html +32 -0
  84. data/vendor/Console/doc/classes/Win32/Console/API.src/M000043.html +32 -0
  85. data/vendor/Console/doc/classes/Win32/Console/API.src/M000044.html +28 -0
  86. data/vendor/Console/doc/classes/Win32/Console/API.src/M000045.html +26 -0
  87. data/vendor/Console/doc/classes/Win32/Console/API.src/M000046.html +26 -0
  88. data/vendor/Console/doc/classes/Win32/Console/API.src/M000047.html +27 -0
  89. data/vendor/Console/doc/classes/Win32/Console/API.src/M000048.html +30 -0
  90. data/vendor/Console/doc/classes/Win32/Console/API.src/M000049.html +29 -0
  91. data/vendor/Console/doc/classes/Win32/Console/API.src/M000050.html +27 -0
  92. data/vendor/Console/doc/classes/Win32/Console/API.src/M000051.html +28 -0
  93. data/vendor/Console/doc/classes/Win32/Console/API.src/M000052.html +30 -0
  94. data/vendor/Console/doc/classes/Win32/Console/API.src/M000053.html +27 -0
  95. data/vendor/Console/doc/classes/Win32/Console/API.src/M000054.html +29 -0
  96. data/vendor/Console/doc/classes/Win32/Console/API.src/M000055.html +29 -0
  97. data/vendor/Console/doc/classes/Win32/Console/API.src/M000056.html +28 -0
  98. data/vendor/Console/doc/classes/Win32/Console/API.src/M000057.html +27 -0
  99. data/vendor/Console/doc/classes/Win32/Console/API.src/M000058.html +47 -0
  100. data/vendor/Console/doc/classes/Win32/Console/API.src/M000059.html +32 -0
  101. data/vendor/Console/doc/classes/Win32/Console/API.src/M000060.html +47 -0
  102. data/vendor/Console/doc/classes/Win32/Console/API.src/M000061.html +34 -0
  103. data/vendor/Console/doc/classes/Win32/Console/API.src/M000062.html +32 -0
  104. data/vendor/Console/doc/classes/Win32/Console/API.src/M000063.html +32 -0
  105. data/vendor/Console/doc/classes/Win32/Console/API.src/M000064.html +35 -0
  106. data/vendor/Console/doc/classes/Win32/Console/API.src/M000065.html +26 -0
  107. data/vendor/Console/doc/classes/Win32/Console/API.src/M000066.html +27 -0
  108. data/vendor/Console/doc/classes/Win32/Console/API.src/M000067.html +29 -0
  109. data/vendor/Console/doc/classes/Win32/Console/API.src/M000068.html +27 -0
  110. data/vendor/Console/doc/classes/Win32/Console/API.src/M000069.html +27 -0
  111. data/vendor/Console/doc/classes/Win32/Console/API.src/M000070.html +28 -0
  112. data/vendor/Console/doc/classes/Win32/Console/API.src/M000071.html +27 -0
  113. data/vendor/Console/doc/classes/Win32/Console/API.src/M000072.html +26 -0
  114. data/vendor/Console/doc/classes/Win32/Console/API.src/M000073.html +27 -0
  115. data/vendor/Console/doc/classes/Win32/Console/API.src/M000074.html +31 -0
  116. data/vendor/Console/doc/classes/Win32/Console/API.src/M000075.html +27 -0
  117. data/vendor/Console/doc/classes/Win32/Console/API.src/M000076.html +32 -0
  118. data/vendor/Console/doc/classes/Win32/Console/API.src/M000077.html +27 -0
  119. data/vendor/Console/doc/classes/Win32/Console/API.src/M000078.html +32 -0
  120. data/vendor/Console/doc/classes/Win32/Console/API.src/M000079.html +32 -0
  121. data/vendor/Console/doc/classes/Win32/Console/API.src/M000080.html +32 -0
  122. data/vendor/Console/doc/classes/Win32/Console/Constants.html +360 -0
  123. data/vendor/Console/doc/created.rid +1 -0
  124. data/vendor/Console/doc/files/Console_ANSI_rdoc.html +407 -0
  125. data/vendor/Console/doc/files/Console_cpp.html +104 -0
  126. data/vendor/Console/doc/files/Console_rdoc.html +964 -0
  127. data/vendor/Console/doc/files/lib/Win32/Console/ANSI_rb.html +123 -0
  128. data/vendor/Console/doc/files/lib/Win32/Console_rb.html +297 -0
  129. data/vendor/Console/doc/fr_class_index.html +32 -0
  130. data/vendor/Console/doc/fr_file_index.html +31 -0
  131. data/vendor/Console/doc/fr_method_index.html +106 -0
  132. data/vendor/Console/doc/index.html +24 -0
  133. data/vendor/Console/doc/rdoc-style.css +172 -0
  134. data/vendor/Console/extconf.rb +18 -0
  135. data/vendor/Console/lib/Term/ansicolor.rb +76 -0
  136. data/vendor/Console/lib/Win32/Console.rb +970 -0
  137. data/vendor/Console/lib/Win32/Console/ANSI.rb +305 -0
  138. data/vendor/Console/test/test_cursor.rb +9 -0
  139. data/vendor/Console/test/test_mouse.rb +6 -0
  140. data/vendor/Console/test/test_readinput.rb +62 -0
  141. data/vendor/Console/test/test_readoutput.rb +52 -0
  142. data/vendor/Console/test/test_sendevent.rb +17 -0
  143. data/vendor/Console/test/test_title.rb +14 -0
  144. data/vendor/Console/test/test_write.rb +36 -0
  145. metadata +253 -0
@@ -0,0 +1,275 @@
1
+ require 'shellwords'
2
+ require 'facets/kernel/object_class'
3
+ require 'facets/array/indexable'
4
+
5
+ module Clio
6
+ ### = Commandline
7
+ ###
8
+ ### What a strange thing is the Clio Commandline.
9
+ ### An entity unknown until put upon.
10
+ ###
11
+ ### cmd = Clio::Commandline.new("--force copy --file try.rb")
12
+ ### cmd.option_alias(:f?, :force?)
13
+ ### cmd.option_alias(:o, :file)
14
+ ###
15
+ ### cmd.file #=> 'try.rb'
16
+ ### cmd.force? #=> true
17
+ ### cmd.o #=> 'try.rb'
18
+ ### cmd.f? #=> true
19
+ ###
20
+ ### TODO: Allow option setter methods (?)
21
+ ### TODO: Allow a hash as argument to initialize (?)
22
+ class Commandline
23
+ instance_methods.each{ |m| private m if m !~ /^(__|instance_|object_|send$|inspect$)/ }
24
+
25
+ ### Splits a raw command line into two smaller
26
+ ### ones. The first including only options
27
+ ### upto the first non-option argument. This
28
+ ### makes quick work of separating a subcommand
29
+ ### from the options for a main command.
30
+ # TODO: Rename this method.
31
+ def self.gerrymander(argv=ARGV)
32
+ if String===argv
33
+ argv = Shellwords.shellwords(argv)
34
+ end
35
+ sub = argv.find{ |x| x !~ /^[-]/ }
36
+ idx = argv.index(sub)
37
+ opts = argv[0...idx]
38
+ scmd = argv[idx..-1]
39
+ return opts, scmd
40
+ end
41
+
42
+ ### Define an option attibute.
43
+ ### While commandline can be used without
44
+ ### pre-declartion of support options
45
+ ### doding so allows for creating option
46
+ ### aliases. Eg. --quiet and -q.
47
+ def self.attr(name, *aliases)
48
+ (@predefined_options ||= []) << [name, *aliases]
49
+
50
+ name = name.to_s
51
+ if name =~ /\?$/
52
+ key = name.chomp('?')
53
+ #attr_writer name
54
+ module_eval "def #{key}?; @#{key} ; end"
55
+ aliases.each do |alt|
56
+ alt = alt.to_s.chomp('?')
57
+ alias_method("#{alt}?", "#{key}?")
58
+ #alias_method("#{alt}=", "#{name}=")
59
+ end
60
+ else
61
+ attr_reader name
62
+ #module_eval "def #{name}; self[:#{name}] ; end"
63
+ aliases.each do |alt|
64
+ #alt = alt.to_s.chomp('?') # TODO: raise error ?
65
+ alias_method("#{alt}" , "#{name}")
66
+ #alias_method("#{alt}=", "#{name}=")
67
+ end
68
+ end
69
+ end
70
+
71
+ ### Returns a list of all pre-defined options.
72
+ ### It does this by seaching class ancestry
73
+ ### for instance_methods until it reaches the
74
+ ### Commandline base class.
75
+ ### TODO: Rename #runmodes method.
76
+ ### TODO: Robust enough? Use an Inheritor instead?
77
+ def self.predefined_options
78
+ @predefined_options ||= []
79
+ ancestor = ancestors[1]
80
+ if ancestor > ::Clio::Commandline
81
+ @predefined_options
82
+ else
83
+ @predefined_options | ancestor.predefined_options
84
+ end
85
+ end
86
+
87
+ public
88
+
89
+ ### This method provides the centralized means
90
+ ### of accessing the options and arguments on
91
+ ### the commandline.
92
+ def [](index)
93
+ case index
94
+ when Integer
95
+ @arguments[index] ||= (
96
+ args = @argv.select{ |e| e !~ /^-/ }
97
+ val = args[index]
98
+ @argv.delete(args[index])
99
+ val
100
+ )
101
+ else
102
+ return send(index) if respond_to?(index)
103
+ key = index.to_s.chomp('?')
104
+ val = option_parse(index)
105
+ instance_variable_set("@#{key}", val)
106
+ (class << self; self; end).class_eval %{
107
+ def #{index}; @#{key}; end
108
+ }
109
+ return val
110
+ end
111
+ end
112
+
113
+ def shift!
114
+ args = @argv.select{ |e| e !~ /^-/ }
115
+ val = args.first
116
+ @argv.delete(val)
117
+ val
118
+ end
119
+
120
+ ### Define an option alias. This adds en entry to
121
+ ### the aliases hash, pointing new to a list of
122
+ ### all aliases and the first entry on th list
123
+ ### being the master key.
124
+ def option_alias(new, old)
125
+ self[old]
126
+ key = old.to_s.chomp('?')
127
+ val = option_parse(new)
128
+ instance_variable_set("@#{key}", val) if val
129
+ (class << self; self; end).class_eval do
130
+ alias_method new, old
131
+ end
132
+ end
133
+
134
+ ### Access to the underlying commandline "ARGV".
135
+ ### This will show what is yet to be processed.
136
+ def instance_delegate ; @argv ; end
137
+
138
+ ### Returns a hash of all options parsed.
139
+ def instance_options
140
+ h = {}
141
+ ivs = instance_variables - ['@arguments','@argv']
142
+ ivs.each do |iv|
143
+ val = instance_variable_get(iv)
144
+ h[iv.sub('@','').to_sym] = val if val
145
+ end
146
+ h
147
+ end
148
+
149
+ ### Returns a list of all arguments parsed.
150
+ def instance_arguments
151
+ @arguments
152
+ end
153
+
154
+ private
155
+
156
+ ### New Commandline. Takse a single argument
157
+ ### which can be a "shell" string, or an array
158
+ ### of shell arguments, like ARGV. If none
159
+ ### is given it defaults to ARGV.
160
+ def initialize(argv=ARGV)
161
+ case argv
162
+ when String
163
+ @argv = Shellwords.shellwords(argv)
164
+ #when Hash
165
+ # argv.each{ |k,v| send("#{k}=", v) }
166
+ else
167
+ @argv = argv.dup
168
+ end
169
+ @arguments = []
170
+
171
+ # parse predefined options attributes.
172
+ object_class.predefined_options.each do |modes|
173
+ key = modes.first.to_s.chomp('?')
174
+ modes.reverse.each do |i|
175
+ val = option_parse(i)
176
+ instance_variable_set("@#{key}", val) if val
177
+ end
178
+ end
179
+ end
180
+
181
+ ### Routes to #[].
182
+ def method_missing(name, *args)
183
+ super unless args.empty?
184
+ case name.to_s
185
+ when /\=$/
186
+ super
187
+ else
188
+ self[name]
189
+ end
190
+ end
191
+
192
+ def option_parse(index)
193
+ index = index.to_s
194
+ name = index.chomp('?')
195
+ key = name.to_sym
196
+
197
+ kind = name.size == 1 ? 'letter' : 'word'
198
+ flag = index =~ /\?$/ ? 'flag' : 'value'
199
+
200
+ send("option_#{kind}_#{flag}", key)
201
+ end
202
+
203
+ ### Parse a flag option.
204
+ def option_word_flag(name)
205
+ o = "--#{name}"
206
+ i = @argv.index_of{ |e| e =~ /^#{o}[=]?/ }
207
+ return false unless i
208
+ raise ArgumentError if @argv[i] =~ /=/
209
+ @argv.delete_at(i)
210
+ return true
211
+ end
212
+
213
+ ### Parse a value option.
214
+ def option_word_value(name)
215
+ o = "--#{name}"
216
+ i = @argv.index_of{ |e| e =~ /^#{o}[=]?/ }
217
+ return false unless i
218
+
219
+ if @argv[i] =~ /=/
220
+ key, val = *@argv[i].split('=')
221
+ argv[i] = nil
222
+ else
223
+ case @argv[i+1]
224
+ when nil, /^-/
225
+ raise ArgumentError
226
+ else
227
+ key = @argv[i]
228
+ val = @argv[i+1]
229
+ @argv.delete_at(i) # do it twice
230
+ @argv.delete_at(i)
231
+ end
232
+ end
233
+ return val
234
+ end
235
+
236
+ ### Parse a single letter flag option.
237
+ def option_letter_flag(letter)
238
+ o = letter
239
+ i = @argv.index_of{ |e| e =~ /[-][^-]\w*(#{o})\w*$/ }
240
+ if i
241
+ @argv[i] = @argv[i].gsub(o.to_s,'')
242
+ true
243
+ end
244
+ false
245
+ end
246
+
247
+ ### Parse a single letter value option.
248
+ def option_letter_value(letter)
249
+ o = letter
250
+ i = @argv.index_of{ |e| e =~ /[-]\w*#{o}(\=|$)/ }
251
+ return nil unless i
252
+ if @argv[i] =~ /=/
253
+ rest, val = argv[i].split('=')
254
+ @argv[i] = rest
255
+ else
256
+ case @argv[i+1]
257
+ when nil, /^-/
258
+ raise ArgumentError
259
+ else
260
+ val = @argv[i+1]
261
+ new = @argv[i].gsub(o.to_s,'')
262
+ if new == '-'
263
+ @argv.delete_at(i)
264
+ else
265
+ @argv[i] = new
266
+ end
267
+ @argv.delete_at(i+1)
268
+ end
269
+ end
270
+ return val
271
+ end
272
+
273
+ end
274
+ end
275
+
@@ -0,0 +1,117 @@
1
+ # = Console Utilities
2
+ #
3
+ # ConsoleUtils provides methods that are
4
+ # generally useful in the context of
5
+ # creating console output.
6
+ #
7
+ # = Authors
8
+ #
9
+ # * Thomas Sawyer
10
+ #
11
+ # == Copying
12
+ #
13
+ # Copyright (c) 2006,2007 Thomas Sawyer
14
+ # Ruby/GPL
15
+
16
+
17
+ module Clio
18
+
19
+ # = Termninal
20
+ #
21
+ # ConsoleUtils provides methods that are
22
+ # generally useful in the context of
23
+ # creating console output.
24
+ #
25
+ module Terminal
26
+
27
+ module_function
28
+
29
+ # Convenient method to get simple console reply.
30
+
31
+ def ask(question, answers=nil)
32
+ print "#{question}"
33
+ print " [#{answers}] " if answers
34
+ until inp = $stdin.gets ; sleep 1 ; end
35
+ inp
36
+ end
37
+
38
+ # Convenience method for puts. Use this instead of
39
+ # puts when the output should be supressed if the
40
+ # global $QUIET option is set.
41
+
42
+ #def say(statement)
43
+ # puts statement #unless quiet? $QUIET
44
+ #end
45
+
46
+ # Ask for a password. (FIXME: only for unix so far)
47
+
48
+ def password(msg=nil)
49
+ msg ||= "Enter Password: "
50
+ inp = ''
51
+
52
+ $stdout << msg
53
+
54
+ begin
55
+ system "stty -echo"
56
+ inp = gets.chomp
57
+ ensure
58
+ system "stty echo"
59
+ end
60
+
61
+ return inp
62
+ end
63
+
64
+ # Console screen width (taken from progress bar)
65
+ #
66
+ # TODO: Don't know how portable #screen_width is.
67
+
68
+ def screen_width(out=STDERR)
69
+ default_width = ENV['COLUMNS'] || 80
70
+ begin
71
+ tiocgwinsz = 0x5413
72
+ data = [0, 0, 0, 0].pack("SSSS")
73
+ if out.ioctl(tiocgwinsz, data) >= 0 then
74
+ rows, cols, xpixels, ypixels = data.unpack("SSSS")
75
+ if cols >= 0 then cols else default_width end
76
+ else
77
+ default_width
78
+ end
79
+ rescue Exception
80
+ default_width
81
+ end
82
+ end
83
+
84
+ # Print a justified line with left and right entries.
85
+ #
86
+ # A fill option can be given to fill in any empty space
87
+ # between the two. And a ratio option can be given which defaults
88
+ # to 0.8 (eg. 80/20)
89
+
90
+ def print_justified(left, right, options={})
91
+ fill = options[:fill] || '.'
92
+ fill = ' ' if fill == ''
93
+ fill = fill[0,1]
94
+
95
+ ratio = options[:ratio] || 0.8
96
+ ratio = 1 + ratio if ratio < 0
97
+
98
+ width = (@screen_width ||= screen_width) - 1
99
+
100
+ #l = (width * ratio).to_i
101
+ r = (width * (1 - ratio)).to_i
102
+ l = width - r
103
+
104
+ left = left[0,l]
105
+ right = right[0,r]
106
+
107
+ str = fill * width
108
+ str[0,left.size] = left
109
+ str[width-right.size,right.size] = right
110
+
111
+ print str
112
+ end
113
+
114
+ end
115
+
116
+ end
117
+
@@ -0,0 +1,16 @@
1
+ module Clio
2
+
3
+ class NoOptionError < ::NoMethodError # ArgumentError ?
4
+ def initialize(name, *arg)
5
+ super("unknown option -- #{name}", name, *args)
6
+ end
7
+ end
8
+
9
+ class NoCommandError < ::NoMethodError
10
+ def initialize(name, *arg)
11
+ super("unknown subcommand -- #{name}", name, *args)
12
+ end
13
+ end
14
+
15
+ end
16
+
@@ -0,0 +1,36 @@
1
+ module Clio
2
+
3
+ # Option class. This is used by some command
4
+ # of the command line parser class to store
5
+ # option information.
6
+ class Option
7
+ attr_reader :name
8
+ attr_accessor :type
9
+ attr_accessor :init
10
+ attr_accessor :desc
11
+
12
+ alias_method :default, :init
13
+ alias_method :description, :desc
14
+
15
+ def initialize(name, desc, opts)
16
+ @name = name
17
+ @desc = desc
18
+ @type = opts[:type] || 'value'
19
+ @init = opts[:default] || opts[:init]
20
+ end
21
+ def usage
22
+ "--#{name}=#{type.to_s.upcase}"
23
+ end
24
+ def assert_valid(value)
25
+ raise "invalid" unless valid?(value)
26
+ end
27
+ def valid?(value)
28
+ validation ? validation.call(value) : true
29
+ end
30
+ def validation(&block)
31
+ @validation = block if block
32
+ @validation
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,253 @@
1
+ # = Progressbar
2
+ #
3
+ # ProgressBar is a text-based progressbar library.
4
+ #
5
+ # == Usage
6
+ #
7
+ # pbar = ProgressBar.new( "Demo", 100 )
8
+ # 100.times { pbar.inc }
9
+ # pbar.finish
10
+ #
11
+ # == Copying
12
+ #
13
+ # Copyright (C) 2001 Satoru Takabayashi
14
+ #
15
+ # Ruby License
16
+ #
17
+ # This module is free software. You may use, modify, and/or redistribute this
18
+ # software under the same terms as Ruby.
19
+ #
20
+ # This program is distributed in the hope that it will be useful, but WITHOUT
21
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22
+ # FOR A PARTICULAR PURPOSE.
23
+ #
24
+ # == Author
25
+ #
26
+ # * Satoru Takabayashi
27
+
28
+ # = ProgressBar
29
+ #
30
+ # ProgressBar is a text-based progressbar library.
31
+ #
32
+ # pbar = ProgressBar.new( "Demo", 100 )
33
+ # 100.times { pbar.inc }
34
+ # pbar.finish
35
+ #
36
+ class ProgressBar
37
+
38
+ def initialize(title, total, out = STDERR)
39
+ @title = title
40
+ @total = total
41
+ @out = out
42
+ @bar_length = 80
43
+ @bar_mark = "o"
44
+ @total_overflow = true
45
+ @current = 0
46
+ @previous = 0
47
+ @is_finished = false
48
+ @start_time = Time.now
49
+ @format = "%-14s %3d%% %s %s"
50
+ @format_arguments = [:title, :percentage, :bar, :stat]
51
+ show_progress
52
+ end
53
+
54
+ private
55
+ def convert_bytes (bytes)
56
+ if bytes < 1024
57
+ sprintf("%6dB", bytes)
58
+ elsif bytes < 1024 * 1000 # 1000kb
59
+ sprintf("%5.1fKB", bytes.to_f / 1024)
60
+ elsif bytes < 1024 * 1024 * 1000 # 1000mb
61
+ sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
62
+ else
63
+ sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
64
+ end
65
+ end
66
+
67
+ def transfer_rate
68
+ bytes_per_second = @current.to_f / (Time.now - @start_time)
69
+ sprintf("%s/s", convert_bytes(bytes_per_second))
70
+ end
71
+
72
+ def bytes
73
+ convert_bytes(@current)
74
+ end
75
+
76
+ def format_time(t)
77
+ t = t.to_i
78
+ sec = t % 60
79
+ min = (t / 60) % 60
80
+ hour = t / 3600
81
+ sprintf("%02d:%02d:%02d", hour, min, sec);
82
+ end
83
+
84
+ # ETA stands for Estimated Time of Arrival.
85
+ def eta
86
+ if @current == 0
87
+ "ETA: --:--:--"
88
+ else
89
+ elapsed = Time.now - @start_time
90
+ eta = elapsed * @total / @current - elapsed;
91
+ sprintf("ETA: %s", format_time(eta))
92
+ end
93
+ end
94
+
95
+ def elapsed
96
+ elapsed = Time.now - @start_time
97
+ sprintf("Time: %s", format_time(elapsed))
98
+ end
99
+
100
+ def stat
101
+ if @is_finished then elapsed else eta end
102
+ end
103
+
104
+ def stat_for_file_transfer
105
+ if @is_finished then
106
+ sprintf("%s %s %s", bytes, transfer_rate, elapsed)
107
+ else
108
+ sprintf("%s %s %s", bytes, transfer_rate, eta)
109
+ end
110
+ end
111
+
112
+ def eol
113
+ if @is_finished then "\n" else "\r" end
114
+ end
115
+
116
+ def bar
117
+ len = percentage * @bar_length / 100
118
+ sprintf("|%s%s|", @bar_mark * len, " " * (@bar_length - len))
119
+ end
120
+
121
+ def percentage
122
+ if @total.zero?
123
+ 100
124
+ else
125
+ @current * 100 / @total
126
+ end
127
+ end
128
+
129
+ def title
130
+ @title[0,13] + ":"
131
+ end
132
+
133
+ def get_width
134
+ # FIXME: I don't know how portable it is.
135
+ default_width = 80
136
+ begin
137
+ tiocgwinsz = 0x5413
138
+ data = [0, 0, 0, 0].pack("SSSS")
139
+ if @out.ioctl(tiocgwinsz, data) >= 0 then
140
+ rows, cols, xpixels, ypixels = data.unpack("SSSS")
141
+ if cols >= 0 then cols else default_width end
142
+ else
143
+ default_width
144
+ end
145
+ rescue Exception
146
+ default_width
147
+ end
148
+ end
149
+
150
+ def show
151
+ arguments = @format_arguments.map{|method| send(method)}
152
+ line = sprintf(@format, *arguments)
153
+
154
+ width = get_width
155
+ if line.length == width - 1
156
+ @out.print(line + eol)
157
+ elsif line.length >= width
158
+ @bar_length = [@bar_length - (line.length - width + 1), 0].max
159
+ if @bar_length == 0 then @out.print(line + eol) else show end
160
+ else #line.length < width - 1
161
+ @bar_length += width - line.length + 1
162
+ show
163
+ end
164
+ end
165
+
166
+ def show_progress
167
+ if @total.zero?
168
+ cur_percentage = 100
169
+ prev_percentage = 0
170
+ else
171
+ cur_percentage = (@current * 100 / @total).to_i
172
+ prev_percentage = (@previous * 100 / @total).to_i
173
+ end
174
+
175
+ if cur_percentage > prev_percentage || @is_finished
176
+ show
177
+ end
178
+ end
179
+
180
+ public
181
+ def file_transfer_mode
182
+ @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
183
+ end
184
+
185
+ def title=(str)
186
+ @title = str
187
+ end
188
+
189
+ def bar_mark=(mark)
190
+ @bar_mark = String(mark)[0..0]
191
+ end
192
+
193
+ def total_overflow=(boolv)
194
+ @total_overflow = boolv ? true : false
195
+ end
196
+
197
+ def format=(format)
198
+ @format = format
199
+ end
200
+
201
+ def format_arguments=(arguments)
202
+ @format_arguments = arguments
203
+ end
204
+
205
+ def finish
206
+ @current = @total
207
+ @is_finished = true
208
+ show_progress
209
+ end
210
+
211
+ def flush
212
+ @out.flush
213
+ end
214
+
215
+ def halt
216
+ @is_finished = true
217
+ show_progress
218
+ end
219
+
220
+ def set(count)
221
+ if count < 0
222
+ raise "invalid count less than zero: #{count}"
223
+ elsif count > @total
224
+ if @total_overflow
225
+ @total = count + 1
226
+ else
227
+ raise "invalid count greater than total: #{count}"
228
+ end
229
+ end
230
+ @current = count
231
+ show_progress
232
+ @previous = @current
233
+ end
234
+
235
+ def inc(step = 1)
236
+ @current += step
237
+ @current = @total if @current > @total
238
+ show_progress
239
+ @previous = @current
240
+ end
241
+
242
+ def inspect
243
+ "(ProgressBar: #{@current}/#{@total})"
244
+ end
245
+
246
+ end
247
+
248
+
249
+ module Console #:nodoc:
250
+ # For backward compatibility
251
+ ProgressBar = ::ProgressBar
252
+ end
253
+