about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buffer/container.nim21
-rw-r--r--src/display/client.nim27
-rw-r--r--src/display/pager.nim11
-rw-r--r--src/display/term.nim67
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