Skip to content

Commit

Permalink
Fix crash in Terminal256 formatter with escaped tokens (#1402)
Browse files Browse the repository at this point in the history
Escaped tokens were causing a crash in the 256-color terminal formatter.
This commit fixes the bug and adds tests.
  • Loading branch information
jneen authored and pyrmont committed Jan 22, 2020
1 parent a821e3f commit 75ca818
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 5 deletions.
22 changes: 17 additions & 5 deletions lib/rouge/formatters/terminal256.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@ def initialize(theme = Themes::ThankfulEyes.new)

def stream(tokens, &b)
tokens.each do |tok, val|
escape = escape_sequence(tok)
yield escape.style_string
yield val.gsub("\n", "#{escape.reset_string}\n#{escape.style_string}")
yield escape.reset_string
escape_sequence(tok).stream_value(val, &b)
end
end

Expand Down Expand Up @@ -85,6 +82,14 @@ def bg
@bg = style.bg && self.class.color_index(style.bg)
end


def stream_value(val, &b)
yield style_string
yield val.gsub("\n", "#{reset_string}\n#{style_string}")
.gsub("\e", "\\e")
yield reset_string
end

def style_string
@style_string ||= begin
attrs = []
Expand Down Expand Up @@ -157,9 +162,16 @@ def self.closest_color(r, g, b)
end
end

class Unescape < EscapeSequence
def initialize(*) end
def style_string(*) '' end
def reset_string(*) '' end
def stream_value(val) yield val end
end

# private
def escape_sequence(token)
return '' if escape?(token)
return Unescape.new if escape?(token)
@escape_sequences ||= {}
@escape_sequences[token.qualname] ||=
EscapeSequence.new(get_style(token))
Expand Down
26 changes: 26 additions & 0 deletions spec/lexers/escape_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
describe Rouge::Lexers::Escape do
let(:lexer) { Rouge::Lexers::Escape.new(lang: 'json') }
let(:text) { '{ "foo": <!<bar>!> }' }
let(:result) {
Rouge::Formatter.with_escape do
formatter.format(lexer.lex(text))
end
}

describe 'html' do
let(:formatter) { Rouge::Formatters::HTML.new }

it 'unescapes' do
assert { result =~ /<bar>/ }
end
end

describe 'terminal256' do
let(:formatter) { Rouge::Formatters::Terminal256.new }
let(:text) { %({ "foo": <!\e123!> }) }

it 'unescapes' do
assert { result =~ /\e123/ }
end
end
end

0 comments on commit 75ca818

Please sign in to comment.