terminal 0.3.2 → 0.3.3
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 +4 -4
- data/Gemfile.lock +1 -1
- data/app/assets/stylesheets/terminal.css +9 -2
- data/bin/terminal +12 -1
- data/examples/curl.sh +1 -1
- data/lib/terminal.rb +1 -0
- data/lib/terminal/cache.rb +13 -0
- data/lib/terminal/renderer.rb +96 -96
- data/lib/terminal/screen.rb +69 -65
- data/lib/terminal/version.rb +1 -1
- data/script/benchmark +16 -8
- data/script/profile_methods +13 -2
- data/spec/terminal/renderer_spec.rb +20 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef903d157312bb149fac82a78546b0d92f7280a2
|
4
|
+
data.tar.gz: cfd561ae29ce4c0157cb8daf2226ca3f9c1e515f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fafa7d5e0e0072b81e2f90ca3b91c300d11b7f71a51dfc62d2b22d3abbae2a5d8c322d8d5a2a181693d2e5ffff98acf3f8507ab931711ea9c043f311eab8a823
|
7
|
+
data.tar.gz: 85727be39d6e58c6dac422f02a567644eb337bdbeb4cec280a99a42634421daa8ec9a6e573b79b913d2f4cad868088b8f4c11c997d40e3d633cc87726aec21c3
|
data/Gemfile.lock
CHANGED
@@ -11,12 +11,15 @@
|
|
11
11
|
white-space: pre-wrap;
|
12
12
|
}
|
13
13
|
|
14
|
+
.term-fg1 { } /* don't bold beccause it looks weird */
|
15
|
+
.term-fg4 { text-decoration: underline; } /* underline */
|
16
|
+
|
14
17
|
.term-fg30 { color: #666; } /* black (but we can't use black, so a diff color) */
|
15
18
|
.term-fg31 { color: #e10c02; } /* red */
|
16
|
-
.term-fg32 { color: #
|
19
|
+
.term-fg32 { color: #99ff5e; } /* green */
|
17
20
|
.term-fg33 { color: #c6c502; } /* yellow */
|
18
21
|
.term-fg34 { color: #8db7e0; } /* blue */
|
19
|
-
.term-fg35 { color: #
|
22
|
+
.term-fg35 { color: #f271fb; } /* magenta */
|
20
23
|
.term-fg36 { color: #00cdd9; } /* cyan */
|
21
24
|
|
22
25
|
/* high intense colors */
|
@@ -25,6 +28,10 @@
|
|
25
28
|
|
26
29
|
/* background colors */
|
27
30
|
.term-bg42 { background: #99ff5f; }
|
31
|
+
.term-bg40 { background: #676767; }
|
32
|
+
|
33
|
+
/* custom foreground/background combos for readability */
|
34
|
+
.term-fg31.term-bg40 { color: #F8A39F; }
|
28
35
|
|
29
36
|
/* xterm colors */
|
30
37
|
.term-fgx16 { color: #000000; }
|
data/bin/terminal
CHANGED
@@ -13,18 +13,29 @@ Usage:
|
|
13
13
|
|
14
14
|
Help:
|
15
15
|
$ terminal -h
|
16
|
+
$ terminal --help
|
17
|
+
|
18
|
+
Version:
|
19
|
+
$ terminal -v
|
20
|
+
$ terminal --version
|
16
21
|
|
17
22
|
Preview in the browser:
|
18
23
|
$ terminal --preview
|
19
24
|
|
20
|
-
See https://
|
25
|
+
See https://buildbox.github.io/terminal for more information.
|
21
26
|
usage
|
22
27
|
end
|
23
28
|
|
29
|
+
def version
|
30
|
+
puts "terminal v#{Terminal::VERSION}"
|
31
|
+
end
|
32
|
+
|
24
33
|
preview = ARGV.delete('--preview')
|
25
34
|
|
26
35
|
if ($stdin.tty? && ARGV.empty?) || ARGV.delete('-h') || ARGV.delete('--help')
|
27
36
|
help
|
37
|
+
elsif ARGV.delete('-v') || ARGV.delete('--version')
|
38
|
+
version
|
28
39
|
else
|
29
40
|
raw = ARGF.read
|
30
41
|
rendered = Terminal.render(raw)
|
data/examples/curl.sh
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
#!/bin/bash
|
2
2
|
|
3
3
|
echo -e "\033[90m$\033[0m curl -o /tmp/file.txt https://example.com/file.txt"
|
4
|
-
curl -o /tmp/buildbox-agent.tar.gz https://github.com/
|
4
|
+
curl -o /tmp/buildbox-agent.tar.gz https://github.com/buildbox/buildbox-agent/releases/download/v0.1-alpha/buildbox-agent-darwin-386.tar.gz
|
data/lib/terminal.rb
CHANGED
data/lib/terminal/renderer.rb
CHANGED
@@ -5,10 +5,16 @@ require 'emoji'
|
|
5
5
|
|
6
6
|
module Terminal
|
7
7
|
class Renderer
|
8
|
-
EMOJI_UNICODE_REGEXP = /[\u{1f600}-\u{1f64f}]|[\u{2702}-\u{27b0}]|[\u{1f680}-\u{1f6ff}]|[\u{24C2}-\u{1F251}]|[\u{1f300}-\u{1f5ff}]/
|
9
|
-
ESCAPE_CONTROL_CHARACTERS = "qQmKGgKAaBbCcDd"
|
10
8
|
MEGABYTES = 1024 * 1024
|
11
9
|
|
10
|
+
EMOJI_UNICODE_REGEXP = /[\u{1f600}-\u{1f64f}]|[\u{2702}-\u{27b0}]|[\u{1f680}-\u{1f6ff}]|[\u{24C2}-\u{1F251}]|[\u{1f300}-\u{1f5ff}]/
|
11
|
+
EMOJI_IGNORE = [ "heavy_check_mark".freeze, "heavy_multiplication_x".freeze ]
|
12
|
+
|
13
|
+
ESCAPE_CONTROL_CHARACTERS = "qQmKGgKAaBbCcDd".freeze
|
14
|
+
ESCAPE_CAPTURE_REGEX = /\e\[(.*)([#{ESCAPE_CONTROL_CHARACTERS}])/
|
15
|
+
|
16
|
+
INTERESTING_PARTS_REGEX=/[\n\r\b]|\e\[[\d;]*[#{ESCAPE_CONTROL_CHARACTERS}]|./
|
17
|
+
|
12
18
|
def initialize(output, options = {})
|
13
19
|
@output = output
|
14
20
|
|
@@ -19,30 +25,14 @@ module Terminal
|
|
19
25
|
end
|
20
26
|
|
21
27
|
def render
|
22
|
-
return "" if @output.nil?
|
28
|
+
return "" if @output.nil?
|
23
29
|
|
24
30
|
# First duplicate the string, because we're going to be editing and chopping it
|
25
31
|
# up directly.
|
26
|
-
output = @output.dup
|
32
|
+
output = @output.to_s.dup
|
27
33
|
|
28
|
-
|
29
|
-
|
30
|
-
if output.bytesize > max_total_size
|
31
|
-
output = output.byteslice(0, max_total_size)
|
32
|
-
output << "\n\nWarning: Terminal has chopped off the rest of the build as it's over the allowed 4 megabyte limit for logs."
|
33
|
-
end
|
34
|
-
|
35
|
-
# Limit each line to (x) chars
|
36
|
-
# TODO: Move this to the screen
|
37
|
-
max_line_length = 50_000
|
38
|
-
output = output.split("\n").map do |line|
|
39
|
-
if line.length > max_line_length
|
40
|
-
line = line[0..max_line_length]
|
41
|
-
line << " Warning: Terminal has chopped the rest of this line off as it's over the allowed #{max_line_length} characters per line limit."
|
42
|
-
else
|
43
|
-
line
|
44
|
-
end
|
45
|
-
end.join("\n")
|
34
|
+
output = check_size(output)
|
35
|
+
output = check_line_lengths(output)
|
46
36
|
|
47
37
|
# Force encoding on the output first
|
48
38
|
force_encoding!(output)
|
@@ -54,17 +44,45 @@ module Terminal
|
|
54
44
|
output = convert_screen_to_string
|
55
45
|
|
56
46
|
# Escape any HTML
|
57
|
-
|
47
|
+
escaped_html = escape_html(output)
|
58
48
|
|
59
49
|
# Now convert the colors to HTML
|
60
|
-
|
50
|
+
convert_to_html!(escaped_html)
|
61
51
|
|
62
52
|
# And emojify
|
63
|
-
replace_unicode_with_emoji(
|
53
|
+
replace_unicode_with_emoji!(escaped_html)
|
54
|
+
|
55
|
+
escaped_html
|
64
56
|
end
|
65
57
|
|
66
58
|
private
|
67
59
|
|
60
|
+
def check_size(output)
|
61
|
+
# Limit the entire size of the output to 4 meg
|
62
|
+
max_total_size = 4 * MEGABYTES
|
63
|
+
if output.bytesize > max_total_size
|
64
|
+
new_output = output.byteslice(0, max_total_size)
|
65
|
+
new_output << "\n\nWarning: Terminal has chopped off the rest of the build as it's over the allowed 4 megabyte limit for logs."
|
66
|
+
new_output
|
67
|
+
else
|
68
|
+
output
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_line_lengths(output)
|
73
|
+
# Limit each line to (x) chars
|
74
|
+
# TODO: Move this to the screen
|
75
|
+
max_line_length = 50_000
|
76
|
+
output.split("\n".freeze).map do |line|
|
77
|
+
if line.length > max_line_length
|
78
|
+
line = line[0..max_line_length]
|
79
|
+
line << " Warning: Terminal has chopped the rest of this line off as it's over the allowed #{max_line_length} characters per line limit."
|
80
|
+
else
|
81
|
+
line
|
82
|
+
end
|
83
|
+
end.join("\n".freeze)
|
84
|
+
end
|
85
|
+
|
68
86
|
def force_encoding!(string)
|
69
87
|
string.force_encoding('UTF-8')
|
70
88
|
|
@@ -75,29 +93,58 @@ module Terminal
|
|
75
93
|
end
|
76
94
|
end
|
77
95
|
|
96
|
+
# Scan the string to create an array of interesting things, for example
|
97
|
+
# it would look like this:
|
98
|
+
# [ '\n', '\r', 'a', 'b', '\e123m' ]
|
99
|
+
def split_by_escape_character(string)
|
100
|
+
string.scan(INTERESTING_PARTS_REGEX)
|
101
|
+
end
|
102
|
+
|
78
103
|
def render_to_screen(string)
|
79
104
|
# The when cases are ordered by most likely, the lest checks it has to go
|
80
105
|
# through before matching, the faster the render will be. Colors are
|
81
106
|
# usually most likey, so that's first.
|
82
107
|
split_by_escape_character(string).each do |char|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
108
|
+
if char == "\n".freeze
|
109
|
+
@screen.x = 0
|
110
|
+
@screen.y += 1
|
111
|
+
elsif char == "\r".freeze
|
112
|
+
@screen.x = 0
|
113
|
+
elsif char == "\b".freeze
|
114
|
+
@screen.x -= 1
|
115
|
+
elsif char[0] == "\e".freeze && char.length > 1
|
116
|
+
sequence = char.match(ESCAPE_CAPTURE_REGEX)
|
117
|
+
|
118
|
+
instruction = sequence[1]
|
119
|
+
code = sequence[2]
|
120
|
+
|
121
|
+
if code == "".freeze
|
122
|
+
# no-op - an empty \e
|
123
|
+
elsif code == "m".freeze
|
124
|
+
@screen.color(instruction)
|
125
|
+
elsif code == "G".freeze || code == "g".freeze
|
88
126
|
@screen.x = 0
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
127
|
+
elsif code == "K".freeze || code == "k".freeze
|
128
|
+
if instruction == nil || instruction == "0".freeze
|
129
|
+
# clear everything after the current x co-ordinate
|
130
|
+
@screen.clear(@screen.y, @screen.x, Screen::END_OF_LINE)
|
131
|
+
elsif instruction == "1".freeze
|
132
|
+
# clear everything before the current x co-ordinate
|
133
|
+
@screen.clear(@screen.y, Screen::START_OF_LINE, @screen.x)
|
134
|
+
elsif instruction == "2".freeze
|
135
|
+
@screen.clear(@screen.y, Screen::START_OF_LINE, Screen::END_OF_LINE)
|
136
|
+
end
|
137
|
+
elsif code == "A".freeze
|
138
|
+
@screen.up(instruction)
|
139
|
+
elsif code == "B".freeze
|
140
|
+
@screen.down(instruction)
|
141
|
+
elsif code == "C".freeze
|
142
|
+
@screen.foward(instruction)
|
143
|
+
elsif code == "D".freeze
|
144
|
+
@screen.backward(instruction)
|
98
145
|
end
|
99
146
|
else
|
100
|
-
|
147
|
+
@screen << char
|
101
148
|
end
|
102
149
|
end
|
103
150
|
end
|
@@ -110,67 +157,20 @@ module Terminal
|
|
110
157
|
@screen.to_s
|
111
158
|
end
|
112
159
|
|
113
|
-
def
|
114
|
-
|
115
|
-
parts = sequence.match(/\e\[(.*)([#{ESCAPE_CONTROL_CHARACTERS}])/)
|
116
|
-
|
117
|
-
instruction = parts[1].to_s
|
118
|
-
code = parts[2].to_s
|
119
|
-
|
120
|
-
case code
|
121
|
-
when ""
|
122
|
-
# no-op - an empty \e
|
123
|
-
when "m"
|
124
|
-
@screen.color(instruction)
|
125
|
-
when "G", "g"
|
126
|
-
@screen.x = 0
|
127
|
-
when "K", "k"
|
128
|
-
case instruction
|
129
|
-
when nil, "0"
|
130
|
-
# clear everything after the current x co-ordinate
|
131
|
-
@screen.clear(@screen.y, @screen.x, Screen::END_OF_LINE)
|
132
|
-
when "1"
|
133
|
-
# clear everything before the current x co-ordinate
|
134
|
-
@screen.clear(@screen.y, Screen::START_OF_LINE, @screen.x)
|
135
|
-
when "2"
|
136
|
-
@screen.clear(@screen.y, Screen::START_OF_LINE, Screen::END_OF_LINE)
|
137
|
-
end
|
138
|
-
when "A"
|
139
|
-
@screen.up(instruction)
|
140
|
-
when "B"
|
141
|
-
@screen.down(instruction)
|
142
|
-
when "C"
|
143
|
-
@screen.foward(instruction)
|
144
|
-
when "D"
|
145
|
-
@screen.backward(instruction)
|
146
|
-
end
|
147
|
-
end
|
160
|
+
def convert_to_html!(string)
|
161
|
+
string.gsub!("\terminal[0]", "</span>")
|
148
162
|
|
149
|
-
|
150
|
-
|
151
|
-
if $2
|
152
|
-
%{<span class='term-#{$1} term-#{$2}'>}
|
153
|
-
else
|
154
|
-
%{<span class='term-#{$1}'>}
|
155
|
-
end
|
163
|
+
string.gsub!(/\terminal\[([^\]]+)\]/) do |match|
|
164
|
+
%{<span class='#{$1}'>}
|
156
165
|
end
|
157
166
|
|
158
|
-
string = string.gsub("\e[0m", "</span>")
|
159
|
-
|
160
167
|
# Replace empty lines with a non breaking space.
|
161
|
-
string.gsub(/$^/, " ")
|
162
|
-
end
|
163
|
-
|
164
|
-
# Scan the string to create an array of interesting things, for example
|
165
|
-
# it would look like this:
|
166
|
-
# [ '\n', '\r', 'a', 'b', '\e123m' ]
|
167
|
-
def split_by_escape_character(string)
|
168
|
-
string.scan(/[\n\r\b]|\e\[[\d;]*[#{ESCAPE_CONTROL_CHARACTERS}]|./)
|
168
|
+
string.gsub!(/$^/, " ")
|
169
169
|
end
|
170
170
|
|
171
|
-
def replace_unicode_with_emoji(string)
|
172
|
-
string.gsub(EMOJI_UNICODE_REGEXP) do |match|
|
173
|
-
emoji_image_from_unicode(match)
|
171
|
+
def replace_unicode_with_emoji!(string)
|
172
|
+
string.gsub!(EMOJI_UNICODE_REGEXP) do |match|
|
173
|
+
Terminal::Cache.cache(:emoji, match) { emoji_image_from_unicode(match) }
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
@@ -181,7 +181,7 @@ module Terminal
|
|
181
181
|
def emoji_image_from_unicode(unicode)
|
182
182
|
emoji = Emoji.find_by_unicode(unicode)
|
183
183
|
|
184
|
-
if emoji
|
184
|
+
if emoji && !EMOJI_IGNORE.include?(emoji.name)
|
185
185
|
name = ":#{emoji.name}:"
|
186
186
|
path = File.join(@options[:emoji_asset_path], emoji.image_filename)
|
187
187
|
|
data/lib/terminal/screen.rb
CHANGED
@@ -27,27 +27,11 @@
|
|
27
27
|
|
28
28
|
module Terminal
|
29
29
|
class Screen
|
30
|
-
class Node < Struct.new(:blob, :
|
30
|
+
class Node < Struct.new(:blob, :style)
|
31
31
|
def ==(value)
|
32
32
|
blob == value
|
33
33
|
end
|
34
34
|
|
35
|
-
# Every node has a style, a foreground style, and a background
|
36
|
-
# style. This method returns what essentially becomes the escape
|
37
|
-
# sequence:
|
38
|
-
#
|
39
|
-
# \e[fg;bg;
|
40
|
-
#
|
41
|
-
# As the screen is turned into a string, the style is used to compare
|
42
|
-
# whether or not a new escape sequence is required.
|
43
|
-
def style
|
44
|
-
if fg || bg
|
45
|
-
"#{fg};#{bg};"
|
46
|
-
else
|
47
|
-
nil
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
35
|
def to_s
|
52
36
|
blob
|
53
37
|
end
|
@@ -55,7 +39,7 @@ module Terminal
|
|
55
39
|
|
56
40
|
END_OF_LINE = :end_of_line
|
57
41
|
START_OF_LINE = :start_of_line
|
58
|
-
EMPTY = Node.new(" ")
|
42
|
+
EMPTY = Node.new(" ", [])
|
59
43
|
|
60
44
|
attr_reader :x, :y
|
61
45
|
|
@@ -63,7 +47,10 @@ module Terminal
|
|
63
47
|
@x = 0
|
64
48
|
@y = 0
|
65
49
|
@screen = []
|
66
|
-
|
50
|
+
|
51
|
+
@fg_color = nil
|
52
|
+
@bg_color = nil
|
53
|
+
@other_colors = []
|
67
54
|
end
|
68
55
|
|
69
56
|
def write(character)
|
@@ -81,21 +68,28 @@ module Terminal
|
|
81
68
|
end
|
82
69
|
|
83
70
|
# Write the character to the slot
|
84
|
-
line[@x] = Node.new(character, @
|
71
|
+
line[@x] = Node.new(character, [ @fg_color, @bg_color, *@other_colors ].compact)
|
85
72
|
end
|
86
73
|
|
87
74
|
def <<(character)
|
88
75
|
write(character)
|
89
76
|
@x += 1
|
90
|
-
character
|
91
77
|
end
|
92
78
|
|
93
79
|
def x=(value)
|
94
|
-
|
80
|
+
if value > 0
|
81
|
+
@x = value
|
82
|
+
else
|
83
|
+
@x = 0
|
84
|
+
end
|
95
85
|
end
|
96
86
|
|
97
87
|
def y=(value)
|
98
|
-
|
88
|
+
if value > 0
|
89
|
+
@y = value
|
90
|
+
else
|
91
|
+
@y = 0
|
92
|
+
end
|
99
93
|
end
|
100
94
|
|
101
95
|
def clear(y, x_start, x_end)
|
@@ -117,54 +111,60 @@ module Terminal
|
|
117
111
|
# Changes the current foreground color that all new characters
|
118
112
|
# will be written with.
|
119
113
|
def color(color_code)
|
120
|
-
|
121
|
-
if color_code == "0"
|
122
|
-
@fg = nil
|
123
|
-
@bg = nil
|
124
|
-
return color_code
|
125
|
-
end
|
126
|
-
|
127
|
-
# Reset foreground color only
|
128
|
-
if color_code == "39"
|
129
|
-
@fg = nil
|
130
|
-
return color_code
|
131
|
-
end
|
132
|
-
|
133
|
-
# Reset background color only
|
134
|
-
if color_code == "49"
|
135
|
-
@bg = nil
|
136
|
-
return color_code
|
137
|
-
end
|
138
|
-
|
139
|
-
colors = color_code.to_s.split(";")
|
114
|
+
colors = color_code.scan(/\d+/)
|
140
115
|
|
141
116
|
# Extended set foreground x-term color
|
142
117
|
if colors[0] == "38" && colors[1] == "5"
|
143
|
-
return @
|
118
|
+
return @fg_color = "term-fgx#{colors[2]}"
|
144
119
|
end
|
145
120
|
|
146
121
|
# Extended set background x-term color
|
147
122
|
if colors[0] == "48" && colors[1] == "5"
|
148
|
-
return @
|
123
|
+
return @bg_color = "term-bgx#{colors[2]}"
|
149
124
|
end
|
150
125
|
|
151
|
-
# If multiple colors are defined, i.e. \e[30;42m\e
|
152
|
-
#
|
153
|
-
# or @bg
|
126
|
+
# If multiple colors are defined, i.e. \e[30;42m\e then loop through each
|
127
|
+
# one, and assign it to @fg_color or @bg_color
|
154
128
|
colors.each do |cc|
|
155
|
-
# If the number is between 30–37, then it's a foreground color,
|
156
|
-
# if it's 40–47, then it's a background color. 90-97 is like the regular
|
157
|
-
# foreground 30-37, but it's high intensity
|
158
|
-
#
|
159
|
-
# I don't use ranges and a select because I've found that to be rather
|
160
|
-
# slow.
|
161
129
|
c_integer = cc.to_i
|
162
|
-
|
163
|
-
|
130
|
+
|
131
|
+
# Reset all styles
|
132
|
+
if c_integer == 0
|
133
|
+
@fg_color = nil
|
134
|
+
@bg_color = nil
|
135
|
+
@other_colors = []
|
136
|
+
|
137
|
+
# Primary (default) font
|
138
|
+
elsif c_integer == 10
|
139
|
+
# no-op
|
140
|
+
|
141
|
+
# Reset foreground color only
|
142
|
+
elsif c_integer == 39
|
143
|
+
@fg_color = nil
|
144
|
+
|
145
|
+
# Reset background color only
|
146
|
+
elsif c_integer == 49
|
147
|
+
@bg_color = nil
|
148
|
+
|
149
|
+
# 30–37, then it's a foreground color
|
150
|
+
elsif c_integer >= 30 && c_integer <= 37
|
151
|
+
@fg_color = "term-fg#{cc}"
|
152
|
+
|
153
|
+
# 40–47, then it's a background color.
|
164
154
|
elsif c_integer >= 40 && c_integer <= 47
|
165
|
-
@
|
155
|
+
@bg_color = "term-bg#{cc}"
|
156
|
+
|
157
|
+
# 90-97 is like the regular fg color, but high intensity
|
166
158
|
elsif c_integer >= 90 && c_integer <= 97
|
167
|
-
@
|
159
|
+
@fg_color = "term-fgi#{cc}"
|
160
|
+
|
161
|
+
# 100-107 is like the regular bg color, but high intensity
|
162
|
+
elsif c_integer >= 100 && c_integer <= 107
|
163
|
+
@fg_color = "term-bgi#{cc}"
|
164
|
+
|
165
|
+
# 1-9 random other styles
|
166
|
+
elsif c_integer >= 1 && c_integer <= 9
|
167
|
+
@other_colors << "term-fg#{cc}"
|
168
168
|
end
|
169
169
|
end
|
170
170
|
end
|
@@ -231,8 +231,8 @@ module Terminal
|
|
231
231
|
line.each do |node|
|
232
232
|
# If there is no previous node, and the current node has a color
|
233
233
|
# (first node in a line) then add the escape character.
|
234
|
-
if !previous && node.style
|
235
|
-
buffer << "\
|
234
|
+
if !previous && node.style.length > 0
|
235
|
+
buffer << "\terminal[#{node.style.join(" ")}]"
|
236
236
|
|
237
237
|
# Increment the open style counter
|
238
238
|
open_styles += 1
|
@@ -242,14 +242,14 @@ module Terminal
|
|
242
242
|
elsif previous && previous.style != node.style
|
243
243
|
# If the new node has no style, that means that all the styles
|
244
244
|
# have been closed.
|
245
|
-
if
|
245
|
+
if node.style.length == 0
|
246
246
|
# Add our reset escape character
|
247
|
-
buffer << "\
|
247
|
+
buffer << "\terminal[0]"
|
248
248
|
|
249
249
|
# Decrement the open style counter
|
250
250
|
open_styles -= 1
|
251
251
|
else
|
252
|
-
buffer << "\
|
252
|
+
buffer << "\terminal[#{node.style.join(" ")}]"
|
253
253
|
|
254
254
|
# Increment the open style counter
|
255
255
|
open_styles += 1
|
@@ -264,7 +264,7 @@ module Terminal
|
|
264
264
|
end
|
265
265
|
|
266
266
|
# Be sure to close off any open styles for this line
|
267
|
-
open_styles.times { buffer << "\
|
267
|
+
open_styles.times { buffer << "\terminal[0]" }
|
268
268
|
|
269
269
|
# Add a new line as long as this line isn't the last
|
270
270
|
buffer << "\n" if line_index != last_line_index
|
@@ -276,7 +276,11 @@ module Terminal
|
|
276
276
|
private
|
277
277
|
|
278
278
|
def parse_integer(value)
|
279
|
-
value
|
279
|
+
if value == nil || value == ""
|
280
|
+
1
|
281
|
+
else
|
282
|
+
value.to_i
|
283
|
+
end
|
280
284
|
end
|
281
285
|
end
|
282
286
|
end
|
data/lib/terminal/version.rb
CHANGED
data/script/benchmark
CHANGED
@@ -6,15 +6,23 @@ require 'terminal'
|
|
6
6
|
require 'benchmark/ips'
|
7
7
|
require 'timeout'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def benchmark(bm, file)
|
10
|
+
output = File.read(file)
|
11
|
+
basename = File.basename(file)
|
12
|
+
|
13
|
+
bm.report basename do
|
14
|
+
Timeout.timeout(100) do
|
15
|
+
Terminal.render(output)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
13
19
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
20
|
+
Benchmark.ips do |bm|
|
21
|
+
if ARGV[0]
|
22
|
+
benchmark(bm, ARGV[0])
|
23
|
+
else
|
24
|
+
Dir.glob("spec/fixtures/*.raw").each do |file|
|
25
|
+
benchmark(bm, file)
|
18
26
|
end
|
19
27
|
end
|
20
28
|
end
|
data/script/profile_methods
CHANGED
@@ -7,9 +7,14 @@ require 'method_profiler'
|
|
7
7
|
|
8
8
|
screen_profiler = MethodProfiler.observe(Terminal::Screen)
|
9
9
|
render_profiler = MethodProfiler.observe(Terminal::Renderer)
|
10
|
-
iterations = 10
|
11
10
|
|
12
|
-
|
11
|
+
iterations = if ARGV[1]
|
12
|
+
ARGV[1].to_i
|
13
|
+
else
|
14
|
+
10
|
15
|
+
end
|
16
|
+
|
17
|
+
def profile(file, iterations)
|
13
18
|
output = File.read(file)
|
14
19
|
basename = File.basename(file)
|
15
20
|
|
@@ -17,5 +22,11 @@ Dir.glob("spec/fixtures/*.raw").each do |file|
|
|
17
22
|
iterations.times { Terminal.render(output) }
|
18
23
|
end
|
19
24
|
|
25
|
+
if ARGV[0]
|
26
|
+
profile(ARGV[0], iterations)
|
27
|
+
else
|
28
|
+
Dir.glob("spec/fixtures/*.raw").each { |file| profile(file, iterations) }
|
29
|
+
end
|
30
|
+
|
20
31
|
puts screen_profiler.report
|
21
32
|
puts render_profiler.report
|
@@ -203,9 +203,27 @@ describe Terminal::Renderer do
|
|
203
203
|
|
204
204
|
it "returns nothing if the unicode emoji can't be found" do
|
205
205
|
expect(Emoji).to receive(:unicodes_index) { {} }
|
206
|
-
raw = "this is great
|
206
|
+
raw = "this is great 😎"
|
207
|
+
|
208
|
+
expect(render(raw)).to eql(%{this is great 😎})
|
209
|
+
end
|
210
|
+
|
211
|
+
it "leaves the tick emoji alone (it looks better and is colored)" do
|
212
|
+
raw = "works ✔"
|
213
|
+
|
214
|
+
expect(render(raw)).to eql(%{works ✔})
|
215
|
+
end
|
216
|
+
|
217
|
+
it "leaves the ✖ emoji alone as well" do
|
218
|
+
raw = "broke ✖"
|
219
|
+
|
220
|
+
expect(render(raw)).to eql(%{broke ✖})
|
221
|
+
end
|
222
|
+
|
223
|
+
it "handles colors with 3 attributes" do
|
224
|
+
raw = "\e[0;10;4m\e[1m\e[34mgood news\e[0;10m\n\neveryone"
|
207
225
|
|
208
|
-
expect(render(raw)).to eql(
|
226
|
+
expect(render(raw)).to eql("<span class='term-fg34 term-fg4 term-fg1'>good news</span>\n \neveryone")
|
209
227
|
end
|
210
228
|
end
|
211
229
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: terminal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keith Pitt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: escape_utils
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- examples/pikachu.ansi
|
132
132
|
- examples/pikachu.sh
|
133
133
|
- lib/terminal.rb
|
134
|
+
- lib/terminal/cache.rb
|
134
135
|
- lib/terminal/cli.rb
|
135
136
|
- lib/terminal/engine.rb
|
136
137
|
- lib/terminal/preview.rb
|