rudy 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/CHANGES.txt +28 -5
  2. data/README.rdoc +1 -1
  3. data/Rudyfile +51 -19
  4. data/bin/ird +153 -0
  5. data/bin/rudy +18 -23
  6. data/bin/rudy-ec2 +5 -10
  7. data/bin/rudy-s3 +1 -3
  8. data/bin/rudy-sdb +0 -2
  9. data/examples/README.md +10 -0
  10. data/examples/debian-sinatra-passenger/commands.rb +19 -0
  11. data/examples/debian-sinatra-passenger/machines.rb +32 -0
  12. data/examples/debian-sinatra-passenger/routines.rb +30 -0
  13. data/examples/debian-sinatra-thin/commands.rb +17 -0
  14. data/examples/debian-sinatra-thin/machines.rb +35 -0
  15. data/examples/debian-sinatra-thin/routines.rb +72 -0
  16. data/lib/rudy.rb +8 -17
  17. data/lib/rudy/aws.rb +1 -2
  18. data/lib/rudy/aws/ec2/address.rb +0 -1
  19. data/lib/rudy/aws/ec2/snapshot.rb +11 -0
  20. data/lib/rudy/aws/s3.rb +6 -3
  21. data/lib/rudy/cli.rb +12 -2
  22. data/lib/rudy/cli/aws/ec2/candy.rb +19 -48
  23. data/lib/rudy/cli/aws/ec2/images.rb +109 -122
  24. data/lib/rudy/cli/aws/s3/buckets.rb +1 -2
  25. data/lib/rudy/cli/config.rb +13 -0
  26. data/lib/rudy/cli/disks.rb +24 -1
  27. data/lib/rudy/cli/routines.rb +10 -11
  28. data/lib/rudy/config.rb +6 -9
  29. data/lib/rudy/config/objects.rb +4 -0
  30. data/lib/rudy/global.rb +4 -5
  31. data/lib/rudy/huxtable.rb +23 -8
  32. data/lib/rudy/machines.rb +11 -4
  33. data/lib/rudy/metadata.rb +8 -94
  34. data/lib/rudy/metadata/backup.rb +113 -0
  35. data/lib/rudy/metadata/backups.rb +65 -0
  36. data/lib/rudy/{disks.rb → metadata/disk.rb} +36 -69
  37. data/lib/rudy/metadata/disks.rb +67 -0
  38. data/lib/rudy/metadata/objectbase.rb +104 -0
  39. data/lib/rudy/mixins.rb +2 -0
  40. data/lib/rudy/routines.rb +173 -88
  41. data/lib/rudy/routines/helpers/dependshelper.rb +34 -0
  42. data/lib/rudy/routines/helpers/diskhelper.rb +174 -5
  43. data/lib/rudy/routines/helpers/scmhelper.rb +2 -2
  44. data/lib/rudy/routines/helpers/scripthelper.rb +11 -4
  45. data/lib/rudy/routines/passthrough.rb +3 -1
  46. data/lib/rudy/routines/reboot.rb +75 -0
  47. data/lib/rudy/routines/startup.rb +3 -3
  48. data/lib/rudy/scm/git.rb +17 -17
  49. data/lib/rudy/scm/svn.rb +46 -5
  50. data/lib/rudy/utils.rb +3 -2
  51. data/rudy.gemspec +24 -46
  52. data/test/30_sdb_metadata/10_disks_test.rb +5 -5
  53. metadata +36 -68
  54. data/lib/annoy.rb +0 -298
  55. data/lib/console.rb +0 -404
  56. data/lib/escape.rb +0 -305
  57. data/lib/rudy/backup.rb +0 -135
  58. data/lib/storable.rb +0 -292
  59. data/lib/sysinfo.rb +0 -285
  60. data/lib/tryouts.rb +0 -33
  61. data/vendor/highline-1.5.1/CHANGELOG +0 -222
  62. data/vendor/highline-1.5.1/INSTALL +0 -35
  63. data/vendor/highline-1.5.1/LICENSE +0 -7
  64. data/vendor/highline-1.5.1/README +0 -63
  65. data/vendor/highline-1.5.1/Rakefile +0 -82
  66. data/vendor/highline-1.5.1/TODO +0 -6
  67. data/vendor/highline-1.5.1/examples/ansi_colors.rb +0 -38
  68. data/vendor/highline-1.5.1/examples/asking_for_arrays.rb +0 -18
  69. data/vendor/highline-1.5.1/examples/basic_usage.rb +0 -75
  70. data/vendor/highline-1.5.1/examples/color_scheme.rb +0 -32
  71. data/vendor/highline-1.5.1/examples/limit.rb +0 -12
  72. data/vendor/highline-1.5.1/examples/menus.rb +0 -65
  73. data/vendor/highline-1.5.1/examples/overwrite.rb +0 -19
  74. data/vendor/highline-1.5.1/examples/page_and_wrap.rb +0 -322
  75. data/vendor/highline-1.5.1/examples/password.rb +0 -7
  76. data/vendor/highline-1.5.1/examples/trapping_eof.rb +0 -22
  77. data/vendor/highline-1.5.1/examples/using_readline.rb +0 -17
  78. data/vendor/highline-1.5.1/lib/highline.rb +0 -758
  79. data/vendor/highline-1.5.1/lib/highline/color_scheme.rb +0 -120
  80. data/vendor/highline-1.5.1/lib/highline/compatibility.rb +0 -17
  81. data/vendor/highline-1.5.1/lib/highline/import.rb +0 -43
  82. data/vendor/highline-1.5.1/lib/highline/menu.rb +0 -395
  83. data/vendor/highline-1.5.1/lib/highline/question.rb +0 -463
  84. data/vendor/highline-1.5.1/lib/highline/system_extensions.rb +0 -193
  85. data/vendor/highline-1.5.1/setup.rb +0 -1360
  86. data/vendor/highline-1.5.1/test/tc_color_scheme.rb +0 -56
  87. data/vendor/highline-1.5.1/test/tc_highline.rb +0 -823
  88. data/vendor/highline-1.5.1/test/tc_import.rb +0 -54
  89. data/vendor/highline-1.5.1/test/tc_menu.rb +0 -429
  90. data/vendor/highline-1.5.1/test/ts_all.rb +0 -15
data/lib/annoy.rb DELETED
@@ -1,298 +0,0 @@
1
- #---
2
- # TODO: Use Matrix to give a more accurate annoyance factor
3
- # TODO: Add trivia questions
4
- #+++
5
-
6
- require 'timeout'
7
- require 'sysinfo'
8
- require 'highline'
9
-
10
- # = Annoy
11
- #
12
- # Like your annoying friend that asks you questions all the time.
13
- #
14
- # Rudy uses Annoy to present the user with a simple question before
15
- # continuing with a destructive action.
16
- #
17
- class Annoy
18
-
19
- attr_accessor :factor
20
- attr_accessor :flavor
21
- attr_accessor :answer
22
- attr_accessor :writer
23
- attr_accessor :period
24
- attr_accessor :system
25
-
26
- @@operators = {
27
- :low => %w(+ -),
28
- :medium => %w(* -),
29
- :high => %w(& * -),
30
- :insane => %w(** << | & *)
31
- }.freeze
32
-
33
- @@strlen = {
34
- :low => 2,
35
- :medium => 3,
36
- :high => 4,
37
- :insane => 32
38
- }.freeze
39
-
40
- @@randsize = {
41
- :low => 10,
42
- :medium => 12,
43
- :high => 50,
44
- :insane => 1000
45
- }.freeze
46
-
47
- @@period = 60.freeze # max seconds to wait
48
- @@flavors = [:numeric, :string].freeze
49
- @@skip = false # skip questions
50
-
51
- # Calling this method tells Annoy to not prompt for
52
- # a response. All questions will return true.
53
- def Annoy.enable_skip; @@skip = true; end
54
- # Tells annoy to prompt for a response.
55
- def Annoy.disable_skip; @@skip = false; end
56
- # Returns true of Annoy is in skip mode
57
- def Annoy.skip?; @@skip; end
58
-
59
- # * +factor+ annoyance factor, one of :low (default), :medium, :high, :insane
60
- # * +flavor+ annoyance flavor, one of :rand (default), :numeric, string
61
- # * +writer+ an IO object to write to. Default: STDERR
62
- # * +period+ the amount of time to wait in seconds. Default: 60
63
- def initialize(opts={:factor=>:medium, :flavor=>:rand, :writer=>STDOUT, :period=>nil})
64
- @factor = opts[:factor]
65
- @flavor = Annoy.get_flavor(opts[:flavor])
66
- @writer = opts[:writer]
67
- @period = opts[:period] || @@period
68
- unless Annoy.respond_to?("#{@flavor}_question")
69
- raise "Hey, hey, hey. I don't know that flavor! (#{@flavor})"
70
- end
71
- end
72
-
73
- # Generates and returns a question. The correct response is available
74
- # as +@answer+.
75
- def question
76
- q, @answer =Annoy.question(@factor, @flavor)
77
- q
78
- end
79
-
80
- # A wrapper for string_question and numberic_question
81
- def Annoy.question(factor=:medium, flavor=:rand)
82
- raise "Come on, you ruined the flavor!" unless flavor
83
- Annoy.send("#{flavor}_question", factor)
84
- end
85
-
86
- # Generates a random string
87
- def Annoy.string_question(factor=:medium)
88
- # Strings don't need to be evaluated so the answer is the
89
- # same as the question.
90
- str = strand @@strlen[factor]
91
- [str,str]
92
- end
93
-
94
- # * Generates a rudimentary numeric equation in the form: (Integer OPERATOR Integer).
95
- # * Returns [equation, answer]
96
- def Annoy.numeric_question(factor=:medium)
97
- equation = answer = 0
98
- while answer < 10
99
- vals = [rand(@@randsize[factor])+1,
100
- @@operators[factor][ rand(@@operators[factor].size) ],
101
- rand(@@randsize[factor])+1 ]
102
- equation = "(%d %s %d)" % vals
103
- answer = eval(equation)
104
- end
105
- [equation, answer]
106
- end
107
-
108
- # Prints a question to +writer+ and waits for a response on STDIN.
109
- # It checks whether STDIN is connected a tty so it doesn't block on gets
110
- # when there's no human around to annoy. It will return <b>TRUE</b> when
111
- # STDIN is NOT connected to a tty (when STDIN.tty? returns false).
112
- # * +msg+ The message to print. Default: "Please confirm."
113
- # Returns true when the answer is correct, otherwise false.
114
- def Annoy.challenge?(msg="Please confirm.", factor=:medium, flavor=:rand, writer=STDOUT, period=nil)
115
- return true unless STDIN.tty? # Humans only!
116
- return true if Annoy.skip?
117
- begin
118
- success = Timeout::timeout(period || @@period) do
119
- flavor = Annoy.get_flavor(flavor)
120
- question, answer = Annoy.question(factor, flavor)
121
- msg = "#{msg} To continue, #{Annoy.verb(flavor)} #{question}: "
122
- #writer.print msg
123
- #if ![:medium, :high, :insane].member?(factor) && flavor == :numeric
124
- #writer.print "(#{answer}) "
125
- #writer.flush
126
- #end
127
- #response = Annoy.get_response(writer)
128
-
129
- highline = HighLine.new
130
- response = highline.ask(msg) { |q|
131
- q.echo = '*' # Don't display response
132
- q.overwrite = true # Erase the question afterwards
133
- q.whitespace = :strip # Remove whitespace from the response
134
- q.answer_type = Integer if flavor == :numeric
135
- }
136
-
137
- ret = (response == answer)
138
- writer.puts "Incorrect" unless ret
139
- ret
140
- end
141
- rescue Interrupt
142
- writer.puts $/, "Giving up!"
143
- false
144
- rescue Annoy::GiveUp => ex
145
- writer.puts $/, "Giving up!"
146
- false
147
- rescue Timeout::Error => ex
148
- writer.puts $/, "Times up!"
149
- false
150
- end
151
- end
152
-
153
- # Runs a challenge with the message, "Are you sure?"
154
- # See: Annoy.challenge?
155
- def Annoy.are_you_sure?(factor=:medium, flavor=:rand, writer=STDOUT)
156
- Annoy.challenge?("Are you sure?", factor, flavor, writer)
157
- end
158
-
159
- # Runs a challenge with the message, "Proceed?"
160
- # See: Annoy.challenge?
161
- def Annoy.proceed?(factor=:medium, flavor=:rand, writer=STDOUT)
162
- Annoy.challenge?("Proceed?", factor, flavor, writer)
163
- end
164
-
165
- # See: Annoy.challenge?
166
- # Uses the value of @flavor, @factor, and @writer
167
- def challenge?(msg="Please confirm.")
168
- Annoy.challenge?(msg, @factor, @flavor, @writer)
169
- end
170
-
171
- # See: Annoy.pose_question
172
- # Uses the value of @writer
173
- def pose_question(msg, regexp)
174
- Annoy.pose_question(msg, regexp, @writer)
175
- end
176
-
177
- # Prints a question to writer and waits for a response on STDIN.
178
- # It checks whether STDIN is connected a tty so it doesn't block on gets.
179
- # when there's no human around to annoy. It will return <b>TRUE</b> when
180
- # STDIN is NOT connected to a tty.
181
- # * +msg+ The question to pose to the user
182
- # * +regexp+ The regular expression to match the answer.
183
- def Annoy.pose_question(msg, regexp, writer=STDOUT, period=nil)
184
- return true unless STDIN.tty? # Only ask a question if there's a human
185
- return true if Annoy.skip?
186
- begin
187
- success = Timeout::timeout(period || @@period) do
188
- regexp &&= Regexp.new regexp
189
- highline = HighLine.new
190
- response = highline.ask(msg) { |q|
191
- q.echo = '*' # Don't display response
192
- q.overwrite = true # Erase the question afterwards
193
- q.whitespace = :strip # Remove whitespace from the response
194
- }
195
- regexp.match(response)
196
- end
197
- rescue Timeout::Error => ex
198
- writer.puts $/, "Times up!"
199
- false
200
- end
201
- end
202
-
203
-
204
- def Annoy.timed_display(msg, writer, period=nil)
205
- return true unless STDIN.tty? # Only ask a question if there's a human
206
- if Annoy.skip?
207
- #writer.puts msg
208
- return true
209
- end
210
- begin
211
- period ||= @@period
212
- success = Timeout::timeout(period) do
213
- writer.puts "Message will display for #{period} seconds"
214
- writer.print msg
215
- writer.flush if writer.respond_to?(:flush)
216
- sleep period+1
217
- end
218
- rescue Timeout::Error => ex
219
- writer.print "\r" << ' '*msg.size
220
- end
221
-
222
- true
223
- end
224
-
225
- private
226
- def Annoy.get_response(writer=STDOUT)
227
- return true unless STDIN.tty? # Humans only
228
- return true if Annoy.skip?
229
- # TODO: Count the number of keystrokes to prevent copy/paste.
230
- # We can probably use Highline.
231
- # We likely need to be more specific but this will do for now.
232
- #if ::SystemInfo.new.os == :unix
233
- # begin
234
- # response = []
235
- # char = nil
236
- # system("stty raw -echo") # Raw mode, no echo
237
- # while char != "\r" || response.size > 5
238
- # char = STDIN.getc.chr
239
- # writer.print char
240
- # writer.flush
241
- # response << char
242
- # end
243
- # writer.print "\n\r"
244
- # response = response.join('')
245
- # rescue => ex
246
- # ensure
247
- # system("stty -raw echo") # Reset terminal mode
248
- # end
249
- #else
250
- response = (STDIN.gets || "")
251
- #end
252
- response.chomp.gsub(/["']/, '')
253
- end
254
- # Returns a verb appropriate to the flavor.
255
- # * :numeric => resolve
256
- # * :string => type
257
- def Annoy.verb(flavor)
258
- case flavor
259
- when :numeric then "resolve"
260
- when :string then "type"
261
- else
262
- nil
263
- end
264
- end
265
-
266
- #
267
- # Generates a string of random alphanumeric characters.
268
- # * +len+ is the length, an Integer. Default: 8
269
- # * +safe+ in safe-mode, ambiguous characters are removed (default: true):
270
- # i l o 1 0
271
- def Annoy.strand( len=8, safe=true )
272
- chars = ("a".."z").to_a + ("0".."9").to_a
273
- chars.delete_if { |v| %w(i l o 1 0).member?(v) } if safe
274
- str = ""
275
- 1.upto(len) { |i| str << chars[rand(chars.size-1)] }
276
- str
277
- end
278
-
279
- # * +f+ a prospective flavor name
280
- def Annoy.get_flavor(f)
281
- f.to_sym == :rand ? flavor_rand : f.to_sym
282
- end
283
-
284
- # Return a random flavor
285
- def Annoy.flavor_rand
286
- @@flavors[rand(@@flavors.size)]
287
- end
288
-
289
-
290
- end
291
-
292
- # = Annoy::GiveUp
293
- #
294
- # This is what happens when you don't answer Annoy's questions.
295
- class Annoy::GiveUp < RuntimeError
296
- end
297
-
298
-
data/lib/console.rb DELETED
@@ -1,404 +0,0 @@
1
- #---
2
- # Adapted from: http://github.com/oneup/ruby-console/tree/tput
3
- # See: http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x405.html
4
- # See: man terminfo
5
- #+++
6
-
7
- #
8
- #
9
- #
10
- class String
11
- @@print_with_attributes = true
12
- def String.disable_colour; @@print_with_attributes = false; end
13
- def String.disable_color; @@print_with_attributes = false; end
14
- def String.enable_colour; @@print_with_attributes = true; end
15
- def String.enable_color; @@print_with_attributes = true; end
16
-
17
- # +col+, +bgcol+, and +attribute+ are symbols corresponding
18
- # to Console::COLOURS, Console::BGCOLOURS, and Console::ATTRIBUTES.
19
- # Returns the string in the format attributes + string + defaults.
20
- #
21
- # "MONKEY_JUNK".colour(:blue, :white, :blink) # => "\e[34;47;5mMONKEY_JUNK\e[39;49;0m"
22
- #
23
- def colour(col, bgcol = nil, attribute = nil)
24
- return self unless @@print_with_attributes
25
- Console.style(col, bgcol, attribute) +
26
- self +
27
- Console.style(:default, :default, :default)
28
- end
29
- alias :color :colour
30
-
31
- # See colour
32
- def bgcolour(bgcol = :default)
33
- return self unless @@print_with_attributes
34
- Console.style(nil, bgcol, nil) +
35
- self +
36
- Console.style(nil, :default, nil)
37
- end
38
- alias :bgcolor :bgcolour
39
-
40
- # See colour
41
- def att(a = :default)
42
- return self unless @@print_with_attributes
43
- Console.style(nil, nil, a) +
44
- self +
45
- Console.style(nil, nil, :default)
46
- end
47
-
48
- # Shortcut for att(:bright)
49
- def bright; att(:bright); end
50
-
51
- # Print the string at +x+ +y+. When +minus+ is any true value
52
- # the length of the string is subtracted from the value of x
53
- # before printing.
54
- def print_at(x=nil, y=nil, minus=false)
55
- args = {:minus=>minus}
56
- args[:x] &&= x
57
- args[:y] &&= y
58
- Console.print_at(self, args)
59
- end
60
-
61
- # Returns the string with ANSI escape codes removed.
62
- #
63
- # NOTE: The non-printable attributes count towards the string size.
64
- # You can use this method to get the "visible" size:
65
- #
66
- # "\e[34;47;5mMONKEY_JUNK\e[39;49;0m".noatt.size # => 11
67
- # "\e[34;47;5mMONKEY_JUNK\e[39;49;0m".size # => 31
68
- #
69
- def noatt
70
- gsub(/\e\[?[0-9;]*[mc]?/, '')
71
- end
72
- alias :noansi :noatt
73
-
74
- end
75
-
76
- class Object #:nodoc:all
77
-
78
- # Executes tput +capnam+ with +args+. Returns true if tcap gives
79
- # 0 exit status and false otherwise.
80
- #
81
- # tput :cup, 1, 4
82
- # $ tput cup 1 4
83
- #
84
- def tput(capnam, *args)
85
- system("tput #{capnam} #{args.flatten.join(' ')}")
86
- end
87
-
88
- # Executes tput +capnam+ with +args+. Returns the output of tput.
89
- #
90
- # tput_val :cols # => 16
91
- # $ tput cols # => 16
92
- #
93
- def tput_val(capnam, *args)
94
- `tput #{capnam} #{args.flatten.join(' ')}`.chomp
95
- end
96
- end
97
-
98
-
99
-
100
- module Console #:nodoc:all
101
- extend self
102
- require 'timeout'
103
- require 'thread'
104
-
105
- # ANSI escape sequence numbers for text attributes
106
- ATTRIBUTES = {
107
- :normal => 0,
108
- :bright => 1,
109
- :dim => 2,
110
- :underline => 4,
111
- :blink => 5,
112
- :reverse => 7,
113
- :hidden => 8,
114
- :default => 0,
115
- }.freeze unless defined? ATTRIBUTES
116
-
117
- # ANSI escape sequence numbers for text colours
118
- COLOURS = {
119
- :black => 30,
120
- :red => 31,
121
- :green => 32,
122
- :yellow => 33,
123
- :blue => 34,
124
- :magenta => 35,
125
- :cyan => 36,
126
- :white => 37,
127
- :default => 39,
128
- :random => 30 + rand(10).to_i
129
- }.freeze unless defined? COLOURS
130
-
131
- # ANSI escape sequence numbers for background colours
132
- BGCOLOURS = {
133
- :black => 40,
134
- :red => 41,
135
- :green => 42,
136
- :yellow => 43,
137
- :blue => 44,
138
- :magenta => 45,
139
- :cyan => 46,
140
- :white => 47,
141
- :default => 49,
142
- :random => 40 + rand(10).to_i
143
- }.freeze unless defined? BGCOLOURS
144
-
145
- def valid_colour?(colour)
146
- COLOURS.has_key? colour
147
- end
148
- alias :valid_color? :valid_colour?
149
-
150
- def print_left(str, props={})
151
- props[:x] ||= 0
152
- props[:y] ||= Cursor.y
153
- # print_at("x:#{props[:x]} y:#{props[:y]}", {:x => 0, :y => 10})
154
- print_at(str, props)
155
- end
156
- def print_right(str, props={})
157
- props[:x] ||= width
158
- props[:y] ||= Cursor.y
159
- props[:minus] = true unless props.has_key?(:minus)
160
- print_at(str, props)
161
- end
162
- def print_spaced(*args)
163
- props = (args.last.is_a? Hash) ? args.pop : {}
164
- props[:y] = Cursor.y
165
- chunk_width = (width / args.flatten.size).to_i
166
- chunk_at = 0
167
- args.each do |chunk|
168
- props[:x] = chunk_at
169
- print_at(chunk.to_s[0, chunk_width], props)
170
- chunk_at += chunk_width
171
- end
172
- puts
173
- end
174
- def print_center(str, props={})
175
- props[:x] = ((width - str.noatt.length) / 2).to_i-1
176
- props[:y] ||= height
177
- print_at(str, props)
178
- end
179
- def print_at(str, props={})
180
- print_at_lamb = lambda {
181
- props[:x] ||= 0
182
- props[:y] ||= 0
183
- props[:minus] = false unless props.has_key?(:minus)
184
- props[:x] = props[:x]-str.noatt.size if props[:x] && props[:minus] # Subtract the str length from the position
185
- Cursor.save
186
- Cursor.move = 0
187
- print str
188
- Cursor.restore
189
- }
190
- RUBY_VERSION =~ /1.9/ ? Thread.exclusive(&print_at_lamb) : print_at_lamb.call
191
- end
192
-
193
- def self.style(col, bgcol=nil, att=nil)
194
- valdor = []
195
- valdor << COLOURS[col] if COLOURS.has_key?(col)
196
- valdor << BGCOLOURS[bgcol] if BGCOLOURS.has_key?(bgcol)
197
- valdor << ATTRIBUTES[att] if ATTRIBUTES.has_key?(att)
198
- "\e[#{valdor.join(";")}m" # => \e[8;34;42m
199
- end
200
-
201
- def self.clear
202
- tput :clear
203
- end
204
-
205
- def reset
206
- tput :reset
207
- end
208
-
209
- def width
210
- tput_val(:cols).to_i
211
- end
212
-
213
- def height
214
- tput_val(:lines).to_i
215
- end
216
- end
217
-
218
- module Cursor #:nodoc:all
219
- extend self
220
-
221
- # Returns [x,y] for the current cursor position.
222
- def position
223
- yx = [0,0]
224
-
225
- position_lamb = lambda {
226
- begin
227
- # NOTE: Can we get cursor position from tput?
228
- termsettings = `stty -g`
229
-
230
- # DEBUGGING: The following code works in Ruby 1.9 but not 1.8.
231
-
232
- system("stty raw -echo")
233
- print "\e[6n" # Forces output of: \e[49;1R (\e is not printable)
234
- c = ''
235
- (pos ||= '') << c while (c = STDIN.getc) != 'R'# NOTE: There must be a better way!
236
- yx = pos.scan(/(\d+);(\d+)/).flatten
237
- yx[0] = yx[0].to_i - 1 # It returns 1 for the first column, but we want 0
238
- yx[1] = yx[1].to_i - 1
239
- ensure
240
- system("stty #{termsettings}") # Get out of raw mode
241
- end
242
- }
243
-
244
- RUBY_VERSION =~ /1.9/ ? Thread.exclusive(&position_lamb) : position_lamb.call
245
- yx.reverse
246
- end
247
-
248
- def x; position[0]; end
249
- def y; position[1]; end
250
-
251
- def move=(*args)
252
- x,y = *args.flatten
253
- tput(:cup, y, x) # "tput cup" takes y before x
254
- end
255
-
256
- def up(n=1)
257
- tput :cuu, n
258
- end
259
-
260
- def down(n=1)
261
- tput :cud, n
262
- end
263
-
264
- def right(x=1)
265
- tput :cuf, x
266
- end
267
-
268
- def left(x=1)
269
- tput :cub, x
270
- end
271
-
272
- def line(n=1)
273
- tput :il, n
274
- end
275
-
276
- def save
277
- tput :sc
278
- end
279
-
280
- def restore
281
- tput :rc
282
- end
283
-
284
- def clear_line
285
- tput :el
286
- end
287
-
288
- # TODO: replace methods with this kinda thing
289
- #@@capnames = {
290
- # :restore => [:rc],
291
- # :save => [:sc],
292
- # :clear_line => [:el],
293
- # :line => [:il, 1, 1],
294
- #
295
- # :up => [:cuu, 1, 1],
296
- # :down => [:cud, 1, 1],
297
- # :right => [:cuf, 1, 1],
298
- # :left => [:cub, 1, 1],
299
- #
300
- # :move => [:cup, 2, 0, 0]
301
- #}
302
- #
303
- #@@capnames.each_pair do |meth, cap|
304
- # module_eval <<-RUBY
305
- # def #{meth}(*args)
306
- # tput '#{cap[0]}'
307
- # end
308
- # RUBY
309
- #end
310
-
311
- end
312
-
313
- class Window #:nodoc:all
314
- attr_accessor :row, :col, :width, :height, :text, :fg, :bg
315
- attr_reader :threads
316
-
317
- def initialize(*args)
318
- @row = 1
319
- @col = 1
320
- @width = 10
321
- @height = 5
322
- @text = ""
323
- @fg = :default
324
- @bg = :default
325
- @threads = []
326
- end
327
-
328
- def position=(x,y=nil)
329
- @x = x
330
- @y = y if y
331
- end
332
-
333
- def position
334
- [@row, @col]
335
- end
336
-
337
- def self.bar(len, unit='=')
338
- unit*len
339
- end
340
-
341
-
342
- # Execute the given block every +n+ seconds in a separate thread.
343
- # The lower limit for +n+ is 1 second.
344
- # Returns a Thread object.
345
- def every_n_seconds(n)
346
- #n = 1 if n < 1
347
- thread = Thread.new do
348
-
349
- begin
350
- while true
351
- before = Time.now
352
- yield
353
- interval = n - (Time.now - before)
354
- sleep(interval) if interval > 0
355
- end
356
- rescue Interrupt
357
- break
358
- ensure
359
- thread
360
- end
361
- end
362
- end
363
-
364
- # Print text to the screen via +type+ every +refresh+ seconds.
365
- # Print the return value of the block to the screen using the
366
- # print_+type+ method. +refresh+ is number of seconds to wait
367
- # +props+ is the hash sent to print_+type+.
368
- # Returns a Thread object.
369
- #
370
- # # Print the time in the upper right corner every second
371
- # thread1 = Console.static(:right, 1, {:y => 0}) do
372
- # Time.now.utc.strftime("%Y-%m-%d %H:%M:%S").colour(:blue, :white, :underline)
373
- # end
374
- #
375
- def static(type, refresh=2, props={}, &b)
376
- meth = "print_#{type}"
377
- raise "#{meth} is not supported" unless Console.respond_to?(meth)
378
-
379
- refresh ||= 0
380
- refreh = refresh.to_s.to_i
381
-
382
- thread = every_n_seconds(refresh) do
383
- Console.send(meth, b.call, props.clone)
384
- end
385
-
386
- @threads << thread
387
-
388
- thread
389
- end
390
-
391
- def join_threads
392
- begin
393
- @threads.each do |t|
394
- t.join
395
- end
396
- rescue Interrupt
397
- ensure
398
- @threads.each do |t|
399
- t.kill
400
- end
401
- end
402
- end
403
-
404
- end