about summary refs log tree commit diff stats
path: root/src/buffer
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-11-25 16:38:23 +0100
committerbptato <nincsnevem662@gmail.com>2022-11-25 16:38:23 +0100
commitaaacdc350547dd5a5d637f9a054888792781895a (patch)
tree8a9c0edff45a37a4c31de254b03016e2bfb7fb60 /src/buffer
parent8607bb0c1e7653c1249c40fa573f94718b4d5727 (diff)
downloadchawan-aaacdc350547dd5a5d637f9a054888792781895a.tar.gz
Improve status messages, fix regressions, etc
Diffstat (limited to 'src/buffer')
-rw-r--r--src/buffer/buffer.nim52
-rw-r--r--src/buffer/container.nim55
2 files changed, 72 insertions, 35 deletions
diff --git a/src/buffer/buffer.nim b/src/buffer/buffer.nim
index 0c30ea92..2acf0e6c 100644
--- a/src/buffer/buffer.nim
+++ b/src/buffer/buffer.nim
@@ -36,6 +36,9 @@ import types/url
 import utils/twtstr
 
 type
+  LoadInfo* = enum
+    CONNECT, DOWNLOAD, RENDER, DONE
+
   BufferCommand* = enum
     LOAD, RENDER, WINDOW_CHANGE, GOTO_ANCHOR, READ_SUCCESS, READ_CANCELED,
     CLICK, FIND_NEXT_LINK, FIND_PREV_LINK, FIND_NEXT_MATCH, FIND_PREV_MATCH,
@@ -43,8 +46,8 @@ type
 
   ContainerCommand* = enum
     SET_LINES, SET_NEEDS_AUTH, SET_CONTENT_TYPE, SET_REDIRECT, SET_TITLE,
-    SET_HOVER, READ_LINE, LOAD_DONE, ANCHOR_FOUND, ANCHOR_FAIL, JUMP, OPEN,
-    BUFFER_READY, SOURCE_READY, RESHAPE
+    SET_HOVER, SET_LOAD_INFO, SET_NUM_LINES, READ_LINE, LOAD_DONE,
+    ANCHOR_FOUND, ANCHOR_FAIL, JUMP, OPEN, BUFFER_READY, SOURCE_READY, RESHAPE
 
   BufferMatch* = object
     success*: bool
@@ -53,6 +56,7 @@ type
     str*: string
 
   Buffer* = ref object
+    alive: bool
     input: HTMLInputElement
     contenttype: string
     lines: FlexibleGrid
@@ -83,12 +87,14 @@ type
 macro writeCommand(buffer: Buffer, cmd: ContainerCommand, args: varargs[typed]) =
   result = newStmtList()
   let lens = ident("lens")
-  result.add(quote do:
+  let calclens = newStmtList()
+  calclens.add(quote do:
     var `lens` = slen(`cmd`))
   for arg in args:
-    result.add(quote do: `lens` += slen(`arg`))
-  result.add(quote do:
+    calclens.add(quote do: `lens` += slen(`arg`))
+  calclens.add(quote do:
     `buffer`.postream.swrite(`lens`))
+  result.add(newBlockStmt(calclens))
   result.add(quote do: `buffer`.postream.swrite(`cmd`))
   for arg in args:
     result.add(quote do: `buffer`.postream.swrite(`arg`))
@@ -272,15 +278,13 @@ proc gotoAnchor(buffer: Buffer) =
   if buffer.document == nil: return
   let anchor = buffer.document.getElementById(buffer.location.anchor)
   if anchor == nil: return
-  for y in 0..<buffer.lines.len:
+  for y in 0 ..< buffer.lines.len:
     let line = buffer.lines[y]
-    var i = 0
-    while i < line.formats.len:
+    for i in 0 ..< line.formats.len:
       let format = line.formats[i]
       if format.node != nil and anchor in format.node.node:
-        buffer.writeCommand(JUMP, format.pos, y)
+        buffer.writeCommand(JUMP, format.pos, y, 0)
         return
-      inc i
 
 proc windowChange(buffer: Buffer) =
   buffer.viewport = Viewport(window: buffer.attrs)
@@ -732,8 +736,11 @@ proc readCommand(buffer: Buffer) =
     let fd = SocketStream(istream).recvFileHandle()
     buffer.bsource.fd = fd
   of LOAD:
+    buffer.writeCommand(SET_LOAD_INFO, CONNECT)
     let code = buffer.setupSource()
-    buffer.load()
+    if code != -2:
+      buffer.writeCommand(SET_LOAD_INFO, DOWNLOAD)
+      buffer.load()
     buffer.writeCommand(LOAD_DONE, code)
   of GOTO_ANCHOR:
     var anchor: string
@@ -743,7 +750,10 @@ proc readCommand(buffer: Buffer) =
     else:
       buffer.writeCommand(ANCHOR_FAIL)
   of RENDER:
+    buffer.writeCommand(SET_LOAD_INFO, LoadInfo.RENDER)
     buffer.render()
+    buffer.writeCommand(SET_LOAD_INFO, DONE)
+    buffer.writeCommand(SET_NUM_LINES, buffer.lines.len)
     buffer.gotoAnchor()
   of GET_LINES:
     var w: Slice[int]
@@ -826,7 +836,7 @@ proc readCommand(buffer: Buffer) =
 
 proc runBuffer(buffer: Buffer, rfd: int) =
   block loop:
-    while true:
+    while buffer.alive:
       let events = buffer.selector.select(-1)
       for event in events:
         if Read in event.events:
@@ -842,6 +852,8 @@ proc runBuffer(buffer: Buffer, rfd: int) =
             break loop
           elif event.fd == buffer.getFd():
             buffer.finishLoad()
+      if not buffer.alive:
+        break loop
       if buffer.reshape:
         buffer.reshape = false
         buffer.render()
@@ -854,14 +866,16 @@ proc runBuffer(buffer: Buffer, rfd: int) =
 proc launchBuffer*(config: BufferConfig, source: BufferSource,
                    attrs: WindowAttributes, loader: FileLoader,
                    mainproc: Pid) =
-  let buffer = new Buffer
-  buffer.userstyle = parseStylesheet(config.userstyle)
-  buffer.attrs = attrs
+  let buffer = Buffer(
+    alive: true,
+    userstyle: parseStylesheet(config.userstyle),
+    attrs: attrs,
+    config: config,
+    loader: loader,
+    bsource: source,
+    sstream: newStringStream()
+  )
   buffer.windowChange()
-  buffer.sstream = newStringStream()
-  buffer.config = config
-  buffer.loader = loader
-  buffer.bsource = source
   buffer.selector = newSelector[int]()
   let sstream = connectSocketStream(mainproc, false)
   sstream.swrite(getpid())
diff --git a/src/buffer/container.nim b/src/buffer/container.nim
index cd321b48..b1f73629 100644
--- a/src/buffer/container.nim
+++ b/src/buffer/container.nim
@@ -34,7 +34,7 @@ type
 
   ContainerEventType* = enum
     NO_EVENT, FAIL, SUCCESS, NEEDS_AUTH, REDIRECT, ANCHOR, NO_ANCHOR, UPDATE,
-    READ_LINE, OPEN, INVALID_COMMAND
+    READ_LINE, OPEN, INVALID_COMMAND, STATUS
 
   ContainerEvent* = object
     case t*: ContainerEventType
@@ -65,10 +65,10 @@ type
     bpos: seq[CursorPosition]
     highlights: seq[Highlight]
     parent*: Container
-    sourcepair*: Container
     istream*: Stream
     ostream*: Stream
     process*: Pid
+    loadinfo*: string
     lines: SimpleFlexibleGrid
     lineshift: int
     numLines*: int
@@ -76,14 +76,14 @@ type
     code*: int
     retry*: seq[URL]
     redirect*: Option[URL]
-    ispipe: bool
     hlon*: bool
+    sourcepair*: Container
     pipeto: Container
     redraw*: bool
-    sourceready*: bool
     cmdvalid: array[ContainerCommand, bool]
+    needslines*: bool
 
-proc newBuffer*(dispatcher: Dispatcher, config: Config, source: BufferSource, ispipe = false, autoload = true): Container =
+proc newBuffer*(dispatcher: Dispatcher, config: Config, source: BufferSource, title = ""): Container =
   let attrs = getWindowAttributes(stdout)
   let ostream = dispatcher.forkserver.ostream
   let istream = dispatcher.forkserver.istream
@@ -96,7 +96,7 @@ proc newBuffer*(dispatcher: Dispatcher, config: Config, source: BufferSource, is
   result = Container(
     source: source, attrs: attrs, width: attrs.width,
     height: attrs.height - 1, contenttype: source.contenttype,
-    ispipe: ispipe
+    title: title
   )
   result.cmdvalid[BUFFER_READY] = true
   istream.sread(result.process)
@@ -179,8 +179,6 @@ func maxScreenWidth(container: Container): int =
 func getTitle*(container: Container): string =
   if container.title != "":
     return container.title
-  if container.ispipe:
-    return "*pipe*"
   return container.source.location.serialize(excludepassword = true)
 
 func currentLineWidth(container: Container): int =
@@ -268,7 +266,7 @@ proc sendCursorPosition*(container: Container) =
 proc setFromY*(container: Container, y: int) {.jsfunc.} =
   if container.pos.fromy != y:
     container.pos.fromy = max(min(y, container.maxfromy), 0)
-    container.requestLines()
+    container.needslines = true
     container.redraw = true
 
 proc setFromX*(container: Container, x: int) {.jsfunc.} =
@@ -511,7 +509,7 @@ proc popCursorPos*(container: Container, nojump = false) =
   container.updateCursor()
   if not nojump:
     container.sendCursorPosition()
-    container.requestLines()
+    container.needslines = true
 
 macro proxy(fun: typed) =
   let name = fun[0] # sym
@@ -558,10 +556,13 @@ proc cursorPrevMatch*(container: Container, regex: Regex, wrap: bool) {.jsfunc.}
 proc load*(container: Container) =
   container.writeCommand(LOAD)
   container.expect(LOAD_DONE)
+  container.expect(SET_LOAD_INFO)
   container.expect(SET_NEEDS_AUTH)
   container.expect(SET_REDIRECT)
   container.expect(SET_CONTENT_TYPE)
   container.expect(SET_TITLE)
+  if container.source.location.anchor != "":
+    container.expect(JUMP)
 
 proc gotoAnchor*(container: Container, anchor: string) =
   container.writeCommand(GOTO_ANCHOR, anchor)
@@ -574,9 +575,10 @@ proc readSuccess*(container: Container, s: string) {.proxy.} = discard
 proc reshape*(container: Container, noreq = false) {.jsfunc.} =
   container.writeCommand(RENDER)
   container.expect(RESHAPE)
+  container.expect(SET_NUM_LINES)
   container.expect(JUMP)
   if not noreq:
-    container.requestLines()
+    container.needslines = true
 
 proc dupeBuffer*(dispatcher: Dispatcher, container: Container, config: Config, location = none(URL), contenttype = none(string)): Container =
   let source = BufferSource(
@@ -585,7 +587,7 @@ proc dupeBuffer*(dispatcher: Dispatcher, container: Container, config: Config, l
     contenttype: if contenttype.isSome: contenttype else: container.contenttype,
     clonepid: container.process,
   )
-  container.pipeto = dispatcher.newBuffer(config, source, container.ispipe)
+  container.pipeto = dispatcher.newBuffer(config, source, container.title)
   container.writeCommand(GET_SOURCE)
   container.expect(SOURCE_READY)
   return container.pipeto
@@ -611,12 +613,29 @@ proc clearSearchHighlights*(container: Container) =
 proc handleCommand(container: Container, cmd: ContainerCommand, len: int): ContainerEvent =
   if not container.cmdvalid[cmd]:
     let len = len - sizeof(cmd)
-    #TODO TODO TODO this is very dumb
+    #TODO TODO TODO
     for i in 0 ..< len:
       discard container.istream.readChar()
-    return ContainerEvent(t: INVALID_COMMAND)
+    if cmd != RESHAPE:
+      return ContainerEvent(t: INVALID_COMMAND)
   container.cmdvalid[cmd] = false
   case cmd
+  of SET_LOAD_INFO:
+    var li: LoadInfo
+    container.istream.sread(li)
+    case li
+    of CONNECT:
+      container.loadinfo = "Connecting to " & $container.source.location
+      container.expect(SET_LOAD_INFO)
+    of DOWNLOAD:
+      container.loadinfo = "Downloading " & $container.source.location
+      container.expect(SET_LOAD_INFO)
+    of RENDER:
+      container.loadinfo = "Rendering " & $container.source.location
+      container.expect(SET_LOAD_INFO)
+    of DONE:
+      container.loadinfo = ""
+    return ContainerEvent(t: STATUS)
   of SET_LINES:
     var w: Slice[int]
     container.istream.sread(container.numLines)
@@ -629,6 +648,8 @@ proc handleCommand(container: Container, cmd: ContainerCommand, len: int): Conta
     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:
       return ContainerEvent(t: UPDATE)
+  of SET_NUM_LINES:
+    container.istream.sread(container.numLines)
   of SET_NEEDS_AUTH:
     return ContainerEvent(t: NEEDS_AUTH)
   of SET_CONTENT_TYPE:
@@ -643,8 +664,10 @@ proc handleCommand(container: Container, cmd: ContainerCommand, len: int): Conta
       return ContainerEvent(t: REDIRECT)
   of SET_TITLE:
     container.istream.sread(container.title)
+    return ContainerEvent(t: STATUS)
   of SET_HOVER:
     container.istream.sread(container.hovertext)
+    return ContainerEvent(t: STATUS)
   of LOAD_DONE:
     container.istream.sread(container.code)
     if container.code == -2: return
@@ -652,10 +675,8 @@ proc handleCommand(container: Container, cmd: ContainerCommand, len: int): Conta
       return ContainerEvent(t: FAIL)
     return ContainerEvent(t: SUCCESS)
   of ANCHOR_FOUND:
-    container.cmdvalid[ANCHOR_FAIL] = false
     return ContainerEvent(t: ANCHOR)
   of ANCHOR_FAIL:
-    container.cmdvalid[ANCHOR_FOUND] = false
     return ContainerEvent(t: FAIL)
   of READ_LINE:
     var prompt, str: string
@@ -696,6 +717,8 @@ proc handleCommand(container: Container, cmd: ContainerCommand, len: int): Conta
       container.pipeto.load()
       container.pipeto = nil
   of RESHAPE:
+    container.needslines = true
+  if container.needslines:
     container.requestLines()
 
 # Synchronously read all lines in the buffer.