diff options
author | bptato <nincsnevem662@gmail.com> | 2021-12-26 23:50:12 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2021-12-26 23:50:12 +0100 |
commit | 2b1dac71b2886ede9950f4ef91e7a0eb7b3e5ed5 (patch) | |
tree | 0971b3625f6cbc9d978ccb1a01bf7fde815dd94b /src | |
parent | 647089a99e3c44c4115274a8822ca0a4dd947d67 (diff) | |
download | chawan-2b1dac71b2886ede9950f4ef91e7a0eb7b3e5ed5.tar.gz |
Basic content type implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/client.nim | 52 | ||||
-rw-r--r-- | src/css/parser.nim | 1 | ||||
-rw-r--r-- | src/io/buffer.nim | 44 | ||||
-rw-r--r-- | src/io/cell.nim | 2 | ||||
-rw-r--r-- | src/render/rendertext.nim | 11 | ||||
-rw-r--r-- | src/types/mime.nim | 25 |
6 files changed, 99 insertions, 36 deletions
diff --git a/src/client.nim b/src/client.nim index d0956126..23ebb9f3 100644 --- a/src/client.nim +++ b/src/client.nim @@ -7,9 +7,9 @@ import os import io/buffer import io/lineedit import config/config -import html/parser import utils/twtstr import css/sheet +import types/mime import types/url type @@ -91,27 +91,28 @@ proc discardBuffer(client: Client) = proc setupBuffer(client: Client) = let buffer = client.buffer + if not buffer.ispipe: + buffer.contenttype = guessContentType($buffer.location.path) buffer.userstyle = client.userstyle - buffer.document = parseHtml(newStringStream(buffer.source)) + buffer.load() buffer.render() buffer.gotoAnchor() buffer.redraw = true proc readPipe(client: Client) = client.buffer = newBuffer() - client.buffer.showsource = true - try: - while true: - client.buffer.source &= stdin.readChar() - except EOFError: - #TODO is this portable at all? - if reopen(stdin, "/dev/tty", fmReadWrite): - client.setupBuffer() - else: - client.buffer.drawBuffer() + client.buffer.contenttype = "text/plain" + client.buffer.ispipe = true + client.buffer.istream = newFileStream(stdin) + client.buffer.load() + #TODO is this portable at all? + if reopen(stdin, "/dev/tty", fmReadWrite): + client.setupBuffer() + else: + client.buffer.drawBuffer() var g_client: Client -proc gotoUrl(client: Client, url: string, prevurl = none(Url), force = false) = +proc gotoUrl(client: Client, url: string, prevurl = none(Url), force = false, newbuf = true) = var oldurl = prevurl if oldurl.isnone and client.buffer != nil: oldurl = client.buffer.location.some @@ -127,12 +128,14 @@ proc gotoUrl(client: Client, url: string, prevurl = none(Url), force = false) = try: let s = client.getPage(url) if s != nil: - client.addBuffer() - g_client = client - setControlCHook(proc() {.noconv.} = - g_client.discardBuffer() - interruptError()) - client.buffer.source = s.readAll() #TODO + if newbuf: + client.addBuffer() + g_client = client + setControlCHook(proc() {.noconv.} = + g_client.discardBuffer() + interruptError()) + client.buffer.istream = s + client.buffer.streamclosed = false else: loadError("Couldn't load " & $url) except IOError, OSError: @@ -144,7 +147,6 @@ proc gotoUrl(client: Client, url: string, prevurl = none(Url), force = false) = client.setupBuffer() else: loadError("Couldn't parse URL " & url) - eprint "none" proc loadUrl(client: Client, url: string) = let firstparse = parseUrl(url) @@ -160,10 +162,10 @@ proc loadUrl(client: Client, url: string) = proc reloadPage(client: Client) = let pbuffer = client.buffer - client.gotoUrl("", none(Url), true) + client.gotoUrl("", none(Url), true, false) client.buffer.setCursorXY(pbuffer.cursorx, pbuffer.cursory) client.buffer.setFromXY(pbuffer.fromx, pbuffer.fromy) - client.buffer.showsource = pbuffer.showsource + client.buffer.contenttype = pbuffer.contenttype proc changeLocation(client: Client) = let buffer = client.buffer @@ -189,7 +191,11 @@ proc toggleSource*(client: Client) = client.buffer.sourcepair = client.buffer.prev client.buffer.sourcepair.sourcepair = client.buffer client.buffer.source = client.buffer.prev.source - client.buffer.showsource = not client.buffer.prev.showsource + let prevtype = client.buffer.prev.contenttype + if prevtype == "text/html": + client.buffer.contenttype = "text/plain" + else: + client.buffer.contenttype = "text/html" client.setupBuffer() proc input(client: Client) = diff --git a/src/css/parser.nim b/src/css/parser.nim index 5bd2cf8b..c13018de 100644 --- a/src/css/parser.nim +++ b/src/css/parser.nim @@ -588,6 +588,7 @@ proc parseStylesheet(state: var CSSParseState): CSSRawStylesheet = proc parseStylesheet(inputStream: Stream): CSSRawStylesheet = var state = CSSParseState() state.tokens = tokenizeCSS(inputStream) + inputStream.close() return state.parseStylesheet() proc parseListOfRules(state: var CSSParseState): seq[CSSRule] = diff --git a/src/io/buffer.nim b/src/io/buffer.nim index 2610d9b1..a2d44b8c 100644 --- a/src/io/buffer.nim +++ b/src/io/buffer.nim @@ -1,4 +1,5 @@ import options +import streams import terminal import unicode @@ -6,6 +7,7 @@ import css/cascade import css/sheet import html/dom import html/tags +import html/parser import io/term import io/cell import layout/box @@ -16,6 +18,7 @@ import utils/twtstr type Buffer* = ref object + contenttype*: string title*: string lines*: FlexibleGrid display*: FixedGrid @@ -35,9 +38,10 @@ type reshape*: bool nostatus*: bool location*: Url - target*: string + ispipe*: bool + istream*: Stream + streamclosed*: bool source*: string - showsource*: bool rootbox*: CSSBox prevnodes*: seq[Node] sourcepair*: Buffer @@ -257,10 +261,14 @@ 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() + if buffer.document != nil: + let titles = buffer.document.getElementsByTag(TAG_TITLE) + if titles.len > 0: + for text in titles[0].textNodes: + result &= text.data.strip().clearControls() + return + if buffer.ispipe: + result = "*pipe*" else: result = $buffer.location @@ -707,11 +715,29 @@ proc updateHover(buffer: Buffer) = elem.refreshStyle() buffer.prevnodes = nodes -proc render*(buffer: Buffer) = - if buffer.showsource: - buffer.lines = renderPlainText(buffer.source) +proc load*(buffer: Buffer) = + case buffer.contenttype + of "text/html": + if not buffer.streamclosed: + #TODO not sure what to do with this. + #Ideally we could just throw away the source data after parsing but then + #source view won't work. Well we could still generate it... best would be a + #config option like a) store source b) generate source + buffer.source = buffer.istream.readAll() + buffer.istream.close() + buffer.document = parseHtml(newStringStream(buffer.source)) + buffer.streamclosed = true else: + if not buffer.streamclosed: + buffer.lines = renderStream(buffer.istream) + buffer.istream.close() + buffer.streamclosed = true + +proc render*(buffer: Buffer) = + case buffer.contenttype + of "text/html": buffer.lines = renderDocument(buffer.document, buffer.attrs, buffer.userstyle) + else: discard buffer.updateCursor() proc cursorBufferPos(buffer: Buffer) = diff --git a/src/io/cell.nim b/src/io/cell.nim index f5fb9721..fbe35268 100644 --- a/src/io/cell.nim +++ b/src/io/cell.nim @@ -244,7 +244,7 @@ proc parseAnsiCode*(formatting: var Formatting, buf: string, fi: int): int = inc_check i let params = buf.substr(sp, i - 1) - let si = i + #let si = i #intermediate bytes while 0x20 <= int(buf[i]) and int(buf[i]) <= 0x2F: inc_check i diff --git a/src/render/rendertext.nim b/src/render/rendertext.nim index 4c6b56ec..b5054e7b 100644 --- a/src/render/rendertext.nim +++ b/src/render/rendertext.nim @@ -16,9 +16,8 @@ proc renderPlainText*(text: string): FlexibleGrid = while i < text.len: case text[i] of '\n': - if i != text.len - 1: - add_format - result.addLine() + add_format + result.addLine() of '\r': discard of '\t': add_format @@ -35,6 +34,9 @@ proc renderPlainText*(text: string): FlexibleGrid = result[^1].str &= text[i] inc i + if result.len > 1 and result[^1].str.len == 0 and result[^1].formats.len == 0: + discard result.pop() + proc renderStream*(stream: Stream): FlexibleGrid = var format = newFormatting() template add_format() = @@ -64,3 +66,6 @@ proc renderStream*(stream: Stream): FlexibleGrid = else: add_format result[^1].str &= c + + if result.len > 1 and result[^1].str.len == 0 and result[^1].formats.len == 0: + discard result.pop() diff --git a/src/types/mime.nim b/src/types/mime.nim new file mode 100644 index 00000000..4dfe87e9 --- /dev/null +++ b/src/types/mime.nim @@ -0,0 +1,25 @@ +import tables + +const DefaultGuess = [ + ("html", "text/html"), + ("htm", "text/html"), + ("xhtml", "application/xhtml+xml"), + ("xhtm", "application/xhtml+xml"), + ("xht", "application/xhtml+xml"), +].toTable() + +proc guessContentType*(path: string): string = + var i = path.len - 1 + var n = 0 + while i > 0: + if path[i] == '/': + return "text/plain" + if path[i] == '.': + n = i + break + dec i + if n > 0: + let ext = path.substr(n + 1) + if ext in DefaultGuess: + return DefaultGuess[ext] + return "text/plain" |