monocle-print 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NGJjYTRhMWNiZWQ5OTJkYzM4MjgyMDc3MzcxM2RjZWZjMzBjYWNkZA==
5
+ data.tar.gz: !binary |-
6
+ OGU0OGYwZGMxY2VjOTM2ODdkNWI0OTY3MmUxMjRhNWQ2OWQ2MTI2Ng==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ OWM5M2I5YjY1ZjIzMWYxYTUyM2U0MTFlYTk0MGRkZWQ5NjVhYWM4ZTkzNzU5
10
+ ZWIyYjZlN2FmMDlmNTNmNTc4NjM5ZGY2ZTk3NWQ4M2RlNGRiZTRiMWU2NTkw
11
+ ZGI5MGQ1OGVkZGJlMGI5MGFkNDM4YzMyZDRhNDA0NTdkY2M3MTE=
12
+ data.tar.gz: !binary |-
13
+ NzhiYThmYzNjYjJkY2VjNGRmMDM3MmRkNzU4OTA3YzM1MjMzNTZlNmY1ODhm
14
+ OTgxYTU5ODFlNjNkNjUzYzAyZmU5NDYxZjVkYzViNjFjMjc0MTI0Nzg5Yjk4
15
+ NTU0YjNjMDNmNzRmNThjMTcxZWEzODIxYjFmNDAzZmM5ZTYzZmE=
data/.gemtest ADDED
File without changes
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 1.0.0 / 2008-09-01
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
data/Manifest.txt ADDED
@@ -0,0 +1,19 @@
1
+ lib/monocle-print.rb
2
+ lib/monocle-print/layout.rb
3
+ lib/monocle-print/table/segments.rb
4
+ lib/monocle-print/table/members.rb
5
+ lib/monocle-print/table/column.rb
6
+ lib/monocle-print/output-device.rb
7
+ lib/monocle-print/graphics.rb
8
+ lib/monocle-print/table.rb
9
+ lib/monocle-print/list.rb
10
+ lib/monocle-print/progress.rb
11
+ lib/monocle-print/presentation.rb
12
+ lib/monocle-print/utils.rb
13
+ lib/monocle-print/terminal-escapes.rb
14
+ lib/monocle-print/geometry.rb
15
+ lib/monocle-print/atomic.rb
16
+ History.txt
17
+ Manifest.txt
18
+ README.txt
19
+ Rakefile
data/README.txt ADDED
@@ -0,0 +1,40 @@
1
+ = monocle-print
2
+
3
+ * http://ohboyohboyohboy.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ Fancy console output tools
8
+
9
+ == REQUIREMENTS:
10
+
11
+ * ruby (>= 1.8.7)
12
+
13
+ == INSTALL:
14
+
15
+ sudo gem install monocle-print
16
+
17
+ == LICENSE:
18
+
19
+ (The MIT License)
20
+
21
+ Copyright (c) 2012 Kyle Yetter (kyley@inmotionhosting.com)
22
+
23
+ Permission is hereby granted, free of charge, to any person obtaining
24
+ a copy of this software and associated documentation files (the
25
+ 'Software'), to deal in the Software without restriction, including
26
+ without limitation the rights to use, copy, modify, merge, publish,
27
+ distribute, sublicense, and/or sell copies of the Software, and to
28
+ permit persons to whom the Software is furnished to do so, subject to
29
+ the following conditions:
30
+
31
+ The above copyright notice and this permission notice shall be
32
+ included in all copies or substantial portions of the Software.
33
+
34
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
35
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
37
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
38
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
39
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
40
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+ #
4
+ # author: Kyle Yetter
5
+ #
6
+
7
+ $LOAD_PATH.unshift( "lib" )
8
+
9
+ require 'rubygems'
10
+ require 'hoe'
11
+ require 'monocle-print'
12
+
13
+ PACKAGE_NAME = File.basename( File.dirname( __FILE__ ) )
14
+
15
+ Rake.application.options.ignore_deprecate = true
16
+
17
+ Hoe.spec PACKAGE_NAME do
18
+ developer( PACKAGE_NAME, 'kyle@ohboyohboyohboy.org' )
19
+ self.version = MonoclePrint.version
20
+ end
21
+
@@ -0,0 +1,462 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: ascii
3
+ #
4
+ # author: Kyle Yetter
5
+ #
6
+
7
+ require 'monocle-print'
8
+
9
+ module MonoclePrint
10
+ if RUBY_VERSION =~ /^1\.8/
11
+ MULTIBYTE_CHARACTER = %r<
12
+ [\xC2-\xDF][\x80-\xBF]
13
+ | [\xE0-\xEF][\x80-\xBF]{2}
14
+ | [\xF0-\xF4][\x80-\xBF]{3}
15
+ >x
16
+
17
+ ONE_BYTE = 0x20 .. 0x7E
18
+ TWO_BYTES = 0xC2 .. 0xDF
19
+ THREE_BYTES = 0xE0 .. 0xEF
20
+ FOUR_BYTES = 0xF0 .. 0xF4
21
+ end
22
+
23
+ COLOR_ESCAPE = /\e\[[\d:;]*?m/
24
+
25
+ class SingleLine < ::String
26
+ include MonoclePrint
27
+
28
+ def self.clear_cache
29
+ @@width.clear
30
+ @@invisible_size.clear
31
+ return( self )
32
+ end
33
+
34
+ @@width = {}
35
+ @@invisible_size = {}
36
+
37
+ if RUBY_VERSION =~ /^1\.8/
38
+
39
+ def char_byte( n )
40
+ n.zero? and return( 0 )
41
+ seen = byte = 0
42
+ while c = self[ byte ] and seen < n
43
+ step =
44
+ case c
45
+ when ONE_BYTE then seen += 1; 1
46
+ when ?\e
47
+ self[ byte, size ] =~ /^#{COLOR_ESCAPE}/ ? $~.end(0) : 1
48
+ when TWO_BYTES then seen += 1; 2
49
+ when THREE_BYTES then seen += 1; 3
50
+ when FOUR_BYTES then seen += 1; 4
51
+ else 1
52
+ end
53
+ byte += step
54
+ end
55
+ return( byte )
56
+ end
57
+
58
+ def width
59
+ @@width[ hash ] ||= begin
60
+ (temp = bleach).gsub!( MULTIBYTE_CHARACTER, ' ' )
61
+ temp.size
62
+ end
63
+ end
64
+
65
+ else
66
+
67
+ def char_byte( n )
68
+ seen = byte = 0
69
+ if esc = self =~ COLOR_ESCAPE and esc < n
70
+ return( $~.end(0) + $'.char_byte( n - esc ) )
71
+ else n
72
+ end
73
+ end
74
+
75
+ def width
76
+ @@width[ hash ] ||= bleach.length
77
+ end
78
+
79
+ end
80
+
81
+ def align( alignment, width, fill = ' ' )
82
+ dup.align!( alignment, width, fill )
83
+ end
84
+
85
+ def align!( alignment, width, fill = ' ' )
86
+ strip!
87
+ case alignment.to_sym
88
+ when :left then left!( width, fill )
89
+ when :center then center!( width, fill )
90
+ when :right then right!( width, fill )
91
+ end
92
+ end
93
+
94
+ def blank?
95
+ empty? or self =~ /^(\s|#{COLOR_ESCAPE})*$/
96
+ end
97
+
98
+ def bleach
99
+ gsub( COLOR_ESCAPE, '' )
100
+ end
101
+
102
+ def bleach!
103
+ gsub!( COLOR_ESCAPE, '' )
104
+ end
105
+
106
+ def center!( w, fill = ' ' )
107
+ w > width or return( self )
108
+ if fill.length == 1
109
+ replace( center( w + invisible_size, fill ) )
110
+ else fill = self.class.new( fill )
111
+ even, odd = ( width - w ).divmod( 2 )
112
+ insert( 0, fill.tile( even ) )
113
+ self << fill.tile( even + odd )
114
+ end
115
+ self
116
+ end
117
+
118
+ def divide_at( len )
119
+ pos = char_byte( len )
120
+ return( [ self[ 0, pos ], self[ pos, size ] ] )
121
+ end
122
+
123
+ def each_escape
124
+ block_given? or return( enum_for( :each_escape ) )
125
+ scan( COLOR_ESCAPE ) do |esc|
126
+ yield( esc )
127
+ end
128
+ end
129
+
130
+ def escapes
131
+ each_escape.inject( self.class.new ) do | escs, esc |
132
+ escs << esc
133
+ end
134
+ end
135
+
136
+ def indent( n )
137
+ dup.indent!( n )
138
+ end
139
+
140
+ def indent!( num_spaces )
141
+ if num_spaces < 0
142
+ remaining_indent = Utils.at_least( level_of_indent + num_spaces, 0 )
143
+ lstrip!
144
+ indent!( remaining_indent )
145
+ else
146
+ insert( 0, ' ' * num_spaces )
147
+ end
148
+ return( self )
149
+ end
150
+
151
+ def invisible_size
152
+ @@invisible_size[ hash ] ||= size - width
153
+ end
154
+
155
+ def left!( w, fill = ' ' )
156
+ w > width or return( self )
157
+ if fill.length == 1
158
+ replace( ljust( w + invisible_size, fill ) )
159
+ else fill = self.class.new( fill )
160
+ insert( 0, fill.tile( width - w ) )
161
+ end
162
+ self
163
+ end
164
+
165
+ def level_of_indent
166
+ self =~ /^(\s+)/ ? $1.length : 0
167
+ end
168
+
169
+ def pad!( left, right = left )
170
+ right!( width + left )
171
+ left!( width + right )
172
+ end
173
+
174
+ def partial(len)
175
+ self[ 0, char_byte( len ) ]
176
+ end
177
+
178
+ def right!( w, fill = ' ' )
179
+ w > width or return( self )
180
+ if fill.length == 1
181
+ replace( rjust( w + invisible_size, fill ) )
182
+ else fill = self.class.new( fill )
183
+ self.insert( 0, fill.tile( w - width ) )
184
+ end
185
+ self
186
+ end
187
+
188
+ def tile( size )
189
+ width == 0 and return( )
190
+ full, partial = size.divmod( width )
191
+ self * full << partial( partial )
192
+ end
193
+
194
+ def truncate( w, tail = nil )
195
+ dup.truncate!( w, tail )
196
+ end
197
+
198
+ def truncate!( w, tail = nil )
199
+ width > w or return( self )
200
+ if tail then tail = Line( tail )
201
+ return( partial( w - tail.width ) << tail )
202
+ else
203
+ return( partial( w ) )
204
+ end
205
+ return( self )
206
+ end
207
+
208
+ def words
209
+ strip.split(/\s+/)
210
+ end
211
+
212
+ def height
213
+ 1
214
+ end
215
+
216
+ def wrap( w )
217
+ if width > w
218
+ words = split( /\s+/ ).inject( [] ) do | words, word |
219
+ while word.width > w
220
+ frag, word = word.divide_at( w )
221
+ words << frag
222
+ end
223
+ words << word
224
+ end
225
+
226
+ line = words.shift || self.class.new
227
+ text = Text.new
228
+ w -= 1
229
+ while word = words.shift
230
+ if line.width + word.width > w
231
+ text << line
232
+ line = word
233
+ else
234
+ line << ' ' << word
235
+ end
236
+ end
237
+ text << line
238
+ return( text )
239
+ else
240
+ return( Text( self.dup ) )
241
+ end
242
+ end
243
+ end
244
+
245
+ class Text < Array
246
+ def self.clear_cache
247
+ @@width.clear
248
+ @@uniform.clear
249
+ return( self )
250
+ end
251
+
252
+ include MonoclePrint
253
+ @@width = {}
254
+ @@uniform = {}
255
+
256
+ def initialize( lines = nil, default = nil )
257
+ case lines
258
+ when Fixnum
259
+ if block_given?
260
+ super( lines ) { | i | Line( yield( i ) ) }
261
+ else
262
+ default = Line( default )
263
+ super( lines, default )
264
+ end
265
+ when Text then super( lines )
266
+ when Array
267
+ super( lines.join( $/ ).map { | l | Line( l.chomp! || l ) } )
268
+ when SingleLine then super(1, lines)
269
+ when nil then super()
270
+ else
271
+ super( lines.to_s.lines.map { |l| Line( l.chomp! || l ) } )
272
+ end
273
+ end
274
+
275
+ def initialize_copy( orig )
276
+ for line in orig
277
+ self << line.dup
278
+ end
279
+ end
280
+
281
+ def align( alignment, width, fill = ' ' )
282
+ dup.align!( alignment, width, fill )
283
+ end
284
+
285
+ def align!( alignment, width, fill = ' ' )
286
+ # if the width argument is less than the full block width of the text,
287
+ # make it the full block width to ensure uniform width
288
+ width = Utils.at_least( width, self.width )
289
+
290
+ if empty?
291
+ self << SingleLine.new( ' ' * width )
292
+ else
293
+ map! do | line |
294
+ line.align( alignment, width, fill )
295
+ end
296
+ end
297
+
298
+ return( self )
299
+ end
300
+
301
+ def bleach
302
+ dup.bleach!
303
+ end
304
+
305
+ def bleach!
306
+ each { | l | l.bleach! }
307
+ end
308
+
309
+ def fix
310
+ dup.fix!
311
+ end
312
+
313
+ def fix!
314
+ align!( :left, width )
315
+ end
316
+
317
+ def fixed_indent!( level = 0 )
318
+ level = Utils.at_least( level, 0 )
319
+ offset = level - level_of_indent
320
+ indent!( offset )
321
+ end
322
+
323
+ def fixed_indent( level = 0 )
324
+ dup.fixed_indent!( level )
325
+ end
326
+
327
+ def level_of_indent
328
+ level = nil
329
+ levels = map { | line | line.blank? ? nil : line.level_of_indent }
330
+ levels.compact!
331
+ levels.min || 0
332
+ end
333
+
334
+ def indent!( spaces )
335
+ for line in self do line.indent!( spaces ) end
336
+ self
337
+ end
338
+
339
+ def indent( spaces )
340
+ dup.indent!( spaces )
341
+ end
342
+
343
+ def frame( graphic_style )
344
+ dup.frame!( graphic_style )
345
+ end
346
+
347
+ def frame!( graphic_style )
348
+ top = graphic_style.box_top( width )
349
+ bottom = graphic_style.box_bottom( width )
350
+ for line in self
351
+ line.insert( 0, graphic_style.v )
352
+ line.insert( -1, graphic_style.v )
353
+ end
354
+ unshift( top )
355
+ push( bottom )
356
+ return( self )
357
+ end
358
+
359
+ def inspect
360
+ digits = Math.log10( Utils.at_least( length, 1 ) ).floor + 1
361
+ $/ + each_with_index.map do | line, i |
362
+ line_no = i.to_s.rjust( digits )
363
+ "#{ line_no } | #{ line }"
364
+ end.join( $/ ) + $/
365
+ end
366
+
367
+ def juxtapose( text, joint = ' ' )
368
+ dup.juxtapose!( text, joint )
369
+ end
370
+
371
+ def juxtapose!( text, joint = ' ' )
372
+ text = self.class.new( text ).fix!.valign!( :top, height )
373
+ valign!( :top, text.height ); fix!
374
+
375
+ zip( text ) do | left, right |
376
+ left << joint.to_s << right
377
+ end
378
+ return( self )
379
+ end
380
+
381
+ def pad( padding )
382
+ dup.pad!( padding )
383
+ end
384
+
385
+ def pad!( padding )
386
+ padding.top.times { unshift( Line('') ) }
387
+ padding.bottom.times { push( Line('') ) }
388
+ w = width
389
+ for line in self
390
+ line.left!( w )
391
+ line.pad!( padding.left, padding.right )
392
+ end
393
+ self
394
+ end
395
+
396
+ def reflow( paragraph_style = true )
397
+ if paragraph_style
398
+ cursor, new = 0, self.class.new
399
+ text = self.to_s
400
+ while text =~ /\n\s*\n/
401
+ before, text = $`, $'
402
+ new << `#{ before.gsub!( /[ \t]*\n/, ' ' ) || before }`
403
+ new << ``
404
+ end
405
+ new << `#{ text.gsub!( /[ \t]*\n/, ' ' ) || text }`
406
+ return( new )
407
+ else
408
+ text = self.to_s
409
+ text.strip!
410
+ text.gsub!( /\s+/, ' ' )
411
+ self.class.new( text )
412
+ end
413
+ end
414
+
415
+ def reflow!( paragraph_style = true )
416
+ replace( reflow( paragraph_style ) )
417
+ end
418
+
419
+ def wrap( width )
420
+ reflow.inject( self.class.new ) do | wrapped, line |
421
+ wrapped.concat( line.wrap( width ) )
422
+ end
423
+ end
424
+
425
+ def to_s
426
+ join( $/ )
427
+ end
428
+
429
+ def uniform?
430
+ @@uniform.fetch( hash ) do | h |
431
+ @@uniform[ h ] = all? { | l | l.width == width }
432
+ end
433
+ end
434
+
435
+ def valign!( alignment, h, filler = '' )
436
+ filler = Line( filler )
437
+ h > height or return( self )
438
+ case alignment
439
+ when :top
440
+ fill( filler, height, h - height )
441
+ when :bottom
442
+ ( h - height ).times { unshift( filler ) }
443
+ when :center
444
+ even, odd = ( h - height ).divmod( 2 )
445
+ even.times { push( filler ); unshift( filler ) }
446
+ odd == 1 and push( filler )
447
+ end
448
+ return( self )
449
+ end
450
+
451
+ def width
452
+ @@width[ hash ] ||= ( map { | line | line.width }.max || 0 )
453
+ end
454
+
455
+ alias height length
456
+ alias | juxtapose
457
+ def `(str) #` # comment here cos my editor's colorizing freaks out
458
+ SingleLine.new( str )
459
+ end
460
+ end
461
+
462
+ end
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ module MonoclePrint
5
+ Pair = Struct.new( :x, :y )
6
+ class Pair
7
+ alternate_names =
8
+ {
9
+ :x => %w( width column left ),
10
+ :y => %w( height line right )
11
+ }
12
+
13
+ alternate_names.each do | field, name_list |
14
+ name_list.each do | name |
15
+ alias_method( name, field )
16
+ alias_method( "#{ name }=", "#{ field }=" )
17
+ end
18
+ end
19
+
20
+ def initialize( x = 0, y = 0 )
21
+ super
22
+ end
23
+
24
+ def +@
25
+ self.column = 0
26
+ self.line += 1
27
+ self
28
+ end
29
+
30
+ def ~
31
+ self.column = 0
32
+ self
33
+ end
34
+
35
+ def -@
36
+ self.column = 0
37
+ self.line -= 1
38
+ self
39
+ end
40
+
41
+ def +( n )
42
+ self.column += n
43
+ self
44
+ end
45
+
46
+ def -( n )
47
+ self.column -= n
48
+ self
49
+ end
50
+ end
51
+
52
+ Rectangle = Struct.new( :left, :top, :right, :bottom )
53
+ class Rectangle
54
+ def self.create( params )
55
+ left = params.fetch( :left, 0 )
56
+ right = params.fetch( :right, left )
57
+ top = params.fetch( :top, left )
58
+ bottom = params.fetch( :bottom, top )
59
+ new( left, top, right, bottom )
60
+ end
61
+
62
+ def initialize( left = 0, top = left, right = left, bottom = top )
63
+ super( left, top, right, bottom )
64
+ end
65
+ end
66
+ end