rad 0.2.9 → 0.3.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/History.txt +5 -0
- data/Manifest.txt +4 -0
- data/bin/rad +215 -152
- data/lib/examples/software_serial.rb +10 -0
- data/lib/rad/generators/makefile/makefile.erb +1 -1
- data/lib/rad/progressbar.rb +236 -0
- data/lib/rad/version.rb +2 -2
- data/test/hello_world_test/Makefile +436 -0
- data/test/hello_world_test/hello_world.cpp +23 -0
- data/website/index.html +14 -57
- metadata +16 -2
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -37,6 +37,7 @@ lib/examples/motor_knob.rb
|
|
37
37
|
lib/examples/servo_buttons.rb
|
38
38
|
lib/examples/servo_calibrate_continuous.rb
|
39
39
|
lib/examples/servo_throttle.rb
|
40
|
+
lib/examples/software_serial.rb
|
40
41
|
lib/examples/sparkfun_lcd.rb
|
41
42
|
lib/examples/spectra_soft_pot.rb
|
42
43
|
lib/examples/times_method.rb
|
@@ -104,6 +105,7 @@ lib/rad/generators/makefile/makefile.erb
|
|
104
105
|
lib/rad/generators/makefile/makefile.rb
|
105
106
|
lib/rad/hardware_library.rb
|
106
107
|
lib/rad/init.rb
|
108
|
+
lib/rad/progressbar.rb
|
107
109
|
lib/rad/rad_processor.rb
|
108
110
|
lib/rad/rad_rewriter.rb
|
109
111
|
lib/rad/rad_type_checker.rb
|
@@ -123,6 +125,8 @@ spec/models/sketch_compiler_spec.rb
|
|
123
125
|
spec/models/spec_helper.rb
|
124
126
|
spec/sim/hello_world_spec.rb
|
125
127
|
spec/spec.opts
|
128
|
+
test/hello_world_test/Makefile
|
129
|
+
test/hello_world_test/hello_world.cpp
|
126
130
|
test/test_array_processing.rb
|
127
131
|
test/test_plugin_loading.rb
|
128
132
|
test/test_translation_post_processing.rb
|
data/bin/rad
CHANGED
@@ -9,8 +9,11 @@ end
|
|
9
9
|
require 'optparse'
|
10
10
|
require 'fileutils'
|
11
11
|
require 'yaml'
|
12
|
+
require 'open-uri'
|
13
|
+
require 'readline'
|
12
14
|
|
13
15
|
require File.expand_path(File.dirname(__FILE__)) + "/../lib/rad/version.rb"
|
16
|
+
require File.expand_path(File.dirname(__FILE__)) + "/../lib/rad/progressbar.rb"
|
14
17
|
|
15
18
|
class OptionParser #:nodoc:
|
16
19
|
|
@@ -23,7 +26,7 @@ class OptionParser #:nodoc:
|
|
23
26
|
"physical_reset" => false
|
24
27
|
},
|
25
28
|
"software" => {
|
26
|
-
"arduino_root" => "/Applications/arduino-
|
29
|
+
"arduino_root" => "/Applications/arduino-0012"
|
27
30
|
}
|
28
31
|
}
|
29
32
|
|
@@ -90,158 +93,218 @@ end
|
|
90
93
|
#
|
91
94
|
|
92
95
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
96
|
+
if ARGV[0] == "install"
|
97
|
+
raise "Sorry. Can only install Arduino on Mac OS X. See here for Linux instructions: http://www.arduino.cc/playground/Learning/Linux" unless RUBY_PLATFORM =~ /darwin/
|
98
|
+
puts "Downloading arduino-0012 for Mac from Arduino.cc"
|
99
|
+
File.open("/Applications/arduino-0012.zip", "w") do |file|
|
100
|
+
pbar = nil
|
101
|
+
file << open("http://www.arduino.cc/files/arduino-0012-mac.zip",
|
102
|
+
:content_length_proc => lambda {|t|
|
103
|
+
if t && 0 < t
|
104
|
+
pbar = ProgressBar.new(" Progress", t)
|
105
|
+
pbar.file_transfer_mode
|
106
|
+
end
|
107
|
+
},
|
108
|
+
:progress_proc => lambda {|s|
|
109
|
+
pbar.set s if pbar
|
110
|
+
}).read
|
111
|
+
pbar.finish
|
112
|
+
end
|
113
|
+
puts "Unzipping..."
|
114
|
+
`cd /Applications; unzip arduino-0012.zip`
|
115
|
+
`rm /Applications/arduino-0012.zip`
|
116
|
+
puts "installed Arduino here: /Applications/arduino-0012"
|
117
|
+
elsif ARGV[0] == "test"
|
118
|
+
test_dir = File.expand_path(File.dirname(__FILE__)) + "/../test/hello_world_test"
|
119
|
+
puts "Compiling hello_world.cpp to test your Arduino."
|
120
|
+
puts "cd #{test_dir}; make depend; make;"
|
121
|
+
`cd #{test_dir}; make depend; make;`
|
122
|
+
puts
|
123
|
+
puts "Compilation successful."
|
124
|
+
puts
|
125
|
+
puts "Make sure your Arduino is connected and then hit return."
|
126
|
+
Readline::readline('')
|
97
127
|
|
98
|
-
|
99
|
-
# Build vendor/rad:
|
128
|
+
`cd #{test_dir}; make upload`
|
100
129
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
puts "
|
112
|
-
puts
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
puts
|
117
|
-
|
118
|
-
|
119
|
-
puts "
|
120
|
-
puts
|
121
|
-
|
122
|
-
|
123
|
-
puts "
|
124
|
-
puts
|
125
|
-
|
126
|
-
|
127
|
-
puts "
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/LoopTimer/.", "#{sketch_name}/vendor/libraries/LoopTimer"
|
135
|
-
puts "Installed LoopTimer into #{sketch_name}/vendor/libraries"
|
136
|
-
puts
|
137
|
-
|
138
|
-
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/OneWire/.", "#{sketch_name}/vendor/libraries/OneWire"
|
139
|
-
puts "Installed OneWire into #{sketch_name}/vendor/libraries"
|
140
|
-
puts
|
141
|
-
|
142
|
-
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/Servo/.", "#{sketch_name}/vendor/libraries/Servo"
|
143
|
-
puts "Installed Servo into #{sketch_name}/vendor/libraries"
|
144
|
-
puts
|
145
|
-
|
146
|
-
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/Stepper/.", "#{sketch_name}/vendor/libraries/Stepper"
|
147
|
-
puts "Installed Stepper into #{sketch_name}/vendor/libraries"
|
148
|
-
puts
|
149
|
-
|
150
|
-
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/SWSerLCDpa/.", "#{sketch_name}/vendor/libraries/SWSerLCDpa"
|
151
|
-
puts "Installed SWSerLCDpa into #{sketch_name}/vendor/libraries"
|
152
|
-
puts
|
153
|
-
|
154
|
-
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/SWSerLCDsf/.", "#{sketch_name}/vendor/libraries/SWSerLCDsf"
|
155
|
-
puts "Installed SWSerLCDsf into #{sketch_name}/vendor/libraries"
|
156
|
-
puts
|
157
|
-
|
158
|
-
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/Wire/.", "#{sketch_name}/vendor/libraries/Wire"
|
159
|
-
puts "Installed Wire into #{sketch_name}/vendor/libraries"
|
160
|
-
puts
|
161
|
-
|
162
|
-
# Build examples -- used for basic testing
|
163
|
-
|
164
|
-
FileUtils.mkdir_p "#{sketch_name}/vendor/libraries"
|
165
|
-
puts "Successfully created your examples directory."
|
166
|
-
|
167
|
-
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/examples/.", "#{sketch_name}/examples"
|
168
|
-
puts "Installed examples into #{sketch_name}/examples"
|
169
|
-
puts
|
170
|
-
|
171
|
-
# Build test -- used testing
|
172
|
-
|
173
|
-
# FIXME: this should put the tests into the vendor/tests directory instead.
|
174
|
-
|
175
|
-
# FileUtils.mkdir_p "#{sketch_name}/test"
|
176
|
-
# puts "Successfully created your test directory."
|
177
|
-
#
|
178
|
-
# FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/test/.", "#{sketch_name}/test"
|
179
|
-
# puts "Installed tests into #{sketch_name}/test"
|
180
|
-
# puts
|
181
|
-
|
182
|
-
# Build vendor/plugins:
|
183
|
-
|
184
|
-
FileUtils.mkdir_p "#{sketch_name}/vendor/plugins"
|
185
|
-
puts "Successfully created your plugins directory."
|
186
|
-
puts
|
187
|
-
|
188
|
-
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/plugins/.", "#{sketch_name}/vendor/plugins"
|
189
|
-
puts "Installed Default plugins into #{sketch_name}/vendor/plugins"
|
190
|
-
puts
|
191
|
-
|
192
|
-
# Add an default sketch directory # needed to run test:compile
|
193
|
-
|
194
|
-
FileUtils.mkdir_p "#{sketch_name}/#{sketch_name}"
|
195
|
-
puts "Successfully created your default sketch directory."
|
196
|
-
puts
|
197
|
-
|
198
|
-
# Copy the README how_to to the sketch directory
|
199
|
-
|
200
|
-
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/rad/README.rdoc", "#{sketch_name}"
|
201
|
-
puts "Copied README how_to into #{sketch_name}"
|
202
|
-
puts
|
203
|
-
|
204
|
-
|
205
|
-
# Build sketch files, etc.:
|
206
|
-
|
207
|
-
FileUtils.touch "#{sketch_name}/#{sketch_name}.rb"
|
208
|
-
File.open("#{sketch_name}/#{sketch_name}.rb", "w") do |file|
|
209
|
-
file << <<-EOS
|
210
|
-
class #{sketch_name.split("_").collect{|c| c.capitalize}.join("")} < ArduinoSketch
|
211
|
-
|
212
|
-
# looking for hints? check out the examples directory
|
213
|
-
# example sketches can be uploaded to your arduino with
|
214
|
-
# rake make:upload sketch=examples/hello_world
|
215
|
-
# just replace hello_world with other examples
|
216
|
-
|
217
|
-
def loop
|
218
|
-
# your code here
|
219
|
-
end
|
130
|
+
# find the USB port to make sure the Arduino's actually plugged in
|
131
|
+
options, parser = OptionParser.parse(ARGV)
|
132
|
+
usb_port = options["hardware"]["serial_port"]
|
133
|
+
port_name = usb_port.split("/").last
|
134
|
+
port_dir = usb_port.split("/")[0..(usb_port.split("/").length-2)].join("/")
|
135
|
+
unless `ls #{port_dir}`.split(/\n/).any?{|d| d.match(/#{port_name}/)}
|
136
|
+
puts
|
137
|
+
puts "******************************************************"
|
138
|
+
puts "*** It looks like your Arduino is not plugged in. ***"
|
139
|
+
puts "*** Plug it in and try again. ***"
|
140
|
+
puts "*** ***"
|
141
|
+
puts "*** NOTE: If your usb port is not /dev/tty.usb* ***"
|
142
|
+
puts "*** pass it in to this script with the -p option. ***"
|
143
|
+
puts "******************************************************"
|
144
|
+
else
|
145
|
+
puts
|
146
|
+
puts "******************************************************"
|
147
|
+
puts "*** Success! ***"
|
148
|
+
puts "*** If your Arduino's light starts blinking soon, ***"
|
149
|
+
puts "*** then your Arduino environment is ***"
|
150
|
+
puts "*** correctly configured. ***"
|
151
|
+
puts "*** ***"
|
152
|
+
puts "*** Otherwise something is not hooked up properly. ***"
|
153
|
+
puts "******************************************************"
|
154
|
+
end
|
155
|
+
puts
|
156
|
+
puts "cleaning up..."
|
157
|
+
`rm #{test_dir}/hello_world.hex #{test_dir}/core.a #{test_dir}/hello_world.elf`
|
158
|
+
else
|
159
|
+
# Handle options:
|
160
|
+
options, parser = OptionParser.parse(ARGV)
|
161
|
+
sketch_name = ARGV[0]
|
162
|
+
parser.parse!(["-h"]) unless sketch_name
|
220
163
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
FileUtils.mkdir_p "#{sketch_name}/
|
234
|
-
puts "
|
235
|
-
|
236
|
-
File.
|
237
|
-
|
238
|
-
|
239
|
-
puts "Added #{sketch_name}/config/hardware.yml"
|
240
|
-
|
241
|
-
File.open("#{sketch_name}/config/software.yml", 'w') do |file|
|
242
|
-
file << options["software"].to_yaml
|
243
|
-
end
|
244
|
-
puts "Added #{sketch_name}/config/software.yml"
|
164
|
+
|
165
|
+
# Build vendor/rad:
|
166
|
+
|
167
|
+
FileUtils.mkdir_p "#{sketch_name}/vendor/rad"
|
168
|
+
puts "Successfully created your sketch directory."
|
169
|
+
|
170
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/rad/.", "#{sketch_name}/vendor/rad"
|
171
|
+
puts "Installed RAD into #{sketch_name}/vendor/rad"
|
172
|
+
puts
|
173
|
+
|
174
|
+
# Build vendor/libraries:
|
175
|
+
|
176
|
+
FileUtils.mkdir_p "#{sketch_name}/vendor/libraries"
|
177
|
+
puts "Successfully created your libraries directory."
|
178
|
+
|
179
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/AF_XPort/.", "#{sketch_name}/vendor/libraries/AF_XPort"
|
180
|
+
puts "Installed AF_XPort into #{sketch_name}/vendor/libraries"
|
181
|
+
puts
|
245
182
|
|
246
|
-
|
247
|
-
puts "
|
183
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/AFSoftSerial/.", "#{sketch_name}/vendor/libraries/AFSoftSerial"
|
184
|
+
puts "Installed AFSoftSerial into #{sketch_name}/vendor/libraries"
|
185
|
+
puts
|
186
|
+
|
187
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/DS1307/.", "#{sketch_name}/vendor/libraries/DS1307"
|
188
|
+
puts "Installed DS1307 into #{sketch_name}/vendor/libraries"
|
189
|
+
puts
|
190
|
+
|
191
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/FrequencyTimer2/.", "#{sketch_name}/vendor/libraries/FrequencyTimer2"
|
192
|
+
puts "Installed FrequencyTimer2 into #{sketch_name}/vendor/libraries"
|
193
|
+
puts
|
194
|
+
|
195
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/I2CEEPROM/.", "#{sketch_name}/vendor/libraries/I2CEEPROM"
|
196
|
+
puts "Installed I2CEEPROM into #{sketch_name}/vendor/libraries"
|
197
|
+
puts
|
198
|
+
|
199
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/LoopTimer/.", "#{sketch_name}/vendor/libraries/LoopTimer"
|
200
|
+
puts "Installed LoopTimer into #{sketch_name}/vendor/libraries"
|
201
|
+
puts
|
202
|
+
|
203
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/OneWire/.", "#{sketch_name}/vendor/libraries/OneWire"
|
204
|
+
puts "Installed OneWire into #{sketch_name}/vendor/libraries"
|
205
|
+
puts
|
206
|
+
|
207
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/Servo/.", "#{sketch_name}/vendor/libraries/Servo"
|
208
|
+
puts "Installed Servo into #{sketch_name}/vendor/libraries"
|
209
|
+
puts
|
210
|
+
|
211
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/Stepper/.", "#{sketch_name}/vendor/libraries/Stepper"
|
212
|
+
puts "Installed Stepper into #{sketch_name}/vendor/libraries"
|
213
|
+
puts
|
214
|
+
|
215
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/SWSerLCDpa/.", "#{sketch_name}/vendor/libraries/SWSerLCDpa"
|
216
|
+
puts "Installed SWSerLCDpa into #{sketch_name}/vendor/libraries"
|
217
|
+
puts
|
218
|
+
|
219
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/SWSerLCDsf/.", "#{sketch_name}/vendor/libraries/SWSerLCDsf"
|
220
|
+
puts "Installed SWSerLCDsf into #{sketch_name}/vendor/libraries"
|
221
|
+
puts
|
222
|
+
|
223
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/libraries/Wire/.", "#{sketch_name}/vendor/libraries/Wire"
|
224
|
+
puts "Installed Wire into #{sketch_name}/vendor/libraries"
|
225
|
+
puts
|
226
|
+
|
227
|
+
# Build examples -- used for basic testing
|
228
|
+
|
229
|
+
FileUtils.mkdir_p "#{sketch_name}/vendor/libraries"
|
230
|
+
puts "Successfully created your examples directory."
|
231
|
+
|
232
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/examples/.", "#{sketch_name}/examples"
|
233
|
+
puts "Installed examples into #{sketch_name}/examples"
|
234
|
+
puts
|
235
|
+
|
236
|
+
# Build test -- used testing
|
237
|
+
|
238
|
+
# FIXME: this should put the tests into the vendor/tests directory instead.
|
239
|
+
|
240
|
+
# FileUtils.mkdir_p "#{sketch_name}/test"
|
241
|
+
# puts "Successfully created your test directory."
|
242
|
+
#
|
243
|
+
# FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/test/.", "#{sketch_name}/test"
|
244
|
+
# puts "Installed tests into #{sketch_name}/test"
|
245
|
+
# puts
|
246
|
+
|
247
|
+
# Build vendor/plugins:
|
248
|
+
|
249
|
+
FileUtils.mkdir_p "#{sketch_name}/vendor/plugins"
|
250
|
+
puts "Successfully created your plugins directory."
|
251
|
+
|
252
|
+
FileUtils.cp_r "#{File.dirname(__FILE__)}/../lib/plugins/.", "#{sketch_name}/vendor/plugins"
|
253
|
+
puts "Installed Default plugins into #{sketch_name}/vendor/plugins"
|
254
|
+
puts
|
255
|
+
|
256
|
+
# Add an default sketch directory # needed to run test:compile
|
257
|
+
|
258
|
+
FileUtils.mkdir_p "#{sketch_name}/#{sketch_name}"
|
259
|
+
puts "Successfully created your default sketch directory."
|
260
|
+
|
261
|
+
# Build sketch files, etc.:
|
262
|
+
|
263
|
+
FileUtils.touch "#{sketch_name}/#{sketch_name}.rb"
|
264
|
+
File.open("#{sketch_name}/#{sketch_name}.rb", "w") do |file|
|
265
|
+
file << <<-EOS
|
266
|
+
class #{sketch_name.split("_").collect{|c| c.capitalize}.join("")} < ArduinoSketch
|
267
|
+
|
268
|
+
# looking for hints? check out the examples directory
|
269
|
+
# example sketches can be uploaded to your arduino with
|
270
|
+
# rake make:upload sketch=examples/hello_world
|
271
|
+
# just replace hello_world with other examples
|
272
|
+
|
273
|
+
def loop
|
274
|
+
# your code here
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
278
|
+
EOS
|
279
|
+
end
|
280
|
+
puts "Added #{sketch_name}/#{sketch_name}.rb"
|
281
|
+
|
282
|
+
File.open("#{sketch_name}/Rakefile", 'w') do |file|
|
283
|
+
file << <<-EOS
|
284
|
+
require 'vendor/rad/init.rb'
|
285
|
+
EOS
|
286
|
+
end
|
287
|
+
puts "Added #{sketch_name}/Rakefile"
|
288
|
+
|
289
|
+
FileUtils.mkdir_p "#{sketch_name}/config"
|
290
|
+
puts "Added #{sketch_name}/config"
|
291
|
+
|
292
|
+
File.open("#{sketch_name}/config/hardware.yml", 'w') do |file|
|
293
|
+
file << options["hardware"].to_yaml
|
294
|
+
end
|
295
|
+
puts "Added #{sketch_name}/config/hardware.yml"
|
296
|
+
|
297
|
+
File.open("#{sketch_name}/config/software.yml", 'w') do |file|
|
298
|
+
file << options["software"].to_yaml
|
299
|
+
end
|
300
|
+
puts "Added #{sketch_name}/config/software.yml"
|
301
|
+
|
302
|
+
puts
|
303
|
+
puts "Run 'rake -T' inside your sketch dir to learn how to compile and upload it."
|
304
|
+
|
305
|
+
puts "***************************************************"
|
306
|
+
puts "*** Please note: This version supports ***"
|
307
|
+
puts "*** Arduino 12 only! ***"
|
308
|
+
puts "*** run rad install arduino to upgrade ***"
|
309
|
+
puts "***************************************************"
|
310
|
+
end
|
@@ -69,7 +69,7 @@ SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \
|
|
69
69
|
$(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \
|
70
70
|
$(ARDUINO)/wiring_pulse.c $(ARDUINO)/wiring_serial.c \
|
71
71
|
$(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c <%= params['twi_c'] %>
|
72
|
-
CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(SOFTWARE_SERIAL)/SoftwareSerial.cpp<%= params['libraries'].collect{|l| " $(LIBRARY_ROOT)/#{ l }/#{l }.cpp"}.join('') %>
|
72
|
+
CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(SOFTWARE_SERIAL)/SoftwareSerial.cpp $(ARDUINO)/Print.cpp<%= params['libraries'].collect{|l| " $(LIBRARY_ROOT)/#{ l }/#{l }.cpp"}.join('') %>
|
73
73
|
MCU = <%= params['mcu'] %>
|
74
74
|
<% if params['asm_files'] %>ASRC = <%= params['asm_files'].join(' ') %><% end %>
|
75
75
|
F_CPU = 16000000
|
@@ -0,0 +1,236 @@
|
|
1
|
+
#
|
2
|
+
# Ruby/ProgressBar - a text progress bar library
|
3
|
+
#
|
4
|
+
# Copyright (C) 2001-2005 Satoru Takabayashi <satoru@namazu.org>
|
5
|
+
# All rights reserved.
|
6
|
+
# This is free software with ABSOLUTELY NO WARRANTY.
|
7
|
+
#
|
8
|
+
# You can redistribute it and/or modify it under the terms
|
9
|
+
# of Ruby's license.
|
10
|
+
#
|
11
|
+
|
12
|
+
class ProgressBar
|
13
|
+
VERSION = "0.9"
|
14
|
+
|
15
|
+
def initialize (title, total, out = STDERR)
|
16
|
+
@title = title
|
17
|
+
@total = total
|
18
|
+
@out = out
|
19
|
+
@terminal_width = 80
|
20
|
+
@bar_mark = "o"
|
21
|
+
@current = 0
|
22
|
+
@previous = 0
|
23
|
+
@finished_p = false
|
24
|
+
@start_time = Time.now
|
25
|
+
@previous_time = @start_time
|
26
|
+
@title_width = 14
|
27
|
+
@format = "%-#{@title_width}s %3d%% %s %s"
|
28
|
+
@format_arguments = [:title, :percentage, :bar, :stat]
|
29
|
+
clear
|
30
|
+
show
|
31
|
+
end
|
32
|
+
attr_reader :title
|
33
|
+
attr_reader :current
|
34
|
+
attr_reader :total
|
35
|
+
attr_accessor :start_time
|
36
|
+
|
37
|
+
private
|
38
|
+
def fmt_bar
|
39
|
+
bar_width = do_percentage * @terminal_width / 100
|
40
|
+
sprintf("|%s%s|",
|
41
|
+
@bar_mark * bar_width,
|
42
|
+
" " * (@terminal_width - bar_width))
|
43
|
+
end
|
44
|
+
|
45
|
+
def fmt_percentage
|
46
|
+
do_percentage
|
47
|
+
end
|
48
|
+
|
49
|
+
def fmt_stat
|
50
|
+
if @finished_p then elapsed else eta end
|
51
|
+
end
|
52
|
+
|
53
|
+
def fmt_stat_for_file_transfer
|
54
|
+
if @finished_p then
|
55
|
+
sprintf("%s %s %s", bytes, transfer_rate, elapsed)
|
56
|
+
else
|
57
|
+
sprintf("%s %s %s", bytes, transfer_rate, eta)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def fmt_title
|
62
|
+
@title[0,(@title_width - 1)] + ":"
|
63
|
+
end
|
64
|
+
|
65
|
+
def convert_bytes (bytes)
|
66
|
+
if bytes < 1024
|
67
|
+
sprintf("%6dB", bytes)
|
68
|
+
elsif bytes < 1024 * 1000 # 1000kb
|
69
|
+
sprintf("%5.1fKB", bytes.to_f / 1024)
|
70
|
+
elsif bytes < 1024 * 1024 * 1000 # 1000mb
|
71
|
+
sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
|
72
|
+
else
|
73
|
+
sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def transfer_rate
|
78
|
+
bytes_per_second = @current.to_f / (Time.now - @start_time)
|
79
|
+
sprintf("%s/s", convert_bytes(bytes_per_second))
|
80
|
+
end
|
81
|
+
|
82
|
+
def bytes
|
83
|
+
convert_bytes(@current)
|
84
|
+
end
|
85
|
+
|
86
|
+
def format_time (t)
|
87
|
+
t = t.to_i
|
88
|
+
sec = t % 60
|
89
|
+
min = (t / 60) % 60
|
90
|
+
hour = t / 3600
|
91
|
+
sprintf("%02d:%02d:%02d", hour, min, sec);
|
92
|
+
end
|
93
|
+
|
94
|
+
# ETA stands for Estimated Time of Arrival.
|
95
|
+
def eta
|
96
|
+
if @current == 0
|
97
|
+
"ETA: --:--:--"
|
98
|
+
else
|
99
|
+
elapsed = Time.now - @start_time
|
100
|
+
eta = elapsed * @total / @current - elapsed;
|
101
|
+
sprintf("ETA: %s", format_time(eta))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def elapsed
|
106
|
+
elapsed = Time.now - @start_time
|
107
|
+
sprintf("Time: %s", format_time(elapsed))
|
108
|
+
end
|
109
|
+
|
110
|
+
def eol
|
111
|
+
if @finished_p then "\n" else "\r" end
|
112
|
+
end
|
113
|
+
|
114
|
+
def do_percentage
|
115
|
+
if @total.zero?
|
116
|
+
100
|
117
|
+
else
|
118
|
+
@current * 100 / @total
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def get_width
|
123
|
+
# FIXME: I don't know how portable it is.
|
124
|
+
default_width = 80
|
125
|
+
begin
|
126
|
+
tiocgwinsz = 0x5413
|
127
|
+
data = [0, 0, 0, 0].pack("SSSS")
|
128
|
+
if @out.ioctl(tiocgwinsz, data) >= 0 then
|
129
|
+
rows, cols, xpixels, ypixels = data.unpack("SSSS")
|
130
|
+
if cols >= 0 then cols else default_width end
|
131
|
+
else
|
132
|
+
default_width
|
133
|
+
end
|
134
|
+
rescue Exception
|
135
|
+
default_width
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def show
|
140
|
+
arguments = @format_arguments.map {|method|
|
141
|
+
method = sprintf("fmt_%s", method)
|
142
|
+
send(method)
|
143
|
+
}
|
144
|
+
line = sprintf(@format, *arguments)
|
145
|
+
|
146
|
+
width = get_width
|
147
|
+
if line.length == width - 1
|
148
|
+
@out.print(line + eol)
|
149
|
+
@out.flush
|
150
|
+
elsif line.length >= width
|
151
|
+
@terminal_width = [@terminal_width - (line.length - width + 1), 0].max
|
152
|
+
if @terminal_width == 0 then @out.print(line + eol) else show end
|
153
|
+
else # line.length < width - 1
|
154
|
+
@terminal_width += width - line.length + 1
|
155
|
+
show
|
156
|
+
end
|
157
|
+
@previous_time = Time.now
|
158
|
+
end
|
159
|
+
|
160
|
+
def show_if_needed
|
161
|
+
if @total.zero?
|
162
|
+
cur_percentage = 100
|
163
|
+
prev_percentage = 0
|
164
|
+
else
|
165
|
+
cur_percentage = (@current * 100 / @total).to_i
|
166
|
+
prev_percentage = (@previous * 100 / @total).to_i
|
167
|
+
end
|
168
|
+
|
169
|
+
# Use "!=" instead of ">" to support negative changes
|
170
|
+
if cur_percentage != prev_percentage ||
|
171
|
+
Time.now - @previous_time >= 1 || @finished_p
|
172
|
+
show
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
public
|
177
|
+
def clear
|
178
|
+
@out.print "\r"
|
179
|
+
@out.print(" " * (get_width - 1))
|
180
|
+
@out.print "\r"
|
181
|
+
end
|
182
|
+
|
183
|
+
def finish
|
184
|
+
@current = @total
|
185
|
+
@finished_p = true
|
186
|
+
show
|
187
|
+
end
|
188
|
+
|
189
|
+
def finished?
|
190
|
+
@finished_p
|
191
|
+
end
|
192
|
+
|
193
|
+
def file_transfer_mode
|
194
|
+
@format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
|
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 halt
|
206
|
+
@finished_p = true
|
207
|
+
show
|
208
|
+
end
|
209
|
+
|
210
|
+
def inc (step = 1)
|
211
|
+
@current += step
|
212
|
+
@current = @total if @current > @total
|
213
|
+
show_if_needed
|
214
|
+
@previous = @current
|
215
|
+
end
|
216
|
+
|
217
|
+
def set (count)
|
218
|
+
if count < 0 || count > @total
|
219
|
+
raise "invalid count: #{count} (total: #{@total})"
|
220
|
+
end
|
221
|
+
@current = count
|
222
|
+
show_if_needed
|
223
|
+
@previous = @current
|
224
|
+
end
|
225
|
+
|
226
|
+
def inspect
|
227
|
+
"#<ProgressBar:#{@current}/#{@total}>"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
class ReversedProgressBar < ProgressBar
|
232
|
+
def do_percentage
|
233
|
+
100 - super
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|