ohboyohboyohboy-monocle-print 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 86040373aa1a0083834327588b976a16f75d9a71
4
+ data.tar.gz: cf64e4578d808060fc9f9b1bc32690f21d1c648e
5
+ SHA512:
6
+ metadata.gz: 15bef20ee331f6d2c9c896562c5e9dd23183d136d73be3c6dcf06e0fbb4632c8363a659ca6745c40d081441ac791d845b6ed0b88189ac7150c6e349caee70a0e
7
+ data.tar.gz: cc1c985d702a06c2dc5262eca2208c29d60993987c69c811169eb189599a25b961f471656989cd0e4a8f6b97e5e9823e8493507e682b654549767ee66a65ea2f
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ # A sample Gemfile
2
+
3
+ source "https://rubygems.org"
@@ -0,0 +1,4 @@
1
+ == 1.0.0 / 2008-09-01
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
@@ -0,0 +1,21 @@
1
+ Gemfile
2
+ History.txt
3
+ Manifest.txt
4
+ Rakefile
5
+ README.txt
6
+ lib/monocle-print.rb
7
+ lib/monocle-print/layout.rb
8
+ lib/monocle-print/table/segments.rb
9
+ lib/monocle-print/table/members.rb
10
+ lib/monocle-print/table/column.rb
11
+ lib/monocle-print/output-device.rb
12
+ lib/monocle-print/graphics.rb
13
+ lib/monocle-print/table.rb
14
+ lib/monocle-print/graphics/registry.rb
15
+ lib/monocle-print/list.rb
16
+ lib/monocle-print/progress.rb
17
+ lib/monocle-print/presentation.rb
18
+ lib/monocle-print/utils.rb
19
+ lib/monocle-print/terminal-escapes.rb
20
+ lib/monocle-print/geometry.rb
21
+ lib/monocle-print/atomic.rb
@@ -0,0 +1,40 @@
1
+ = ohboyohboyohboy-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 ohboyohboyohboy-monocle-print
16
+
17
+ == LICENSE:
18
+
19
+ (The MIT License)
20
+
21
+ Copyright (c) 2012-2018 Kyle Yetter (kyle@ohboyohboyohboy.org)
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.
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+ #
4
+
5
+ PROJECT_NAME = "ohboyohboyohboy-monocle-print"
6
+
7
+ require "rubygems"
8
+ require "hoe"
9
+
10
+ # Hoe.plugin :compiler
11
+ # Hoe.plugin :gem_prelude_sucks
12
+ # Hoe.plugin :inline
13
+ # Hoe.plugin :minitest
14
+ # Hoe.plugin :racc
15
+ # Hoe.plugin :rcov
16
+ # Hoe.plugin :rubyforge
17
+
18
+ Hoe.spec PROJECT_NAME do
19
+ developer( "Kyle Yetter", "kyle@ohboyohboyohboy.org")
20
+ license "MIT" # this should match the license in the README
21
+ end
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ begin
5
+ require 'io/console'
6
+ rescue LoadError
7
+ # ignore
8
+ end
9
+
10
+ require 'delegate'
11
+ autoload :StringIO, 'stringio' unless defined?( StringIO )
12
+
13
+ module MonoclePrint
14
+ VERSION = '1.1.1'
15
+
16
+ def self.version
17
+ VERSION
18
+ end
19
+
20
+ def self.included( kl )
21
+ super
22
+ kl.extend( self )
23
+ end
24
+
25
+ def self.library_path( *args )
26
+ File.join( File.dirname( __FILE__ ), *args )
27
+ end
28
+
29
+ def self.stdout( options = {}, &block )
30
+ OutputDevice.stdout( options, &block )
31
+ end
32
+
33
+ def self.stderr( options = {}, &block )
34
+ OutputDevice.stderr( options, &block )
35
+ end
36
+
37
+ def self.buffer( options = {}, &block )
38
+ OutputDevice.buffer( options, &block )
39
+ end
40
+
41
+ module_function
42
+
43
+ def Line( obj )
44
+ SingleLine === obj ? obj : SingleLine.new( obj.to_s )
45
+ end
46
+
47
+ def Output( dev )
48
+ OutputDevice === dev ? dev : OutputDevice.new( dev )
49
+ end
50
+
51
+ def Text( obj )
52
+ case obj
53
+ when Text then obj
54
+ when nil then Text.new( '' )
55
+ else Text.new( obj.to_s )
56
+ end
57
+ end
58
+
59
+ def Style( obj )
60
+ Graphics === obj ? obj : Graphics.style( obj )
61
+ end
62
+
63
+ def Rectangle( obj )
64
+ case obj
65
+ when Rectangle then obj
66
+ when Array then Rectangle.new( *obj )
67
+ when Hash then Rectangle.create( obj )
68
+ else Rectangle.new( obj )
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ $LOAD_PATH.unshift( MonoclePrint.library_path )
75
+
76
+ %w(
77
+ utils
78
+ geometry
79
+ presentation
80
+ terminal-escapes
81
+ atomic
82
+ graphics
83
+ output-device
84
+ progress
85
+ table
86
+ list
87
+ ).each { | lib | require "monocle-print/#{ lib }" }
@@ -0,0 +1,461 @@
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
+ case alignment.to_sym
87
+ when :left then left!( width, fill )
88
+ when :center then center!( width, fill )
89
+ when :right then right!( width, fill )
90
+ end
91
+ end
92
+
93
+ def blank?
94
+ empty? or self =~ /^(\s|#{COLOR_ESCAPE})*$/
95
+ end
96
+
97
+ def bleach
98
+ gsub( COLOR_ESCAPE, '' )
99
+ end
100
+
101
+ def bleach!
102
+ gsub!( COLOR_ESCAPE, '' )
103
+ end
104
+
105
+ def center!( w, fill = ' ' )
106
+ w > width or return( self )
107
+ if fill.length == 1
108
+ replace( center( w + invisible_size, fill ) )
109
+ else fill = self.class.new( fill )
110
+ even, odd = ( width - w ).divmod( 2 )
111
+ insert( 0, fill.tile( even ) )
112
+ self << fill.tile( even + odd )
113
+ end
114
+ self
115
+ end
116
+
117
+ def divide_at( len )
118
+ pos = char_byte( len )
119
+ return( [ self[ 0, pos ], self[ pos, size ] ] )
120
+ end
121
+
122
+ def each_escape
123
+ block_given? or return( enum_for( :each_escape ) )
124
+ scan( COLOR_ESCAPE ) do |esc|
125
+ yield( esc )
126
+ end
127
+ end
128
+
129
+ def escapes
130
+ each_escape.inject( self.class.new ) do | escs, esc |
131
+ escs << esc
132
+ end
133
+ end
134
+
135
+ def indent( n )
136
+ dup.indent!( n )
137
+ end
138
+
139
+ def indent!( num_spaces )
140
+ if num_spaces < 0
141
+ remaining_indent = Utils.at_least( level_of_indent + num_spaces, 0 )
142
+ lstrip!
143
+ indent!( remaining_indent )
144
+ else
145
+ insert( 0, ' ' * num_spaces )
146
+ end
147
+ return( self )
148
+ end
149
+
150
+ def invisible_size
151
+ @@invisible_size[ hash ] ||= size - width
152
+ end
153
+
154
+ def left!( w, fill = ' ' )
155
+ w > width or return( self )
156
+ if fill.length == 1
157
+ replace( ljust( w + invisible_size, fill ) )
158
+ else fill = self.class.new( fill )
159
+ insert( 0, fill.tile( width - w ) )
160
+ end
161
+ self
162
+ end
163
+
164
+ def level_of_indent
165
+ self =~ /^(\s+)/ ? $1.length : 0
166
+ end
167
+
168
+ def pad!( left, right = left )
169
+ right!( width + left )
170
+ left!( width + right )
171
+ end
172
+
173
+ def partial(len)
174
+ self[ 0, char_byte( len ) ]
175
+ end
176
+
177
+ def right!( w, fill = ' ' )
178
+ w > width or return( self )
179
+ if fill.length == 1
180
+ replace( rjust( w + invisible_size, fill ) )
181
+ else fill = self.class.new( fill )
182
+ self.insert( 0, fill.tile( w - width ) )
183
+ end
184
+ self
185
+ end
186
+
187
+ def tile( size )
188
+ width == 0 and return( )
189
+ full, partial = size.divmod( width )
190
+ self * full << partial( partial )
191
+ end
192
+
193
+ def truncate( w, tail = nil )
194
+ dup.truncate!( w, tail )
195
+ end
196
+
197
+ def truncate!( w, tail = nil )
198
+ width > w or return( self )
199
+ if tail then tail = Line( tail )
200
+ return( partial( w - tail.width ) << tail )
201
+ else
202
+ return( partial( w ) )
203
+ end
204
+ return( self )
205
+ end
206
+
207
+ def words
208
+ strip.split(/\s+/)
209
+ end
210
+
211
+ def height
212
+ 1
213
+ end
214
+
215
+ def wrap( w )
216
+ if width > w
217
+ words = split( /\s+/ ).inject( [] ) do | words, word |
218
+ while word.width > w
219
+ frag, word = word.divide_at( w )
220
+ words << frag
221
+ end
222
+ words << word
223
+ end
224
+
225
+ line = words.shift || self.class.new
226
+ text = Text.new
227
+ w -= 1
228
+ while word = words.shift
229
+ if line.width + word.width > w
230
+ text << line
231
+ line = word
232
+ else
233
+ line << ' ' << word
234
+ end
235
+ end
236
+ text << line
237
+ return( text )
238
+ else
239
+ return( Text( self.dup ) )
240
+ end
241
+ end
242
+ end
243
+
244
+ class Text < Array
245
+ def self.clear_cache
246
+ @@width.clear
247
+ @@uniform.clear
248
+ return( self )
249
+ end
250
+
251
+ include MonoclePrint
252
+ @@width = {}
253
+ @@uniform = {}
254
+
255
+ def initialize( lines = nil, default = nil )
256
+ case lines
257
+ when Fixnum
258
+ if block_given?
259
+ super( lines ) { | i | Line( yield( i ) ) }
260
+ else
261
+ default = Line( default )
262
+ super( lines, default )
263
+ end
264
+ when Text then super( lines )
265
+ when Array
266
+ super( lines.join( $/ ).map { | l | Line( l.chomp! || l ) } )
267
+ when SingleLine then super(1, lines)
268
+ when nil then super()
269
+ else
270
+ super( lines.to_s.lines.map { |l| Line( l.chomp! || l ) } )
271
+ end
272
+ end
273
+
274
+ def initialize_copy( orig )
275
+ for line in orig
276
+ self << line.dup
277
+ end
278
+ end
279
+
280
+ def align( alignment, width, fill = ' ' )
281
+ dup.align!( alignment, width, fill )
282
+ end
283
+
284
+ def align!( alignment, width, fill = ' ' )
285
+ # if the width argument is less than the full block width of the text,
286
+ # make it the full block width to ensure uniform width
287
+ width = Utils.at_least( width, self.width )
288
+
289
+ if empty?
290
+ self << SingleLine.new( ' ' * width )
291
+ else
292
+ map! do | line |
293
+ line.align( alignment, width, fill )
294
+ end
295
+ end
296
+
297
+ return( self )
298
+ end
299
+
300
+ def bleach
301
+ dup.bleach!
302
+ end
303
+
304
+ def bleach!
305
+ each { | l | l.bleach! }
306
+ end
307
+
308
+ def fix
309
+ dup.fix!
310
+ end
311
+
312
+ def fix!
313
+ align!( :left, width )
314
+ end
315
+
316
+ def fixed_indent!( level = 0 )
317
+ level = Utils.at_least( level, 0 )
318
+ offset = level - level_of_indent
319
+ indent!( offset )
320
+ end
321
+
322
+ def fixed_indent( level = 0 )
323
+ dup.fixed_indent!( level )
324
+ end
325
+
326
+ def level_of_indent
327
+ level = nil
328
+ levels = map { | line | line.blank? ? nil : line.level_of_indent }
329
+ levels.compact!
330
+ levels.min || 0
331
+ end
332
+
333
+ def indent!( spaces )
334
+ for line in self do line.indent!( spaces ) end
335
+ self
336
+ end
337
+
338
+ def indent( spaces )
339
+ dup.indent!( spaces )
340
+ end
341
+
342
+ def frame( graphic_style )
343
+ dup.frame!( graphic_style )
344
+ end
345
+
346
+ def frame!( graphic_style )
347
+ top = graphic_style.box_top( width )
348
+ bottom = graphic_style.box_bottom( width )
349
+ for line in self
350
+ line.insert( 0, graphic_style.v )
351
+ line.insert( -1, graphic_style.v )
352
+ end
353
+ unshift( top )
354
+ push( bottom )
355
+ return( self )
356
+ end
357
+
358
+ def inspect
359
+ digits = Math.log10( Utils.at_least( length, 1 ) ).floor + 1
360
+ $/ + each_with_index.map do | line, i |
361
+ line_no = i.to_s.rjust( digits )
362
+ "#{ line_no } | #{ line }"
363
+ end.join( $/ ) + $/
364
+ end
365
+
366
+ def juxtapose( text, joint = ' ' )
367
+ dup.juxtapose!( text, joint )
368
+ end
369
+
370
+ def juxtapose!( text, joint = ' ' )
371
+ text = self.class.new( text ).fix!.valign!( :top, height )
372
+ valign!( :top, text.height ); fix!
373
+
374
+ zip( text ) do | left, right |
375
+ left << joint.to_s << right
376
+ end
377
+ return( self )
378
+ end
379
+
380
+ def pad( padding )
381
+ dup.pad!( padding )
382
+ end
383
+
384
+ def pad!( padding )
385
+ padding.top.times { unshift( Line('') ) }
386
+ padding.bottom.times { push( Line('') ) }
387
+ w = width
388
+ for line in self
389
+ line.left!( w )
390
+ line.pad!( padding.left, padding.right )
391
+ end
392
+ self
393
+ end
394
+
395
+ def reflow( paragraph_style = true )
396
+ if paragraph_style
397
+ cursor, new = 0, self.class.new
398
+ text = self.to_s
399
+ while text =~ /\n\s*\n/
400
+ before, text = $`, $'
401
+ new << `#{ before.gsub!( /[ \t]*\n/, ' ' ) || before }`
402
+ new << ``
403
+ end
404
+ new << `#{ text.gsub!( /[ \t]*\n/, ' ' ) || text }`
405
+ return( new )
406
+ else
407
+ text = self.to_s
408
+ text.strip!
409
+ text.gsub!( /\s+/, ' ' )
410
+ self.class.new( text )
411
+ end
412
+ end
413
+
414
+ def reflow!( paragraph_style = true )
415
+ replace( reflow( paragraph_style ) )
416
+ end
417
+
418
+ def wrap( width )
419
+ reflow.inject( self.class.new ) do | wrapped, line |
420
+ wrapped.concat( line.wrap( width ) )
421
+ end
422
+ end
423
+
424
+ def to_s
425
+ join( $/ )
426
+ end
427
+
428
+ def uniform?
429
+ @@uniform.fetch( hash ) do | h |
430
+ @@uniform[ h ] = all? { | l | l.width == width }
431
+ end
432
+ end
433
+
434
+ def valign!( alignment, h, filler = '' )
435
+ filler = Line( filler )
436
+ h > height or return( self )
437
+ case alignment
438
+ when :top
439
+ fill( filler, height, h - height )
440
+ when :bottom
441
+ ( h - height ).times { unshift( filler ) }
442
+ when :center
443
+ even, odd = ( h - height ).divmod( 2 )
444
+ even.times { push( filler ); unshift( filler ) }
445
+ odd == 1 and push( filler )
446
+ end
447
+ return( self )
448
+ end
449
+
450
+ def width
451
+ @@width[ hash ] ||= ( map { | line | line.width }.max || 0 )
452
+ end
453
+
454
+ alias height length
455
+ alias | juxtapose
456
+ def `(str) #` # comment here cos my editor's colorizing freaks out
457
+ SingleLine.new( str )
458
+ end
459
+ end
460
+
461
+ end