about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2021-12-21 22:14:26 +0100
committerbptato <nincsnevem662@gmail.com>2021-12-21 22:33:57 +0100
commit8ea2c50b0d869228a28e132a6a053c52a8222fec (patch)
tree3032d1be5b401874ebeffa2f1d068bad6ab1bd35 /src
parent0440397664d7561e2dd6e21afc1c1128e3dd45b5 (diff)
downloadchawan-8ea2c50b0d869228a28e132a6a053c52a8222fec.tar.gz
Use a linked list for buffers, allow pipe as output
Diffstat (limited to 'src')
-rw-r--r--src/client.nim126
-rw-r--r--src/io/buffer.nim30
2 files changed, 77 insertions, 79 deletions
diff --git a/src/client.nim b/src/client.nim
index ca2ad00c..e9d8ef17 100644
--- a/src/client.nim
+++ b/src/client.nim
@@ -2,7 +2,6 @@ import httpclient
 import streams
 import uri
 import terminal
-import os
 
 import io/buffer
 import io/lineedit
@@ -14,8 +13,7 @@ import utils/twtstr
 type
   Client* = ref object
     http: HttpClient
-    buffers: seq[Buffer]
-    currentbuffer: int
+    buffer: Buffer
     feednext: bool
     s: string
 
@@ -26,24 +24,6 @@ proc die() =
 proc newClient*(): Client =
   new(result)
   result.http = newHttpClient()
-  result.currentbuffer = -1
-
-func pbuffer(client: Client): Buffer =
-  if client.currentbuffer > 0:
-    return client.buffers[client.currentbuffer - 1]
-  return nil
-
-func buffer(client: Client): Buffer =
-  return client.buffers[client.currentbuffer]
-
-func nbuffer(client: Client): Buffer =
-  if client.currentbuffer < client.buffers.len - 1:
-    return client.buffers[client.currentbuffer + 1]
-  return nil
-
-func puri(client: Client): Uri =
-  if client.currentbuffer > 0:
-    return client.pbuffer.location
 
 proc loadRemotePage*(client: Client, url: string): string =
   return client.http.getContent(url)
@@ -66,39 +46,45 @@ proc getPageUri(client: Client, uri: Uri): Stream =
     return client.getRemotePage($moduri)
 
 proc addBuffer(client: Client) =
-  inc client.currentbuffer
-  client.buffers.insert(newBuffer(), client.currentbuffer)
+  let oldnext = client.buffer.next
+  client.buffer.next = newBuffer()
+  if oldnext != nil:
+    oldnext.prev = client.buffer.next
+  client.buffer.next.prev = client.buffer
+  client.buffer.next.next = oldnext
+  client.buffer = client.buffer.next
 
 proc prevBuffer(client: Client) =
-  if client.currentbuffer > 0:
-    dec client.currentbuffer
+  if client.buffer.prev != nil:
+    client.buffer = client.buffer.prev
     client.buffer.redraw = true
 
 proc nextBuffer(client: Client) =
-  if client.currentbuffer < client.buffers.len - 1:
-    inc client.currentbuffer
+  if client.buffer.next != nil:
+    client.buffer = client.buffer.next
     client.buffer.redraw = true
 
 proc discardBuffer(client: Client) =
-  if client.currentbuffer < client.buffers.len - 1:
-    client.buffers.delete(client.currentbuffer)
+  if client.buffer.next != nil:
+    client.buffer.next.prev = client.buffer.prev
+    client.buffer = client.buffer.next
     client.buffer.redraw = true
-  elif client.currentbuffer > 0:
-    client.buffers.delete(client.currentbuffer)
-    dec client.currentbuffer
+  elif client.buffer.prev != nil:
+    client.buffer.prev.next = client.buffer.next
+    client.buffer = client.buffer.prev
     client.buffer.redraw = true
   else:
     client.buffer.setStatusMessage("Can't discard last buffer!")
 
 proc setupBuffer(client: Client) =
   let buffer = client.buffer
-  buffer.document = parseHtml(newStringStream(client.buffer.source))
+  buffer.document = parseHtml(newStringStream(buffer.source))
   buffer.render()
   buffer.gotoAnchor()
+  buffer.location.anchor = ""
   buffer.redraw = true
 
 proc readPipe(client: Client) =
-  client.addBuffer()
   if not stdin.isatty:
     client.buffer.showsource = true
     try:
@@ -111,27 +97,14 @@ proc readPipe(client: Client) =
     die()
   client.setupBuffer()
 
-proc mergeURLs(client: Client, urla, urlb: Uri): Uri =
-  var moduri = urlb
-  if moduri.scheme == "":
-    moduri.scheme = urla.scheme
-  if moduri.scheme == "":
-    moduri.scheme = "file"
-  if moduri.hostname == "":
-    moduri.hostname = urla.hostname
-    if moduri.path == "":
-      moduri.path = urla.path
-    elif urla.path != "":
-      moduri.path = urla.path.splitFile().dir / moduri.path
-  return moduri
-
-proc gotoURL(client: Client, url: Uri) =
-  var newuri = url
-  client.addBuffer()
-  newuri = client.mergeUrls(client.puri, newuri)
+proc gotoURL_impl(client: Client, uri: Uri) {.inline.} =
+  var olduri: Uri
+  if client.buffer.prev != nil:
+    olduri = client.buffer.prev.location
+  var newuri = olduri.mergeUri(uri)
   let newanchor = newuri.anchor
   newuri.anchor = ""
-  if client.puri != newuri or newanchor == "":
+  if client.buffer.prev == nil or client.buffer.prev.location != newuri or newanchor == "":
     let s = client.getPageUri(newuri)
     if s != nil:
       client.buffer.source = s.readAll() #TODO
@@ -140,26 +113,28 @@ proc gotoURL(client: Client, url: Uri) =
       client.buffer.setStatusMessage("Couldn't load " & $newuri)
       return
   elif newanchor != "":
-    if not client.pbuffer.hasAnchor(newanchor):
+    if not client.buffer.prev.hasAnchor(newanchor):
       client.discardBuffer()
       client.buffer.setStatusMessage("Couldn't find anchor " & newanchor)
       return
-    client.buffer.source = client.pbuffer.source
+    client.buffer.source = client.buffer.prev.source
     newuri.anchor = newanchor
   client.buffer.setLocation(newuri)
   client.setupBuffer()
 
+proc gotoURL(client: Client, url: Uri) =
+  client.addBuffer()
+  client.gotoURL_impl(url)
+
 proc gotoURL(client: Client, url: string) =
   client.gotoURL(parseUri(url))
 
 proc reloadPage(client: Client) =
-  let buffer = client.buffer
-  var location = buffer.location
-  location.anchor = ""
-  client.gotoURL(location)
-  client.buffer.setCursorXY(client.pbuffer.cursorx, client.pbuffer.cursory)
-  client.buffer.setFromXY(client.pbuffer.fromx, client.pbuffer.fromy)
-  client.buffer.showsource = client.pbuffer.showsource
+  let pbuffer = client.buffer
+  client.gotoURL("")
+  client.buffer.setCursorXY(pbuffer.cursorx, pbuffer.cursory)
+  client.buffer.setFromXY(pbuffer.fromx, pbuffer.fromy)
+  client.buffer.showsource = pbuffer.showsource
 
 proc changeLocation(client: Client) =
   let buffer = client.buffer
@@ -178,16 +153,12 @@ proc click(client: Client) =
 proc toggleSource*(client: Client) =
   let buffer = client.buffer
   if buffer.sourcepair != nil:
-    for i in 0..high(client.buffers):
-      if client.buffers[i] == buffer.sourcepair:
-        client.currentbuffer = i
-        break
-    eprint "Fatal error (???)"
+    client.buffer = buffer.sourcepair
   else:
     client.addBuffer()
-    client.buffer.sourcepair = client.pbuffer
-    client.buffer.source = client.pbuffer.source
-    client.buffer.showsource = not client.pbuffer.showsource
+    client.buffer.sourcepair = client.buffer.prev
+    client.buffer.source = client.buffer.prev.source
+    client.buffer.showsource = not client.buffer.prev.showsource
     client.setupBuffer()
 
 proc input(client: Client) =
@@ -247,11 +218,16 @@ proc input(client: Client) =
   else: discard
 
 proc launchClient*(client: Client, params: seq[string]) =
+  client.buffer = newBuffer()
   if params.len < 1:
     client.readPipe()
-  else: 
-    client.gotoURL(params[0])
+  else:
+    client.gotoURL_impl(parseUri(params[0]))
 
-  while true:
-    client.buffer.refreshBuffer()
-    client.input()
+  if stdout.isatty:
+    while true:
+      client.buffer.refreshBuffer()
+      client.input()
+  else:
+    client.buffer.height = client.buffer.numLines
+    client.buffer.drawBuffer()
diff --git a/src/io/buffer.nim b/src/io/buffer.nim
index 0c600441..3adaf985 100644
--- a/src/io/buffer.nim
+++ b/src/io/buffer.nim
@@ -3,6 +3,7 @@ import uri
 import strutils
 import unicode
 import streams
+import os
 
 import css/values
 import css/cascade
@@ -44,6 +45,8 @@ type
     rootbox*: CSSBox
     prevnodes*: seq[Node]
     sourcepair*: Buffer
+    prev*: Buffer
+    next* {.cursor.}: Buffer
 
 proc newBuffer*(): Buffer =
   new(result)
@@ -164,7 +167,7 @@ func generateStatusMessage(buffer: Buffer): string =
     result &= EL()
   result &= SGR()
 
-func numLines(buffer: Buffer): int = buffer.lines.len
+func numLines*(buffer: Buffer): int = buffer.lines.len
 
 func lastVisibleLine(buffer: Buffer): int = min(buffer.fromy + buffer.height, buffer.numLines)
 
@@ -759,6 +762,21 @@ proc updateCursor(buffer: Buffer) =
   if buffer.lines.len == 0:
     buffer.cursory = 0
 
+#TODO
+func mergeUri*(urla, urlb: Uri): Uri =
+  var moduri = urlb
+  if moduri.scheme == "":
+    moduri.scheme = urla.scheme
+  if moduri.scheme == "":
+    moduri.scheme = "file"
+  if moduri.hostname == "":
+    moduri.hostname = urla.hostname
+    if moduri.path == "":
+      moduri.path = urla.path
+    elif urla.path != "":
+      moduri.path = urla.path.splitFile().dir / moduri.path
+  return moduri
+
 proc updateHover(buffer: Buffer) =
   let nodes = buffer.currentDisplayCell().nodes
   if nodes != buffer.prevnodes:
@@ -777,7 +795,7 @@ proc updateHover(buffer: Buffer) =
     let link = nodes.getLink()
     if link != nil:
       if link.tagType == TAG_A:
-        buffer.hovertext = HTMLAnchorElement(link).href
+        buffer.hovertext = $buffer.location.mergeUri(parseUri(HTMLAnchorElement(link).href))
     else:
       buffer.hovertext = ""
     for node in buffer.prevnodes:
@@ -921,7 +939,12 @@ proc click*(buffer: Buffer): string =
       return HTMLAnchorElement(link).href
   return ""
 
+proc drawBuffer*(buffer: Buffer) =
+  buffer.refreshDisplay()
+  buffer.displayBuffer()
+
 proc refreshBuffer*(buffer: Buffer) =
+  buffer.title = $buffer.location
   stdout.hideCursor()
 
   if buffer.refreshTermAttrs():
@@ -929,8 +952,7 @@ proc refreshBuffer*(buffer: Buffer) =
     buffer.reshape = true
 
   if buffer.redraw:
-    buffer.refreshDisplay()
-    buffer.displayBuffer()
+    buffer.drawBuffer()
     buffer.redraw = false
 
   buffer.updateHover()