monocle-print 1.0.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.
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