bash-visual 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/bash/builder.rb +60 -0
- data/lib/bash/console.rb +143 -0
- data/lib/bash/font.rb +91 -0
- data/lib/common/random_text.rb +12 -0
- data/lib/example1.rb +86 -0
- data/lib/horizontal_scroll.rb +69 -0
- data/lib/main.rb +71 -0
- data/lib/scroll.rb +120 -0
- data/lib/vertical_scroll.rb +54 -0
- metadata +62 -0
data/lib/bash/builder.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'font'
|
2
|
+
|
3
|
+
class Builder
|
4
|
+
|
5
|
+
def initialize (font = Font.new)
|
6
|
+
@default_font = font
|
7
|
+
end
|
8
|
+
|
9
|
+
def clear
|
10
|
+
set_position(0, 0) + "\e[2J"
|
11
|
+
end
|
12
|
+
|
13
|
+
def erase_to_end_line
|
14
|
+
"\e[K"
|
15
|
+
end
|
16
|
+
|
17
|
+
def restore_position
|
18
|
+
"\e[u"
|
19
|
+
end
|
20
|
+
|
21
|
+
def save_position
|
22
|
+
"\e[s"
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_position (x, y)
|
26
|
+
"\e[#{y.to_i};#{x.to_i}H"
|
27
|
+
end
|
28
|
+
|
29
|
+
def move_position(offset_x, offset_y)
|
30
|
+
bash = ''
|
31
|
+
if (offset_y > 0)
|
32
|
+
bash << "\e[#{offset_y}B"
|
33
|
+
else
|
34
|
+
bash << "\e[#{offset_y.abs}A"
|
35
|
+
end
|
36
|
+
if (offset_x > 0)
|
37
|
+
bash << "\e[#{offset_x}C"
|
38
|
+
else
|
39
|
+
bash << "\e[#{offset_x.abs}D"
|
40
|
+
end
|
41
|
+
bash
|
42
|
+
end
|
43
|
+
|
44
|
+
def write_to_position (x, y, text, font = @default_font)
|
45
|
+
bash = ''
|
46
|
+
bash << save_position()
|
47
|
+
bash << move_position(x, y)
|
48
|
+
bash << write(text, font)
|
49
|
+
bash << restore_position()
|
50
|
+
bash
|
51
|
+
end
|
52
|
+
|
53
|
+
def write (text, font = @default_font)
|
54
|
+
font.to_bash + text + Font::RESET
|
55
|
+
end
|
56
|
+
|
57
|
+
def write_ln (text, font = @default_font)
|
58
|
+
font.to_bash + text << "\n" << Font::RESET
|
59
|
+
end
|
60
|
+
end
|
data/lib/bash/console.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
require 'font'
|
4
|
+
require 'builder'
|
5
|
+
|
6
|
+
class Console
|
7
|
+
@@mutex = Mutex.new
|
8
|
+
|
9
|
+
OUTPUT_STRING = 0
|
10
|
+
OUTPUT_WITHOUT_BLOCK = 1
|
11
|
+
OUPUT_WITH_BLOCK = 2
|
12
|
+
# see: http://en.wikipedia.org/wiki/Box-drawing_characters
|
13
|
+
BORDER_UTF = ["\u250C","\u2500","\u2510",
|
14
|
+
"\u2502", "\u2502",
|
15
|
+
"\u2514","\u2500","\u2518"]
|
16
|
+
|
17
|
+
BORDER_UTF_ROUND = ["\u256D","\u2500","\u256E",
|
18
|
+
"\u2502", "\u2502",
|
19
|
+
"\u2570","\u2500","\u256F"]
|
20
|
+
|
21
|
+
BORDER_UTF_DOUBLE = ["\u2554","\u2550","\u2557",
|
22
|
+
"\u2551", "\u2551",
|
23
|
+
"\u255A","\u2550","\u255D"]
|
24
|
+
|
25
|
+
attr_reader :current_x, :current_y, :font;
|
26
|
+
|
27
|
+
def initialize (font = Font.new, way_outnput = OUTPUT_WITHOUT_BLOCK, builder = Builder.new)
|
28
|
+
@current_x = 0
|
29
|
+
@current_y = 0
|
30
|
+
@font = font
|
31
|
+
@way_output = way_outnput
|
32
|
+
@builder = builder
|
33
|
+
end
|
34
|
+
|
35
|
+
def position= coord
|
36
|
+
@current_x , @current_y = *coord
|
37
|
+
print @builder.set_position(@current_x, @current_y)
|
38
|
+
end
|
39
|
+
|
40
|
+
def move_position(offset_x, offset_y)
|
41
|
+
@current_x += offset_x
|
42
|
+
@current_y += offset_y
|
43
|
+
print @builder.move_position(offset_x, offset_y)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Записать что-то в определенной позиции, а потом вернуться на текущую
|
47
|
+
# Если необходимо сохранить позицию после записи - используйте связку
|
48
|
+
# move_position/position= и write
|
49
|
+
def write_to_position (x, y, text, font = @font)
|
50
|
+
print @builder.write_to_position(x, y, text, font)
|
51
|
+
end
|
52
|
+
|
53
|
+
def write (text, font = @font)
|
54
|
+
print @builder.write(text, font)
|
55
|
+
end
|
56
|
+
|
57
|
+
def write_ln (text, font = @font)
|
58
|
+
print @builder.write_ln(text, font)
|
59
|
+
end
|
60
|
+
|
61
|
+
def erase_to_end_line
|
62
|
+
print @builder.erase_to_end_line
|
63
|
+
end
|
64
|
+
|
65
|
+
def draw_rectangle(x, y, width, height, font = nil)
|
66
|
+
bash = ''
|
67
|
+
bash << @builder.save_position()
|
68
|
+
bash << @builder.set_position(x,y)
|
69
|
+
height.times do
|
70
|
+
bash << @builder.write(' ' * width, font)
|
71
|
+
bash << @builder.move_position(-width, 1)
|
72
|
+
end
|
73
|
+
bash << @builder.restore_position()
|
74
|
+
print @builder.write(bash, font)
|
75
|
+
end
|
76
|
+
|
77
|
+
def draw_border(x, y, width, height, font = nil, border = BORDER_UTF)
|
78
|
+
raise 'width,height must be great than 1' if (width < 2 or height < 2)
|
79
|
+
|
80
|
+
bash = ''
|
81
|
+
bash << @builder.save_position()
|
82
|
+
bash << @builder.set_position(x,y)
|
83
|
+
|
84
|
+
bash << @builder.write(border[0] + border[1] * (width - 2) + border[2], font)
|
85
|
+
(height - 2).times do
|
86
|
+
bash << @builder.move_position(-width, 1)
|
87
|
+
bash << @builder.write(border[3] + ' ' * (width - 2) + border[4], font)
|
88
|
+
end
|
89
|
+
bash << @builder.move_position(-width, 1)
|
90
|
+
bash << @builder.write(border[5] + border[6] * (width - 2) + border[7], font)
|
91
|
+
|
92
|
+
bash << @builder.restore_position()
|
93
|
+
print @builder.write(bash, font)
|
94
|
+
end
|
95
|
+
|
96
|
+
def draw_window(x, y, width, height, text = '', font = nil, border = BORDER_UTF_DOUBLE, text_wrap = ["\u2561","\u255E"])
|
97
|
+
raise 'width,height must be great than 2' if (width < 3 or height < 3)
|
98
|
+
|
99
|
+
text = text.slice(0, width - 2)
|
100
|
+
if text.size < (width - 3) && (text_wrap.instance_of? Array)
|
101
|
+
text = text_wrap[0] + text + text_wrap[1]
|
102
|
+
end
|
103
|
+
text = text.center(width - 2, border[1])
|
104
|
+
bash = ''
|
105
|
+
bash << @builder.save_position()
|
106
|
+
bash << @builder.set_position(x,y)
|
107
|
+
|
108
|
+
bash << @builder.write(border[0] + text + border[2], font)
|
109
|
+
(height - 2).times do
|
110
|
+
bash << @builder.move_position(-width, 1)
|
111
|
+
bash << @builder.write(border[3] + ' ' * (width - 2) + border[4], font)
|
112
|
+
end
|
113
|
+
bash << @builder.move_position(-width, 1)
|
114
|
+
bash << @builder.write(border[5] + border[6] * (width - 2) + border[7], font)
|
115
|
+
|
116
|
+
bash << @builder.restore_position()
|
117
|
+
print @builder.write(bash, font)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Clear the screen and move to (0,0)
|
121
|
+
def clear
|
122
|
+
@current_x = 0
|
123
|
+
@current_y = 0
|
124
|
+
print @builder.clear
|
125
|
+
end
|
126
|
+
|
127
|
+
def font= font
|
128
|
+
@font = font
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
def print string
|
133
|
+
|
134
|
+
return string if OUTPUT_STRING == @way_output
|
135
|
+
|
136
|
+
if OUPUT_WITH_BLOCK == @way_output
|
137
|
+
@@mutex.synchronize {super}
|
138
|
+
else
|
139
|
+
super
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
data/lib/bash/font.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
|
2
|
+
class Font
|
3
|
+
BLACK = 0
|
4
|
+
RED = 1
|
5
|
+
GREEN = 2
|
6
|
+
BROWN = 3
|
7
|
+
BLUE = 4
|
8
|
+
MAGENTA = 5
|
9
|
+
CYAN = 6
|
10
|
+
LIGHT_GRAY = 7
|
11
|
+
|
12
|
+
GRAY = 10
|
13
|
+
LIGHT_RED = 11
|
14
|
+
LIGHT_GREEN = 12
|
15
|
+
YELLOW = 13
|
16
|
+
LIGHT_BLUE = 14
|
17
|
+
LIGHT_MAGENTA = 15
|
18
|
+
LIGHT_CYAN = 16
|
19
|
+
WHITE = 17
|
20
|
+
|
21
|
+
RESET = "\e[0m"
|
22
|
+
|
23
|
+
#types font
|
24
|
+
STD = 0
|
25
|
+
BOLD = 1
|
26
|
+
UNDERLINE = 2
|
27
|
+
BLINK = 4
|
28
|
+
|
29
|
+
attr_reader :font, :foreground, :background
|
30
|
+
|
31
|
+
def initialize (font = STD, foreground = WHITE, background = nil)
|
32
|
+
raise "not found color #{foreground}" unless (0..7).cover? foreground or (10..17).cover? foreground
|
33
|
+
@font, @foreground, @background = font, foreground, background
|
34
|
+
|
35
|
+
@bash_command = ''
|
36
|
+
|
37
|
+
@string = "<type=%s, foreground=%s, background=%s>" % [@font, @foreground, @background]
|
38
|
+
if font == STD
|
39
|
+
if foreground and foreground < 10
|
40
|
+
@bash_command << "\e[3#{foreground}m"
|
41
|
+
else
|
42
|
+
@bash_command << "\e[9#{foreground-10}m"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if font & BOLD != 0
|
47
|
+
if foreground < 10
|
48
|
+
@bash_command << "\e[1;3#{foreground}m"
|
49
|
+
else
|
50
|
+
@bash_command << "\e[1;9#{foreground-10}m"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if font & UNDERLINE != 0
|
55
|
+
if foreground < 10
|
56
|
+
@bash_command << "\e[4;3#{foreground}m"
|
57
|
+
else
|
58
|
+
@bash_command << "\e[4;9#{foreground-10}m"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
if background.instance_of? Fixnum
|
63
|
+
if background < 10
|
64
|
+
@bash_command << "\e[4#{background}m"
|
65
|
+
else
|
66
|
+
@bash_command << "\e[10#{background-10}m"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_bash
|
73
|
+
@bash_command
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_s
|
77
|
+
@string
|
78
|
+
end
|
79
|
+
|
80
|
+
class << self
|
81
|
+
def rand_color (exclude_color = nil)
|
82
|
+
color = rand(14)
|
83
|
+
color += 1 if color == exclude_color
|
84
|
+
color = 0 if color > 14
|
85
|
+
color += 3 if color > 7
|
86
|
+
color
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
class RandomText
|
3
|
+
@@text = File.open(File.dirname(__FILE__)+'/utf') { |file| file.read }
|
4
|
+
class << self
|
5
|
+
def get
|
6
|
+
aText = @@text.split(' ')
|
7
|
+
len = Random.new.rand(1...70)
|
8
|
+
max = Random.new.rand(0...aText.size-len)
|
9
|
+
aText[max, len].join(' ')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/example1.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'bash/console'
|
5
|
+
require 'bash/font'
|
6
|
+
require 'scroll'
|
7
|
+
require 'vertical_scroll'
|
8
|
+
require 'horizontal_scroll'
|
9
|
+
require 'common/random_text'
|
10
|
+
|
11
|
+
|
12
|
+
def join_all
|
13
|
+
main = Thread.main
|
14
|
+
current = Thread.current
|
15
|
+
all = Thread.list
|
16
|
+
all.each {|t| t.join unless t == current or t == main}
|
17
|
+
end
|
18
|
+
|
19
|
+
default_font = Font.new(Font::STD, Font::LIGHT_BLUE)
|
20
|
+
|
21
|
+
|
22
|
+
console = Console.new(default_font)
|
23
|
+
console.clear()
|
24
|
+
|
25
|
+
window_font = Font.new(Font::STD, Font::WHITE, Font::BLUE)
|
26
|
+
|
27
|
+
|
28
|
+
font_scroll = Font.new(Font::STD, Font::YELLOW)
|
29
|
+
|
30
|
+
scroll = VerticalScroll.new(
|
31
|
+
coordinates: [41, 1],
|
32
|
+
window_size: [80, 28],
|
33
|
+
message_block_size: 23,
|
34
|
+
font: font_scroll,
|
35
|
+
separator: "\u2508",
|
36
|
+
start: Scroll::ENDING,
|
37
|
+
adapt_size_message: true,
|
38
|
+
prefix: ->{ Time.now.strftime('%H-%M-%S:%3N') << " " }
|
39
|
+
)
|
40
|
+
|
41
|
+
|
42
|
+
console.draw_window(4, 31, 122, 6, 'Example List', window_font, Console::BORDER_UTF_DOUBLE)
|
43
|
+
|
44
|
+
scroll2 = HorizontalScroll.new(
|
45
|
+
coordinates: [4, 31],
|
46
|
+
window_size: [120, 4],
|
47
|
+
message_block_size: 10,
|
48
|
+
font: font_scroll,
|
49
|
+
separator: true,
|
50
|
+
start: Scroll::BEGINNING
|
51
|
+
)
|
52
|
+
|
53
|
+
1.upto(28) { |y|
|
54
|
+
if (10..20).include? y
|
55
|
+
console.write_to_position(121, y, "\u2503")
|
56
|
+
else
|
57
|
+
console.write_to_position(121, y, "\u2502")
|
58
|
+
end
|
59
|
+
|
60
|
+
}
|
61
|
+
|
62
|
+
Thread.new do
|
63
|
+
1000.times do
|
64
|
+
font = Font.new(Font::BOLD, rand(7), nil)
|
65
|
+
x = rand(40)
|
66
|
+
y = rand(30)
|
67
|
+
console.write_to_position(x, y, '.', font)
|
68
|
+
|
69
|
+
font = Font.new(Font::STD, Font::rand_color(window_font.background), window_font.background)
|
70
|
+
scroll.add(RandomText::get(), font)
|
71
|
+
scroll2.add(RandomText::get(), font)
|
72
|
+
|
73
|
+
sleep(0.7)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
Thread.new do
|
77
|
+
1000.times do
|
78
|
+
font = Font.new(Font::STD, window_font.foreground, window_font.background)
|
79
|
+
scroll2.add(RandomText::get(), font)
|
80
|
+
|
81
|
+
sleep(0.3)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
join_all
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'scroll'
|
2
|
+
|
3
|
+
class HorizontalScroll < Scroll
|
4
|
+
|
5
|
+
DEFAULT_SEPARATOR = "\u2502"
|
6
|
+
|
7
|
+
def initialize options
|
8
|
+
super
|
9
|
+
@message_block_width = @message_block_size
|
10
|
+
|
11
|
+
@separator =
|
12
|
+
if @separator == true; DEFAULT_SEPARATOR
|
13
|
+
elsif @separator.instance_of? String; @separator[0]
|
14
|
+
else nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_x_position available_area_width, message_width = 0
|
19
|
+
if (@start == BEGINNING)
|
20
|
+
@x + (@area_width - available_area_width)
|
21
|
+
else
|
22
|
+
@x + available_area_width - message_width
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def print_message message, font, available_area
|
27
|
+
|
28
|
+
available_area_width, available_area_height = available_area
|
29
|
+
avail_width = @message_block_width > available_area_width ? available_area_width : @message_block_width
|
30
|
+
|
31
|
+
|
32
|
+
(available_area_height - message.size).times {
|
33
|
+
message << ''
|
34
|
+
}
|
35
|
+
|
36
|
+
if @adapt_size_message
|
37
|
+
message_width = rows_wrap! message, available_area_width
|
38
|
+
else
|
39
|
+
rows_wrap! message, avail_width
|
40
|
+
message_width = avail_width
|
41
|
+
end
|
42
|
+
|
43
|
+
message = message.slice(0, available_area_height) if message.size > available_area_height
|
44
|
+
|
45
|
+
message.map! do |row|
|
46
|
+
row.strip.ljust(message_width)
|
47
|
+
end
|
48
|
+
|
49
|
+
if @separator and @separator.size.nonzero?
|
50
|
+
if @adapt_size_message
|
51
|
+
if message_width < available_area_width
|
52
|
+
message.map! do |row|
|
53
|
+
row << @separator
|
54
|
+
end
|
55
|
+
message_width += 1
|
56
|
+
end
|
57
|
+
else
|
58
|
+
message.each do |row|
|
59
|
+
row[message_width-1] = @separator
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
write(get_x_position(available_area_width, message_width), @y, message, font)
|
65
|
+
|
66
|
+
[available_area_width - message_width, available_area_height]
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/lib/main.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
####!> coding:
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
print "\u2580"
|
4
|
+
exit
|
5
|
+
255.downto(0) { |i|
|
6
|
+
puts i.chr
|
7
|
+
}
|
8
|
+
|
9
|
+
exit
|
10
|
+
require 'bash/console'
|
11
|
+
require 'bash/font'
|
12
|
+
require 'scroll'
|
13
|
+
|
14
|
+
font = Font.new(Font::STD, Font::LIGHT_BLUE)
|
15
|
+
|
16
|
+
#
|
17
|
+
console = Console.new(font)
|
18
|
+
console.clear()
|
19
|
+
#console.write_ln('+' << '-' * 59 << '+')
|
20
|
+
#console.write_ln(("| %9s " % 'Thread') * 5 << '|')
|
21
|
+
#console.write_ln('+' << '-' * 59 << '+')
|
22
|
+
|
23
|
+
#####console.draw_rectangle(1, 1, 100, 40, Font::get(Font::STD, Font::STD, nil))
|
24
|
+
|
25
|
+
font_scroll = Font.new(Font::STD, Font::YELLOW, Font::BLACK)
|
26
|
+
|
27
|
+
font_scroll1 = Font.new(Font::STD, Font::LIGHT_GREEN, Font::BLACK)
|
28
|
+
|
29
|
+
|
30
|
+
scroll = Scroll.new(
|
31
|
+
coordinates: [100, 3],
|
32
|
+
size: [80, 20],
|
33
|
+
message_block_size: [80, 3],
|
34
|
+
message_crop?: true,
|
35
|
+
message_keep: 0,
|
36
|
+
type: Scroll::VERTICAL,
|
37
|
+
font: font_scroll,
|
38
|
+
separator: ' ',
|
39
|
+
start: Scroll::BEGINNING
|
40
|
+
# prefix: ->{ Time.now.strftime('%H-%M-%S:%3N') << "\n" }
|
41
|
+
)
|
42
|
+
|
43
|
+
at_exit do |unusedlocal|
|
44
|
+
#console.clear()
|
45
|
+
end
|
46
|
+
|
47
|
+
#Thread.new {
|
48
|
+
#
|
49
|
+
# scroll.add(gets())
|
50
|
+
#}
|
51
|
+
|
52
|
+
generator = ->(count){
|
53
|
+
value = ''
|
54
|
+
25.times {value << (65 + rand(25)).chr}
|
55
|
+
value
|
56
|
+
}
|
57
|
+
|
58
|
+
100000.times {
|
59
|
+
font = Font.new(Font::BOLD, rand(7), nil)
|
60
|
+
x = rand(100)
|
61
|
+
y = rand(40)
|
62
|
+
console.write_to_position(x, y, '.', font)
|
63
|
+
#
|
64
|
+
#scroll.add("\n01234" * 4, font_scroll2)
|
65
|
+
|
66
|
+
#scroll.add(generator.(50).to_s, font_scroll1)
|
67
|
+
|
68
|
+
scroll.add('' << '[]' * rand(40) << "\n1111\n1221")
|
69
|
+
|
70
|
+
sleep(0.4)
|
71
|
+
}
|
data/lib/scroll.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'console'
|
4
|
+
|
5
|
+
class Scroll
|
6
|
+
|
7
|
+
FORWARD = 1
|
8
|
+
BACKWARD = -1
|
9
|
+
|
10
|
+
BEGINNING = false
|
11
|
+
ENDING = true
|
12
|
+
|
13
|
+
attr_accessor :console
|
14
|
+
|
15
|
+
def initialize(options)
|
16
|
+
|
17
|
+
@x, @y = options[:coordinates]
|
18
|
+
@x = @x.to_i
|
19
|
+
@y = @y.to_i
|
20
|
+
|
21
|
+
raise ':window_size isn\'t array' unless options[:window_size].instance_of? Array
|
22
|
+
raise 'size :window_size must be great than 1' if options[:window_size].size < 2
|
23
|
+
|
24
|
+
@area_width, @area_height = options[:window_size]
|
25
|
+
@area_width = @area_width.to_i
|
26
|
+
@area_height = @area_height.to_i
|
27
|
+
|
28
|
+
@message_block_size = options[:message_block_size] ? options[:message_block_size].to_i : 1
|
29
|
+
@message_block_size = 1 if @message_block_size < 1
|
30
|
+
|
31
|
+
@prefix = options[:prefix] ? options[:prefix] : nil
|
32
|
+
|
33
|
+
@adapt_size_message = options[:adapt_size_message] ? options[:adapt_size_message] : false
|
34
|
+
|
35
|
+
@is_wrap = true
|
36
|
+
@start = options[:start] ? ENDING : BEGINNING
|
37
|
+
@separator = options[:separator] ? options[:separator] : false
|
38
|
+
@font = options[:font] ? options[:font] : nil
|
39
|
+
|
40
|
+
@stack = []
|
41
|
+
@console = Console.new @font,Console::OUTPUT_STRING
|
42
|
+
@mutex = Mutex.new
|
43
|
+
end
|
44
|
+
|
45
|
+
def scroll(positions = 1, direction = @direction * positions)
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
def add (message, font = @font)
|
50
|
+
|
51
|
+
if @stack.size.zero?
|
52
|
+
print @console.draw_rectangle(@x + 1, @y + 1, @area_width, @area_height, font)
|
53
|
+
end
|
54
|
+
|
55
|
+
@stack << {
|
56
|
+
message: prefix() << message.to_s,
|
57
|
+
font: font
|
58
|
+
}
|
59
|
+
|
60
|
+
redraw()
|
61
|
+
#@stack.slice!(-index, index)
|
62
|
+
end
|
63
|
+
|
64
|
+
def prefix= (prefix)
|
65
|
+
@prefix = prefix
|
66
|
+
end
|
67
|
+
|
68
|
+
def prefix
|
69
|
+
if (defined? @prefix.call)
|
70
|
+
@prefix[].to_s
|
71
|
+
else
|
72
|
+
''
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def redraw
|
79
|
+
avail_area = [@area_width, @area_height]
|
80
|
+
@stack.reverse.each do |item|
|
81
|
+
|
82
|
+
message = item[:message].dup.lines.to_a
|
83
|
+
font = item[:font]
|
84
|
+
unless font.background
|
85
|
+
font = Font.new font.font, font.foreground, @font.background
|
86
|
+
end
|
87
|
+
|
88
|
+
avail_area = print_message(message, font, avail_area)
|
89
|
+
# выходим если закончилось место в области
|
90
|
+
return nil if avail_area[0] <= 0 or avail_area[1] <= 0
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# сделать переносы в массиве строк
|
95
|
+
def rows_wrap! arr, max_len
|
96
|
+
max_used_len = 1
|
97
|
+
arr.each_with_index do |row, i|
|
98
|
+
len = row.size
|
99
|
+
max_used_len = len if len > max_used_len
|
100
|
+
next if len <= max_len
|
101
|
+
tail = row.slice!(max_len, len-max_len)
|
102
|
+
arr.insert(i+1, tail)
|
103
|
+
end
|
104
|
+
max_used_len
|
105
|
+
end
|
106
|
+
|
107
|
+
def write (x, y, message, font)
|
108
|
+
|
109
|
+
|
110
|
+
string = ''
|
111
|
+
message.each_with_index { |text, i|
|
112
|
+
string << @console.write_to_position(x, y + i, text, font)
|
113
|
+
}
|
114
|
+
|
115
|
+
@mutex.synchronize {
|
116
|
+
print string
|
117
|
+
}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'scroll'
|
2
|
+
|
3
|
+
class VerticalScroll < Scroll
|
4
|
+
|
5
|
+
def initialize options
|
6
|
+
super
|
7
|
+
@message_block_height = @message_block_size
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_y_position available_area_height, message_size = 0
|
11
|
+
if (@start == BEGINNING)
|
12
|
+
@y + (@area_height - available_area_height)
|
13
|
+
else
|
14
|
+
@y + available_area_height - message_size
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def print_message message, font, available_area
|
19
|
+
|
20
|
+
available_area_width, available_area_height = available_area
|
21
|
+
avail_height = @message_block_height > available_area_height ? available_area_height : @message_block_height
|
22
|
+
|
23
|
+
rows_wrap!(message, available_area_width) if @is_wrap
|
24
|
+
|
25
|
+
if @adapt_size_message
|
26
|
+
message = message.slice(0, available_area_height) if message.size > available_area_height
|
27
|
+
else
|
28
|
+
message = message.slice(0, avail_height) if message.size > avail_height
|
29
|
+
end
|
30
|
+
|
31
|
+
message.map! do |row|
|
32
|
+
row.strip.ljust(available_area_width)
|
33
|
+
end
|
34
|
+
|
35
|
+
if @separator == true
|
36
|
+
message[message.size-1] = Font.new(Font::UNDERLINE, font.foreground, font.background).to_bash +
|
37
|
+
message.last.ljust(available_area_width, ' ')
|
38
|
+
end
|
39
|
+
|
40
|
+
if (@separator.instance_of? String)
|
41
|
+
if (message.size > available_area_height)
|
42
|
+
message[message.size-1] = @separator[0] * available_area_width
|
43
|
+
else
|
44
|
+
message << @separator[0] * available_area_width
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
write(@x, get_y_position(available_area_height, message.size), message, font)
|
49
|
+
|
50
|
+
|
51
|
+
[available_area_width, available_area_height - message.size]
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bash-visual
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: "1.0"
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Almazko
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-12-25 00:00:00 Z
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: a.s.suslov@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- ./lib/scroll.rb
|
26
|
+
- ./lib/example1.rb
|
27
|
+
- ./lib/vertical_scroll.rb
|
28
|
+
- ./lib/main.rb
|
29
|
+
- ./lib/horizontal_scroll.rb
|
30
|
+
- ./lib/common/random_text.rb
|
31
|
+
- ./lib/bash/builder.rb
|
32
|
+
- ./lib/bash/console.rb
|
33
|
+
- ./lib/bash/font.rb
|
34
|
+
homepage: https://github.com/AlmazKo/BashConsole
|
35
|
+
licenses:
|
36
|
+
- MIT
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
requirements: []
|
55
|
+
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.8.11
|
58
|
+
signing_key:
|
59
|
+
specification_version: 3
|
60
|
+
summary: Bash visualization tools.
|
61
|
+
test_files: []
|
62
|
+
|