diff options
author | bptato <nincsnevem662@gmail.com> | 2024-10-13 20:39:52 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-10-13 21:09:18 +0200 |
commit | 4fb37158efa37a01a2ecc86be024c22202a879d0 (patch) | |
tree | d8dd7032eb37ef2e0aabbedf32968b7e3c0ee971 /adapter | |
parent | b773f053478dfae83719417b434f9e232d374b0b (diff) | |
download | chawan-4fb37158efa37a01a2ecc86be024c22202a879d0.tar.gz |
dirlist2html: fix heisenbug, refactor
so it turns out you *can't* just deref refcounted strings through a ptr... the entire algorithm was a mess anyway, so I've just re-done the sorting with refc.
Diffstat (limited to 'adapter')
-rw-r--r-- | adapter/format/dirlist2html.nim | 146 |
1 files changed, 74 insertions, 72 deletions
diff --git a/adapter/format/dirlist2html.nim b/adapter/format/dirlist2html.nim index a64eec9a..08981f20 100644 --- a/adapter/format/dirlist2html.nim +++ b/adapter/format/dirlist2html.nim @@ -9,9 +9,11 @@ import utils/twtstr type DirlistItemType = enum ditFile, ditLink, ditDir -type DirlistItem = object - name: string - modified: string +type DirlistItem = ref object + name: string # real name + dname: string # display name + width: int # display name width + modified: string # date last modified case t: DirlistItemType of ditLink: linkto: string @@ -20,30 +22,9 @@ type DirlistItem = object of ditDir: discard -type NameWidthTuple = tuple[name: string, width: int, item: ptr DirlistItem] - -func makeDirlist(items: seq[DirlistItem]): string = - var names: seq[NameWidthTuple] = @[] - var maxw = 20 +proc printDirlist(f: File; items: seq[DirlistItem]; maxw: int) = + f.writeLine("<a href=\"../\">[Upper Directory]</a>") for item in items: - var name = item.name - if item.t == ditLink: - name &= '@' - elif item.t == ditDir: - name &= '/' - let w = name.width() - maxw = max(w, maxw) - names.add((name, w, unsafeAddr item)) - names.sort(proc(a, b: NameWidthTuple): int = - if a.item.t == ditDir and b.item.t != ditDir: - return -1 - if a.item.t != ditDir and b.item.t == ditDir: - return 1 - return cmp(a.name, b.name) - ) - var outs = "<A HREF=\"../\">[Upper Directory]</A>\n" - for (name, width, itemp) in names.mitems: - let item = itemp[] var path = percentEncode(item.name, PathPercentEncodeSet) if item.t == ditLink: if item.linkto.len > 0 and item.linkto[^1] == '/': @@ -51,7 +32,8 @@ func makeDirlist(items: seq[DirlistItem]): string = path &= '/' elif item.t == ditDir: path &= '/' - var line = "<A HREF=\"" & path & "\">" & htmlEscape(name) & "</A>" + var line = "<a href=\"" & path & "\">" & htmlEscape(item.dname) & "</a>" + var width = item.width while width <= maxw: if width mod 2 == 0: line &= ' ' @@ -65,45 +47,25 @@ func makeDirlist(items: seq[DirlistItem]): string = line &= ' ' & convertSize(item.nsize) elif item.t == ditLink: line &= " -> " & htmlEscape(item.linkto) - outs &= line & '\n' - return outs + f.writeLine(line) proc usage() = stderr.write("Usage: dirlist2html [-t title]\n") quit(1) -proc main() = - # parse args - let H = paramCount() - var i = 1 - var title = "" - while i <= H: - let s = paramStr(i) - if s == "": - inc i - if s[0] != '-': - usage() - for j in 1 ..< s.len: - case s[j] - of 't': - inc i - if i > H: usage() - title = paramStr(i).percentDecode() - else: - usage() - inc i - if title != "": - stdout.write(""" -<!DOCTYPE html> -<head> -<title>""" & title.htmlEscape() & """</title> -</head> -<body> -<h1>""" & title.htmlEscape() & """</h1> -<pre>""") - var items: seq[DirlistItem] = @[] +proc addItem(items: var seq[DirlistItem]; item: DirlistItem; maxw: var int) = + if item.t == ditDir: + item.name &= '/' + item.dname = item.name + if item.t == ditLink: + item.dname &= '@' + item.width = item.dname.width() + maxw = max(item.width, maxw) + items.add(item) + +proc parseInput(f: File; items: var seq[DirlistItem]; maxw: var int) = var line: string - while stdin.readLine(line): + while f.readLine(line): if line.len == 0: continue var i = 10 # permission template skip_till_space = @@ -111,15 +73,13 @@ proc main() = inc i # link count i = line.skipBlanks(i) - while i < line.len and line[i] in AsciiDigit: - inc i + skip_till_space # owner i = line.skipBlanks(i) skip_till_space # group i = line.skipBlanks(i) - while i < line.len and line[i] != ' ': - inc i + skip_till_space # size i = line.skipBlanks(i) var sizes = "" @@ -141,32 +101,74 @@ proc main() = if line[^1] == '\r': dec j let name = line.substr(i, j - 1) - if name == "." or name == "..": continue + if name == "." or name == "..": + continue case line[0] of 'l': # link let linki = name.find(" -> ") let linkfrom = name.substr(0, linki - 1) let linkto = name.substr(linki + 4) # you? - items.add(DirlistItem( + items.addItem(DirlistItem( t: ditLink, name: linkfrom, modified: dates, linkto: linkto - )) + ), maxw) of 'd': # directory - items.add(DirlistItem( + items.addItem(DirlistItem( t: ditDir, name: name, modified: dates - )) + ), maxw) else: # file - items.add(DirlistItem( + items.addItem(DirlistItem( t: ditFile, name: name, modified: dates, nsize: int(nsize) - )) - stdout.write(makeDirlist(items)) + ), maxw) + +proc parseArgs(title: var string) = + let H = paramCount() + var i = 1 + while i <= H: + let s = paramStr(i) + if s == "": + inc i + if s[0] != '-': + usage() + for j in 1 ..< s.len: + case s[j] + of 't': + inc i + if i > H: usage() + title = paramStr(i).percentDecode() + else: + usage() + inc i + +proc main() = + var title = "" + parseArgs(title) + stdout.write(""" +<!DOCTYPE html> +<head> +<title>""" & title.htmlEscape() & """</title> +</head> +<body> +<h1>""" & title.htmlEscape() & """</h1> +<pre>""") + var items: seq[DirlistItem] = @[] + var maxw = 20 + stdin.parseInput(items, maxw) + items.sort(proc(a, b: DirlistItem): int = + if a.t == ditDir and b.t != ditDir: + return -1 + if a.t != ditDir and b.t == ditDir: + return 1 + return cmp(a.dname, b.dname) + ) + stdout.printDirlist(items, maxw) stdout.write("</pre></body>") main() |