From 39adab0a3fba32f1c6313b77ef11bfb8a01c83a3 Mon Sep 17 00:00:00 2001 From: Gavin Laking Date: Wed, 11 Nov 2015 19:02:41 +0000 Subject: [PATCH] Compress position escape sequences; 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. --- lib/vedeu/output/compressor.rb | 23 +++++++++++- test/lib/vedeu/output/compressor_test.rb | 45 ++++++++++++++---------- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/lib/vedeu/output/compressor.rb b/lib/vedeu/output/compressor.rb index 0052de086..e4c8b8d49 100644 --- a/lib/vedeu/output/compressor.rb +++ b/lib/vedeu/output/compressor.rb @@ -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 @@ -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) @@ -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) diff --git a/test/lib/vedeu/output/compressor_test.rb b/test/lib/vedeu/output/compressor_test.rb index e533c50dc..2dfe41669 100644 --- a/test/lib/vedeu/output/compressor_test.rb +++ b/test/lib/vedeu/output/compressor_test.rb @@ -28,35 +28,42 @@ 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', - colour: { foreground: '#ff0000' }), - Vedeu::Views::Char.new(value: 'e', - colour: { foreground: '#ff0000' }), - Vedeu::Views::Char.new(value: 's', - colour: { foreground: '#ff0000' }), + Vedeu::Views::Char.new(value: 'Y', + colour: { foreground: '#ff0000' }, + position: [1, 1]), + Vedeu::Views::Char.new(value: 'e', + colour: { foreground: '#ff0000' }, + position: [1, 2]), + Vedeu::Views::Char.new(value: 's', + 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', - colour: { foreground: '#ff0000' }), - Vedeu::Views::Char.new(value: 'b', - colour: { foreground: '#ff0000' }), - Vedeu::Views::Char.new(value: 'c', - colour: { foreground: '#0000ff' }), - Vedeu::Views::Char.new(value: 'd', - colour: { foreground: '#0000ff' }), + Vedeu::Views::Char.new(value: 'a', + colour: { foreground: '#ff0000' }, + position: [1, 1]), + Vedeu::Views::Char.new(value: 'b', + colour: { foreground: '#ff0000' }, + position: [1, 2]), + Vedeu::Views::Char.new(value: 'c', + colour: { foreground: '#0000ff' }, + position: [1, 3]), + Vedeu::Views::Char.new(value: 'd', + 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 @@ -64,14 +71,14 @@ module Output 'elements' do let(:output) { Vedeu::Models::Page.coerce([ - Vedeu::Views::Char.new(value: 'N'), + Vedeu::Views::Char.new(value: 'N', position: [1, 1]), Vedeu::Models::Escape.new(value: "\e[?25l"), - Vedeu::Views::Char.new(value: 't'), + Vedeu::Views::Char.new(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