diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buffer/container.nim | 21 | ||||
-rw-r--r-- | src/display/client.nim | 27 | ||||
-rw-r--r-- | src/display/pager.nim | 11 | ||||
-rw-r--r-- | src/display/term.nim | 67 |
4 files changed, 88 insertions, 38 deletions
diff --git a/src/buffer/container.nim b/src/buffer/container.nim index fdebb204..2a68a24b 100644 --- a/src/buffer/container.nim +++ b/src/buffer/container.nim @@ -32,7 +32,7 @@ type ContainerEventType* = enum NO_EVENT, FAIL, SUCCESS, NEEDS_AUTH, REDIRECT, ANCHOR, NO_ANCHOR, UPDATE, - READ_LINE, READ_AREA, OPEN, INVALID_COMMAND, STATUS, ALERT + READ_LINE, READ_AREA, OPEN, INVALID_COMMAND, STATUS, ALERT, LOADED ContainerEvent* = object case t*: ContainerEventType @@ -623,6 +623,7 @@ proc onload(container: Container, res: tuple[atend: bool, lines, bytes: int]) = container.iface.render().then(proc(lines: int): auto = container.setNumLines(lines, true) container.needslines = true + container.triggerEvent(LOADED) if not container.hasstart and container.source.location.anchor != "": return container.iface.gotoAnchor() ).then(proc(res: tuple[x, y: int]) = @@ -751,19 +752,15 @@ proc setStream*(container: Container, stream: Stream) = # Synchronously read all lines in the buffer. iterator readLines*(container: Container): SimpleFlexibleLine {.inline.} = - while container.iface.hasPromises: - # Spin event loop till container has been loaded - container.handleCommand() if container.code == 0: # load succeded - discard container.iface.getLines(0 .. -1) - var plen, len, packetid: int - container.iface.stream.sread(plen) - container.iface.stream.sread(packetid) - container.iface.stream.sread(len) - var line: SimpleFlexibleLine - for y in 0 ..< len: - container.iface.stream.sread(line) + container.iface.getLines(0 .. -1).then(proc(res: tuple[numLines: int, lines: seq[SimpleFlexibleLine]]) = + container.lines = res.lines + container.setNumLines(res.numLines, true)) + while container.iface.hasPromises: + # receive all lines + container.handleCommand() + for line in container.lines: yield line proc handleEvent*(container: Container) = diff --git a/src/display/client.nim b/src/display/client.nim index e696457c..7bf9a278 100644 --- a/src/display/client.nim +++ b/src/display/client.nim @@ -313,6 +313,32 @@ proc inputLoop(client: Client) = client.pager.draw() client.acceptBuffers() +proc dumpLoop(client: Client) = + while client.pager.numload > 0: + let events = client.selector.select(-1) + for event in events: + if Read in event.events: + let container = client.fdmap[event.fd] + if not client.pager.handleEvent(container): + client.quit(1) + if Error in event.events: + #TODO handle errors + client.alert("Error in selected fds, check console") + client.console.log($event) + if Event.Timer in event.events: + if event.fd in client.interval_fdis: + client.intervals[client.interval_fdis[event.fd]].handler() + elif event.fd in client.timeout_fdis: + let id = client.timeout_fdis[event.fd] + let timeout = client.timeouts[id] + timeout.handler() + client.clearTimeout(id) + if client.pager.scommand != "": + client.command(client.pager.scommand) + client.pager.scommand = "" + client.pager.refreshStatusMsg() + client.acceptBuffers() + proc headlessLoop(client: Client) = while client.timeouts.len + client.intervals.len != 0: let events = client.selector.select(-1) @@ -366,6 +392,7 @@ proc newConsole(pager: Pager, tty: File): Console = result.err = newFileStream(stderr) proc dumpBuffers(client: Client) = + client.dumpLoop() let ostream = newFileStream(stdout) for container in client.pager.containers: client.pager.drawBuffer(container, ostream) diff --git a/src/display/pager.nim b/src/display/pager.nim index adec0d9e..7123ea97 100644 --- a/src/display/pager.nim +++ b/src/display/pager.nim @@ -32,6 +32,7 @@ type SEARCH_B, ISEARCH_F, ISEARCH_B Pager* = ref object + numload*: int alerts: seq[string] commandMode*: bool container*: Container @@ -162,8 +163,7 @@ proc newPager*(config: Config, attrs: WindowAttributes, dispatcher: Dispatcher, proc launchPager*(pager: Pager, tty: File) = pager.tty = tty - if tty != nil: - pager.term.start(tty) + pager.term.start(tty) proc dumpAlerts*(pager: Pager) = for msg in pager.alerts: @@ -267,6 +267,7 @@ proc refreshStatusMsg*(pager: Pager) = proc drawBuffer*(pager: Pager, container: Container, ostream: Stream) = var format = newFormat() + var i = 0 for line in container.readLines: if line.formats.len == 0: ostream.write(line.str & "\n") @@ -276,7 +277,6 @@ proc drawBuffer*(pager: Pager, container: Container, ostream: Stream) = var s = "" for f in line.formats: var outstr = "" - #assert f.pos < line.str.width(), "fpos " & $f.pos & "\nstr" & line.str & "\n" while x < f.pos: var r: Rune fastRuneAt(line.str, i, r) @@ -286,6 +286,7 @@ proc drawBuffer*(pager: Pager, container: Container, ostream: Stream) = s &= pager.term.processFormat(format, f.format) s &= line.str.substr(i) & pager.term.processFormat(format, newFormat()) & "\n" ostream.write(s) + inc i ostream.flush() proc redraw(pager: Pager) {.jsfunc.} = @@ -457,6 +458,7 @@ proc gotoURL*(pager: Pager, request: Request, prevurl = none(URL), ctype = none( container.replace = replace container.copyCursorPos(container.replace) pager.addContainer(container) + inc pager.numload else: pager.container.findAnchor(request.url.anchor) @@ -618,6 +620,7 @@ proc authorize*(pager: Pager) = proc handleEvent0(pager: Pager, container: Container, event: ContainerEvent): bool = case event.t of FAIL: + dec pager.numload pager.deleteContainer(container) if container.retry.len > 0: pager.gotoURL(newRequest(container.retry.pop()), ctype = container.contenttype) @@ -639,6 +642,8 @@ proc handleEvent0(pager: Pager, container: Container, event: ContainerEvent): bo container.parent.children[n] = container if pager.container == container.replace: pager.setContainer(container) + of LOADED: + dec pager.numload of NEEDS_AUTH: if pager.container == container: pager.authorize() diff --git a/src/display/term.nim b/src/display/term.nim index 4a166c90..5312bad2 100644 --- a/src/display/term.nim +++ b/src/display/term.nim @@ -130,12 +130,34 @@ proc clearEnd(term: Terminal): string = else: return EL() +proc isatty(term: Terminal): bool = + term.infile != nil and term.infile.isatty() and term.outfile.isatty() + proc resetFormat(term: Terminal): string = when termcap_found: - return term.cap me + if term.isatty(): + return term.cap me + return SGR() else: return SGR() +proc startFormat(term: Terminal, flag: FormatFlags): string = + when termcap_found: + if term.isatty(): + case flag + of FLAG_BOLD: return term.cap md + of FLAG_UNDERLINE: return term.cap us + of FLAG_REVERSE: return term.cap mr + of FLAG_BLINK: return term.cap mb + else: discard + return SGR(FormatCodes[flag].s) + +proc endFormat(term: Terminal, flag: FormatFlags): string = + when termcap_found: + if flag == FLAG_UNDERLINE and term.isatty(): + return term.cap ue + return SGR(FormatCodes[flag].e) + #TODO get rid of these proc setCursor*(term: Terminal, x, y: int) = term.write(term.cursorGoto(x, y)) @@ -218,7 +240,7 @@ proc processFormat*(term: Terminal, format: var Format, cellf: Format): string = for flag in FormatFlags: if flag in term.formatmode: if flag in format.flags and flag notin cellf.flags: - result &= SGR(FormatCodes[flag].e) + result &= term.endFormat(flag) var cellf = cellf if term.mincontrast >= 0 and distance(cellf.bgcolor, cellf.fgcolor) <= term.mincontrast: @@ -278,7 +300,7 @@ proc processFormat*(term: Terminal, format: var Format, cellf: Format): string = for flag in FormatFlags: if flag in term.formatmode: if flag notin format.flags and flag in cellf.flags: - result &= SGR(FormatCodes[flag].s) + result &= term.startFormat(flag) format = cellf @@ -422,11 +444,8 @@ else: proc restoreStdin*(flags: cint) = discard -proc isatty*(term: Terminal): bool = - term.infile.isatty() and term.outfile.isatty() - proc quit*(term: Terminal) = - if term.infile != nil and term.isatty(): + if term.isatty(): disableRawMode() if term.smcup: term.write(term.disableAltScreen()) @@ -453,24 +472,26 @@ proc detectTermAttributes(term: Terminal) = if term.tname == "": term.tname = "dosansi" when termcap_found: - term.loadTermcap() - if term.tc != nil: - term.smcup = term.hascap(ti) - term.formatmode = {FLAG_ITALIC, FLAG_OVERLINE, FLAG_STRIKE} - if term.hascap(us): - term.formatmode.incl(FLAG_UNDERLINE) - if term.hascap(md): - term.formatmode.incl(FLAG_BOLD) - if term.hascap(mr): - term.formatmode.incl(FLAG_REVERSE) - if term.hascap(mb): - term.formatmode.incl(FLAG_BLINK) + if term.isatty(): + term.loadTermcap() + if term.tc != nil: + term.smcup = term.hascap(ti) + term.formatmode = {FLAG_ITALIC, FLAG_OVERLINE, FLAG_STRIKE} + if term.hascap(us): + term.formatmode.incl(FLAG_UNDERLINE) + if term.hascap(md): + term.formatmode.incl(FLAG_BOLD) + if term.hascap(mr): + term.formatmode.incl(FLAG_REVERSE) + if term.hascap(mb): + term.formatmode.incl(FLAG_BLINK) else: - term.smcup = true - term.formatmode = {low(FormatFlags)..high(FormatFlags)} + if term.isatty(): + term.smcup = true + term.formatmode = {low(FormatFlags)..high(FormatFlags)} if term.config.colormode.isSome: term.colormode = term.config.colormode.get - else: + elif term.isatty(): term.colormode = ANSI let colorterm = getEnv("COLORTERM") case colorterm @@ -480,7 +501,7 @@ proc detectTermAttributes(term: Terminal) = for fm in FormatFlags: if fm in term.config.noformatmode: term.formatmode.excl(fm) - if term.config.altscreen.isSome: + if term.isatty() and term.config.altscreen.isSome: term.smcup = term.config.altscreen.get term.mincontrast = term.config.mincontrast |