about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/local/client.nim3
-rw-r--r--src/local/container.nim79
-rw-r--r--src/server/buffer.nim28
3 files changed, 51 insertions, 59 deletions
diff --git a/src/local/client.nim b/src/local/client.nim
index d088982f..11b3a8f2 100644
--- a/src/local/client.nim
+++ b/src/local/client.nim
@@ -144,8 +144,7 @@ proc command0(client: Client, src: string, filename = "<command>",
 proc command(client: Client, src: string) =
   client.command0(src)
   let container = client.consoleWrapper.container
-  container.requestLines().then(proc() =
-    container.cursorLastLine())
+  container.tailOnLoad = true
 
 proc suspend(client: Client) {.jsfunc.} =
   client.pager.term.quit()
diff --git a/src/local/container.nim b/src/local/container.nim
index 8008a896..ef14a303 100644
--- a/src/local/container.nim
+++ b/src/local/container.nim
@@ -137,6 +137,7 @@ type
     ishtml*: bool
     filter*: BufferFilter
     bgcolor*: CellColor
+    tailOnLoad*: bool
 
 jsDestructor(Highlight)
 jsDestructor(Container)
@@ -461,6 +462,8 @@ proc setNumLines(container: Container, lines: int, finish = false) =
       container.startpos = none(CursorPosition)
     container.updateCursor()
 
+proc cursorLastLine*(container: Container)
+
 proc requestLines*(container: Container, w = container.lineWindow): EmptyPromise
     {.discardable.} =
   if container.iface == nil:
@@ -473,13 +476,17 @@ proc requestLines*(container: Container, w = container.lineWindow): EmptyPromise
     for y in 0 ..< min(res.lines.len, w.len):
       container.lines[y] = res.lines[y]
       container.lines[y].str.mnormalize()
-    container.updateCursor()
     var isBgNew = container.bgcolor != res.bgcolor
     if isBgNew:
       container.bgcolor = res.bgcolor
     if res.numLines != container.numLines:
       container.setNumLines(res.numLines, true)
       container.triggerEvent(STATUS)
+    if res.numLines > 0:
+      container.updateCursor()
+      if container.tailOnLoad:
+        container.tailOnLoad = false
+        container.cursorLastLine()
     let cw = container.fromy ..< container.fromy + container.height
     if w.a in cw or w.b in cw or cw.a in w or cw.b in w or isBgNew:
       container.triggerEvent(UPDATE)
@@ -1334,45 +1341,36 @@ proc setLoadInfo(container: Container, msg: string) =
   container.loadinfo = msg
   container.triggerEvent(STATUS)
 
-#TODO TODO TODO this should be called with a timeout.
-proc onload*(container: Container, res: LoadResult) =
+#TODO this should be called with a timeout.
+proc onload*(container: Container, res: int) =
   if container.canceled:
     container.setLoadInfo("")
-    #TODO we wouldn't need the then part if we had incremental rendering of
-    # HTML.
-    container.iface.cancel().then(proc(lines: int) =
-      if lines != container.numLines:
-        container.setNumLines(lines)
-        container.triggerEvent(STATUS)
+    container.iface.cancel().then(proc() =
       container.needslines = true
     )
-  else:
-    if res.bytes == -1 or res.atend:
-      container.setLoadInfo("")
-    elif not res.atend:
-      container.setLoadInfo(convertSize(res.bytes) & " loaded")
-    if res.lines != container.numLines or res.atend:
-      container.setNumLines(res.lines, res.atend)
-      if res.atend:
-        container.triggerEvent(STATUS)
-      container.needslines = true
-    if not res.atend:
-      discard container.iface.load().then(proc(res: LoadResult) =
-        container.onload(res)
-      )
-    else:
-      container.triggerEvent(LOADED)
-      container.iface.getTitle().then(proc(title: string) =
-        if title != "":
-          container.title = title
-          container.triggerEvent(TITLE)
+  elif res == -1:
+    container.setLoadInfo("")
+    container.triggerEvent(STATUS)
+    container.needslines = true
+    container.triggerEvent(LOADED)
+    container.iface.getTitle().then(proc(title: string) =
+      if title != "":
+        container.title = title
+        container.triggerEvent(TITLE)
+    )
+    if not container.hasstart and container.location.anchor != "":
+      container.iface.gotoAnchor().then(proc(res: Opt[tuple[x, y: int]]) =
+        if res.isSome:
+          let res = res.get
+          container.setCursorXYCenter(res.x, res.y)
       )
-      if not container.hasstart and container.location.anchor != "":
-        container.iface.gotoAnchor().then(proc(res: Opt[tuple[x, y: int]]) =
-          if res.isSome:
-            let res = res.get
-            container.setCursorXYCenter(res.x, res.y)
-        )
+  elif res == -2:
+    container.setLoadInfo(convertSize(res) & " loaded")
+  else:
+    container.needslines = true
+    discard container.iface.load().then(proc(res: int) =
+      container.onload(res)
+    )
 
 proc load(container: Container) =
   container.setLoadInfo("Connecting to " & container.location.host & "...")
@@ -1420,9 +1418,9 @@ proc load(container: Container) =
   )
 
 proc startload*(container: Container) =
-  container.iface.load()
-    .then(proc(res: tuple[atend: bool, lines, bytes: int]) =
-      container.onload(res))
+  container.iface.load().then(proc(res: int) =
+    container.onload(res)
+  )
 
 proc connect2*(container: Container): EmptyPromise =
   return container.iface.connect2(container.ishtml)
@@ -1567,8 +1565,9 @@ proc setStream*(container: Container, stream: Stream) =
   else:
     container.iface = cloneInterface(stream)
     # Maybe we have to resume loading. Let's try.
-    discard container.iface.load().then(proc(res: LoadResult) =
-      container.onload(res))
+    discard container.iface.load().then(proc(res: int) =
+      container.onload(res)
+    )
 
 proc onreadline(container: Container, w: Slice[int],
     handle: (proc(line: SimpleFlexibleLine)), res: GetLinesResult) =
diff --git a/src/server/buffer.nim b/src/server/buffer.nim
index 6f8beb34..cfaa8b12 100644
--- a/src/server/buffer.nim
+++ b/src/server/buffer.nim
@@ -1137,16 +1137,15 @@ proc finishLoad(buffer: Buffer): EmptyPromise =
     buffer.loader.removeCachedURL($buffer.request.url)
   return buffer.loadResources()
 
-type LoadResult* = tuple[
-  atend: bool,
-  lines: int,
-  bytes: int
-]
-
-proc load*(buffer: Buffer): LoadResult {.proxy, task.} =
+# Returns:
+# * -1 if loading is done
+# * -2 if the page was partially rendered
+# * a positive number for just reporting the number of bytes loaded.
+proc load*(buffer: Buffer): int {.proxy, task.} =
   if buffer.state == bsLoaded:
-    return (true, buffer.lines.len, -1)
+    return -1
   else:
+    # will be resolved in onload
     buffer.savetask = true
 
 proc resolveTask[T](buffer: Buffer, cmd: BufferCommand, res: T) =
@@ -1161,12 +1160,11 @@ proc resolveTask[T](buffer: Buffer, cmd: BufferCommand, res: T) =
   buffer.pstream.flush()
 
 proc onload(buffer: Buffer) =
-  var res: LoadResult = (false, buffer.lines.len, -1)
   case buffer.state
   of bsConnecting:
     assert false
   of bsLoadingResources, bsLoaded:
-    buffer.resolveTask(LOAD, res)
+    buffer.resolveTask(LOAD, -1)
     return
   of bsLoadingPage:
     discard
@@ -1178,7 +1176,6 @@ proc onload(buffer: Buffer) =
       if not reprocess:
         n = buffer.istream.recvData(addr iq[0], iq.len)
         buffer.bytesRead += n
-      res.lines = buffer.lines.len
       if n != 0:
         if not buffer.processData(iq.toOpenArray(0, n - 1)):
           if not buffer.firstBufferRead:
@@ -1188,26 +1185,23 @@ proc onload(buffer: Buffer) =
             continue
         buffer.firstBufferRead = true
         reprocess = false
-        res.bytes = buffer.bytesRead
-        res.lines = buffer.lines.len
       else: # EOF
-        res.atend = true
         buffer.finishLoad().then(proc() =
           buffer.do_reshape()
-          res.lines = buffer.lines.len
           buffer.state = bsLoaded
           buffer.document.readyState = rsComplete
           buffer.dispatchLoadEvent()
-          buffer.resolveTask(LOAD, res)
+          buffer.resolveTask(LOAD, -1)
         )
         return # skip incr render
-      buffer.resolveTask(LOAD, res)
+      buffer.resolveTask(LOAD, buffer.bytesRead)
     except ErrorAgain:
       break
   # incremental rendering: only if we cannot read the entire stream in one
   # pass
   #TODO this could be improved
   buffer.do_reshape()
+  buffer.resolveTask(LOAD, -2)
 
 proc getTitle*(buffer: Buffer): string {.proxy.} =
   if buffer.document != nil: