delano-drydock 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  == Overview
6
6
 
7
- Drydock is a seaworthy DSL for building really powerful command line applications. It's contained in a single .rb file so it's easy to copy directly into your project. See below for examples.
7
+ Drydock is a seaworthy DSL for building really powerful command line applications. The core class is contained in a single .rb file so it's easy to copy directly into your project. See below for examples.
8
8
 
9
9
  == Install
10
10
 
data/drydock.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  @spec = Gem::Specification.new do |s|
2
2
  s.name = %q{drydock}
3
- s.version = "0.6.1"
3
+ s.version = "0.6.2"
4
4
  s.specification_version = 1 if s.respond_to? :specification_version=
5
5
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
6
 
@@ -19,6 +19,9 @@
19
19
  bin/example
20
20
  drydock.gemspec
21
21
  lib/drydock.rb
22
+ lib/drydock/console.rb
23
+ lib/mixins/object.rb
24
+ lib/mixins/string.rb
22
25
  )
23
26
 
24
27
  # s.add_dependency ''
@@ -0,0 +1,313 @@
1
+ #--
2
+ # TODO: Make it Drydock-like
3
+ # Adapted from: http://github.com/oneup/ruby-console/tree/tput
4
+ # See: http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x405.html
5
+ # See: man terminfo
6
+ #++
7
+
8
+
9
+ module Console #:nodoc:all
10
+ extend self
11
+ require 'timeout'
12
+ require 'thread'
13
+
14
+ # ANSI escape sequence numbers for text attributes
15
+ ATTRIBUTES = {
16
+ :normal => 0,
17
+ :bright => 1,
18
+ :dim => 2,
19
+ :underline => 4,
20
+ :blink => 5,
21
+ :reverse => 7,
22
+ :hidden => 8,
23
+ :default => 0,
24
+ }.freeze unless defined? ATTRIBUTES
25
+
26
+ # ANSI escape sequence numbers for text colours
27
+ COLOURS = {
28
+ :black => 30,
29
+ :red => 31,
30
+ :green => 32,
31
+ :yellow => 33,
32
+ :blue => 34,
33
+ :magenta => 35,
34
+ :cyan => 36,
35
+ :white => 37,
36
+ :default => 39,
37
+ :random => 30 + rand(10).to_i
38
+ }.freeze unless defined? COLOURS
39
+
40
+ # ANSI escape sequence numbers for background colours
41
+ BGCOLOURS = {
42
+ :black => 40,
43
+ :red => 41,
44
+ :green => 42,
45
+ :yellow => 43,
46
+ :blue => 44,
47
+ :magenta => 45,
48
+ :cyan => 46,
49
+ :white => 47,
50
+ :default => 49,
51
+ :random => 40 + rand(10).to_i
52
+ }.freeze unless defined? BGCOLOURS
53
+
54
+ def valid_colour?(colour)
55
+ COLOURS.has_key? colour
56
+ end
57
+ alias :valid_color? :valid_colour?
58
+
59
+ def print_left(str, props={})
60
+ props[:x] ||= 0
61
+ props[:y] ||= Cursor.y
62
+ # print_at("x:#{props[:x]} y:#{props[:y]}", {:x => 0, :y => 10})
63
+ print_at(str, props)
64
+ end
65
+ def print_right(str, props={})
66
+ props[:x] ||= width
67
+ props[:y] ||= Cursor.y
68
+ props[:minus] = true unless props.has_key?(:minus)
69
+ print_at(str, props)
70
+ end
71
+ def print_spaced(*args)
72
+ props = (args.last.is_a? Hash) ? args.pop : {}
73
+ props[:y] = Cursor.y
74
+ chunk_width = (width / args.flatten.size).to_i
75
+ chunk_at = 0
76
+ args.each do |chunk|
77
+ props[:x] = chunk_at
78
+ print_at(chunk.to_s[0, chunk_width], props)
79
+ chunk_at += chunk_width
80
+ end
81
+ puts
82
+ end
83
+ def print_center(str, props={})
84
+ props[:x] = ((width - str.noatt.length) / 2).to_i-1
85
+ props[:y] ||= height
86
+ print_at(str, props)
87
+ end
88
+ def print_at(str, props={})
89
+ print_at_lamb = lambda {
90
+ props[:x] ||= 0
91
+ props[:y] ||= 0
92
+ props[:minus] = false unless props.has_key?(:minus)
93
+ props[:x] = props[:x]-str.noatt.size if props[:x] && props[:minus] # Subtract the str length from the position
94
+ Cursor.save
95
+ Cursor.move = 0
96
+ print str
97
+ Cursor.restore
98
+ }
99
+ RUBY_VERSION =~ /1.9/ ? Thread.exclusive(&print_at_lamb) : print_at_lamb.call
100
+ end
101
+
102
+ def self.style(col, bgcol=nil, att=nil)
103
+ valdor = []
104
+ valdor << COLOURS[col] if COLOURS.has_key?(col)
105
+ valdor << BGCOLOURS[bgcol] if BGCOLOURS.has_key?(bgcol)
106
+ valdor << ATTRIBUTES[att] if ATTRIBUTES.has_key?(att)
107
+ "\e[#{valdor.join(";")}m" # => \e[8;34;42m
108
+ end
109
+
110
+ def self.clear
111
+ tput :clear
112
+ end
113
+
114
+ def reset
115
+ tput :reset
116
+ end
117
+
118
+ def width
119
+ tput_val(:cols).to_i
120
+ end
121
+
122
+ def height
123
+ tput_val(:lines).to_i
124
+ end
125
+ end
126
+
127
+ module Cursor #:nodoc:all
128
+ extend self
129
+
130
+ # Returns [x,y] for the current cursor position.
131
+ def position
132
+ yx = [0,0]
133
+
134
+ position_lamb = lambda {
135
+ begin
136
+ # NOTE: Can we get cursor position from tput?
137
+ termsettings = `stty -g`
138
+
139
+ # DEBUGGING: The following code works in Ruby 1.9 but not 1.8.
140
+
141
+ system("stty raw -echo")
142
+ print "\e[6n" # Forces output of: \e[49;1R (\e is not printable)
143
+ c = ''
144
+ (pos ||= '') << c while (c = STDIN.getc) != 'R'# NOTE: There must be a better way!
145
+ yx = pos.scan(/(\d+);(\d+)/).flatten
146
+ yx[0] = yx[0].to_i - 1 # It returns 1 for the first column, but we want 0
147
+ yx[1] = yx[1].to_i - 1
148
+ ensure
149
+ system("stty #{termsettings}") # Get out of raw mode
150
+ end
151
+ }
152
+
153
+ RUBY_VERSION =~ /1.9/ ? Thread.exclusive(&position_lamb) : position_lamb.call
154
+ yx.reverse
155
+ end
156
+
157
+ def x; position[0]; end
158
+ def y; position[1]; end
159
+
160
+ def move=(*args)
161
+ x,y = *args.flatten
162
+ tput(:cup, y, x) # "tput cup" takes y before x
163
+ end
164
+
165
+ def up(n=1)
166
+ tput :cuu, n
167
+ end
168
+
169
+ def down(n=1)
170
+ tput :cud, n
171
+ end
172
+
173
+ def right(x=1)
174
+ tput :cuf, x
175
+ end
176
+
177
+ def left(x=1)
178
+ tput :cub, x
179
+ end
180
+
181
+ def line(n=1)
182
+ tput :il, n
183
+ end
184
+
185
+ def save
186
+ tput :sc
187
+ end
188
+
189
+ def restore
190
+ tput :rc
191
+ end
192
+
193
+ def clear_line
194
+ tput :el
195
+ end
196
+
197
+ # TODO: replace methods with this kinda thing
198
+ #@@capnames = {
199
+ # :restore => [:rc],
200
+ # :save => [:sc],
201
+ # :clear_line => [:el],
202
+ # :line => [:il, 1, 1],
203
+ #
204
+ # :up => [:cuu, 1, 1],
205
+ # :down => [:cud, 1, 1],
206
+ # :right => [:cuf, 1, 1],
207
+ # :left => [:cub, 1, 1],
208
+ #
209
+ # :move => [:cup, 2, 0, 0]
210
+ #}
211
+ #
212
+ #@@capnames.each_pair do |meth, cap|
213
+ # module_eval <<-RUBY
214
+ # def #{meth}(*args)
215
+ # tput '#{cap[0]}'
216
+ # end
217
+ # RUBY
218
+ #end
219
+
220
+ end
221
+
222
+ class Window #:nodoc:all
223
+ attr_accessor :row, :col, :width, :height, :text, :fg, :bg
224
+ attr_reader :threads
225
+
226
+ def initialize(*args)
227
+ @row = 1
228
+ @col = 1
229
+ @width = 10
230
+ @height = 5
231
+ @text = ""
232
+ @fg = :default
233
+ @bg = :default
234
+ @threads = []
235
+ end
236
+
237
+ def position=(x,y=nil)
238
+ @x = x
239
+ @y = y if y
240
+ end
241
+
242
+ def position
243
+ [@row, @col]
244
+ end
245
+
246
+ def self.bar(len, unit='=')
247
+ unit*len
248
+ end
249
+
250
+
251
+ # Execute the given block every +n+ seconds in a separate thread.
252
+ # The lower limit for +n+ is 1 second.
253
+ # Returns a Thread object.
254
+ def every_n_seconds(n)
255
+ #n = 1 if n < 1
256
+ thread = Thread.new do
257
+
258
+ begin
259
+ while true
260
+ before = Time.now
261
+ yield
262
+ interval = n - (Time.now - before)
263
+ sleep(interval) if interval > 0
264
+ end
265
+ rescue Interrupt
266
+ break
267
+ ensure
268
+ thread
269
+ end
270
+ end
271
+ end
272
+
273
+ # Print text to the screen via +type+ every +refresh+ seconds.
274
+ # Print the return value of the block to the screen using the
275
+ # print_+type+ method. +refresh+ is number of seconds to wait
276
+ # +props+ is the hash sent to print_+type+.
277
+ # Returns a Thread object.
278
+ #
279
+ # # Print the time in the upper right corner every second
280
+ # thread1 = Console.static(:right, 1, {:y => 0}) do
281
+ # Time.now.utc.strftime("%Y-%m-%d %H:%M:%S").colour(:blue, :white, :underline)
282
+ # end
283
+ #
284
+ def static(type, refresh=2, props={}, &b)
285
+ meth = "print_#{type}"
286
+ raise "#{meth} is not supported" unless Console.respond_to?(meth)
287
+
288
+ refresh ||= 0
289
+ refreh = refresh.to_s.to_i
290
+
291
+ thread = every_n_seconds(refresh) do
292
+ Console.send(meth, b.call, props.clone)
293
+ end
294
+
295
+ @threads << thread
296
+
297
+ thread
298
+ end
299
+
300
+ def join_threads
301
+ begin
302
+ @threads.each do |t|
303
+ t.join
304
+ end
305
+ rescue Interrupt
306
+ ensure
307
+ @threads.each do |t|
308
+ t.kill
309
+ end
310
+ end
311
+ end
312
+
313
+ end
data/lib/drydock.rb CHANGED
@@ -2,6 +2,10 @@ require 'optparse'
2
2
  require 'ostruct'
3
3
  require 'stringio'
4
4
 
5
+ require 'drydock/console'
6
+ require 'mixins/string'
7
+ require 'mixins/object'
8
+
5
9
  module Drydock
6
10
  class FancyArray < Array #:nodoc:
7
11
  attr_reader :fields
@@ -0,0 +1,23 @@
1
+ class Object
2
+
3
+ # Executes tput +capnam+ with +args+. Returns true if tcap gives
4
+ # 0 exit status and false otherwise.
5
+ #
6
+ # tput :cup, 1, 4
7
+ # $ tput cup 1 4
8
+ #
9
+ def tput(capnam, *args)
10
+ system("tput #{capnam} #{args.flatten.join(' ')}")
11
+ end
12
+
13
+ # Executes tput +capnam+ with +args+. Returns the output of tput.
14
+ #
15
+ # tput_val :cols # => 16
16
+ # $ tput cols # => 16
17
+ #
18
+ def tput_val(capnam, *args)
19
+ `tput #{capnam} #{args.flatten.join(' ')}`.chomp
20
+ end
21
+ end
22
+
23
+
@@ -0,0 +1,66 @@
1
+ class String
2
+ @@print_with_attributes = true
3
+ def String.disable_colour; @@print_with_attributes = false; end
4
+ def String.disable_color; @@print_with_attributes = false; end
5
+ def String.enable_colour; @@print_with_attributes = true; end
6
+ def String.enable_color; @@print_with_attributes = true; end
7
+
8
+ # +col+, +bgcol+, and +attribute+ are symbols corresponding
9
+ # to Console::COLOURS, Console::BGCOLOURS, and Console::ATTRIBUTES.
10
+ # Returns the string in the format attributes + string + defaults.
11
+ #
12
+ # "MONKEY_JUNK".colour(:blue, :white, :blink) # => "\e[34;47;5mMONKEY_JUNK\e[39;49;0m"
13
+ #
14
+ def colour(col, bgcol = nil, attribute = nil)
15
+ return self unless @@print_with_attributes
16
+ Console.style(col, bgcol, attribute) +
17
+ self +
18
+ Console.style(:default, :default, :default)
19
+ end
20
+ alias :color :colour
21
+
22
+ # See colour
23
+ def bgcolour(bgcol = :default)
24
+ return self unless @@print_with_attributes
25
+ Console.style(nil, bgcol, nil) +
26
+ self +
27
+ Console.style(nil, :default, nil)
28
+ end
29
+ alias :bgcolor :bgcolour
30
+
31
+ # See colour
32
+ def att(a = :default)
33
+ return self unless @@print_with_attributes
34
+ Console.style(nil, nil, a) +
35
+ self +
36
+ Console.style(nil, nil, :default)
37
+ end
38
+
39
+ # Shortcut for att(:bright)
40
+ def bright; att(:bright); end
41
+
42
+ # Print the string at +x+ +y+. When +minus+ is any true value
43
+ # the length of the string is subtracted from the value of x
44
+ # before printing.
45
+ def print_at(x=nil, y=nil, minus=false)
46
+ args = {:minus=>minus}
47
+ args[:x] &&= x
48
+ args[:y] &&= y
49
+ Console.print_at(self, args)
50
+ end
51
+
52
+ # Returns the string with ANSI escape codes removed.
53
+ #
54
+ # NOTE: The non-printable attributes count towards the string size.
55
+ # You can use this method to get the "visible" size:
56
+ #
57
+ # "\e[34;47;5mMONKEY_JUNK\e[39;49;0m".noatt.size # => 11
58
+ # "\e[34;47;5mMONKEY_JUNK\e[39;49;0m".size # => 31
59
+ #
60
+ def noatt
61
+ gsub(/\e\[?[0-9;]*[mc]?/, '')
62
+ end
63
+ alias :noansi :noatt
64
+
65
+ end
66
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delano-drydock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -31,6 +31,9 @@ files:
31
31
  - bin/example
32
32
  - drydock.gemspec
33
33
  - lib/drydock.rb
34
+ - lib/drydock/console.rb
35
+ - lib/mixins/object.rb
36
+ - lib/mixins/string.rb
34
37
  has_rdoc: true
35
38
  homepage: http://github.com/delano/drydock
36
39
  post_install_message: