import options import os import streams import terminal import css/sheet import config/config import io/buffer import io/lineedit import io/loader import js/javascript import types/url import utils/twtstr type Client* = ref ClientObj ClientObj = object buffer: Buffer feednext: bool s: string iserror: bool errormessage: string userstyle: CSSStylesheet loader: FileLoader jsrt: JSRuntime jsctx: JSContext ActionError = object of IOError LoadError = object of ActionError InterruptError = object of LoadError proc js_console_log(ctx: JSContext, this: JSValue, argc: int, argv: ptr JSValue): JSValue {.cdecl.} = let opaque = ctx.getOpaque() for i in 0.. 0: let ret = client.jsctx.eval(iput, "", JS_EVAL_TYPE_GLOBAL) let opaque = client.jsctx.getOpaque() if ret.isException(): let ex = client.jsctx.getException() let str = ex.toString() if str.issome: opaque.err &= str.get & '\n' let stack = ex.getProperty("stack") if not stack.isUndefined(): let str = stack.toString() if str.issome: opaque.err &= str.get & '\n' free(stack) free(ex) else: let str = ret.toString() if str.issome: opaque.err &= str.get & '\n' free(ret) client.addBuffer() g_client = client setControlCHook(proc() {.noconv.} = if g_client.buffer.prev != nil or g_client.buffer.next != nil: g_client.discardBuffer() interruptError()) client.buffer.istream = newStringStream(opaque.err) client.buffer.contenttype = "text/plain" client.setupBuffer() proc quit(client: Client) = eraseScreen() print(HVP(0, 0)) quit(0) proc input(client: Client) = let buffer = client.buffer if not client.feednext: client.s = "" else: client.feednext = false let c = getch() client.s &= c let action = getNormalAction(client.s) case action of ACTION_QUIT: client.quit() 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_CURSOR_LEFT_EDGE: buffer.cursorLeftEdge() of ACTION_CURSOR_VERT_MIDDLE: buffer.cursorVertMiddle() of ACTION_CURSOR_RIGHT_EDGE: buffer.cursorRightEdge() 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: client.click() of ACTION_CHANGE_LOCATION: client.changeLocation() of ACTION_LINE_INFO: buffer.lineInfo() of ACTION_FEED_NEXT: client.feednext = true of ACTION_RELOAD: client.reloadPage() of ACTION_RESHAPE: buffer.reshape = true of ACTION_REDRAW: buffer.redraw = true of ACTION_TOGGLE_SOURCE: client.toggleSource() of ACTION_PREV_BUFFER: client.prevBuffer() of ACTION_NEXT_BUFFER: client.nextBuffer() of ACTION_DISCARD_BUFFER: client.discardBuffer() of ACTION_COMMAND: client.command() else: discard proc inputLoop(client: Client) = while true: g_client = client setControlCHook(proc() {.noconv.} = g_client.buffer.setStatusMessage("Interrupted rendering procedure") g_client.buffer.redraw = true g_client.buffer.reshape = false g_client.inputLoop()) client.buffer.refreshBuffer() try: client.input() except ActionError as e: client.buffer.setStatusMessage(e.msg) proc launchClient*(client: Client, pages: seq[string], ctype: string, dump: bool) = client.userstyle = gconfig.stylesheet.parseStylesheet() if not stdin.isatty: client.readPipe(ctype) try: for page in pages: client.loadUrl(page, ctype) except LoadError as e: eprint(e.msg & '\n') quit(1) if stdout.isatty and not dump: client.inputLoop() else: var buffer = client.buffer while buffer.next != nil: buffer = buffer.next buffer.drawBuffer() while buffer.prev != nil: buffer = buffer.prev buffer.drawBuffer()