import std/streams import std/strutils import std/unicode import types/cell import utils/strwidth import chakasu/charset import chakasu/decoderstream import chakasu/encoderstream type StreamRenderer* = object ansiparser: AnsiCodeParser format: Format af: bool stream: Stream decoder: DecoderStream encoder: EncoderStream charsets: seq[Charset] newline: bool w: int j: int # byte in line #TODO pass bool for whether we can rewind proc newStreamRenderer*(stream: Stream, charsets0: openArray[Charset]): ref StreamRenderer = var charsets = newSeq[Charset](charsets0.len) for i in 0 ..< charsets.len: charsets[i] = charsets0[charsets.high - i] if charsets.len == 0: charsets.add(DefaultCharset) let cs = charsets.pop() let em = if charsets.len > 0: DECODER_ERROR_MODE_FATAL else: DECODER_ERROR_MODE_REPLACEMENT let decoder = newDecoderStream(stream, cs, errormode = em) decoder.setInhibitCheckEnd(true) let encoder = newEncoderStream(decoder) return (ref StreamRenderer)( stream: stream, decoder: decoder, encoder: encoder, format: Format(), charsets: charsets, ansiparser: AnsiCodeParser( state: PARSE_DONE ) ) proc rewind(renderer: var StreamRenderer) = let cs = renderer.charsets.pop() let em = if renderer.charsets.len > 0: DECODER_ERROR_MODE_FATAL else: DECODER_ERROR_MODE_REPLACEMENT let decoder = newDecoderStream(renderer.stream, cs, errormode = em) decoder.setInhibitCheckEnd(true) renderer.decoder = decoder renderer.encoder = newEncoderStream(decoder) renderer.format = Format() renderer.ansiparser.state = PARSE_DONE proc addFormat(grid: var FlexibleGrid, renderer: var StreamRenderer) = if renderer.af: renderer.af = false if renderer.j == grid[^1].str.len: grid[^1].addFormat(renderer.w, renderer.format) proc processBackspace(grid: var FlexibleGrid, renderer: var StreamRenderer, r: Rune): bool = let pj = renderer.j var cr: Rune fastRuneAt(grid[^1].str, renderer.j, cr) if r == Rune('_') or cr == Rune('_') or r == cr: let flag = if r == cr: FLAG_BOLD else: FLAG_UNDERLINE if r != cr and cr == Rune('_'): # original is _, we must replace :( # like less, we assume no double _ for double width characters. grid[^1].str.delete(pj..