monocle-print 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|