ohboyohboyohboy-monocle-print 1.1.1

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.
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ module MonoclePrint
5
+ class Table
6
+ class Column
7
+ include MonoclePrint
8
+
9
+ def initialize( table, index )
10
+ @table = table
11
+ @index = index
12
+ @wrap = false
13
+ @flow = false
14
+ @alignment = :left
15
+ @fixed_width = nil
16
+ @cached_width = nil
17
+ end
18
+
19
+ attr_reader :table, :index
20
+ attr_accessor :alignment
21
+
22
+ for m in %w( wrap flow )
23
+ attr_accessor( m )
24
+ alias_method( "#{m}?", m )
25
+ undef_method( m )
26
+ end
27
+
28
+ def malleable?
29
+ @wrap and @flow
30
+ end
31
+
32
+ def malleable=( bool )
33
+ @wrap = @flow = bool
34
+ end
35
+
36
+ def fixed?
37
+ not malleable?
38
+ end
39
+
40
+ def fixed=( bool )
41
+ self.malleable = !bool
42
+ end
43
+
44
+ def title
45
+ @table.titles[ @index ]
46
+ end
47
+
48
+ def cells
49
+ @table.grep( Row ) { | row | row[ @index ] || Line( '' ) }
50
+ end
51
+
52
+ def previous_column
53
+ @index.zero? ? nil : @table.columns[ @index - 1 ]
54
+ end
55
+
56
+ def next_column
57
+ @table.columns[ @index + 1 ]
58
+ end
59
+
60
+ def first?
61
+ @index.zero?
62
+ end
63
+
64
+ def last?
65
+ @index == (table.columns.length - 1)
66
+ end
67
+
68
+ def prepare( cell_text )
69
+ cell_text = cell_text ? cell_text.dup : Text( ' ' )
70
+ @flow and cell_text.reflow!( false )
71
+ @wrap and cell_text = cell_text.wrap( width - 1 )
72
+ cell_text.align!( @alignment, width )
73
+ end
74
+
75
+ def width=( w )
76
+ @fixed_width = Utils.at_least( w.to_i, 1 )
77
+ end
78
+
79
+ def width
80
+ @fixed_width or @cached_width or calculate_width
81
+ end
82
+
83
+ def calculate_metrics
84
+ @cached_width = @fixed_width || calculate_width
85
+ end
86
+
87
+ def clear_metrics
88
+ @cached_width = nil
89
+ end
90
+
91
+ protected
92
+
93
+ def calculate_width
94
+ @table.grep( Row ) { |r| c = r[ @index ] and c.width or 0 }.max || 0
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ module MonoclePrint
5
+ class Table
6
+ class Member
7
+ include MonoclePrint
8
+ include Enumerable
9
+
10
+ class << self
11
+ attr_reader :member_name
12
+ def define( member_name, sup = self, &body )
13
+ klass =
14
+ Class.new( sup ) do
15
+ @member_name = member_name
16
+ class_eval( &body )
17
+ end
18
+
19
+ define_method( "#{ member_name }!" ) do |*args|
20
+ klass.new( @table, *args ) { |m| link( m ) }.tail
21
+ end
22
+ return( klass )
23
+ end
24
+ end
25
+
26
+ attr_reader :table
27
+ attr_accessor :before, :after
28
+ protected :before=, :after=
29
+
30
+ def initialize( table, *args )
31
+ @table = table
32
+ @before = nil
33
+ @after = nil
34
+ @disabled = false
35
+ block_given? and yield( self )
36
+ initialize!( *args )
37
+ end
38
+
39
+ def initialize!( * )
40
+ # do nothing
41
+ end
42
+
43
+ def inspect( *args )
44
+ content = args.map! { |a| a.inspect }.join(', ')
45
+ "#{self.class.member_name}(#{content})"
46
+ end
47
+
48
+ def each
49
+ block_given? or return( enum_for( __method__ ) )
50
+ node = self
51
+ begin
52
+ yield( node )
53
+ node = node.after
54
+ end while( node )
55
+ end
56
+
57
+ def disable
58
+ @disabled = true
59
+ end
60
+
61
+ def enable
62
+ @disabled = false
63
+ end
64
+
65
+ def enabled?
66
+ not disabled?
67
+ end
68
+
69
+ def disabled?
70
+ @disabled
71
+ end
72
+
73
+ def first?
74
+ @before.nil?
75
+ end
76
+
77
+ def last?
78
+ @after.nil?
79
+ end
80
+
81
+ def link( item )
82
+ after, @after, item.before = @after, item, self
83
+ after ? item.link( after ) : item
84
+ end
85
+
86
+ def unlink
87
+ @before and @before.after = nil
88
+ @before = nil
89
+ return( self )
90
+ end
91
+
92
+ def render( out, style )
93
+ render!( out, style ) unless disabled?
94
+ end
95
+
96
+ def columns
97
+ table.columns
98
+ end
99
+
100
+ def tail
101
+ @after ? @after.tail : self
102
+ end
103
+ end
104
+
105
+ Blank =
106
+ Member.define( 'blank' ) do
107
+ def render!( * )
108
+ end
109
+ end
110
+
111
+ Row =
112
+ Member.define( 'row' ) do
113
+ def initialize!( *content )
114
+ @cells = [ content ].flatten!.map! { | c | Text( c ) }
115
+ @table.expand_columns( @cells.length )
116
+ end
117
+
118
+ def []( index )
119
+ @cells[ index ]
120
+ end
121
+
122
+ def []=(index, value)
123
+ @cells[ index ] = value
124
+ end
125
+
126
+ def cells
127
+ @table.columns.zip( @cells ).
128
+ map! { | col, cell | col.prepare( cell ) }
129
+ end
130
+
131
+ def height
132
+ cells.map! { | c | c.height }.max
133
+ end
134
+
135
+ def render!( out, style )
136
+ cells =
137
+ @table.columns.zip( @cells ).map! do | col, cell |
138
+ col.prepare( cell )
139
+ end
140
+
141
+ height = cells.map { | col, cell | cell ? cell.height : 1 }.max
142
+
143
+ joint = style.format( ' <v> ' )
144
+ left = style.format( '<v> ' )
145
+ right = style.format( ' <v>' )
146
+
147
+ result = cells.inject { | result, cell | result.juxtapose( cell, joint ) }
148
+ result.each do | line |
149
+ out.put!( left + line + right )
150
+ end
151
+ return( out )
152
+ end
153
+
154
+ def inspect
155
+ super( *cells )
156
+ end
157
+
158
+ private
159
+
160
+ def prepare
161
+ height = cells.map { | c | c.height }.max
162
+ if height > 1
163
+ cell_lines.zip( @table.columns ) do | lines, col |
164
+ if lines.length < height
165
+ blank = col.fill_text( ' ' )
166
+ lines.fill( blank, lines.length, height - lines.length )
167
+ end
168
+ end
169
+ end
170
+ return( cell_lines )
171
+ end
172
+
173
+ def pad
174
+ n = @table.columns.length
175
+ m = @cells.length
176
+ @cells.fill( Text(' '), m, n - m ) if n > m
177
+ end
178
+ end
179
+
180
+ TitleRow =
181
+ Member.define( 'title_row', Row ) do
182
+ def initialize!( *content )
183
+ super
184
+ divider!( :title )
185
+ end
186
+ end
187
+
188
+ Divider =
189
+ Member.define( 'divider' ) do
190
+ attr_accessor :type
191
+
192
+ def initialize!( type )
193
+ @type = type.to_sym
194
+ end
195
+
196
+ def render( out, style )
197
+ super( out, style ) unless @after.is_a?( Divider )
198
+ end
199
+
200
+ def inspect( *args )
201
+ super( @type, *args )
202
+ end
203
+
204
+ def render!( out, style )
205
+ fills = @table.columns.map { | c | "<h:#{ c.width + 2 }>" }
206
+ template =
207
+ case @type
208
+ when :row, :title
209
+ '<nse>' << fills.join( '<hv>' ) << '<nsw>'
210
+ when :section_open
211
+ '<nse>' << fills.join( '<hs>' ) << '<nsw>'
212
+ when :section_close
213
+ '<nse>' << fills.join( '<hn>' ) << '<nsw>'
214
+ when :head
215
+ '<se>' << fills.join( '<hs>' ) << '<sw>'
216
+ when :foot
217
+ '<ne>' << fills.join( '<hn>' ) << '<nw>'
218
+ end
219
+ out.puts( style.format( template ) )
220
+ end
221
+ end
222
+
223
+ SectionTitle =
224
+ Member.define( 'section' ) do
225
+ attr_accessor :title, :alignment
226
+
227
+ def initialize!( title, options = {} )
228
+ @title = Text( title )
229
+ @alignment = options.fetch( :align, :left )
230
+ @before.divider!( :section_close )
231
+ divider!( :section_open )
232
+ end
233
+
234
+ def inspect
235
+ super( @title, @alignment )
236
+ end
237
+
238
+ def render!( out, style )
239
+ w = @table.inner_width
240
+ title = @title.width > w ? @title.wrap( w ) : @title
241
+ left = style.format( '<v> ' )
242
+ right = style.format( ' <v>' )
243
+
244
+ for line in title.align( @alignment, w )
245
+ out.puts( left + line + right )
246
+ end
247
+ end
248
+
249
+ end
250
+
251
+ end
252
+ end
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ module MonoclePrint
5
+ class Table
6
+
7
+ Segments = Struct.new(
8
+ :head, :title_row, :title_divider, :row, :row_divider,
9
+ :section, :section_close, :section_open, :foot
10
+ )
11
+
12
+ class Segments
13
+ include MonoclePrint
14
+
15
+ def self.default_filling( style )
16
+ fill = style.new.dup
17
+ new( fill, nil, fill, nil, fill, nil, fill, fill, fill )
18
+ end
19
+
20
+ def self.default_joints( style )
21
+ head = style.format( "<h><hd><h>" )
22
+ row = style.format( " <v> " )
23
+ div = style.format( "<h><hv><h>" )
24
+ foot = style.format( "<h><hu><h>" )
25
+
26
+ new( head, row, div, row, div, nil, foot, head, foot )
27
+ end
28
+
29
+ def self.default_left_edge( style )
30
+ head = style.format( "<dr><h>" )
31
+ row = style.format( "<v> " )
32
+ div = style.format( "<vr><h>" )
33
+ foot = style.format( "<ur><h>" )
34
+ new( head, row, div, row, div, row, div, div, foot )
35
+ end
36
+
37
+ def self.default_right_edge( style )
38
+ head = style.format( "<h><dl>" )
39
+ row = style.format( " <v>" )
40
+ div = style.format( "<h><vl>" )
41
+ foot = style.format( "<h><ul>" )
42
+ new( head, row, div, row, div, row, div, div, foot )
43
+ end
44
+
45
+ def mask( inclusion_settings )
46
+ masked = self.class.new
47
+ each_pair do | name, text |
48
+ if text and inclusion_settings[ name ]
49
+ masked[ name ] = text
50
+ end
51
+ end
52
+ return( masked )
53
+ end
54
+
55
+ def width( inclusion_mask = nil )
56
+ inclusion_mask and return( self.mask( inclusion_mask ).width )
57
+ return( map { |text| text ? text.width : 0 }.max )
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,205 @@
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
+ ANSI_COLOR_NAMES = ANSI_COLORS.keys.freeze
15
+
16
+ ANSI_MODIFIERS =
17
+ {
18
+ :bold => 1,
19
+ :underline => 4,
20
+ :blink => 5,
21
+ :reverse => 7,
22
+ :conceal => 8
23
+ }
24
+ ANSI_MODIFIER_NAMES = ANSI_MODIFIERS.keys.freeze
25
+
26
+ module_function
27
+
28
+ #def term_info
29
+ # @term_info ||= TermInfo.new
30
+ #end
31
+
32
+ def ansi_color( type, color, bold = nil )
33
+ offset =
34
+ case type
35
+ when ?f then 30 # foreground
36
+ when ?b then 40 # background
37
+ end
38
+ code = offset + ANSI_COLORS.fetch( color.to_sym ) do
39
+ raise( ArgumentError, "unknown color name `%s'" % color )
40
+ end
41
+ "\e[#{ '1;' if bold }#{ code }m"
42
+ end
43
+
44
+ def xterm_color( type, color_index, bold = nil )
45
+ prefix =
46
+ case type
47
+ when ?f then 38 # foreground
48
+ when ?b then 48 # background
49
+ end
50
+ "\e[#{ prefix };5;#{ color_index }m"
51
+ end
52
+
53
+ def konsole_color( type, r, g, b, bold = nil)
54
+ prefix =
55
+ case type
56
+ when ?f then 38 # foreground
57
+ when ?b then 48 # background
58
+ end
59
+ "\e[#{ prefix };2;#{ r };#{ g };#{ b }m"
60
+ end
61
+
62
+ def ansi_modifier( name )
63
+ code =
64
+ ANSI_MODIFIERS.fetch( name.to_sym ) do
65
+ fail ArgumentError, "unknown modifier name `%s'" % name
66
+ end
67
+ "\e[#{ code }m"
68
+ end
69
+
70
+ def clear_attr
71
+ "\e[0m"
72
+ end
73
+
74
+ def bold
75
+ "\e[1m"
76
+ end
77
+
78
+ def underline
79
+ "\e[4m"
80
+ end
81
+
82
+ def blink
83
+ "\e[5m"
84
+ end
85
+
86
+ def reverse
87
+ "\e[7m"
88
+ end
89
+
90
+ def conceal
91
+ "\e[8m"
92
+ end
93
+
94
+ def set_cursor( line = 0, column = 0 )
95
+ "\e[%i;%iH" % [ line, column ]
96
+ end
97
+
98
+ def cursor_up( lines = 1 )
99
+ "\e[%iA" % lines
100
+ end
101
+
102
+ def cursor_down( lines = 1 )
103
+ "\e[%iB" % lines
104
+ end
105
+
106
+ def cursor_forward( columns = 1 )
107
+ "\e[%iC" % columns
108
+ end
109
+
110
+ def cursor_backward( columns = 1 )
111
+ "\e[%iD" % columns
112
+ end
113
+
114
+ def save_cursor
115
+ "\e[s"
116
+ end
117
+
118
+ def restore_cursor
119
+ "\e[u"
120
+ end
121
+
122
+ #def clear_line
123
+ # "\e[K"
124
+ #end
125
+
126
+ # VT100 escapes
127
+ def double_height_top
128
+ "\e#3"
129
+ end
130
+
131
+ def dobule_height_bottom
132
+ "\e#4"
133
+ end
134
+
135
+ def single_width
136
+ "\e#5"
137
+ end
138
+
139
+ def double_width
140
+ "\e#6"
141
+ end
142
+
143
+ def clear_right
144
+ "\e[0K"
145
+ end
146
+
147
+ def clear_left
148
+ "\e[1K"
149
+ end
150
+
151
+ def clear_line
152
+ "\e[2K"
153
+ end
154
+
155
+ def clear_down
156
+ "\e[0J"
157
+ end
158
+
159
+ def clear_up
160
+ "\e[1J"
161
+ end
162
+
163
+ def clear_screen
164
+ "\e[2J"
165
+ end
166
+
167
+ end
168
+ end
169
+
170
+ if __FILE__ == $0
171
+
172
+ TE = MonoclePrint::TerminalEscapes
173
+ for attr in %w[ bold underline blink reverse conceal ]
174
+ print( "This should be #{ attr }:".ljust( 30 ) )
175
+ printf( "%swhateva\e[0m\n", TE.send( attr ) )
176
+ end
177
+
178
+ colors = TE::ANSI_COLORS.keys.map(&:to_s).sort!
179
+ for color in colors
180
+ print( "This should be #{ color }:".ljust( 30 ) )
181
+ printf( "%swhateva\e[0m\t", TE.ansi_color( ?f, color ) )
182
+ printf( "%swhateva\e[0m\t", TE.ansi_color( ?b, color ) )
183
+ printf( "%sbright_whateva\e[0m\n", TE.ansi_color( ?f, color, true ) )
184
+ end
185
+
186
+ for dir in %w( left right line )
187
+ name = "clear_#{ dir }"
188
+ code = TE.send( name )
189
+ puts
190
+ puts("[ Clear Code: #{ name } ]")
191
+ puts
192
+ puts("at start")
193
+ printf("%s<= %-14s\n", code, name)
194
+ puts("in middle")
195
+ printf("%-14s =>%s<= %-14s\n", name, code, name)
196
+ puts("at end")
197
+ printf("%-14s =>%s\n", name, code, name)
198
+ end
199
+
200
+ puts( "[ Tabs ]" )
201
+ puts( " \eHx \eHx \eHx ")
202
+ puts( "one\ttwo\tthree\tfour" )
203
+ puts( "\e[3g" )
204
+ puts( "one\ttwo\tthree\tfour" )
205
+ end