diff options
author | bptato <nincsnevem662@gmail.com> | 2024-10-10 17:22:15 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-10-10 17:31:18 +0200 |
commit | 8c64d7cb4e54c289a6c18f6c144125196d888296 (patch) | |
tree | 4cc8de480912beebe62ccf9cf9ba826dc160fe2c /src/local | |
parent | cf31d252ffe0aa195909a03efa714c6fc6e5fddf (diff) | |
download | chawan-8c64d7cb4e54c289a6c18f6c144125196d888296.tar.gz |
layout, pager: preserve tabs on display, selection & output
Substitute tabs with one of eight PUA characters based on their width, and convert them back in the pager: * TUI mode always prints spaces, but now handles tabs appropriately on cursor movement * dump mode tries to preserve hard tabs, but uses soft tabs when that is not possible (e.g. tabs after a margin, tab with background color, etc) * selection mode always outputs hard tabs.
Diffstat (limited to 'src/local')
-rw-r--r-- | src/local/container.nim | 9 | ||||
-rw-r--r-- | src/local/pager.nim | 59 |
2 files changed, 45 insertions, 23 deletions
diff --git a/src/local/container.nim b/src/local/container.nim index 88becc71..6a8471df 100644 --- a/src/local/container.nim +++ b/src/local/container.nim @@ -1346,9 +1346,7 @@ proc getSelectionText(container: Container; hl: Highlight = nil): if hl == nil: return nil if hl.t != hltSelect: - let p = newPromise[string]() - p.resolve("") - return p + return newResolvedPromise("") let startx = hl.startx let starty = hl.starty let endx = hl.endx @@ -1381,7 +1379,7 @@ proc getSelectionText(container: Container; hl: Highlight = nil): if i > 0: s &= '\n' s &= line.str - return s + return s.expandPUATabsHard() ) proc markURL(container: Container) {.jsfunc.} = @@ -1751,6 +1749,9 @@ proc drawLines*(container: Container; display: var FixedGrid; hlcolor: CellColor nf = line.findNextFormat(pw) if u <= 0xFF and char(u) in Controls: display[dls + k].str &= '^' & char(u).getControlLetter() + elif u in TabPUARange: + for i in 0 ..< uw: + display[dls + k].str &= ' ' else: for j in pi ..< i: display[dls + k].str &= line.str[j] diff --git a/src/local/pager.nim b/src/local/pager.nim index f757f1d0..e8bb92bf 100644 --- a/src/local/pager.nim +++ b/src/local/pager.nim @@ -479,28 +479,49 @@ proc showAlerts*(pager: Pager) = pager.inputBuffer == "" and pager.precnum == 0: pager.refreshStatusMsg() +proc drawBufferAdvance(s: openArray[char]; bgcolor: CellColor; oi, ox: var int; + ex: int): string = + var ls = newStringOfCap(s.len) + var i = oi + var x = ox + while x < ex and i < s.len: + let pi = i + let u = s.nextUTF8(i) + let uw = u.width() + x += uw + if u in TabPUARange: + # PUA tabs can be expanded to hard tabs if + # * they are correctly aligned + # * they don't have a bgcolor (terminals will fail to output bgcolor with + # tabs) + if bgcolor == defaultColor and (x and 7) == 0: + ls &= '\t' + else: + for i in 0 ..< uw: + ls &= ' ' + else: + for i in pi ..< i: + ls &= s[i] + oi = i + ox = x + return ls + proc drawBuffer*(pager: Pager; container: Container; ofile: File) = var format = Format() container.readLines(proc(line: SimpleFlexibleLine) = - if line.formats.len == 0: - ofile.writeLine(line.str) - else: - var x = 0 - var w = -1 - var i = 0 - var s = "" - for f in line.formats: - let si = i - while x < f.pos: - let u = line.str.nextUTF8(i) - x += u.width() - s.processOutputString(pager.term, line.str.toOpenArray(si, i - 1), w) - s.processFormat(pager.term, format, f.format) - if i < line.str.len: - s.processOutputString(pager.term, - line.str.toOpenArray(i, line.str.high), w) - s.processFormat(pager.term, format, Format()) - ofile.writeLine(s) + var x = 0 + var w = -1 + var i = 0 + var s = "" + for f in line.formats: + let ls = line.str.drawBufferAdvance(format.bgcolor, i, x, f.pos) + s.processOutputString(pager.term, ls, w) + s.processFormat(pager.term, format, f.format) + if i < line.str.len: + let ls = line.str.drawBufferAdvance(format.bgcolor, i, x, int.high) + s.processOutputString(pager.term, ls, w) + s.processFormat(pager.term, format, Format()) + ofile.writeLine(s) ) ofile.flushFile() |