bash-visual 1.0.6 → 1.0.7
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.
- data/README.md +1 -1
- data/bash-visual-1.0.6.gem +0 -0
- data/example/hello_world.rb +3 -6
- data/example/painter.rb +36 -0
- data/example/scroll.rb +45 -0
- data/lib/bash-visual.rb +2 -0
- data/lib/bash-visual/builder.rb +6 -4
- data/lib/bash-visual/console.rb +12 -80
- data/lib/bash-visual/fixed_object.rb +16 -0
- data/lib/bash-visual/font.rb +81 -43
- data/lib/bash-visual/horizontal_scroll.rb +21 -34
- data/lib/bash-visual/painter.rb +110 -0
- data/lib/bash-visual/scroll.rb +65 -64
- data/lib/bash-visual/version.rb +1 -1
- data/lib/bash-visual/vertical_scroll.rb +19 -31
- data/test/console_test.rb +15 -0
- data/test/font_test.rb +38 -0
- data/test/helper.rb +1 -0
- data/test/painter_test.rb +32 -0
- data/test/scroll_test.rb +61 -0
- data/test/vertical_scroll_test.rb +16 -0
- metadata +11 -2
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
Bash visualisation library
|
4
4
|
|
5
5
|
## Description
|
6
|
-
**BashVisual** simplifies Unix-console operation (bash, csh etc). It uses _tput_ and standard Unix-terminal facilities. It is also thread-safe.
|
6
|
+
**BashVisual** simplifies Unix-console operation (sh, bash, csh etc). It uses _tput_ and standard Unix-terminal facilities. It is also thread-safe.
|
7
7
|
|
8
8
|
BashVisual allows:
|
9
9
|
- control position, colors and text's form
|
Binary file
|
data/example/hello_world.rb
CHANGED
@@ -3,12 +3,9 @@ $:.push File.expand_path('../../lib', __FILE__)
|
|
3
3
|
require 'bash-visual'
|
4
4
|
include Bash_Visual
|
5
5
|
|
6
|
-
|
7
|
-
main_color = Font.new(:bold, :green)
|
8
|
-
|
9
|
-
console = Console.new(main_color)
|
6
|
+
console = Console.new
|
10
7
|
console.clear
|
11
8
|
|
12
|
-
console.draw_window
|
13
|
-
console.write_to_position
|
9
|
+
console.draw_window [3, 3], [18, 5], 'Example', {font: Font.new(:std, :red)}
|
10
|
+
console.write_to_position 5, 4, 'Hello World!', Font.new(:bold)
|
14
11
|
console.position = [0, 8]
|
data/example/painter.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
$:.push File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'bash-visual'
|
4
|
+
include Bash_Visual
|
5
|
+
|
6
|
+
console = Console.new
|
7
|
+
console.clear
|
8
|
+
Thread.new {
|
9
|
+
100.times {
|
10
|
+
x, y = 0, 0
|
11
|
+
width, height = 20, 12
|
12
|
+
5.times {
|
13
|
+
x, y = x+1, y+1
|
14
|
+
width, height = width-2, height-2
|
15
|
+
console.draw_border([x, y], [width, height], {font: Font::rand_font})
|
16
|
+
sleep 0.08
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
Thread.new {
|
22
|
+
100.times {
|
23
|
+
x, y = 22, 0
|
24
|
+
width, height = 20, 12
|
25
|
+
5.times {
|
26
|
+
x, y = x+1, y+1
|
27
|
+
width, height = width-2, height-2
|
28
|
+
console.draw_filled_rectangle([x, y], [width, height], Font::rand_color(:black))
|
29
|
+
sleep 0.09
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
}
|
34
|
+
|
35
|
+
sleep 10
|
36
|
+
console.position = [0, 12]
|
data/example/scroll.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
$:.push File.expand_path('../../lib', __FILE__)
|
3
|
+
require 'bash-visual'
|
4
|
+
include Bash_Visual
|
5
|
+
|
6
|
+
console = Console.new
|
7
|
+
console.clear
|
8
|
+
|
9
|
+
console.draw_window([32, 0] ,[42, 11], 'Vertical scroll')
|
10
|
+
console.draw_window([0, 12] ,[73, 6], 'Horizontal scroll')
|
11
|
+
|
12
|
+
v_scroll = VerticalScroll.new(
|
13
|
+
position: [33, 1],
|
14
|
+
size: [39, 9],
|
15
|
+
prefix: ->{Time.now.strftime('%H-%M-%S:%3N') + ' '}
|
16
|
+
)
|
17
|
+
|
18
|
+
h_scroll = HorizontalScroll.new(
|
19
|
+
position: [2, 12],
|
20
|
+
size: [70, 4],
|
21
|
+
fixed_message_block_size: 20,
|
22
|
+
separator: true
|
23
|
+
)
|
24
|
+
|
25
|
+
phrases =[
|
26
|
+
"Bash is a Unix shell",
|
27
|
+
"GNU’s Not UNIX",
|
28
|
+
"Answer to the Ultimate Question of Life, the Universe, and Everything"]
|
29
|
+
|
30
|
+
|
31
|
+
Thread.new {
|
32
|
+
10.times do
|
33
|
+
h_scroll.add phrases.sample
|
34
|
+
sleep 0.3
|
35
|
+
end
|
36
|
+
}
|
37
|
+
Thread.new {
|
38
|
+
10.times do
|
39
|
+
v_scroll.add phrases.sample
|
40
|
+
sleep 0.15
|
41
|
+
end
|
42
|
+
}
|
43
|
+
|
44
|
+
sleep 4
|
45
|
+
console.position = [1,18]
|
data/lib/bash-visual.rb
CHANGED
data/lib/bash-visual/builder.rb
CHANGED
@@ -42,7 +42,7 @@ module Bash_Visual
|
|
42
42
|
bash
|
43
43
|
end
|
44
44
|
|
45
|
-
def write_to_position(x, y, text, font =
|
45
|
+
def write_to_position(x, y, text, font = nil)
|
46
46
|
bash = ''
|
47
47
|
bash << save_position()
|
48
48
|
bash << move_position(x, y)
|
@@ -51,12 +51,14 @@ module Bash_Visual
|
|
51
51
|
bash
|
52
52
|
end
|
53
53
|
|
54
|
-
def write(text, font =
|
54
|
+
def write(text, font = nil)
|
55
|
+
return text if font.nil?
|
55
56
|
font.to_bash + text + Font::RESET
|
56
57
|
end
|
57
58
|
|
58
|
-
def write_ln(text, font =
|
59
|
-
|
59
|
+
def write_ln(text, font = nil)
|
60
|
+
return text + "\n" if font.nil?
|
61
|
+
font.to_bash + text.to_s + "\n" + Font::RESET
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
data/lib/bash-visual/console.rb
CHANGED
@@ -1,30 +1,22 @@
|
|
1
1
|
module Bash_Visual
|
2
2
|
class Console
|
3
|
+
include Painter
|
4
|
+
|
3
5
|
@@mutex = Mutex.new
|
4
6
|
|
5
7
|
OUTPUT_STRING = 0
|
6
8
|
OUTPUT_WITHOUT_BLOCK = 1
|
7
9
|
OUTPUT_WITH_BLOCK = 2
|
8
|
-
# see: http://en.wikipedia.org/wiki/Box-drawing_characters
|
9
|
-
BORDER_UTF = ["\u250C","\u2500","\u2510",
|
10
|
-
"\u2502", "\u2502",
|
11
|
-
"\u2514","\u2500","\u2518"]
|
12
|
-
|
13
|
-
BORDER_UTF_ROUND = ["\u256D","\u2500","\u256E",
|
14
|
-
"\u2502", "\u2502",
|
15
|
-
"\u2570","\u2500","\u256F"]
|
16
|
-
|
17
|
-
BORDER_UTF_DOUBLE = ["\u2554","\u2550","\u2557",
|
18
|
-
"\u2551", "\u2551",
|
19
|
-
"\u255A","\u2550","\u255D"]
|
20
|
-
|
21
10
|
attr_reader :current_x, :current_y, :font;
|
22
11
|
|
23
|
-
|
12
|
+
# @param [Bash_Visual::Font] font
|
13
|
+
# @param [Object] way_output
|
14
|
+
# @param [Bash_Visual::Builder] builder
|
15
|
+
def initialize (font = Font.new, way_output = OUTPUT_WITHOUT_BLOCK, builder = Builder.new)
|
24
16
|
@current_x = 0
|
25
17
|
@current_y = 0
|
26
|
-
@
|
27
|
-
@way_output =
|
18
|
+
@font = font
|
19
|
+
@way_output = way_output
|
28
20
|
@builder = builder
|
29
21
|
end
|
30
22
|
|
@@ -42,20 +34,15 @@ module Bash_Visual
|
|
42
34
|
# Записать что-то в определенной позиции, а потом вернуться на текущую
|
43
35
|
# Если необходимо сохранить позицию после записи - используйте связку
|
44
36
|
# move_position/position= и write
|
45
|
-
def write_to_position (x, y, text, font = @
|
37
|
+
def write_to_position (x, y, text, font = @font)
|
46
38
|
print @builder.write_to_position(x, y, text, font)
|
47
39
|
end
|
48
40
|
|
49
|
-
def write (text, font = @
|
41
|
+
def write (text, font = @font)
|
50
42
|
print @builder.write(text, font)
|
51
43
|
end
|
52
44
|
|
53
|
-
def write_ln (text =
|
54
|
-
if text.nil?
|
55
|
-
print $/
|
56
|
-
return
|
57
|
-
end
|
58
|
-
|
45
|
+
def write_ln (text = '', font = @font)
|
59
46
|
print @builder.write_ln(text, font)
|
60
47
|
end
|
61
48
|
|
@@ -63,61 +50,6 @@ module Bash_Visual
|
|
63
50
|
print @builder.erase_to_end_line
|
64
51
|
end
|
65
52
|
|
66
|
-
def draw_rectangle(x, y, width, height, font = nil)
|
67
|
-
bash = ''
|
68
|
-
bash << @builder.save_position()
|
69
|
-
bash << @builder.set_position(x,y)
|
70
|
-
height.times do
|
71
|
-
bash << @builder.write(' ' * width, font)
|
72
|
-
bash << @builder.move_position(-width, 1)
|
73
|
-
end
|
74
|
-
bash << @builder.restore_position()
|
75
|
-
print @builder.write(bash, font)
|
76
|
-
end
|
77
|
-
|
78
|
-
def draw_border(x, y, width, height, font = nil, border = BORDER_UTF)
|
79
|
-
raise 'width,height must be great than 1' if (width < 2 or height < 2)
|
80
|
-
|
81
|
-
bash = ''
|
82
|
-
bash << @builder.save_position()
|
83
|
-
bash << @builder.set_position(x,y)
|
84
|
-
|
85
|
-
bash << @builder.write(border[0] + border[1] * (width - 2) + border[2], font)
|
86
|
-
(height - 2).times do
|
87
|
-
bash << @builder.move_position(-width, 1)
|
88
|
-
bash << @builder.write(border[3] + ' ' * (width - 2) + border[4], font)
|
89
|
-
end
|
90
|
-
bash << @builder.move_position(-width, 1)
|
91
|
-
bash << @builder.write(border[5] + border[6] * (width - 2) + border[7], font)
|
92
|
-
|
93
|
-
bash << @builder.restore_position()
|
94
|
-
print @builder.write(bash, font)
|
95
|
-
end
|
96
|
-
|
97
|
-
def draw_window(x, y, width, height, text = '', font = nil, border = BORDER_UTF_DOUBLE, text_wrap = ["\u2561","\u255E"])
|
98
|
-
raise 'width,height must be great than 2' if (width < 3 or height < 3)
|
99
|
-
|
100
|
-
text = text.slice(0, width - 2)
|
101
|
-
if text.size < (width - 3) && (text_wrap.instance_of? Array)
|
102
|
-
text = text_wrap[0] + text + text_wrap[1]
|
103
|
-
end
|
104
|
-
text = text.center(width - 2, border[1])
|
105
|
-
bash = ''
|
106
|
-
bash << @builder.save_position()
|
107
|
-
bash << @builder.set_position(x,y)
|
108
|
-
|
109
|
-
bash << @builder.write(border[0] + text + border[2], font)
|
110
|
-
(height - 2).times do
|
111
|
-
bash << @builder.move_position(-width, 1)
|
112
|
-
bash << @builder.write(border[3] + ' ' * (width - 2) + border[4], font)
|
113
|
-
end
|
114
|
-
bash << @builder.move_position(-width, 1)
|
115
|
-
bash << @builder.write(border[5] + border[6] * (width - 2) + border[7], font)
|
116
|
-
|
117
|
-
bash << @builder.restore_position()
|
118
|
-
print @builder.write(bash, font)
|
119
|
-
end
|
120
|
-
|
121
53
|
# Clear the screen and move to (0,0)
|
122
54
|
def clear
|
123
55
|
@current_x = 0
|
@@ -126,7 +58,7 @@ module Bash_Visual
|
|
126
58
|
end
|
127
59
|
|
128
60
|
def font= font
|
129
|
-
@
|
61
|
+
@font = font
|
130
62
|
end
|
131
63
|
|
132
64
|
def lines
|
data/lib/bash-visual/font.rb
CHANGED
@@ -2,7 +2,7 @@ module Bash_Visual
|
|
2
2
|
class Font
|
3
3
|
|
4
4
|
COLORS = [:black, :dark_red, :dark_green, :dark_yellow, :dark_blue, :dark_magenta, :dark_cyan, :grey,
|
5
|
-
|
5
|
+
:dark_grey, :red, :green, :yellow, :blue, :magenta, :cyan, :white]
|
6
6
|
|
7
7
|
TYPES = [:std, :bold, :underline, :blink]
|
8
8
|
|
@@ -32,60 +32,33 @@ module Bash_Visual
|
|
32
32
|
blink: 5
|
33
33
|
}
|
34
34
|
|
35
|
-
RESET
|
35
|
+
RESET = "\e[0m"
|
36
36
|
|
37
37
|
attr_reader :types, :foreground, :background
|
38
38
|
|
39
39
|
def initialize(types = :std, foreground = :white, background = nil)
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
end
|
41
|
+
build(types, foreground, background)
|
42
|
+
end
|
44
43
|
|
45
|
-
|
44
|
+
def add_type(type)
|
45
|
+
return false if @types.include? type
|
46
46
|
|
47
|
-
@types
|
47
|
+
@types << type
|
48
|
+
build(@types, @foreground, @background)
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
sequence << @@types_map[type]
|
52
|
-
end
|
50
|
+
true
|
51
|
+
end
|
53
52
|
|
54
|
-
|
53
|
+
def remove_type(type)
|
55
54
|
|
56
|
-
|
57
|
-
|
58
|
-
else
|
59
|
-
"9#{color_index - 10}"
|
60
|
-
end
|
55
|
+
return false unless @types.include? type
|
56
|
+
return false if @types == [:std]
|
61
57
|
|
62
|
-
|
63
|
-
|
64
|
-
sequence << if color_index < 10
|
65
|
-
"4#{color_index}"
|
66
|
-
else
|
67
|
-
"10#{color_index - 10}"
|
68
|
-
end
|
69
|
-
end
|
58
|
+
@types.delete type
|
59
|
+
build(@types, @foreground, @background)
|
70
60
|
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
# @return [Array]
|
76
|
-
def prepare_types(types)
|
77
|
-
case types
|
78
|
-
when Symbol then
|
79
|
-
[types]
|
80
|
-
when Array then
|
81
|
-
if types.size > 2
|
82
|
-
types.delete_if { |type| type == :std }
|
83
|
-
else
|
84
|
-
types
|
85
|
-
end
|
86
|
-
else
|
87
|
-
raise "types must be Array or Symbol"
|
88
|
-
end
|
61
|
+
true
|
89
62
|
end
|
90
63
|
|
91
64
|
def inspect
|
@@ -116,6 +89,71 @@ module Bash_Visual
|
|
116
89
|
end
|
117
90
|
|
118
91
|
end
|
92
|
+
|
93
|
+
def rand_font
|
94
|
+
color = self.rand_color
|
95
|
+
Font.new :std, color
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def build(types, foreground, background)
|
102
|
+
|
103
|
+
unless COLORS.include?(foreground)
|
104
|
+
raise "Illegal color #{foreground}"
|
105
|
+
end
|
106
|
+
|
107
|
+
@foreground, @background = foreground, background
|
108
|
+
|
109
|
+
@types = prepare_types types
|
110
|
+
|
111
|
+
sequence = []
|
112
|
+
@types.each do |type|
|
113
|
+
sequence << @@types_map[type]
|
114
|
+
end
|
115
|
+
|
116
|
+
color_index = @@colors_map[@foreground]
|
117
|
+
|
118
|
+
sequence << if color_index < 10
|
119
|
+
"3#{color_index}"
|
120
|
+
else
|
121
|
+
"9#{color_index - 10}"
|
122
|
+
end
|
123
|
+
|
124
|
+
if @background
|
125
|
+
color_index = @@colors_map[@background]
|
126
|
+
sequence << if color_index < 10
|
127
|
+
"4#{color_index}"
|
128
|
+
else
|
129
|
+
"10#{color_index - 10}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
@bash_command = "\e[#{sequence.join(';')}m"
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
# @return [Array]
|
138
|
+
def prepare_types(types)
|
139
|
+
types = case types
|
140
|
+
when Symbol then
|
141
|
+
[types]
|
142
|
+
when Array then
|
143
|
+
if types.size > 2
|
144
|
+
types.delete_if { |type| type == :std }
|
145
|
+
else
|
146
|
+
types
|
147
|
+
end
|
148
|
+
else
|
149
|
+
raise "types must be Array or Symbol"
|
150
|
+
end
|
151
|
+
|
152
|
+
if types.size > 1 && types.include?(:std)
|
153
|
+
types.delete :std
|
154
|
+
end
|
155
|
+
|
156
|
+
types
|
119
157
|
end
|
120
158
|
|
121
159
|
end
|
@@ -5,18 +5,17 @@ module Bash_Visual
|
|
5
5
|
|
6
6
|
def initialize options
|
7
7
|
super
|
8
|
-
@message_block_width = @message_block_size
|
9
8
|
|
10
9
|
@separator =
|
11
10
|
if @separator == true; DEFAULT_SEPARATOR
|
12
|
-
elsif @
|
11
|
+
elsif @s.instance_of? String; @separator[0]
|
13
12
|
else nil
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
17
16
|
def get_x_position available_area_width, message_width = 0
|
18
17
|
if (@start == BEGINNING)
|
19
|
-
@x + (@
|
18
|
+
@x + (@width - available_area_width)
|
20
19
|
else
|
21
20
|
@x + available_area_width - message_width
|
22
21
|
end
|
@@ -25,45 +24,33 @@ module Bash_Visual
|
|
25
24
|
def print_message message, font, available_area
|
26
25
|
|
27
26
|
available_area_width, available_area_height = available_area
|
28
|
-
avail_width = @message_block_width > available_area_width ? available_area_width : @message_block_width
|
29
27
|
|
28
|
+
msg_block_width =
|
29
|
+
case
|
30
|
+
when @fixed_message_block_size
|
31
|
+
@fixed_message_block_size
|
32
|
+
when @max_message_block_size
|
33
|
+
@max_message_block_size
|
34
|
+
else
|
35
|
+
available_area_width
|
36
|
+
end
|
30
37
|
|
31
|
-
|
32
|
-
|
33
|
-
}
|
38
|
+
msg_block_width -= 1 if @separator
|
39
|
+
msg_block_width = available_area_width if msg_block_width > available_area_width
|
34
40
|
|
35
|
-
|
36
|
-
message_width = rows_wrap! message, available_area_width
|
37
|
-
else
|
38
|
-
rows_wrap! message, avail_width
|
39
|
-
message_width = avail_width
|
40
|
-
end
|
41
|
+
#msg_block_height = @adapt ? available_area_height : 1
|
41
42
|
|
42
|
-
message =
|
43
|
-
|
44
|
-
|
45
|
-
row
|
46
|
-
end
|
47
|
-
|
48
|
-
if @separator and @separator.size.nonzero?
|
49
|
-
if @adapt_size_message
|
50
|
-
if message_width < available_area_width
|
51
|
-
message.map! do |row|
|
52
|
-
row << @separator
|
53
|
-
end
|
54
|
-
message_width += 1
|
55
|
-
end
|
56
|
-
else
|
57
|
-
message.each do |row|
|
58
|
-
row[message_width-1] = @separator
|
59
|
-
end
|
43
|
+
message = Scroll.form_block message, [msg_block_width, available_area_height], @fixed_message_block_size
|
44
|
+
if @separator
|
45
|
+
message.map! do |row|
|
46
|
+
row = row + DEFAULT_SEPARATOR
|
60
47
|
end
|
61
48
|
end
|
62
49
|
|
63
|
-
|
50
|
+
msg_block_width += 1
|
51
|
+
write(get_x_position(available_area_width, msg_block_width), @y, message, font)
|
64
52
|
|
65
|
-
[available_area_width -
|
53
|
+
[available_area_width - msg_block_width, available_area_height]
|
66
54
|
end
|
67
|
-
|
68
55
|
end
|
69
56
|
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Bash_Visual
|
4
|
+
module Painter
|
5
|
+
|
6
|
+
@@default_window_wrap = ["\u257C ", " \u257E"]
|
7
|
+
#@@default_window_wrap = ["", ""]
|
8
|
+
|
9
|
+
# see: http://en.wikipedia.org/wiki/Box-drawing_characters
|
10
|
+
BORDER_UTF = ["\u250C", "\u2500", "\u2510",
|
11
|
+
"\u2502", "\u2502",
|
12
|
+
"\u2514", "\u2500", "\u2518"]
|
13
|
+
|
14
|
+
BORDER_UTF_ROUND = ["\u256D", "\u2500", "\u256E",
|
15
|
+
"\u2502", "\u2502",
|
16
|
+
"\u2570", "\u2500", "\u256F"]
|
17
|
+
|
18
|
+
BORDER_UTF_DOUBLE = ["\u2554", "\u2550", "\u2557",
|
19
|
+
"\u2551", "\u2551",
|
20
|
+
"\u255A", "\u2550", "\u255D"]
|
21
|
+
|
22
|
+
# @param [Array] position
|
23
|
+
# @param [Array] size
|
24
|
+
def draw_filled_rectangle(position, size, color = :white)
|
25
|
+
x, y = *position
|
26
|
+
width, height = *size
|
27
|
+
raise 'width,height must be great than 1' if (width < 1 or height < 1)
|
28
|
+
|
29
|
+
color = color.background if color.is_a? Font
|
30
|
+
font = Font.new :std, :white, color
|
31
|
+
|
32
|
+
bash = @builder.save_position
|
33
|
+
bash << @builder.set_position(x+1, y+1)
|
34
|
+
|
35
|
+
row = @builder.write(' ' * width)
|
36
|
+
row << @builder.move_position(-width, 1)
|
37
|
+
bash << row*height
|
38
|
+
|
39
|
+
bash << @builder.restore_position
|
40
|
+
print @builder.write(bash, font)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param [Array] position
|
44
|
+
# @param [Array] size
|
45
|
+
def draw_border(position, size, params = {})
|
46
|
+
x, y = *position
|
47
|
+
width, height = *size
|
48
|
+
raise 'width,height must be great than 1' if (width < 2 or height < 2)
|
49
|
+
|
50
|
+
border = params[:border] ? params[:border] : BORDER_UTF
|
51
|
+
font = params[:font] ? params[:font] : @font
|
52
|
+
|
53
|
+
bash = @builder.save_position
|
54
|
+
bash << @builder.set_position(x, y)
|
55
|
+
body_width = width - 2
|
56
|
+
|
57
|
+
bash << @builder.write(border[0] + border[1] * body_width + border[2])
|
58
|
+
|
59
|
+
row = @builder.move_position(-width, 1)
|
60
|
+
row << @builder.write(border[3] + ' ' * body_width + border[4])
|
61
|
+
bash << row*(height - 2)
|
62
|
+
|
63
|
+
bash << @builder.move_position(-width, 1)
|
64
|
+
bash << @builder.write(border[5] + border[6] * body_width + border[7])
|
65
|
+
|
66
|
+
bash << @builder.restore_position
|
67
|
+
print @builder.write(bash, font)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param [Array] position
|
71
|
+
# @param [Array] size
|
72
|
+
# @param [String] text
|
73
|
+
# @param [Hash] params
|
74
|
+
def draw_window(position, size, text = '', params = {})
|
75
|
+
x, y = *position
|
76
|
+
width, height = *size
|
77
|
+
raise 'width,height must be great than 2' if (width < 3 or height < 3)
|
78
|
+
|
79
|
+
wrap = params[:wrap].nil? ? @@default_window_wrap : params[:wrap]
|
80
|
+
border = params[:border] ? params[:border] : BORDER_UTF
|
81
|
+
font = params[:font] ? params[:font] : @font
|
82
|
+
|
83
|
+
body_width = width - 2
|
84
|
+
text = if wrap
|
85
|
+
wrap_size = wrap[0].size + wrap[1].size
|
86
|
+
text_width = body_width - wrap_size
|
87
|
+
wrap[0] + text.to_s[0, text_width] + wrap[1]
|
88
|
+
else
|
89
|
+
text.to_s.slice(0, body_width)
|
90
|
+
end
|
91
|
+
|
92
|
+
text = text.center(body_width, border[1])
|
93
|
+
|
94
|
+
bash = @builder.save_position
|
95
|
+
bash << @builder.set_position(x, y)
|
96
|
+
|
97
|
+
bash << @builder.write(border[0] + text + border[2])
|
98
|
+
|
99
|
+
row = @builder.move_position(-width, 1)
|
100
|
+
row << @builder.write(border[3] + ' ' * body_width + border[4])
|
101
|
+
bash << row*(height - 2)
|
102
|
+
|
103
|
+
bash << @builder.move_position(-width, 1)
|
104
|
+
bash << @builder.write(border[5] + border[6] * body_width + border[7])
|
105
|
+
|
106
|
+
bash << @builder.restore_position
|
107
|
+
print @builder.write(bash, font)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/lib/bash-visual/scroll.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Bash_Visual
|
2
|
-
|
2
|
+
class Scroll
|
3
|
+
|
4
|
+
include FixedObject
|
3
5
|
|
4
6
|
FORWARD = 1
|
5
7
|
BACKWARD = -1
|
@@ -7,15 +9,15 @@ module Bash_Visual
|
|
7
9
|
BEGINNING = false
|
8
10
|
ENDING = true
|
9
11
|
|
10
|
-
|
12
|
+
attr_reader :console
|
11
13
|
|
12
14
|
|
13
15
|
# @param [Hash] options
|
14
16
|
#
|
15
17
|
# options = {
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# font: Font.new
|
18
|
+
# position: [x, y],
|
19
|
+
# size: [width, height],
|
20
|
+
# font: Font.new (:bold)
|
19
21
|
# start: Scroll::ENDING,
|
20
22
|
# adapt_size_message: true,
|
21
23
|
# prefix: -> { '>' }
|
@@ -25,33 +27,28 @@ module Bash_Visual
|
|
25
27
|
#
|
26
28
|
def initialize(options)
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
unless options[:position] && options[:size]
|
31
|
+
raise "Minimum needs: :size and :position"
|
32
|
+
end
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
+
@width, @height = options[:size]
|
35
|
+
@x, @y = options[:position]
|
36
|
+
@prefix = options[:prefix]
|
37
|
+
@adapt = options[:adapt].nil? ? true : options[:adapt]
|
38
|
+
@separator = options[:separator]
|
34
39
|
|
35
|
-
@
|
36
|
-
@
|
37
|
-
@area_height = @area_height.to_i
|
40
|
+
@max_message_block_size = options[:max_message_block_size]
|
41
|
+
@fixed_message_block_size = options[:fixed_message_block_size]
|
38
42
|
|
39
|
-
@
|
40
|
-
@
|
43
|
+
@start = options[:start] ? ENDING : BEGINNING
|
44
|
+
@font = options[:font] ? options[:font] : Font.new
|
41
45
|
|
42
|
-
@
|
46
|
+
@stack = []
|
47
|
+
@stateless = false
|
43
48
|
|
44
|
-
@
|
49
|
+
@console = Console.new @font, Console::OUTPUT_STRING
|
50
|
+
@mutex = Mutex.new
|
45
51
|
|
46
|
-
@is_wrap = true
|
47
|
-
@start = options[:start] ? ENDING : BEGINNING
|
48
|
-
@separator = options[:separator] ? options[:separator] : false
|
49
|
-
@type = options[:type] ? options[:type] : nil
|
50
|
-
|
51
|
-
@stack = []
|
52
|
-
@console = Console.new @type, Console::OUTPUT_STRING
|
53
|
-
@mutex = Mutex.new
|
54
|
-
nil
|
55
52
|
end
|
56
53
|
|
57
54
|
def scroll(positions = 1, direction = @direction * positions)
|
@@ -60,67 +57,64 @@ module Bash_Visual
|
|
60
57
|
|
61
58
|
# @param [String] message
|
62
59
|
# @param [Bash_Visual::Font] font
|
63
|
-
def add(message, font = @
|
60
|
+
def add(message, font = @font)
|
64
61
|
|
65
|
-
|
66
|
-
|
62
|
+
unless font.background
|
63
|
+
font = Font.new font.types, font.foreground, @font.background
|
67
64
|
end
|
68
65
|
|
69
|
-
@stack << {
|
70
|
-
|
71
|
-
|
72
|
-
|
66
|
+
@stack << {message: prefix() + message.to_s, font: font}
|
67
|
+
|
68
|
+
clear
|
69
|
+
redraw
|
73
70
|
|
74
|
-
redraw()
|
75
|
-
#@stack.slice!(-index, index)
|
76
71
|
nil
|
77
72
|
end
|
78
73
|
|
79
74
|
|
80
|
-
# @param [
|
75
|
+
# @param [Proc] prefix
|
81
76
|
def prefix= (prefix)
|
82
77
|
@prefix = prefix
|
83
78
|
end
|
84
79
|
|
85
80
|
def prefix
|
86
|
-
if (defined? @prefix.call)
|
87
|
-
|
88
|
-
|
89
|
-
|
81
|
+
return @prefix[].to_s if (defined? @prefix.call)
|
82
|
+
''
|
83
|
+
end
|
84
|
+
|
85
|
+
class << self
|
86
|
+
def form_block(text, size, fixate = false)
|
87
|
+
width, height = size
|
88
|
+
result = []
|
89
|
+
|
90
|
+
height.times do |i|
|
91
|
+
line = text[i * width, width]
|
92
|
+
|
93
|
+
unless line
|
94
|
+
break unless fixate
|
95
|
+
result.fill(' ' * width, i, height - i)
|
96
|
+
break
|
97
|
+
end
|
98
|
+
|
99
|
+
result << line.ljust(width)
|
100
|
+
end
|
101
|
+
|
102
|
+
result
|
90
103
|
end
|
91
104
|
end
|
92
105
|
|
93
106
|
private
|
94
107
|
|
95
108
|
def redraw
|
96
|
-
avail_area = [@
|
109
|
+
avail_area = [@width, @height]
|
97
110
|
@stack.reverse.each do |item|
|
98
111
|
|
99
|
-
message
|
100
|
-
font
|
101
|
-
unless font.background
|
102
|
-
font = Font.new font.type, font.foreground, @type.background
|
103
|
-
end
|
104
|
-
|
112
|
+
message = item[:message]
|
113
|
+
font = item[:font]
|
105
114
|
avail_area = print_message(message, font, avail_area)
|
106
|
-
# выходим если закончилось место в области
|
107
|
-
return nil if avail_area[0] <= 0 or avail_area[1] <= 0
|
108
|
-
end
|
109
|
-
end
|
110
115
|
|
111
|
-
|
112
|
-
# @param [String] arr
|
113
|
-
# @param [Integer] max_len
|
114
|
-
def rows_wrap!(arr, max_len)
|
115
|
-
max_used_len = 1
|
116
|
-
arr.each_with_index do |row, i|
|
117
|
-
len = row.size
|
118
|
-
max_used_len = len if len > max_used_len
|
119
|
-
next if len <= max_len
|
120
|
-
tail = row.slice!(max_len, len-max_len)
|
121
|
-
arr.insert(i+1, tail)
|
116
|
+
return nil if avail_area[0] <= 0 or avail_area[1] <= 0
|
122
117
|
end
|
123
|
-
max_used_len
|
124
118
|
end
|
125
119
|
|
126
120
|
# @param [Integer] x
|
@@ -130,12 +124,19 @@ module Bash_Visual
|
|
130
124
|
def write(x, y, message, font)
|
131
125
|
string = ''
|
132
126
|
message.each_with_index { |text, i|
|
133
|
-
|
127
|
+
string << @console.write_to_position(x, y + i, text, font)
|
134
128
|
}
|
135
129
|
|
136
130
|
@mutex.synchronize {
|
137
131
|
print string
|
138
132
|
}
|
139
133
|
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
# Clear scroll's area
|
138
|
+
def clear(font = @font)
|
139
|
+
print @console.draw_filled_rectangle([@x, @y], [@width, @height], font.background)
|
140
|
+
end
|
140
141
|
end
|
141
142
|
end
|
data/lib/bash-visual/version.rb
CHANGED
@@ -1,14 +1,9 @@
|
|
1
1
|
module Bash_Visual
|
2
2
|
class VerticalScroll < Scroll
|
3
3
|
|
4
|
-
def initialize options
|
5
|
-
super
|
6
|
-
@message_block_height = @message_block_size
|
7
|
-
end
|
8
|
-
|
9
4
|
def get_y_position available_area_height, message_size = 0
|
10
5
|
if (@start == BEGINNING)
|
11
|
-
@y + (@
|
6
|
+
@y + (@height - available_area_height)
|
12
7
|
else
|
13
8
|
@y + available_area_height - message_size
|
14
9
|
end
|
@@ -17,36 +12,29 @@ module Bash_Visual
|
|
17
12
|
def print_message message, font, available_area
|
18
13
|
|
19
14
|
available_area_width, available_area_height = available_area
|
20
|
-
avail_height = @message_block_height > available_area_height ? available_area_height : @message_block_height
|
21
|
-
|
22
|
-
rows_wrap!(message, available_area_width) if @is_wrap
|
23
|
-
|
24
|
-
if @adapt_size_message
|
25
|
-
message = message.slice(0, available_area_height) if message.size > available_area_height
|
26
|
-
else
|
27
|
-
message = message.slice(0, avail_height) if message.size > avail_height
|
28
|
-
end
|
29
15
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
16
|
+
msg_block_height =
|
17
|
+
case
|
18
|
+
when !@adapt
|
19
|
+
1
|
20
|
+
when @fixed_message_block_size
|
21
|
+
@fixed_message_block_size
|
22
|
+
when @max_message_block_size
|
23
|
+
@max_message_block_size
|
24
|
+
else
|
25
|
+
available_area_height
|
26
|
+
end
|
27
|
+
|
28
|
+
msg_block_height -= 1 if @separator
|
29
|
+
msg_block_height = available_area_height if msg_block_height > available_area_height
|
30
|
+
|
31
|
+
message = Scroll.form_block message, [available_area_width, msg_block_height]
|
32
|
+
if @separator
|
33
|
+
message << @separator * available_area_width
|
45
34
|
end
|
46
35
|
|
47
36
|
write(@x, get_y_position(available_area_height, message.size), message, font)
|
48
37
|
|
49
|
-
|
50
38
|
[available_area_width, available_area_height - message.size]
|
51
39
|
end
|
52
40
|
|
data/test/font_test.rb
CHANGED
@@ -71,6 +71,44 @@ class FontTest < Test::Unit::TestCase
|
|
71
71
|
|
72
72
|
end
|
73
73
|
|
74
|
+
def test_rand
|
75
|
+
assert_instance_of Font, Font::rand_font
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_illegal_color
|
79
|
+
assert_raise_message "Illegal color wrong_color" do
|
80
|
+
font = Font.new :std, :wrong_color
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_add_type
|
85
|
+
font = Font.new
|
86
|
+
|
87
|
+
assert_false(font.add_type :std)
|
88
|
+
|
89
|
+
assert_true(font.add_type :bold)
|
90
|
+
assert_equal [:bold], font.types
|
91
|
+
|
92
|
+
assert_true(font.add_type :underline)
|
93
|
+
assert_equal [:bold, :underline], font.types
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def test_remove_type
|
98
|
+
font = Font.new
|
99
|
+
|
100
|
+
assert_false(font.remove_type :std)
|
101
|
+
assert_equal [:std], font.types
|
102
|
+
|
103
|
+
font.add_type :underline
|
104
|
+
assert_false(font.remove_type :std)
|
105
|
+
|
106
|
+
assert_true(font.add_type :bold)
|
107
|
+
font.remove_type :underline
|
108
|
+
assert_equal [:bold], font.types
|
109
|
+
|
110
|
+
end
|
111
|
+
|
74
112
|
protected
|
75
113
|
|
76
114
|
def mock_class_method(class_name, eval_string)
|
data/test/helper.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'helper'
|
5
|
+
|
6
|
+
|
7
|
+
class PainterTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
include Bash_Visual
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@painter = Object.new
|
13
|
+
@painter.extend(Painter)
|
14
|
+
builder = Bash_Visual::Builder.new #mock('Bash_Visual::Builder')
|
15
|
+
@painter.instance_variable_set(:@builder, builder)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_draw_window
|
19
|
+
@painter.draw_window([1, 1], [10, 10], 'logs')
|
20
|
+
@painter.draw_window([1, 1], [10, 10], 'logs', {font: Font.new(:bold)})
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_draw_border
|
24
|
+
@painter.draw_border([1, 1], [10, 10])
|
25
|
+
@painter.draw_border([1, 1], [10, 10], {font: Font.new(:bold)})
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_draw_filled_rectangle
|
29
|
+
@painter.draw_filled_rectangle([1, 1], [10, 10])
|
30
|
+
@painter.draw_filled_rectangle([1, 1], [10, 10], :red)
|
31
|
+
end
|
32
|
+
end
|
data/test/scroll_test.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'helper'
|
5
|
+
|
6
|
+
class ScrollTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
include Bash_Visual
|
9
|
+
|
10
|
+
def test_empty_params
|
11
|
+
|
12
|
+
assert_raise_message "Minimum needs: :size and :position" do
|
13
|
+
scroll = Scroll.new :prefix => nil
|
14
|
+
end
|
15
|
+
|
16
|
+
assert_raise_message "Minimum needs: :size and :position" do
|
17
|
+
scroll = Scroll.new :size => [1,1]
|
18
|
+
end
|
19
|
+
|
20
|
+
assert_raise_message "Minimum needs: :size and :position" do
|
21
|
+
scroll = Scroll.new :position => [1,1]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_rows_wrap__example
|
26
|
+
|
27
|
+
text = 'Hello world. Lot of words...'
|
28
|
+
expected = ['Hell', 'o wo', 'rld.', ' Lot']
|
29
|
+
result = Scroll::form_block(text, [4,4])
|
30
|
+
|
31
|
+
assert_equal expected, result
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_rows_wrap__min
|
35
|
+
|
36
|
+
text = 'Hello world. Lot of words...'
|
37
|
+
expected = ['H']
|
38
|
+
result = Scroll::form_block(text, [1,1])
|
39
|
+
|
40
|
+
assert_equal expected, result
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def test_rows_wrap__fill
|
45
|
+
|
46
|
+
text = 'Hell'
|
47
|
+
expected = ['Hell ']
|
48
|
+
result = Scroll::form_block(text, [5, 3])
|
49
|
+
|
50
|
+
assert_equal expected, result
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_rows_wrap__fixate_fill
|
54
|
+
|
55
|
+
text = 'Hell'
|
56
|
+
expected = ['Hell ', ' ' * 5, ' ' * 5]
|
57
|
+
result = Scroll::form_block(text, [5, 3], true)
|
58
|
+
|
59
|
+
assert_equal expected, result
|
60
|
+
end
|
61
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bash-visual
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-30 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Bash visualisation tools
|
15
15
|
email:
|
@@ -23,21 +23,30 @@ files:
|
|
23
23
|
- LICENSE
|
24
24
|
- README.md
|
25
25
|
- Rakefile
|
26
|
+
- bash-visual-1.0.6.gem
|
26
27
|
- bash-visual.gemspec
|
27
28
|
- example/hello_world.rb
|
29
|
+
- example/painter.rb
|
28
30
|
- example/random.rb
|
31
|
+
- example/scroll.rb
|
29
32
|
- example/spectrum.rb
|
30
33
|
- lib/bash-visual.rb
|
31
34
|
- lib/bash-visual/builder.rb
|
32
35
|
- lib/bash-visual/console.rb
|
36
|
+
- lib/bash-visual/fixed_object.rb
|
33
37
|
- lib/bash-visual/font.rb
|
34
38
|
- lib/bash-visual/horizontal_scroll.rb
|
39
|
+
- lib/bash-visual/painter.rb
|
35
40
|
- lib/bash-visual/scroll.rb
|
36
41
|
- lib/bash-visual/version.rb
|
37
42
|
- lib/bash-visual/vertical_scroll.rb
|
38
43
|
- test/builder_test.rb
|
44
|
+
- test/console_test.rb
|
39
45
|
- test/font_test.rb
|
40
46
|
- test/helper.rb
|
47
|
+
- test/painter_test.rb
|
48
|
+
- test/scroll_test.rb
|
49
|
+
- test/vertical_scroll_test.rb
|
41
50
|
homepage: https://github.com/AlmazKo/BashVisual
|
42
51
|
licenses:
|
43
52
|
- MIT
|