diff options
author | bptato <nincsnevem662@gmail.com> | 2021-08-06 17:38:40 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2021-08-06 17:38:40 +0200 |
commit | 56b308e71f20dd6563634867e698e5c8d3290f58 (patch) | |
tree | 0cebb2740f344ad4f2262ccb3f5fff4e58e9c16d | |
parent | 6d50a0f7d1af3da77fcea7290ac02a43e8f454e4 (diff) | |
download | chawan-56b308e71f20dd6563634867e698e5c8d3290f58.tar.gz |
Refactor display.nim and twtio.nim
-rw-r--r-- | res/config | 6 | ||||
-rw-r--r-- | src/config.nim | 11 | ||||
-rw-r--r-- | src/html/dom.nim | 2 | ||||
-rw-r--r-- | src/html/htmlparser.nim | 2 | ||||
-rw-r--r-- | src/io/buffer.nim | 147 | ||||
-rw-r--r-- | src/io/display.nim | 374 | ||||
-rw-r--r-- | src/io/lineedit.nim (renamed from src/io/twtio.nim) | 25 | ||||
-rw-r--r-- | src/main.nim | 6 | ||||
-rw-r--r-- | src/utils/eprint.nim | 13 |
9 files changed, 170 insertions, 416 deletions
diff --git a/res/config b/res/config index c9a7c099..f059898e 100644 --- a/res/config +++ b/res/config @@ -27,10 +27,10 @@ nmap > PAGE_RIGHT nmap < PAGE_LEFT nmap C-e SCROLL_DOWN nmap C-y SCROLL_UP -nmap zh SCROLL_LEFT -nmap zl SCROLL_RIGHT nmap J SCROLL_DOWN nmap K SCROLL_UP +nmap ( SCROLL_LEFT +nmap ) SCROLL_RIGHT nmap C-m CLICK nmap C-j CLICK nmap C-l CHANGE_LOCATION @@ -41,7 +41,7 @@ nmap gg CURSOR_FIRST_LINE nmap G CURSOR_LAST_LINE nmap M-[H CURSOR_FIRST_LINE nmap M-[F CURSOR_LAST_LINE -nmap zz CENTER_LINE +nmap z CENTER_LINE nmap C-g LINE_INFO #line editing keybindings diff --git a/src/config.nim b/src/config.nim index 4713db07..1d2e2a46 100644 --- a/src/config.nim +++ b/src/config.nim @@ -151,3 +151,14 @@ proc readConfig*() = when defined(debug): readConfig("res" / "config") readConfig(getConfigDir() / "twt" / "config") + +proc getNormalAction*(s: string): TwtAction = + if gconfig.nmap.hasKey(s): + return gconfig.nmap[s] + return NO_ACTION + +proc getLinedAction*(s: string): TwtAction = + if gconfig.lemap.hasKey(s): + return gconfig.lemap[s] + return NO_ACTION + diff --git a/src/html/dom.nim b/src/html/dom.nim index 2227aece..b1e1af4c 100644 --- a/src/html/dom.nim +++ b/src/html/dom.nim @@ -16,8 +16,6 @@ import ../types/enums import ../utils/twtstr -import ../io/twtio - const css = staticRead"../../res/default.css" let stylesheet = parseCSS(newStringStream(css)) diff --git a/src/html/htmlparser.nim b/src/html/htmlparser.nim index 94c474f0..f5a8190b 100644 --- a/src/html/htmlparser.nim +++ b/src/html/htmlparser.nim @@ -10,8 +10,6 @@ import ../types/tagtypes import ../utils/twtstr import ../utils/radixtree -import ../io/twtio - import dom import entity diff --git a/src/io/buffer.nim b/src/io/buffer.nim index 5eb2c71b..7032a138 100644 --- a/src/io/buffer.nim +++ b/src/io/buffer.nim @@ -1,4 +1,5 @@ import options +import terminal import uri import tables import strutils @@ -12,8 +13,10 @@ import ../utils/eprint import ../html/dom -import ./twtio +import ../config + import ./term +import ./lineedit type Cell = object of RootObj @@ -52,7 +55,6 @@ type elements*: seq[Element] idelements*: Table[string, Element] selectedlink*: Node - printwrite*: bool attrs*: TermAttributes document*: Document displaycontrols*: bool @@ -187,7 +189,7 @@ proc clearBuffer*(buffer: Buffer) = buffer.selectedlink = nil proc restoreCursorX(buffer: Buffer) = - buffer.cursorx = min(buffer.currentLineWidth() - 1, buffer.xend) + buffer.cursorx = max(min(buffer.currentLineWidth() - 1, buffer.xend), 0) proc scrollTo*(buffer: Buffer, y: int) = if y == buffer.fromy: @@ -206,8 +208,14 @@ proc cursorTo*(buffer: Buffer, x: int, y: int) = elif buffer.fromy + buffer.height - 1 <= buffer.cursory: buffer.fromy = max(buffer.cursory - buffer.height + 2, 0) buffer.redraw = true + buffer.cursorx = min(max(x, 0), buffer.currentLineWidth()) - #buffer.fromX = min(max(buffer.currentLineWidth() - buffer.width + 1, 0), 0) #TODO + if buffer.fromx < buffer.cursorx - buffer.width: + buffer.fromx = max(0, buffer.cursorx - buffer.width) + buffer.redraw = true + elif buffer.fromx > buffer.cursorx: + buffer.fromx = buffer.cursorx + buffer.redraw = true proc cursorDown*(buffer: Buffer) = if buffer.cursory < buffer.lastLine(): @@ -273,12 +281,12 @@ proc cursorNextWord*(buffer: Buffer) = var y = buffer.cursory if llen >= 0: - while buffer.lines[y][x].rune != Rune(' '): + while not buffer.lines[y][x].rune.breaksWord(): if x >= llen: break inc x - while buffer.lines[y][x].rune == Rune(' '): + while buffer.lines[y][x].rune.breaksWord(): if x >= llen: break inc x @@ -293,12 +301,12 @@ proc cursorPrevWord*(buffer: Buffer) = var x = buffer.cursorx var y = buffer.cursory if buffer.currentLineWidth() > 0: - while buffer.lines[y][x].rune != Rune(' '): + while not buffer.lines[y][x].rune.breaksWord(): if x == 0: break dec x - while buffer.lines[y][x].rune == Rune(' '): + while buffer.lines[y][x].rune.breaksWord(): if x == 0: break dec x @@ -520,3 +528,126 @@ proc renderPlainText*(buffer: Buffer, text: string) = buffer.setText(0, y, line.toRunes()) buffer.refreshDisplay() + +proc cursorBufferPos(buffer: Buffer) = + var x = max(buffer.cursorx - buffer.fromx, 0) + var y = buffer.cursory - buffer.fromy + termGoto(x, y) + +proc clearStatusMsg*(at: int) = + setCursorPos(0, at) + eraseLine() + +proc statusMsg*(str: string, at: int) = + clearStatusMsg(at) + print(str.ansiStyle(styleReverse).ansiReset()) + +proc statusMsgForBuffer(buffer: Buffer) = + var msg = $(buffer.cursory + 1) & "/" & $(buffer.lastLine() + 1) & " (" & + $buffer.atPercentOf() & "%) " & + "<" & buffer.title & ">" + if buffer.hovertext.len > 0: + msg &= " " & buffer.hovertext + statusMsg(msg.maxString(buffer.width), buffer.height) + +proc displayBuffer(buffer: Buffer) = + eraseScreen() + termGoto(0, 0) + + print(buffer.generateFullOutput().ansiReset()) + +proc inputLoop(attrs: TermAttributes, buffer: Buffer): bool = + var s = "" + var feedNext = false + while true: + buffer.redraw = false + stdout.showCursor() + buffer.cursorBufferPos() + if not feedNext: + s = "" + else: + feedNext = false + let c = getch() + s &= c + let action = getNormalAction(s) + var redraw = false + var reshape = false + var nostatus = false + case action + of ACTION_QUIT: + eraseScreen() + setCursorPos(0, 0) + return false + of ACTION_CURSOR_LEFT: buffer.cursorLeft() + of ACTION_CURSOR_DOWN: buffer.cursorDown() + of ACTION_CURSOR_UP: buffer.cursorUp() + of ACTION_CURSOR_RIGHT: buffer.cursorRight() + of ACTION_CURSOR_LINEBEGIN: buffer.cursorLineBegin() + of ACTION_CURSOR_LINEEND: buffer.cursorLineEnd() + of ACTION_CURSOR_NEXT_WORD: buffer.cursorNextWord() + of ACTION_CURSOR_PREV_WORD: buffer.cursorPrevWord() + of ACTION_CURSOR_NEXT_LINK: buffer.cursorNextLink() + of ACTION_CURSOR_PREV_LINK: buffer.cursorPrevLink() + of ACTION_PAGE_DOWN: buffer.pageDown() + of ACTION_PAGE_UP: buffer.pageUp() + of ACTION_PAGE_RIGHT: buffer.pageRight() + of ACTION_PAGE_LEFT: buffer.pageLeft() + of ACTION_HALF_PAGE_DOWN: buffer.halfPageDown() + of ACTION_HALF_PAGE_UP: buffer.halfPageUp() + of ACTION_CURSOR_FIRST_LINE: buffer.cursorFirstLine() + of ACTION_CURSOR_LAST_LINE: buffer.cursorLastLine() + of ACTION_CURSOR_TOP: buffer.cursorTop() + of ACTION_CURSOR_MIDDLE: buffer.cursorMiddle() + of ACTION_CURSOR_BOTTOM: buffer.cursorBottom() + of ACTION_CENTER_LINE: buffer.centerLine() + of ACTION_SCROLL_DOWN: buffer.scrollDown() + of ACTION_SCROLL_UP: buffer.scrollUp() + of ACTION_SCROLL_LEFT: buffer.scrollLeft() + of ACTION_SCROLL_RIGHT: buffer.scrollRight() + of ACTION_CLICK: + discard + of ACTION_CHANGE_LOCATION: + var url = $buffer.location + + clearStatusMsg(buffer.height) + let status = readLine("URL: ", url, buffer.width) + if status: + buffer.setLocation(parseUri(url)) + return true + of ACTION_LINE_INFO: + statusMsg("line " & $buffer.cursory & "/" & $buffer.lastLine() & " col " & $(buffer.cursorx + 1) & "/" & $buffer.currentLineWidth() & " cell width: " & $buffer.currentCellWidth(), buffer.width) + nostatus = true + of ACTION_FEED_NEXT: + feedNext = true + of ACTION_RELOAD: return true + of ACTION_RESHAPE: + reshape = true + redraw = true + of ACTION_REDRAW: redraw = true + else: discard + stdout.hideCursor() + + if buffer.refreshTermAttrs(): + redraw = true + reshape = true + + if buffer.redraw: + redraw = true + + if reshape: + buffer.reshape() + if redraw: + buffer.refreshDisplay() + buffer.displayBuffer() + + if not nostatus: + buffer.statusMsgForBuffer() + else: + nostatus = false + +proc displayPage*(attrs: TermAttributes, buffer: Buffer): bool = + discard buffer.gotoAnchor() + buffer.displayBuffer() + buffer.statusMsgForBuffer() + return inputLoop(attrs, buffer) + diff --git a/src/io/display.nim b/src/io/display.nim deleted file mode 100644 index f5c9f645..00000000 --- a/src/io/display.nim +++ /dev/null @@ -1,374 +0,0 @@ -import terminal -import options -import uri -import strutils -import unicode - -import ../types/enums - -import ../utils/twtstr - -import ../html/dom - -import ../config - -import ./buffer -import ./twtio -import ./term - -proc clearStatusMsg*(at: int) = - setCursorPos(0, at) - eraseLine() - -proc statusMsg*(str: string, at: int) = - clearStatusMsg(at) - print(str.ansiStyle(styleReverse).ansiReset()) - -type - RenderState = object - x: int - y: int - lastwidth: int - fmtline: string - rawline: string - centerqueue: seq[Node] - centerlen: int - blanklines: int - blankspaces: int - nextspaces: int - docenter: bool - indent: int - listval: int - lastelem: Element - -func newRenderState(): RenderState = - return RenderState(blanklines: 1) - -proc write(state: var RenderState, s: string) = - state.fmtline &= s - state.rawline &= s - -proc write(state: var RenderState, fs: string, rs: string) = - state.fmtline &= fs - state.rawline &= rs - -proc flushLine(buffer: Buffer, state: var RenderState) = - if state.rawline.len == 0: - inc state.blanklines - assert(state.rawline.runeLen() < buffer.width, "line too long: (for node " & - $state.lastelem & " " & $state.lastelem.style.display & ")\n" & state.rawline) - buffer.writefmt(state.fmtline) - buffer.writeraw(state.rawline) - state.x = 0 - inc state.y - state.nextspaces = 0 - state.fmtline = "" - state.rawline = "" - -proc addSpaces(buffer: Buffer, state: var RenderState, n: int) = - if state.x + n > buffer.width: - buffer.flushLine(state) - return - state.blankspaces += n - state.write(' '.repeat(n)) - state.x += n - -proc writeWrappedText(buffer: Buffer, state: var RenderState, node: Node) = - state.lastwidth = 0 - var n = 0 - var fmtword = "" - var rawword = "" - var prevl = false - let fmttext = node.getFmtText() - for w in fmttext: - if w.len > 0 and w[0] == '\e': - fmtword &= w - continue - - for r in w.runes: - if r == Rune(' '): - if rawword.len > 0 and rawword[0] == ' ' and prevl: - fmtword = fmtword.substr(1) - rawword = rawword.substr(1) - state.x -= 1 - prevl = false - state.write(fmtword, rawword) - fmtword = "" - rawword = "" - - if r == Rune('\n'): - state.write(fmtword, rawword) - buffer.flushLine(state) - rawword = "" - fmtword = "" - else: - fmtword &= r - rawword &= r - - state.x += r.width() - - if state.x >= buffer.width: - state.lastwidth = max(state.lastwidth, state.x) - buffer.flushLine(state) - state.x = rawword.width() - prevl = true - else: - state.lastwidth = max(state.lastwidth, state.x) - - inc n - - state.write(fmtword, rawword) - if prevl: - state.x += rawword.width() - prevl = false - - state.lastwidth = max(state.lastwidth, state.x) - -proc preAlignNode(buffer: Buffer, node: Node, state: var RenderState) = - let style = node.getStyle() - if state.rawline.len > 0 and node.firstNode() and state.blanklines == 0: - buffer.flushLine(state) - - if node.firstNode(): - #while state.blanklines < max(style.margin, style.margintop): - # buffer.flushLine(state) - state.indent += style.indent - - if state.rawline.len > 0 and state.blanklines == 0 and node.displayed(): - buffer.addSpaces(state, state.nextspaces) - state.nextspaces = 0 - #if state.blankspaces < max(style.margin, style.marginleft): - # buffer.addSpaces(state, max(style.margin, style.marginleft) - state.blankspaces) - - if style.centered and state.rawline.len == 0 and node.displayed(): - buffer.addSpaces(state, max(buffer.width div 2 - state.centerlen div 2, 0)) - state.centerlen = 0 - - if node.isElemNode() and style.display == DISPLAY_LIST_ITEM and state.indent > 0: - if state.blanklines == 0: - buffer.flushLine(state) - var listchar = "•" - #case elem.parentElement.tagType - #of TAG_UL: - # listchar = "•" - #of TAG_OL: - # inc state.listval - # listchar = $state.listval & ")" - #else: - # return - buffer.addSpaces(state, state.indent) - state.write(listchar) - state.x += listchar.runeLen() - buffer.addSpaces(state, 1) - -proc postAlignNode(buffer: Buffer, node: Node, state: var RenderState) = - let style = node.getStyle() - - if node.getRawLen() > 0: - state.blanklines = 0 - state.blankspaces = 0 - - #if state.rawline.len > 0 and state.blanklines == 0: - # state.nextspaces += max(style.margin, style.marginright) - # if node.lastNode() and (node.isTextNode() or elem.childNodes.len == 0): - # buffer.flushLine(state) - - if node.lastNode(): - #while state.blanklines < max(style.margin, style.marginbottom): - # buffer.flushLine(state) - state.indent -= style.indent - - if style.display == DISPLAY_LIST_ITEM and node.lastNode(): - buffer.flushLine(state) - -proc renderNode(buffer: Buffer, node: Node, state: var RenderState) = - if not (node.nodeType in {ELEMENT_NODE, TEXT_NODE}): - return - let style = node.getStyle() - if node.nodeType == ELEMENT_NODE: - if Element(node).tagType in {TAG_SCRIPT, TAG_STYLE, TAG_NOSCRIPT, TAG_TITLE}: - return - if style.hidden or style.display == DISPLAY_NONE: return - if node.nodeType == ELEMENT_NODE: - state.lastelem = (Element)node - else: - state.lastelem = node.parentElement - - if not state.docenter: - if style.centered: - state.centerqueue.add(node) - if node.lastNode(): - state.docenter = true - state.centerlen = 0 - for node in state.centerqueue: - state.centerlen += node.getRawLen() - for node in state.centerqueue: - buffer.renderNode(node, state) - state.centerqueue.setLen(0) - state.docenter = false - return - else: - return - if state.centerqueue.len > 0: - state.docenter = true - state.centerlen = 0 - for node in state.centerqueue: - state.centerlen += node.getRawLen() - for node in state.centerqueue: - buffer.renderNode(node, state) - state.centerqueue.setLen(0) - state.docenter = false - - buffer.preAlignNode(node, state) - - node.x = state.x - node.y = state.y - buffer.writeWrappedText(state, node) - node.ex = state.x - node.ey = state.y - node.width = state.lastwidth - node.x - 1 - node.height = state.y - node.y + 1 - - buffer.postAlignNode(node, state) - -proc setLastHtmlLine(buffer: Buffer, state: var RenderState) = - if state.rawline.len != 0: - buffer.flushLine(state) - -proc renderHtml*(buffer: Buffer) = - var stack: seq[Node] - let first = buffer.document.root - stack.add(first) - - var state = newRenderState() - while stack.len > 0: - let currElem = stack.pop() - buffer.renderNode(currElem, state) - var i = currElem.childNodes.len - 1 - while i >= 0: - stack.add(currElem.childNodes[i]) - i -= 1 - - buffer.setLastHtmlLine(state) - -proc drawHtml(buffer: Buffer) = - var state = newRenderState() - for node in buffer.nodes: - buffer.renderNode(node, state) - buffer.setLastHtmlLine(state) - -proc statusMsgForBuffer(buffer: Buffer) = - var msg = $(buffer.cursory + 1) & "/" & $(buffer.lastLine() + 1) & " (" & - $buffer.atPercentOf() & "%) " & - "<" & buffer.title & ">" - if buffer.hovertext.len > 0: - msg &= " " & buffer.hovertext - statusMsg(msg.maxString(buffer.width), buffer.height) - -proc cursorBufferPos(buffer: Buffer) = - var x = max(buffer.cursorx - buffer.fromx, 0) - var y = buffer.cursory - buffer.fromy - termGoto(x, y) - -proc displayBuffer(buffer: Buffer) = - eraseScreen() - termGoto(0, 0) - - print(buffer.generateFullOutput().ansiReset()) - -proc inputLoop(attrs: TermAttributes, buffer: Buffer): bool = - var s = "" - var feedNext = false - while true: - buffer.redraw = false - stdout.showCursor() - buffer.cursorBufferPos() - if not feedNext: - s = "" - else: - feedNext = false - let c = getch() - s &= c - let action = getNormalAction(s) - var redraw = false - var reshape = false - var nostatus = false - case action - of ACTION_QUIT: - eraseScreen() - setCursorPos(0, 0) - return false - of ACTION_CURSOR_LEFT: buffer.cursorLeft() - of ACTION_CURSOR_DOWN: buffer.cursorDown() - of ACTION_CURSOR_UP: buffer.cursorUp() - of ACTION_CURSOR_RIGHT: buffer.cursorRight() - of ACTION_CURSOR_LINEBEGIN: buffer.cursorLineBegin() - of ACTION_CURSOR_LINEEND: buffer.cursorLineEnd() - of ACTION_CURSOR_NEXT_WORD: buffer.cursorNextWord() - of ACTION_CURSOR_PREV_WORD: buffer.cursorPrevWord() - of ACTION_CURSOR_NEXT_LINK: buffer.cursorNextLink() - of ACTION_CURSOR_PREV_LINK: buffer.cursorPrevLink() - of ACTION_PAGE_DOWN: buffer.pageDown() - of ACTION_PAGE_UP: buffer.pageUp() - of ACTION_PAGE_RIGHT: buffer.pageRight() - of ACTION_PAGE_LEFT: buffer.pageLeft() - of ACTION_HALF_PAGE_DOWN: buffer.halfPageDown() - of ACTION_HALF_PAGE_UP: buffer.halfPageUp() - of ACTION_CURSOR_FIRST_LINE: buffer.cursorFirstLine() - of ACTION_CURSOR_LAST_LINE: buffer.cursorLastLine() - of ACTION_CURSOR_TOP: buffer.cursorTop() - of ACTION_CURSOR_MIDDLE: buffer.cursorMiddle() - of ACTION_CURSOR_BOTTOM: buffer.cursorBottom() - of ACTION_CENTER_LINE: buffer.centerLine() - of ACTION_SCROLL_DOWN: buffer.scrollDown() - of ACTION_SCROLL_UP: buffer.scrollUp() - of ACTION_SCROLL_LEFT: buffer.scrollLeft() - of ACTION_SCROLL_RIGHT: buffer.scrollRight() - of ACTION_CLICK: - discard - of ACTION_CHANGE_LOCATION: - var url = $buffer.location - - clearStatusMsg(buffer.height) - let status = readLine("URL: ", url, buffer.width) - if status: - buffer.setLocation(parseUri(url)) - return true - of ACTION_LINE_INFO: - statusMsg("line " & $buffer.cursory & "/" & $buffer.lastLine() & " col " & $(buffer.cursorx + 1) & "/" & $buffer.currentLineWidth() & " cell width: " & $buffer.currentCellWidth(), buffer.width) - nostatus = true - of ACTION_FEED_NEXT: - feedNext = true - of ACTION_RELOAD: return true - of ACTION_RESHAPE: - reshape = true - redraw = true - of ACTION_REDRAW: redraw = true - else: discard - stdout.hideCursor() - - if buffer.refreshTermAttrs(): - redraw = true - reshape = true - - if buffer.redraw: - redraw = true - - if reshape: - buffer.reshape() - if redraw: - buffer.refreshDisplay() - buffer.displayBuffer() - - if not nostatus: - buffer.statusMsgForBuffer() - else: - nostatus = false - -proc displayPage*(attrs: TermAttributes, buffer: Buffer): bool = - #buffer.printwrite = true - discard buffer.gotoAnchor() - buffer.displayBuffer() - buffer.statusMsgForBuffer() - return inputLoop(attrs, buffer) - diff --git a/src/io/twtio.nim b/src/io/lineedit.nim index 26c5be02..c1c5c187 100644 --- a/src/io/twtio.nim +++ b/src/io/lineedit.nim @@ -1,4 +1,4 @@ -import std/terminal +import terminal import tables import unicode import strutils @@ -7,33 +7,12 @@ import sugar import ../utils/twtstr import ../utils/radixtree +import ../utils/eprint import ../config import ./terminal -template print*(s: varargs[string, `$`]) = - for x in s: - stdout.write(x) - -template printesc*(s: string) = - for r in s.runes: - if r.isControlChar(): - stdout.write(('^' & $($r)[0].getControlLetter()) - .ansiFgColor(fgBlue).ansiStyle(styleBright).ansiReset()) - else: - stdout.write($r) - -proc getNormalAction*(s: string): TwtAction = - if gconfig.nmap.hasKey(s): - return gconfig.nmap[s] - return NO_ACTION - -proc getLinedAction*(s: string): TwtAction = - if gconfig.lemap.hasKey(s): - return gconfig.lemap[s] - return NO_ACTION - type LineState = object news: seq[Rune] s: string diff --git a/src/main.nim b/src/main.nim index 8394b5ab..198eedb8 100644 --- a/src/main.nim +++ b/src/main.nim @@ -8,7 +8,6 @@ import utils/eprint import html/dom import html/htmlparser -import io/display import io/buffer import io/term @@ -47,11 +46,10 @@ proc main*() = let buffer = newBuffer(attrs) let uri = parseUri(paramStr(1)) buffers.add(buffer) - buffer.renderPlainText(getPageUri(uri).readAll()) #buffer.document = parseHtml(getPageUri(uri)) #buffer.setLocation(uri) #buffer.document.applyDefaultStylesheet() - #buffer.renderHtml() + buffer.renderPlainText(getPageUri(uri).readAll()) var lastUri = uri while displayPage(attrs, buffer): statusMsg("Loading...", buffer.height) @@ -64,6 +62,6 @@ proc main*() = discard else: buffer.document = parseHtml(getPageUri(buffer.location)) - buffer.renderHtml() + buffer.renderPlainText(getPageUri(uri).readAll()) lastUri = newUri main() diff --git a/src/utils/eprint.nim b/src/utils/eprint.nim index 23248363..128d34d9 100644 --- a/src/utils/eprint.nim +++ b/src/utils/eprint.nim @@ -9,3 +9,16 @@ template eprint*(s: varargs[string, `$`]) = {.cast(noSideEffect).}: stderr.write(' ') stderr.write(x) stderr.write('\n') + +template print*(s: varargs[string, `$`]) = + for x in s: + stdout.write(x) + +template printesc*(s: string) = + for r in s.runes: + if r.isControlChar(): + stdout.write(('^' & $($r)[0].getControlLetter()) + .ansiFgColor(fgBlue).ansiStyle(styleBright).ansiReset()) + else: + stdout.write($r) + |