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 +15 -0
- data/.gemtest +0 -0
- data/History.txt +4 -0
- data/Manifest.txt +19 -0
- data/README.txt +40 -0
- data/Rakefile +21 -0
- data/lib/monocle-print/atomic.rb +462 -0
- data/lib/monocle-print/geometry.rb +66 -0
- data/lib/monocle-print/graphics.rb +111 -0
- data/lib/monocle-print/layout.rb +58 -0
- data/lib/monocle-print/list.rb +138 -0
- data/lib/monocle-print/output-device.rb +491 -0
- data/lib/monocle-print/presentation.rb +132 -0
- data/lib/monocle-print/progress.rb +192 -0
- data/lib/monocle-print/table/column.rb +98 -0
- data/lib/monocle-print/table/members.rb +252 -0
- data/lib/monocle-print/table/segments.rb +62 -0
- data/lib/monocle-print/table.rb +229 -0
- data/lib/monocle-print/terminal-escapes.rb +186 -0
- data/lib/monocle-print/utils.rb +23 -0
- data/lib/monocle-print.rb +70 -0
- metadata +97 -0
@@ -0,0 +1,229 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'monocle-print/table/segments'
|
4
|
+
require 'monocle-print/table/members'
|
5
|
+
require 'monocle-print/table/column'
|
6
|
+
|
7
|
+
module MonoclePrint
|
8
|
+
class Table
|
9
|
+
include MonoclePrint
|
10
|
+
include Presentation
|
11
|
+
include Enumerable
|
12
|
+
|
13
|
+
def self.build( *args )
|
14
|
+
table = new( *args ) do | table |
|
15
|
+
block_given? and yield( table )
|
16
|
+
end
|
17
|
+
return( table.render )
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def initialize( columns, options = {} )
|
22
|
+
initialize_view( options )
|
23
|
+
|
24
|
+
@titles = nil
|
25
|
+
@item = @head = Divider.new( self, :head )
|
26
|
+
@foot = Divider.new( self, :foot )
|
27
|
+
@columns = []
|
28
|
+
@body = []
|
29
|
+
|
30
|
+
case columns
|
31
|
+
when Fixnum
|
32
|
+
expand_columns( columns )
|
33
|
+
when Array
|
34
|
+
title_row( *columns )
|
35
|
+
end
|
36
|
+
|
37
|
+
block_given? and yield( self )
|
38
|
+
end
|
39
|
+
|
40
|
+
def render_content( out )
|
41
|
+
style = @style || out.style
|
42
|
+
lock do
|
43
|
+
width > out.width and resize( out.width )
|
44
|
+
each { | member | member.render( out, style ) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def each
|
49
|
+
block_given? or return( enum_for( :each ) )
|
50
|
+
for item in @head
|
51
|
+
yield( item )
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_reader :columns, :titles
|
56
|
+
|
57
|
+
def row( *members )
|
58
|
+
@item = @item.row!( *members )
|
59
|
+
end
|
60
|
+
|
61
|
+
def title_row( *members )
|
62
|
+
@titles = @item = @item.title_row!( *members )
|
63
|
+
while @titles
|
64
|
+
if TitleRow === @titles
|
65
|
+
@titles = @titles.cells.map { | c | c.to_s }
|
66
|
+
break
|
67
|
+
end
|
68
|
+
@titles = @titles.before
|
69
|
+
end
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def rows( *list_of_rows )
|
74
|
+
for row in list_of_rows do row( *row ) end
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
def section( title, options = {} )
|
79
|
+
@item = @item.section!( title, options )
|
80
|
+
end
|
81
|
+
|
82
|
+
def divider( type = :row_divider )
|
83
|
+
@item = @item.divider!( type )
|
84
|
+
end
|
85
|
+
|
86
|
+
def fixed_columns( *column_indicies )
|
87
|
+
for column_index in column_indicies
|
88
|
+
if c = column( column_indicies )
|
89
|
+
if Array === c then c.each { | i | i.fixed = true }
|
90
|
+
else c.fixed = true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def malleable_columns( *column_indicies )
|
97
|
+
for column_index in column_indicies
|
98
|
+
if c = column( column_index )
|
99
|
+
if Array === c then c.each { | i | i.malleable = true }
|
100
|
+
else c.malleable = true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def column( name_or_index )
|
107
|
+
case name_or_index
|
108
|
+
when Integer, Range then @columns[ name_or_index ]
|
109
|
+
else
|
110
|
+
@columns.find do | col |
|
111
|
+
name_or_index === col.title
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def resize( new_size )
|
117
|
+
resizable = @columns.select { | c | c.malleable? }
|
118
|
+
if resizable.empty?
|
119
|
+
warn( "cannot resize #{ self.inspect } as all columns are fixed" )
|
120
|
+
return( self )
|
121
|
+
end
|
122
|
+
|
123
|
+
lock do
|
124
|
+
difference = new_size - @width
|
125
|
+
resize_columns( difference, resizable )
|
126
|
+
end
|
127
|
+
|
128
|
+
return( self )
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
def inner_width
|
134
|
+
@inner_width or calculate_inner_width
|
135
|
+
end
|
136
|
+
|
137
|
+
def width
|
138
|
+
@width or calculate_width
|
139
|
+
end
|
140
|
+
|
141
|
+
def expand_columns(new_size)
|
142
|
+
new_size.zero? and return
|
143
|
+
|
144
|
+
until @columns.length >= new_size
|
145
|
+
@columns << Column.new( self, @columns.length )
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def resize_columns( amount, columns )
|
152
|
+
leftover = amount
|
153
|
+
resizable_area = columns.inject( 0 ) do | sz, c |
|
154
|
+
sz + c.width
|
155
|
+
end
|
156
|
+
|
157
|
+
for column in columns
|
158
|
+
proportion = ( column.width.to_f / resizable_area )
|
159
|
+
delta = ( proportion * amount ).round
|
160
|
+
column.width += delta
|
161
|
+
leftover -= delta
|
162
|
+
end
|
163
|
+
|
164
|
+
columns.last.width += leftover
|
165
|
+
end
|
166
|
+
|
167
|
+
def expand( amount, columns )
|
168
|
+
leftover = amount
|
169
|
+
resizable_area = columns.inject( 0 ) do | sz, c |
|
170
|
+
sz + c.width
|
171
|
+
end
|
172
|
+
|
173
|
+
for column in columns
|
174
|
+
proportion = ( column.width.to_f / resizable_area )
|
175
|
+
delta = ( proportion * amount ).round
|
176
|
+
column.width += delta
|
177
|
+
leftover -= delta
|
178
|
+
end
|
179
|
+
|
180
|
+
columns.last.width += leftover
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
|
185
|
+
def lock
|
186
|
+
calculate_metrics
|
187
|
+
@item.link( @foot )
|
188
|
+
yield
|
189
|
+
ensure
|
190
|
+
@foot.unlink
|
191
|
+
clear_metrics
|
192
|
+
end
|
193
|
+
|
194
|
+
def calculate_metrics
|
195
|
+
@columns.each { | c | c.calculate_metrics }
|
196
|
+
@inner_width = calculate_inner_width
|
197
|
+
@width = calculate_width
|
198
|
+
end
|
199
|
+
|
200
|
+
def clear_metrics
|
201
|
+
@columns.each { | c | c.clear_metrics }
|
202
|
+
@inner_width = nil
|
203
|
+
@width = nil
|
204
|
+
end
|
205
|
+
|
206
|
+
def calculate_inner_width
|
207
|
+
w = @columns.inject( 0 ) { | w, c | w + c.width }
|
208
|
+
w + ( @columns.length - 1 ) * 3
|
209
|
+
end
|
210
|
+
|
211
|
+
def calculate_width
|
212
|
+
calculate_inner_width + 4
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
class ColumnLayout < Table
|
218
|
+
def initialize( columns, options = {} )
|
219
|
+
super( columns, options ) do
|
220
|
+
@item = @head = Blank.new( self )
|
221
|
+
@foot = Blank.new( self )
|
222
|
+
@style = Style( :blank )
|
223
|
+
block_given? and yield( self )
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
|
@@ -0,0 +1,186 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
#require 'termios'
|
5
|
+
#require 'terminfo'
|
6
|
+
|
7
|
+
module MonoclePrint
|
8
|
+
module TerminalEscapes
|
9
|
+
ANSI_COLORS = {
|
10
|
+
:blue => 4, :white => 7, :magenta => 5,
|
11
|
+
:yellow => 3, :green => 2, :black => 0,
|
12
|
+
:red => 1, :cyan => 6
|
13
|
+
}
|
14
|
+
|
15
|
+
module_function
|
16
|
+
|
17
|
+
#def term_info
|
18
|
+
# @term_info ||= TermInfo.new
|
19
|
+
#end
|
20
|
+
|
21
|
+
def ansi_color( type, color, bold = nil )
|
22
|
+
offset =
|
23
|
+
case type
|
24
|
+
when ?f then 30 # foreground
|
25
|
+
when ?b then 40 # background
|
26
|
+
end
|
27
|
+
code = offset + ANSI_COLORS.fetch( color.to_sym ) do
|
28
|
+
raise( ArgumentError, "unknown color name `%s'" % color )
|
29
|
+
end
|
30
|
+
"\e[#{ '1;' if bold }#{ code }m"
|
31
|
+
end
|
32
|
+
|
33
|
+
def xterm_color( type, color_index, bold = nil )
|
34
|
+
prefix =
|
35
|
+
case type
|
36
|
+
when ?f then 38 # foreground
|
37
|
+
when ?b then 48 # background
|
38
|
+
end
|
39
|
+
"\e[#{ prefix };5;#{ color_index }m"
|
40
|
+
end
|
41
|
+
|
42
|
+
def konsole_color( type, r, g, b, bold = nil)
|
43
|
+
prefix =
|
44
|
+
case type
|
45
|
+
when ?f then 38 # foreground
|
46
|
+
when ?b then 48 # background
|
47
|
+
end
|
48
|
+
"\e[#{ prefix };2;#{ r };#{ g };#{ b }m"
|
49
|
+
end
|
50
|
+
|
51
|
+
def clear_attr
|
52
|
+
"\e[0m"
|
53
|
+
end
|
54
|
+
|
55
|
+
def bold
|
56
|
+
"\e[1m"
|
57
|
+
end
|
58
|
+
|
59
|
+
def underline
|
60
|
+
"\e[4m"
|
61
|
+
end
|
62
|
+
|
63
|
+
def blink
|
64
|
+
"\e[5m"
|
65
|
+
end
|
66
|
+
|
67
|
+
def reverse
|
68
|
+
"\e[7m"
|
69
|
+
end
|
70
|
+
|
71
|
+
def conceal
|
72
|
+
"\e[8m"
|
73
|
+
end
|
74
|
+
|
75
|
+
def set_cursor( line = 0, column = 0 )
|
76
|
+
"\e[%i;%iH" % [ line, column ]
|
77
|
+
end
|
78
|
+
|
79
|
+
def cursor_up( lines = 1 )
|
80
|
+
"\e[%iA" % lines
|
81
|
+
end
|
82
|
+
|
83
|
+
def cursor_down( lines = 1 )
|
84
|
+
"\e[%iB" % lines
|
85
|
+
end
|
86
|
+
|
87
|
+
def cursor_forward( columns = 1 )
|
88
|
+
"\e[%iC" % columns
|
89
|
+
end
|
90
|
+
|
91
|
+
def cursor_backward( columns = 1 )
|
92
|
+
"\e[%iD" % columns
|
93
|
+
end
|
94
|
+
|
95
|
+
def save_cursor
|
96
|
+
"\e[s"
|
97
|
+
end
|
98
|
+
|
99
|
+
def restore_cursor
|
100
|
+
"\e[u"
|
101
|
+
end
|
102
|
+
|
103
|
+
#def clear_line
|
104
|
+
# "\e[K"
|
105
|
+
#end
|
106
|
+
|
107
|
+
# VT100 escapes
|
108
|
+
def double_height_top
|
109
|
+
"\e#3"
|
110
|
+
end
|
111
|
+
|
112
|
+
def dobule_height_bottom
|
113
|
+
"\e#4"
|
114
|
+
end
|
115
|
+
|
116
|
+
def single_width
|
117
|
+
"\e#5"
|
118
|
+
end
|
119
|
+
|
120
|
+
def double_width
|
121
|
+
"\e#6"
|
122
|
+
end
|
123
|
+
|
124
|
+
def clear_right
|
125
|
+
"\e[0K"
|
126
|
+
end
|
127
|
+
|
128
|
+
def clear_left
|
129
|
+
"\e[1K"
|
130
|
+
end
|
131
|
+
|
132
|
+
def clear_line
|
133
|
+
"\e[2K"
|
134
|
+
end
|
135
|
+
|
136
|
+
def clear_down
|
137
|
+
"\e[0J"
|
138
|
+
end
|
139
|
+
|
140
|
+
def clear_up
|
141
|
+
"\e[1J"
|
142
|
+
end
|
143
|
+
|
144
|
+
def clear_screen
|
145
|
+
"\e[2J"
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
if __FILE__ == $0
|
152
|
+
|
153
|
+
TE = MonoclePrint::TerminalEscapes
|
154
|
+
for attr in %w[ bold underline blink reverse conceal ]
|
155
|
+
print( "This should be #{ attr }:".ljust( 30 ) )
|
156
|
+
printf( "%swhateva\e[0m\n", TE.send( attr ) )
|
157
|
+
end
|
158
|
+
|
159
|
+
colors = TE::ANSI_COLORS.keys.map(&:to_s).sort!
|
160
|
+
for color in colors
|
161
|
+
print( "This should be #{ color }:".ljust( 30 ) )
|
162
|
+
printf( "%swhateva\e[0m\t", TE.ansi_color( ?f, color ) )
|
163
|
+
printf( "%swhateva\e[0m\t", TE.ansi_color( ?b, color ) )
|
164
|
+
printf( "%sbright_whateva\e[0m\n", TE.ansi_color( ?f, color, true ) )
|
165
|
+
end
|
166
|
+
|
167
|
+
for dir in %w( left right line )
|
168
|
+
name = "clear_#{ dir }"
|
169
|
+
code = TE.send( name )
|
170
|
+
puts
|
171
|
+
puts("[ Clear Code: #{ name } ]")
|
172
|
+
puts
|
173
|
+
puts("at start")
|
174
|
+
printf("%s<= %-14s\n", code, name)
|
175
|
+
puts("in middle")
|
176
|
+
printf("%-14s =>%s<= %-14s\n", name, code, name)
|
177
|
+
puts("at end")
|
178
|
+
printf("%-14s =>%s\n", name, code, name)
|
179
|
+
end
|
180
|
+
|
181
|
+
puts( "[ Tabs ]" )
|
182
|
+
puts( " \eHx \eHx \eHx ")
|
183
|
+
puts( "one\ttwo\tthree\tfour" )
|
184
|
+
puts( "\e[3g" )
|
185
|
+
puts( "one\ttwo\tthree\tfour" )
|
186
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
module MonoclePrint
|
5
|
+
module Utils
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def at_least( comparable, min )
|
9
|
+
( comparable >= min ) ? comparable : min
|
10
|
+
end
|
11
|
+
|
12
|
+
def at_most( comparable, max )
|
13
|
+
( comparable <= max ) ? comparable : max
|
14
|
+
end
|
15
|
+
|
16
|
+
def bound( comparable, lower, upper = nil )
|
17
|
+
return lower if comparable < lower
|
18
|
+
return comparable unless upper
|
19
|
+
return upper if comparable > upper
|
20
|
+
return comparable
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
module MonoclePrint
|
5
|
+
VERSION = '1.0.0'
|
6
|
+
|
7
|
+
def self.version
|
8
|
+
VERSION
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.included( kl )
|
12
|
+
super
|
13
|
+
kl.extend( self )
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.library_path( *args )
|
17
|
+
File.join( File.dirname( __FILE__ ), *args )
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.stdout
|
21
|
+
Output( $stdout )
|
22
|
+
end
|
23
|
+
|
24
|
+
module_function
|
25
|
+
|
26
|
+
def Line( obj )
|
27
|
+
SingleLine === obj ? obj : SingleLine.new( obj.to_s )
|
28
|
+
end
|
29
|
+
|
30
|
+
def Output( dev )
|
31
|
+
OutputDevice === dev ? dev : OutputDevice.new( dev )
|
32
|
+
end
|
33
|
+
|
34
|
+
def Text( obj )
|
35
|
+
case obj
|
36
|
+
when Text then obj
|
37
|
+
when nil then Text.new( '' )
|
38
|
+
else Text.new( obj.to_s )
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def Style( obj )
|
43
|
+
Graphics === obj ? obj : Graphics::NAMED_STYLES[ obj.to_s ]
|
44
|
+
end
|
45
|
+
|
46
|
+
def Rectangle( obj )
|
47
|
+
case obj
|
48
|
+
when Rectangle then obj
|
49
|
+
when Array then Rectangle.new( *obj )
|
50
|
+
when Hash then Rectangle.create( obj )
|
51
|
+
else Rectangle.new( obj )
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
$LOAD_PATH.unshift( MonoclePrint.library_path )
|
58
|
+
|
59
|
+
%w(
|
60
|
+
utils
|
61
|
+
geometry
|
62
|
+
presentation
|
63
|
+
terminal-escapes
|
64
|
+
atomic
|
65
|
+
graphics
|
66
|
+
output-device
|
67
|
+
progress
|
68
|
+
table
|
69
|
+
list
|
70
|
+
).each { | lib | require "monocle-print/#{ lib }" }
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: monocle-print
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- monocle-print
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rdoc
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: hoe
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.7'
|
41
|
+
description: Fancy console output tools
|
42
|
+
email:
|
43
|
+
- kyle@ohboyohboyohboy.org
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files:
|
47
|
+
- History.txt
|
48
|
+
- Manifest.txt
|
49
|
+
- README.txt
|
50
|
+
files:
|
51
|
+
- lib/monocle-print.rb
|
52
|
+
- lib/monocle-print/layout.rb
|
53
|
+
- lib/monocle-print/table/segments.rb
|
54
|
+
- lib/monocle-print/table/members.rb
|
55
|
+
- lib/monocle-print/table/column.rb
|
56
|
+
- lib/monocle-print/output-device.rb
|
57
|
+
- lib/monocle-print/graphics.rb
|
58
|
+
- lib/monocle-print/table.rb
|
59
|
+
- lib/monocle-print/list.rb
|
60
|
+
- lib/monocle-print/progress.rb
|
61
|
+
- lib/monocle-print/presentation.rb
|
62
|
+
- lib/monocle-print/utils.rb
|
63
|
+
- lib/monocle-print/terminal-escapes.rb
|
64
|
+
- lib/monocle-print/geometry.rb
|
65
|
+
- lib/monocle-print/atomic.rb
|
66
|
+
- History.txt
|
67
|
+
- Manifest.txt
|
68
|
+
- README.txt
|
69
|
+
- Rakefile
|
70
|
+
- .gemtest
|
71
|
+
homepage: http://ohboyohboyohboy.org
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
metadata: {}
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options:
|
77
|
+
- --main
|
78
|
+
- README.txt
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project: monocle-print
|
93
|
+
rubygems_version: 2.0.3
|
94
|
+
signing_key:
|
95
|
+
specification_version: 4
|
96
|
+
summary: Fancy console output tools
|
97
|
+
test_files: []
|