From baef6728fa4e8e515ccdeba1ea54da996f322aab Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 9 May 2016 19:59:45 +0300 Subject: 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. --- lib/ci/ansi2html.rb | 78 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 21 deletions(-) (limited to 'lib') 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(/ 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 << %{} @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 -- cgit v1.2.1 From 74520f23db51c95b4aea8856fb51c4246785f776 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 9 May 2016 20:19:27 +0300 Subject: Encode state as base64 string --- lib/ci/ansi2html.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ci/ansi2html.rb b/lib/ci/ansi2html.rb index d29e68570ff..5fed43aaebd 100644 --- a/lib/ci/ansi2html.rb +++ b/lib/ci/ansi2html.rb @@ -90,7 +90,7 @@ module Ci def convert(raw, new_state) reset_state - restore_state(new_state) if new_state && new_state[:offset].to_i < raw.length + restore_state(raw, new_state) if new_state start = @offset ansi = raw[@offset..-1] @@ -187,15 +187,20 @@ module Ci end def state - STATE_PARAMS.inject({}) do |h, param| + state = STATE_PARAMS.inject({}) do |h, param| h[param] = send(param) h end + Base64.urlsafe_encode64(state.to_json) end - def restore_state(new_state) + def restore_state(raw, new_state) + state = Base64.urlsafe_decode64(new_state) + state = JSON.parse(state, symbolize_names: true) + return if state[:offset].to_i > raw.length + STATE_PARAMS.each do |param| - send("#{param}=".to_sym, new_state[param]) + send("#{param}=".to_sym, state[param]) end end -- cgit v1.2.1