diff options
author | bptato <nincsnevem662@gmail.com> | 2024-03-18 16:32:40 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-03-18 16:41:10 +0100 |
commit | 50ee9b03e320628b73d511c7d5ae217b07f00cce (patch) | |
tree | af1443a6dd310721dbf0a27d1f008a30b26f2cfa | |
parent | c0af45b47a78bc4d3f07d84b2e04d61e9ced75ac (diff) | |
download | chawan-50ee9b03e320628b73d511c7d5ae217b07f00cce.tar.gz |
config: parse mime.types/mailcap/urimethodmap inside parseConfig
Better (and simpler) than storing them all over the place. extra: change lmDownload text to match w3m
-rw-r--r-- | src/config/config.nim | 146 | ||||
-rw-r--r-- | src/config/mimetypes.nim | 6 | ||||
-rw-r--r-- | src/local/client.nim | 2 | ||||
-rw-r--r-- | src/local/pager.nim | 25 | ||||
-rw-r--r-- | src/utils/mimeguess.nim | 1 |
5 files changed, 76 insertions, 104 deletions
diff --git a/src/config/config.nim b/src/config/config.nim index b019ec70..23762c02 100644 --- a/src/config/config.nim +++ b/src/config/config.nim @@ -19,7 +19,6 @@ import types/cookie import types/opt import types/urimethodmap import types/url -import utils/mimeguess import utils/twtstr import chagashi/charset @@ -73,10 +72,10 @@ type ExternalConfig = object tmpdir* {.jsgetset.}: ChaPathResolved editor* {.jsgetset.}: string - mailcap* {.jsgetset.}: seq[ChaPathResolved] - mime_types* {.jsgetset.}: seq[ChaPathResolved] + mailcap*: Mailcap + mime_types*: MimeTypes cgi_dir* {.jsgetset.}: seq[ChaPathResolved] - urimethodmap* {.jsgetset.}: seq[ChaPathResolved] + urimethodmap*: URIMethodMap download_dir* {.jsgetset.}: string w3m_cgi_compat* {.jsgetset.}: bool @@ -280,85 +279,6 @@ proc readUserStylesheet(dir, file: string): string = result = s.readAll() s.close() -# The overall configuration will be obtained through the virtual concatenation -# of several individual configuration files known as mailcap files. -proc getMailcap*(config: Config): tuple[mailcap: Mailcap, errs: seq[string]] = - let configDir = config.configdir - template uq(s: string): string = - ChaPath(s).unquote.get - let gopherPath = "${%CHA_LIBEXEC_DIR}/gopher2html -u \\$MAILCAP_URL".uq - let geminiPath = "${%CHA_LIBEXEC_DIR}/gmi2html".uq - let mdPath = "${%CHA_LIBEXEC_DIR}/md2html".uq - let ansiPath = "${%CHA_LIBEXEC_DIR}/ansi2html".uq - var mailcap: Mailcap = @[] - var errs: seq[string] - var found = false - for p in config.external.mailcap: - let f = openFileExpand(configDir, p) - if f != nil: - let res = parseMailcap(f) - if res.isSome: - mailcap.add(res.get) - else: - errs.add(res.error) - found = true - mailcap.add(MailcapEntry( - mt: "text", - subt: "gopher", - cmd: gopherPath, - flags: {HTMLOUTPUT} - )) - mailcap.add(MailcapEntry( - mt: "text", - subt: "gemini", - cmd: geminiPath, - flags: {HTMLOUTPUT} - )) - mailcap.add(MailcapEntry( - mt: "text", - subt: "markdown", - cmd: mdPath, - flags: {HTMLOUTPUT} - )) - mailcap.add(MailcapEntry( - mt: "text", - subt: "x-ansi", - cmd: ansiPath, - flags: {HTMLOUTPUT} - )) - return (mailcap, errs) - -# We try to source mime types declared in config. -# If none of these files can be found, fall back to DefaultGuess. -#TODO some error handling would be nice, to at least show a warning to -# the user. Not sure how this could be done, though. -proc getMimeTypes*(config: Config): MimeTypes = - if config.external.mime_types.len == 0: - return DefaultGuess - var mimeTypes: MimeTypes - let configDir = config.configdir - var found = false - for p in config.external.mime_types: - let f = openFileExpand(configDir, p) - if f != nil: - mimeTypes.parseMimeTypes(f) - found = true - if not found: - return DefaultGuess - return mimeTypes - -const DefaultURIMethodMap = parseURIMethodMap(staticRead"res/urimethodmap") - -proc getURIMethodMap*(config: Config): URIMethodMap = - let configDir = config.configdir - var urimethodmap: URIMethodMap - for p in config.external.urimethodmap: - let f = openFileExpand(configDir, p) - if f != nil: - urimethodmap.parseURIMethodMap(f.readAll()) - urimethodmap.append(DefaultURIMethodMap) - return urimethodmap - proc getForkServerConfig*(config: Config): ForkServerConfig = return ForkServerConfig( tmpdir: config.external.tmpdir, @@ -416,6 +336,12 @@ proc parseConfigValue[T](ctx: var ConfigParser; x: var proc(x: T): JSResult[T]; v: TomlValue; k: string) proc parseConfigValue(ctx: var ConfigParser; x: var ChaPathResolved; v: TomlValue; k: string) +proc parseConfigValue(ctx: var ConfigParser; x: var MimeTypes; v: TomlValue; + k: string) +proc parseConfigValue(ctx: var ConfigParser; x: var Mailcap; v: TomlValue; + k: string) +proc parseConfigValue(ctx: var ConfigParser; x: var URIMethodMap; v: TomlValue; + k: string) proc typeCheck(v: TomlValue, vt: ValueType, k: string) = if v.vt != vt: @@ -659,9 +585,61 @@ proc parseConfigValue(ctx: var ConfigParser; x: var ChaPathResolved; raise newException(ValueError, y.error) x = ChaPathResolved(y.get) +proc parseConfigValue(ctx: var ConfigParser; x: var MimeTypes; v: TomlValue; + k: string) = + var paths: seq[ChaPathResolved] + ctx.parseConfigValue(paths, v, k) + x = default(MimeTypes) + for p in paths: + let f = openFileExpand(ctx.config.configdir, p) + if f != nil: + x.parseMimeTypes(f) + +proc parseConfigValue(ctx: var ConfigParser; x: var Mailcap; v: TomlValue; + k: string) = + var paths: seq[ChaPathResolved] + ctx.parseConfigValue(paths, v, k) + x = default(Mailcap) + for p in paths: + let f = openFileExpand(ctx.config.configdir, p) + if f != nil: + let res = parseMailcap(f) + if res.isSome: + x.add(res.get) + else: + ctx.warnings.add("Error reading mailcap: " & res.error) + template uq(s: string): string = + ChaPath(s).unquote.get + let defaultCmds = { + "gopher": "${%CHA_LIBEXEC_DIR}/gopher2html -u \\$MAILCAP_URL".uq, + "gemini": "${%CHA_LIBEXEC_DIR}/gmi2html".uq, + "markdown": "${%CHA_LIBEXEC_DIR}/md2html".uq, + "x-ansi":"${%CHA_LIBEXEC_DIR}/ansi2html".uq + } + for (subt, cmd) in defaultCmds: + x.add(MailcapEntry( + mt: "text", + subt: subt, + cmd: cmd, + flags: {HTMLOUTPUT} + )) + +const DefaultURIMethodMap = parseURIMethodMap(staticRead"res/urimethodmap") + +proc parseConfigValue(ctx: var ConfigParser; x: var URIMethodMap; v: TomlValue; + k: string) = + var paths: seq[ChaPathResolved] + ctx.parseConfigValue(paths, v, k) + x = default(URIMethodMap) + for p in paths: + let f = openFileExpand(ctx.config.configdir, p) + if f != nil: + x.parseURIMethodMap(f.readAll()) + x.append(DefaultURIMethodMap) + type ParseConfigResult* = object success*: bool - warnings*: seq[string] #TODO actually use warnings + warnings*: seq[string] errorMsg*: string proc parseConfig(config: Config; dir: string; stream: Stream; name = "<input>"; diff --git a/src/config/mimetypes.nim b/src/config/mimetypes.nim index 542bc267..e8a0fd07 100644 --- a/src/config/mimetypes.nim +++ b/src/config/mimetypes.nim @@ -4,7 +4,11 @@ import std/tables import utils/twtstr # extension -> type -type MimeTypes* = Table[string, string] +type MimeTypes* = distinct Table[string, string] + +proc `[]`*(mimeTypes: MimeTypes; k: string): string {.borrow.} +proc contains*(mimeTypes: MimeTypes; k: string): bool {.borrow.} +proc hasKeyOrPut*(mimeTypes: var MimeTypes; k, v: string): bool {.borrow.} # Add mime types found in stream to mimeTypes. # No error handling for now. diff --git a/src/local/client.nim b/src/local/client.nim index b59e1ef4..8b16339f 100644 --- a/src/local/client.nim +++ b/src/local/client.nim @@ -890,7 +890,7 @@ proc newClient*(config: Config; forkserver: ForkServer; jsctx: JSContext): JS_SetModuleLoaderFunc(jsrt, normalizeModuleName, clientLoadJSModule, nil) let pager = newPager(config, forkserver, jsctx) let loader = forkserver.newFileLoader(LoaderConfig( - urimethodmap: config.getURIMethodMap(), + urimethodmap: config.external.urimethodmap, w3mCGICompat: config.external.w3m_cgi_compat, cgiDir: seq[string](config.external.cgi_dir), tmpdir: config.external.tmpdir diff --git a/src/local/pager.nim b/src/local/pager.nim index f5dbff4b..7c986eff 100644 --- a/src/local/pager.nim +++ b/src/local/pager.nim @@ -14,7 +14,6 @@ when defined(posix): import bindings/libregexp import config/config import config/mailcap -import config/mimetypes import io/posixstream import io/promise import io/serialize @@ -42,7 +41,6 @@ import types/color import types/cookie import types/opt import types/referrer -import types/urimethodmap import types/url import types/winattrs import utils/strwidth @@ -62,7 +60,7 @@ type lmISearchF = "/" lmISearchB = "?" lmGotoLine = "Goto line: " - lmDownload = "(Download) Save file to: " + lmDownload = "(Download)Save file to: " # fdin is the original fd; fdout may be the same, or different if mailcap # is used. @@ -121,8 +119,6 @@ type linehist: array[LineMode, LineHistory] linemode: LineMode loader*: FileLoader - mailcap: Mailcap - mimeTypes: MimeTypes notnum*: bool # has a non-numeric character been input already? numload*: int # number of pages currently being loaded precnum*: int32 # current number prefix (when vi-numeric-prefix is true) @@ -136,7 +132,6 @@ type statusgrid*: FixedGrid term*: Terminal unreg*: seq[Container] - urimethodmap: URIMethodMap jsDestructor(Pager) @@ -277,18 +272,12 @@ proc quit*(pager: Pager, code = 0) = pager.dumpAlerts() proc newPager*(config: Config; forkserver: ForkServer; ctx: JSContext): Pager = - let (mailcap, errs) = config.getMailcap() let pager = Pager( config: config, forkserver: forkserver, - mailcap: mailcap, - mimeTypes: config.getMimeTypes(), proxy: config.getProxy(), - term: newTerminal(stdout, config), - urimethodmap: config.getURIMethodMap() + term: newTerminal(stdout, config) ) - for err in errs: - pager.alert("Error reading mailcap: " & err) return pager proc genClientKey(pager: Pager): ClientKey = @@ -1271,7 +1260,8 @@ type CheckMailcapResult = object # Pipe output of an x-ansioutput mailcap command to the text/x-ansi handler. proc ansiDecode(pager: Pager; url: URL; ishtml: var bool; fdin: cint): cint = - let entry = pager.mailcap.getMailcapEntry("text/x-ansi", "", url) + let entry = pager.config.external.mailcap.getMailcapEntry("text/x-ansi", "", + url) var canpipe = true let cmd = unquoteCommand(entry.cmd, "text/x-ansi", "", url, canpipe) if not canpipe: @@ -1483,7 +1473,8 @@ proc checkMailcap(pager: Pager; container: Container; stream: SocketStream; return CheckMailcapResult(connect: true, fdout: stream.fd, found: true) #TODO callback for outpath or something let url = container.url - let entry = pager.mailcap.getMailcapEntry(contentType, "", url) + let entry = pager.config.external.mailcap.getMailcapEntry(contentType, "", + url) if entry == nil: return CheckMailcapResult(connect: true, fdout: stream.fd, found: false) let ext = url.pathname.afterLast('.') @@ -1555,7 +1546,7 @@ proc fail(pager: Pager; container: Container; errorMessage: string) = proc redirect(pager: Pager; container: Container; response: Response; request: Request) = # still need to apply response, or we lose cookie jars. - container.applyResponse(response, pager.mimeTypes) + container.applyResponse(response, pager.config.external.mime_types) if container.redirectDepth < pager.config.network.max_redirect: if container.url.scheme == request.url.scheme or container.url.scheme == "cgi-bin" or @@ -1574,7 +1565,7 @@ proc redirect(pager: Pager; container: Container; response: Response; proc connected(pager: Pager; container: Container; response: Response) = let istream = response.body - container.applyResponse(response, pager.mimeTypes) + container.applyResponse(response, pager.config.external.mime_types) if response.status == 401: # unauthorized pager.setLineEdit(lmUsername) pager.lineData = LineDataAuth(url: container.url) diff --git a/src/utils/mimeguess.nim b/src/utils/mimeguess.nim index f13eaf89..5bbabcc1 100644 --- a/src/utils/mimeguess.nim +++ b/src/utils/mimeguess.nim @@ -1,6 +1,5 @@ import std/algorithm import std/streams -import std/tables import config/mimetypes |