diff options
author | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-05-09 19:59:45 +0300 |
---|---|---|
committer | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-05-09 19:59:45 +0300 |
commit | baef6728fa4e8e515ccdeba1ea54da996f322aab (patch) | |
tree | 22f664f6beace93bc7d27458a9d4469703d03d60 /lib | |
parent | 44501820152083d231459223fe09b9d9641b7c1e (diff) | |
download | gitlab-ce-baef6728fa4e8e515ccdeba1ea54da996f322aab.tar.gz |
Send trace to a browser incrementally when build is running
We send a state of ansi2html to client, client needs to send this state back.
The state describes the configuration of generator and position within trace.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ci/ansi2html.rb | 78 |
1 files changed, 57 insertions, 21 deletions
diff --git a/lib/ci/ansi2html.rb b/lib/ci/ansi2html.rb index ac6d667cf8d..d29e68570ff 100644 --- a/lib/ci/ansi2html.rb +++ b/lib/ci/ansi2html.rb @@ -23,8 +23,8 @@ module Ci cross: 0x10, } - def self.convert(ansi) - Converter.new().convert(ansi) + def self.convert(ansi, state = nil) + Converter.new.convert(ansi, state) end class Converter @@ -84,22 +84,36 @@ module Ci def on_107(s) set_bg_color(7, 'l') end def on_109(s) set_bg_color(9, 'l') end - def convert(ansi) - @out = "" - @n_open_tags = 0 - reset() + attr_accessor :offset, :n_open_tags, :fg_color, :bg_color, :style_mask + + STATE_PARAMS = [:offset, :n_open_tags, :fg_color, :bg_color, :style_mask] + + def convert(raw, new_state) + reset_state + restore_state(new_state) if new_state && new_state[:offset].to_i < raw.length + + start = @offset + ansi = raw[@offset..-1] + + open_new_tag - s = StringScanner.new(ansi.gsub("<", "<")) + s = StringScanner.new(ansi) while(!s.eos?) if s.scan(/\e([@-_])(.*?)([@-~])/) handle_sequence(s) + elsif s.scan(/\e(([@-_])(.*?)?)?$/) + break + elsif s.scan(/</) + @out << '<' else @out << s.scan(/./m) end + @offset += s.matched_size end close_open_tags() - @out + + { state: state, html: @out, text: ansi[0, @offset - start], append: start > 0 } end def handle_sequence(s) @@ -121,6 +135,20 @@ module Ci evaluate_command_stack(commands) + open_new_tag + end + + def evaluate_command_stack(stack) + return unless command = stack.shift() + + if self.respond_to?("on_#{command}", true) + self.send("on_#{command}", stack) + end + + evaluate_command_stack(stack) + end + + def open_new_tag css_classes = [] unless @fg_color.nil? @@ -138,20 +166,8 @@ module Ci css_classes << "term-#{css_class}" if @style_mask & flag != 0 end - open_new_tag(css_classes) if css_classes.length > 0 - end - - def evaluate_command_stack(stack) - return unless command = stack.shift() - - if self.respond_to?("on_#{command}", true) - self.send("on_#{command}", stack) - end - - evaluate_command_stack(stack) - end + return if css_classes.empty? - def open_new_tag(css_classes) @out << %{<span class="#{css_classes.join(' ')}">} @n_open_tags += 1 end @@ -163,6 +179,26 @@ module Ci end end + def reset_state + @offset = 0 + @n_open_tags = 0 + @out = '' + reset + end + + def state + STATE_PARAMS.inject({}) do |h, param| + h[param] = send(param) + h + end + end + + def restore_state(new_state) + STATE_PARAMS.each do |param| + send("#{param}=".to_sym, new_state[param]) + end + end + def reset @fg_color = nil @bg_color = nil |