about summary refs log tree commit diff stats
path: root/src/io
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2021-12-26 22:17:24 +0100
committerbptato <nincsnevem662@gmail.com>2021-12-26 22:17:24 +0100
commit647089a99e3c44c4115274a8822ca0a4dd947d67 (patch)
tree1fa85f4e12676ef8532ff2c9eaaa065a0bcd263a /src/io
parent9c688a75adcd647723a993f04cb964d62e7f05a4 (diff)
downloadchawan-647089a99e3c44c4115274a8822ca0a4dd947d67.tar.gz
Proper URL handling
Diffstat (limited to 'src/io')
-rw-r--r--src/io/buffer.nim49
-rw-r--r--src/io/cell.nim105
2 files changed, 87 insertions, 67 deletions
diff --git a/src/io/buffer.nim b/src/io/buffer.nim
index 56de9938..2610d9b1 100644
--- a/src/io/buffer.nim
+++ b/src/io/buffer.nim
@@ -1,6 +1,5 @@
-import os
+import options
 import terminal
-import uri
 import unicode
 
 import css/cascade
@@ -12,6 +11,7 @@ import io/cell
 import layout/box
 import render/renderdocument
 import render/rendertext
+import types/url
 import utils/twtstr
 
 type
@@ -34,7 +34,7 @@ type
     redraw*: bool
     reshape*: bool
     nostatus*: bool
-    location*: Uri
+    location*: Url
     target*: string
     source*: string
     showsource*: bool
@@ -151,9 +151,7 @@ func generateSwapOutput(buffer: Buffer): string =
   #if text.len > 0:
   #  result &= $text
 
-func generateStatusMessage(buffer: Buffer): string =
-  result &= HVP(buffer.height + 1, 1)
-  result &= SGR()
+func generateStatusMessage*(buffer: Buffer): string =
   var formatting = newFormatting()
   var w = 0
   for cell in buffer.statusmsg:
@@ -162,7 +160,6 @@ func generateStatusMessage(buffer: Buffer): string =
     w += cell.width()
   if w < buffer.width:
     result &= EL()
-  result &= SGR()
 
 func numLines*(buffer: Buffer): int = buffer.lines.len
 
@@ -259,6 +256,14 @@ func atPercentOf(buffer: Buffer): int =
 func hasAnchor*(buffer: Buffer, anchor: string): bool =
   return buffer.document.getElementById(anchor) != nil
 
+func getTitle(buffer: Buffer): string =
+  let titles = buffer.document.getElementsByTag(TAG_TITLE)
+  if titles.len > 0:
+    for text in titles[0].textNodes:
+      result &= text.data.strip().clearControls()
+  else:
+    result = $buffer.location
+
 proc clearDisplay(buffer: Buffer) =
   buffer.prevdisplay = buffer.display
   buffer.display = newFixedGrid(buffer.width, buffer.height)
@@ -645,11 +650,11 @@ proc gotoAnchor*(buffer: Buffer) =
         return
       inc i
 
-proc setLocation*(buffer: Buffer, uri: Uri) =
-  buffer.location = uri
+proc setLocation*(buffer: Buffer, location: Url) =
+  buffer.location = location
 
-proc gotoLocation*(buffer: Buffer, uri: Uri) =
-  buffer.location = buffer.location.combine(uri)
+proc gotoLocation*(buffer: Buffer, s: string) =
+  discard parseUrl(s, buffer.location.some, buffer.location, true)
 
 proc refreshTermAttrs*(buffer: Buffer): bool =
   let newAttrs = getTermAttributes()
@@ -668,21 +673,6 @@ 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:
@@ -701,7 +691,7 @@ proc updateHover(buffer: Buffer) =
     let link = nodes.getLink()
     if link != nil:
       if link.tagType == TAG_A:
-        buffer.hovertext = $buffer.location.mergeUri(parseUri(HTMLAnchorElement(link).href))
+        buffer.hovertext = parseUrl(HTMLAnchorElement(link).href, buffer.location.some).serialize()
     else:
       buffer.hovertext = ""
     for node in buffer.prevnodes:
@@ -767,7 +757,10 @@ proc displayBuffer(buffer: Buffer) =
   print(buffer.generateFullOutput())
 
 proc displayStatusMessage*(buffer: Buffer) =
+  print(HVP(buffer.height + 1, 1))
+  print(SGR())
   print(buffer.generateStatusMessage())
+  print(SGR())
 
 proc click*(buffer: Buffer): string =
   let link = buffer.getCursorLink()
@@ -790,7 +783,7 @@ proc drawBuffer*(buffer: Buffer) =
       print(line.str.substr(x, line.str.len) & '\n')
 
 proc refreshBuffer*(buffer: Buffer) =
-  buffer.title = $buffer.location
+  buffer.title = buffer.getTitle()
   stdout.hideCursor()
 
   if buffer.refreshTermAttrs():
diff --git a/src/io/cell.nim b/src/io/cell.nim
index f477bafd..f5fb9721 100644
--- a/src/io/cell.nim
+++ b/src/io/cell.nim
@@ -1,11 +1,12 @@
-import unicode
-import strutils
 import sequtils
+import streams
+import strutils
 import sugar
+import unicode
 
+import html/dom
 import types/color
 import utils/twtstr
-import html/dom
 
 type
   FormatFlags* = enum
@@ -48,13 +49,6 @@ const FormatCodes: array[FormatFlags, tuple[s: int, e: int]] = [
   FLAG_OVERLINE: (53, 55),
 ]
 
-func bold(formatting: Formatting): bool = FLAG_BOLD in formatting.flags
-func italic(formatting: Formatting): bool = FLAG_ITALIC in formatting.flags
-func underline(formatting: Formatting): bool = FLAG_UNDERLINE in formatting.flags
-func reverse(formatting: Formatting): bool = FLAG_REVERSE in formatting.flags
-func strike(formatting: Formatting): bool = FLAG_STRIKE in formatting.flags
-func overline(formatting: Formatting): bool = FLAG_OVERLINE in formatting.flags
-
 template flag_template(formatting: Formatting, val: bool, flag: FormatFlags) =
   if val: formatting.flags.incl(flag)
   else: formatting.flags.excl(flag)
@@ -140,6 +134,9 @@ proc add*(a: var FlexibleLine, b: FlexibleLine) =
 proc addLine*(grid: var FlexibleGrid) =
   grid.add(FlexibleLine())
 
+proc addFormat*(line: var FlexibleLine, pos: int, format: Formatting) =
+  line.formats.add(FormattingCell(formatting: format, pos: line.str.len))
+
 proc addFormat*(grid: var FlexibleGrid, y, pos: int, format: Formatting) =
   grid[y].formats.add(FormattingCell(formatting: format, pos: grid[y].str.len))
 
@@ -157,35 +154,7 @@ template inc_check(i: int) =
   if i >= buf.len:
     return i
 
-proc parseAnsiCode*(formatting: var Formatting, buf: string, fi: int): int =
-  var i = fi
-  if buf[i] != '\e':
-    return i
-
-  inc_check i
-  if 0x40 <= int(buf[i]) and int(buf[i]) <= 0x5F:
-    if buf[i] != '[':
-      #C1, TODO?
-      return
-    inc_check i
-
-  let sp = i
-  #parameter bytes
-  while 0x30 <= int(buf[i]) and int(buf[i]) <= 0x3F:
-    inc_check i
-  let params = buf.substr(sp, i - 1)
-
-  let si = i
-  #intermediate bytes
-  while 0x20 <= int(buf[i]) and int(buf[i]) <= 0x2F:
-    inc_check i
-  #let interm = buf.substr(si, i)
-
-  let final = buf[i]
-  #final byte
-  if 0x40 <= int(buf[i]) and int(buf[i]) <= 0x7E:
-    inc_check i
-
+proc handleAnsiCode(formatting: var Formatting, final: char, params: string) =
   case final
   of 'm':
     if params.len == 0:
@@ -257,8 +226,66 @@ proc parseAnsiCode*(formatting: var Formatting, buf: string, fi: int): int =
       except ValueError: discard
   else: discard
 
+proc parseAnsiCode*(formatting: var Formatting, buf: string, fi: int): int =
+  var i = fi
+  if buf[i] != '\e':
+    return i
+
+  inc_check i
+  if 0x40 <= int(buf[i]) and int(buf[i]) <= 0x5F:
+    if buf[i] != '[':
+      #C1, TODO?
+      return
+    inc_check i
+
+  let sp = i
+  #parameter bytes
+  while 0x30 <= int(buf[i]) and int(buf[i]) <= 0x3F:
+    inc_check i
+  let params = buf.substr(sp, i - 1)
+
+  let si = i
+  #intermediate bytes
+  while 0x20 <= int(buf[i]) and int(buf[i]) <= 0x2F:
+    inc_check i
+  #let interm = buf.substr(si, i)
+
+  let final = buf[i]
+  #final byte
+  if 0x40 <= int(buf[i]) and int(buf[i]) <= 0x7E:
+    formatting.handleAnsiCode(final, params)
+
   return i
 
+proc parseAnsiCode*(formatting: var Formatting, stream: Stream) =
+  if stream.atEnd(): return
+  var c = stream.readChar()
+  if 0x40 <= int(c) and int(c) <= 0x5F:
+    if c != '[':
+      #C1, TODO?
+      return
+    if stream.atEnd(): return
+    c = stream.readChar()
+
+  var params = $c
+  #parameter bytes
+  while 0x30 <= int(c) and int(c) <= 0x3F:
+    params &= c
+    if stream.atEnd(): return
+    c = stream.readChar()
+
+  #intermediate bytes
+  #var interm = $c
+  while 0x20 <= int(c) and int(c) <= 0x2F:
+    #interm &= c
+    if stream.atEnd(): return
+    c = stream.readChar()
+
+  #final byte
+  if 0x40 <= int(c) and int(c) <= 0x7E:
+    let final = c
+    formatting.handleAnsiCode(final, params)
+
 proc processFormatting*(formatting: var Formatting, cellf: Formatting): string =
   for flag in FormatFlags:
     if flag in formatting.flags and flag notin cellf.flags: