diff options
-rw-r--r-- | bonus/w3m.toml | 5 | ||||
-rw-r--r-- | res/config.toml | 5 | ||||
-rw-r--r-- | src/config/config.nim | 103 | ||||
-rw-r--r-- | src/css/cascade.nim | 21 | ||||
-rw-r--r-- | src/types/color.nim | 58 |
5 files changed, 133 insertions, 59 deletions
diff --git a/bonus/w3m.toml b/bonus/w3m.toml index 55c792f0..3fad5fea 100644 --- a/bonus/w3m.toml +++ b/bonus/w3m.toml @@ -67,7 +67,10 @@ C-s = 'pager.searchForward()' C-r = 'pager.searchBackward()' n = 'pager.searchNext()' N = 'pager.searchPrev()' -C-w = 'config.searchwrap = !config.searchwrap; pager.alert("Wrap search " + (config.searchwrap ? "on" : "off"))' +C-w = ''' +config.search.wrap = !config.search.wrap; +pager.alert("Wrap search " + (config.search.wrap ? "on" : "off")); +''' # Misc #TODO shell out, help file, options, cookies C-c = 'pager.cancel()' diff --git a/res/config.toml b/res/config.toml index c8b0091a..36d694fb 100644 --- a/res/config.toml +++ b/res/config.toml @@ -123,7 +123,10 @@ n = 'pager.searchNext()' N = 'pager.searchPrev()' c = 'pager.peek()' u = 'pager.peekCursor()' -C-w = 'config.searchwrap = !config.searchwrap; pager.alert("Wrap search " + (config.searchwrap ? "on" : "off"))' +C-w = ''' +config.search.wrap = !config.search.wrap; +pager.alert("Wrap search " + (config.search.wrap ? "on" : "off")); +''' [line] C-m = 'line.submit()' diff --git a/src/config/config.nim b/src/config/config.nim index 0eb2911b..9c2cd0a8 100644 --- a/src/config/config.nim +++ b/src/config/config.nim @@ -66,62 +66,62 @@ type substitute_url*: (proc(s: string): Result[string, JSError]) StartConfig = object - visual_home*: string - startup_script*: string - headless*: bool + visual_home* {.jsgetset.}: string + startup_script* {.jsgetset.}: string + headless* {.jsgetset.}: bool CSSConfig = object - stylesheet*: string + stylesheet* {.jsgetset.}: string SearchConfig = object - wrap*: bool + wrap* {.jsgetset.}: bool EncodingConfig = object - display_charset*: Opt[Charset] - document_charset*: seq[Charset] + display_charset* {.jsgetset.}: Opt[Charset] + document_charset* {.jsgetset.}: seq[Charset] ExternalConfig = object - tmpdir*: string - editor*: string - mailcap*: seq[string] - mime_types*: seq[string] + tmpdir* {.jsgetset.}: string + editor* {.jsgetset.}: string + mailcap* {.jsgetset.}: seq[string] + mime_types* {.jsgetset.}: seq[string] NetworkConfig = object - max_redirect*: int32 - prepend_https*: bool - proxy*: Opt[string] - default_headers*: Table[string, string] + max_redirect* {.jsgetset.}: int32 + prepend_https* {.jsgetset.}: bool + proxy* {.jsgetset.}: Opt[string] + default_headers* {.jsgetset.}: Table[string, string] DisplayConfig = object - color_mode*: Opt[ColorMode] - format_mode*: Opt[FormatMode] - no_format_mode*: FormatMode - emulate_overline*: bool - alt_screen*: Opt[bool] - highlight_color*: RGBAColor - double_width_ambiguous*: bool - minimum_contrast*: int32 - force_clear*: bool - set_title*: bool - default_background_color*: RGBColor - default_foreground_color*: RGBColor - - #TODO: add JS wrappers for objects + color_mode* {.jsgetset.}: Opt[ColorMode] + format_mode*: Opt[FormatMode] #TODO getset + no_format_mode*: FormatMode #TODO getset + emulate_overline* {.jsgetset.}: bool + alt_screen* {.jsgetset.}: Opt[bool] + highlight_color* {.jsgetset.}: RGBAColor + double_width_ambiguous* {.jsgetset.}: bool + minimum_contrast* {.jsgetset.}: int32 + force_clear* {.jsgetset.}: bool + set_title* {.jsgetset.}: bool + default_background_color* {.jsgetset.}: RGBColor + default_foreground_color* {.jsgetset.}: RGBColor + Config* = ref ConfigObj ConfigObj* = object - configdir: string - includes: seq[string] - start*: StartConfig - search*: SearchConfig - css*: CSSConfig - encoding*: EncodingConfig - external*: ExternalConfig - network*: NetworkConfig - display*: DisplayConfig + configdir {.jsget.}: string + includes {.jsget.}: seq[string] + start* {.jsget.}: StartConfig + search* {.jsget.}: SearchConfig + css* {.jsget.}: CSSConfig + encoding* {.jsget.}: EncodingConfig + external* {.jsget.}: ExternalConfig + network* {.jsget.}: NetworkConfig + display* {.jsget.}: DisplayConfig + #TODO getset siteconf: seq[StaticSiteConfig] omnirule: seq[StaticOmniRule] - page*: ActionMap - line*: ActionMap + page* {.jsget.}: ActionMap + line* {.jsget.}: ActionMap BufferConfig* = object userstyle*: string @@ -140,6 +140,13 @@ type tmpdir*: string ambiguous_double*: bool +jsDestructor(StartConfig) +jsDestructor(CSSConfig) +jsDestructor(SearchConfig) +jsDestructor(EncodingConfig) +jsDestructor(ExternalConfig) +jsDestructor(NetworkConfig) +jsDestructor(DisplayConfig) jsDestructor(Config) proc `[]=`(a: var ActionMap, b, c: string) {.borrow.} @@ -147,6 +154,7 @@ proc `[]`*(a: ActionMap, b: string): string {.borrow.} proc contains*(a: ActionMap, b: string): bool {.borrow.} proc getOrDefault(a: ActionMap, b: string): string {.borrow.} proc hasKeyOrPut(a: var ActionMap, b, c: string): bool {.borrow.} +proc toJS(ctx: JSContext, a: ActionMap): JSValue {.borrow.} func getForkServerConfig*(config: Config): ForkServerConfig = return ForkServerConfig( @@ -469,16 +477,16 @@ proc parseConfigValue(x: var RGBAColor, v: TomlValue, k: string) = typeCheck(v, VALUE_STRING, k) let c = parseRGBAColor(v.s) if c.isNone: - raise newException(ValueError, "invalid color '" & v.s & - "' for key " & k) + raise newException(ValueError, "invalid color '" & v.s & + "' for key " & k) x = c.get proc parseConfigValue(x: var RGBColor, v: TomlValue, k: string) = typeCheck(v, VALUE_STRING, k) let c = parseLegacyColor(v.s) if c.isNone: - raise newException(ValueError, "invalid color '" & v.s & - "' for key " & k) + raise newException(ValueError, "invalid color '" & v.s & + "' for key " & k) x = c.get proc parseConfigValue[T](x: var Opt[T], v: TomlValue, k: string) = @@ -576,4 +584,11 @@ proc readConfig*(): Config = result.readConfig(getConfigDir() / "chawan") proc addConfigModule*(ctx: JSContext) = + ctx.registerType(StartConfig) + ctx.registerType(CSSConfig) + ctx.registerType(SearchConfig) + ctx.registerType(EncodingConfig) + ctx.registerType(ExternalConfig) + ctx.registerType(NetworkConfig) + ctx.registerType(DisplayConfig) ctx.registerType(Config) diff --git a/src/css/cascade.nim b/src/css/cascade.nim index 53eff5cf..598e359f 100644 --- a/src/css/cascade.nim +++ b/src/css/cascade.nim @@ -122,9 +122,10 @@ func calcPresentationalHints(element: Element): CSSComputedValues = if s.isSome and s.get.num != 0: set_cv "height", s.get template map_bgcolor = - let c = parseLegacyColor(element.attr("bgcolor")) - if c.isSome: - set_cv "background-color", c.get + let s = element.attr("bgcolor") + if s != "": + let c = parseLegacyColor0(s) + set_cv "background-color", c template map_size = let s = element.attrul("size") if s.isSome: @@ -150,13 +151,15 @@ func calcPresentationalHints(element: Element): CSSComputedValues = set_cv "margin-left", CSSLengthAuto #TODO should be inline-start set_cv "margin-right", CSSLengthAuto #TODO should be inline-end template map_text = - let c = parseLegacyColor(element.attr("text")) - if c.isSome: - set_cv "color", c.get + let s = element.attr("text") + if s != "": + let c = parseLegacyColor0(s) + set_cv "color", c template map_color = - let c = parseLegacyColor(element.attr("color")) - if c.isSome: - set_cv "color", c.get + let s = element.attr("color") + if s != "": + let c = parseLegacyColor0(s) + set_cv "color", c template map_colspan = let colspan = element.attrulgz("colspan") if colspan.isSome: diff --git a/src/types/color.nim b/src/types/color.nim index e628b9ad..f96bfc49 100644 --- a/src/types/color.nim +++ b/src/types/color.nim @@ -2,6 +2,9 @@ import options import strutils import tables +import bindings/quickjs +import js/exception +import js/javascript import utils/twtstr type @@ -455,12 +458,12 @@ func parseRGBAColor*(s: string): Option[RGBAColor] = return parseHexColor(s[2..^1]) return parseHexColor(s) -func parseLegacyColor*(s: string): Option[RGBColor] = +func parseLegacyColor0*(s: string): RGBColor = if s == "": return let s = s.strip(chars = AsciiWhitespace) if s == "transparent": return if s in ColorsRGB: - return some(ColorsRGB[s]) + return ColorsRGB[s] block hex: if s.len == 4: for c in s: @@ -469,7 +472,7 @@ func parseLegacyColor*(s: string): Option[RGBColor] = let c = (hexValue(s[0]) * 17 shl 16) or (hexValue(s[1]) * 17 shl 8) or (hexValue(s[2]) * 17) - return some(RGBColor(c)) + return RGBColor(c) # Seriously, what the hell. var s2 = if s[0] == '#': s.substr(1) @@ -492,4 +495,51 @@ func parseLegacyColor*(s: string): Option[RGBColor] = (hexValue(c1[0]) shl 20) or (hexValue(c1[1]) shl 16) or (hexValue(c2[0]) shl 12) or (hexValue(c2[1]) shl 8) or (hexValue(c3[0]) shl 4) or hexValue(c3[1]) - return some(RGBColor(c)) + return RGBColor(c) + +func parseLegacyColor*(s: string): JSResult[RGBColor] = + if s == "": + return err(newTypeError("Color value must not be the empty string")) + return ok(parseLegacyColor0(s)) + +proc toJS*(ctx: JSContext, rgb: RGBColor): JSValue = + var res = "#" + res.pushHex(rgb.r) + res.pushHex(rgb.g) + res.pushHex(rgb.b) + return toJS(ctx, res) + +proc fromJS2*(ctx: JSContext, val: JSValue, o: var JSResult[RGBColor]) = + let s = fromJS[string](ctx, val) + if s.isSome: + o = parseLegacyColor(s.get) + else: + o.err(s.error) + +proc toJS*(ctx: JSContext, rgba: RGBAColor): JSValue = + var res = "#" + res.pushHex(rgba.r) + res.pushHex(rgba.g) + res.pushHex(rgba.b) + res.pushHex(rgba.a) + return toJS(ctx, res) + +proc fromJS2*(ctx: JSContext, val: JSValue, o: var JSResult[RGBAColor]) = + if JS_IsNumber(val): + # as hex + let x = fromJS[uint32](ctx, val) + if x.isSome: + o.ok(RGBAColor(x.get)) + else: + o.err(x.error) + else: + # parse + let s = fromJS[string](ctx, val) + if s.isSome: + let x = parseHexColor(s.get) + if x.isSome: + o.ok(x.get) + else: + o.err(newTypeError("Unrecognized color")) + else: + o.err(s.error) |