Skip to content

Commit

Permalink
Compress position escape sequences;
Browse files Browse the repository at this point in the history
Compression is achieved by not repeatedly sending a position when only the x
coordinate has changed; i.e. we are on the same line, just advancing a
character.

In the test application, we have gone from sending 72260 characters to the
terminal to just 13971- approximately 80% reduction. Reported compression time
has changed from average 20.6ms to 13.2ms- a ~35% improvement.

Also, add more documentation.

Work related to #302.
  • Loading branch information
gavinlaking committed Nov 12, 2015
1 parent 03b40a0 commit eacbef7
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 27 deletions.
23 changes: 22 additions & 1 deletion lib/vedeu/output/compressor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def compress
out = ''

content.each do |cell|
out << cell.position.to_s
out << position_for(cell)
out << colour_for(cell)
out << style_for(cell)
out << cell.value
Expand Down Expand Up @@ -91,6 +91,23 @@ def uncompress
out
end

# Compress by not repeatedly sending a position when only the x
# coordinate has changed; i.e. we are on the same line, just
# advancing a character.
#
# @param char [Vedeu::Views::Char]
# @return [String]
def position_for(char)
return ''.freeze if char.position.y == @y

@y = char.position.y
char.position.to_s
end

# Compress by not repeatedly sending the same colours for each
# character which has the same colours as the last character
# output.
#
# @param char [Vedeu::Views::Char]
# @return [String]
def colour_for(char)
Expand All @@ -100,6 +117,10 @@ def colour_for(char)
@colour.to_s
end

# Compress by not repeatedly sending the same style(s) for each
# character which has the same style(s) as the last character
# output.
#
# @param char [Vedeu::Views::Char]
# @return [String]
def style_for(char)
Expand Down
59 changes: 33 additions & 26 deletions test/lib/vedeu/output/compressor_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,57 +29,64 @@ module Output
context 'when the output is all Vedeu::Views::Char elements' do
let(:output) {
Vedeu::Models::Page.coerce([
Vedeu::Views::Char.new(value: 'Y',
name: _name,
colour: { foreground: '#ff0000' }),
Vedeu::Views::Char.new(value: 'e',
name: _name,
colour: { foreground: '#ff0000' }),
Vedeu::Views::Char.new(value: 's',
name: _name,
colour: { foreground: '#ff0000' }),
Vedeu::Views::Char.new(value: 'Y',
name: _name,
colour: { foreground: '#ff0000' },
position: [1, 1]),
Vedeu::Views::Char.new(value: 'e',
name: _name,
colour: { foreground: '#ff0000' },
position: [1, 2]),
Vedeu::Views::Char.new(value: 's',
name: _name,
colour: { foreground: '#ff0000' },
position: [1, 3])
])
}
it 'converts the non-Vedeu::Views::Char elements into String ' \
'elements' do
subject.must_equal("\e[38;2;255;0;0mYes")
subject.must_equal("\e[1;1H\e[38;2;255;0;0mYes")
end
end

context 'when the output is all Vedeu::Views::Char elements' do
let(:output) {
Vedeu::Models::Page.coerce([
Vedeu::Views::Char.new(value: 'a',
name: _name,
colour: { foreground: '#ff0000' }),
Vedeu::Views::Char.new(value: 'b',
name: _name,
colour: { foreground: '#ff0000' }),
Vedeu::Views::Char.new(value: 'c',
name: _name,
colour: { foreground: '#0000ff' }),
Vedeu::Views::Char.new(value: 'd',
name: _name,
colour: { foreground: '#0000ff' }),
Vedeu::Views::Char.new(value: 'a',
name: _name,
colour: { foreground: '#ff0000' },
position: [1, 1]),
Vedeu::Views::Char.new(value: 'b',
name: _name,
colour: { foreground: '#ff0000' },
position: [1, 2]),
Vedeu::Views::Char.new(value: 'c',
name: _name,
colour: { foreground: '#0000ff' },
position: [1, 3]),
Vedeu::Views::Char.new(value: 'd',
name: _name,
colour: { foreground: '#0000ff' },
position: [1, 4]),
])
}
it 'compresses multiple colours and styles where possible' do
subject.must_equal("\e[38;2;255;0;0mab\e[38;2;0;0;255mcd")
subject.must_equal("\e[1;1H\e[38;2;255;0;0mab\e[38;2;0;0;255mcd")
end
end

context 'when the output is not all Vedeu::Views::Char ' \
'elements' do
let(:output) {
Vedeu::Models::Page.coerce([
Vedeu::Views::Char.new(name: _name, value: 'N'),
Vedeu::Views::Char.new(name: _name, value: 'N', position: [1, 1]),
Vedeu::Models::Escape.new(value: "\e[?25l"),
Vedeu::Views::Char.new(name: _name, value: 't'),
Vedeu::Views::Char.new(name: _name, value: 't', position: [1, 3]),
])
}
it 'converts the non-Vedeu::Views::Char elements into String ' \
'elements' do
subject.must_equal("N\e[1;1H\e[?25lt")
subject.must_equal("\e[1;1HN\e[?25lt")
end
end
end
Expand Down

0 comments on commit eacbef7

Please sign in to comment.