about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config/config.nim6
-rw-r--r--src/config/toml.nim7
-rw-r--r--src/display/client.nim26
-rw-r--r--src/io/term.nim33
-rw-r--r--src/ips/serialize.nim7
-rw-r--r--src/types/color.nim1
6 files changed, 64 insertions, 16 deletions
diff --git a/src/config/config.nim b/src/config/config.nim
index 131571cb..c8002289 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -25,6 +25,7 @@ type
     colormode*: Option[ColorMode]
     formatmode*: Option[FormatMode]
     altscreen*: Option[bool]
+    mincontrast*: float
 
 func getRealKey(key: string): string =
   var realk: string
@@ -156,6 +157,11 @@ proc parseConfig(config: Config, dir: string, t: TomlValue) =
           config.hlcolor = parseRGBAColor(v.s).get
         of "double-width-ambiguous":
           config.ambiguous_double = v.b
+        of "minimum-contrast":
+          if v.vt == VALUE_INTEGER:
+            config.mincontrast = float(v.i)
+          else:
+            config.mincontrast = float(v.f)
 
 proc parseConfig(config: Config, dir: string, stream: Stream) =
   config.parseConfig(dir, parseToml(stream))
diff --git a/src/config/toml.nim b/src/config/toml.nim
index 03c17af5..7f743f09 100644
--- a/src/config/toml.nim
+++ b/src/config/toml.nim
@@ -299,8 +299,8 @@ proc consumeNoState(state: var TomlParser): bool =
     else: state.syntaxError(fmt"invalid character before key: {c}")
   state.syntaxError("unexpected end of file")
 
-proc consumeNumber(state: var TomlParser): TomlValue =
-  var repr: string
+proc consumeNumber(state: var TomlParser, c: char): TomlValue =
+  var repr = $c
   var isfloat = false
   if state.has():
     if state.peek(0) == '+' or state.peek(0) == '-':
@@ -334,6 +334,7 @@ proc consumeNumber(state: var TomlParser): TomlValue =
     let val = parseFloat64(repr)
     return TomlValue(vt: VALUE_FLOAT, f: val)
 
+  eprint repr
   let val = parseInt64(repr)
   return TomlValue(vt: VALUE_INTEGER, i: val)
 
@@ -370,7 +371,7 @@ proc consumeValue(state: var TomlParser): TomlValue =
     of '#':
       state.syntaxError("comment without value")
     of '+', '-', '0'..'9':
-      return state.consumeNumber()
+      return state.consumeNumber(c)
       #TODO date-time
     of '[':
       return state.consumeArray()
diff --git a/src/display/client.nim b/src/display/client.nim
index f4acaee4..05a5a0fc 100644
--- a/src/display/client.nim
+++ b/src/display/client.nim
@@ -246,16 +246,6 @@ proc inputLoop(client: Client) =
         if event.fd == client.console.tty.getFileHandle():
           client.input()
           stdout.flushFile()
-        elif event.fd in client.interval_fdis:
-          client.intervals[client.interval_fdis[event.fd]].handler()
-        elif event.fd in client.timeout_fdis:
-          let id = client.timeout_fdis[event.fd]
-          let timeout = client.timeouts[id]
-          timeout.handler()
-          client.clearTimeout(id)
-        elif event.fd == sigwinch:
-          client.attrs = getWindowAttributes(client.console.tty)
-          client.pager.windowChange(client.attrs)
         else:
           let container = client.fdmap[event.fd]
           if not client.pager.handleEvent(container):
@@ -263,10 +253,22 @@ proc inputLoop(client: Client) =
             for msg in client.pager.status:
               eprint msg
             client.quit(1)
-      elif Error in event.events:
+      if Error in event.events:
         eprint "Error", event
         #TODO handle errors
-      else: assert false
+      if Signal in event.events: 
+        if event.fd == sigwinch:
+          client.attrs = getWindowAttributes(client.console.tty)
+          client.pager.windowChange(client.attrs)
+        else: assert false
+      if Event.Timer in event.events:
+        if event.fd in client.interval_fdis:
+          client.intervals[client.interval_fdis[event.fd]].handler()
+        if event.fd in client.timeout_fdis:
+          let id = client.timeout_fdis[event.fd]
+          let timeout = client.timeouts[id]
+          timeout.handler()
+          client.clearTimeout(id)
     if client.pager.scommand != "":
       client.command(client.pager.scommand)
       client.pager.scommand = ""
diff --git a/src/io/term.nim b/src/io/term.nim
index 0406907d..518990e3 100644
--- a/src/io/term.nim
+++ b/src/io/term.nim
@@ -42,6 +42,7 @@ type
     cleared: bool
     prevgrid: FixedGrid
     attrs*: WindowAttributes
+    mincontrast: float
     colormode: ColorMode
     formatmode: FormatMode
     smcup: bool
@@ -162,6 +163,32 @@ proc disableAltScreen(term: Terminal): string =
   else:
     return RMCUP()
 
+proc distance(a, b: CellColor): float =
+  let a = if a.rgb:
+    a.rgbcolor
+  elif a == defaultColor:
+    ColorsRGB["black"]
+  else:
+    ANSIColorMap[a.color mod 10]
+  let b = if b.rgb:
+    b.rgbcolor
+  elif b == defaultColor:
+    ColorsRGB["white"]
+  else:
+    ANSIColorMap[b.color mod 10]
+  sqrt(float((a.r - b.r) ^  2 + (a.g - b.b) ^ 2 + (a.g - b.g) ^ 2))
+
+proc invert(color: CellColor, bg: bool): CellColor =
+  if color == defaultColor:
+    if bg:
+      return CellColor(rgb: true, rgbcolor: ColorsRGB["white"])
+    else:
+      return CellColor(rgb: true, rgbcolor: ColorsRGB["black"])
+  elif color.rgb:
+    return CellColor(rgb: true, rgbcolor: RGBColor(0xFFFFFF - uint32(color.rgbcolor)))
+  else:
+    return CellColor(rgb: true, rgbcolor: RGBColor(0xFFFFFF - uint32(ANSIColorMap[color.color mod 10])))
+
 # Use euclidian distance to quantize RGB colors.
 proc approximateANSIColor(rgb: RGBColor, exclude = -1): int =
   var a = 0
@@ -183,6 +210,11 @@ proc processFormat*(term: Terminal, format: var Format, cellf: Format): string =
         result &= SGR(FormatCodes[flag].e)
 
   var cellf = cellf
+  if term.mincontrast >= 0 and distance(cellf.bgcolor, cellf.fgcolor) <= term.mincontrast:
+    cellf.fgcolor = invert(cellf.fgcolor, false)
+    if distance(cellf.bgcolor, cellf.fgcolor) <= term.mincontrast:
+      cellf.fgcolor = defaultColor
+      cellf.bgcolor = defaultColor
   case term.colormode
   of ANSI, EIGHT_BIT:
     if cellf.bgcolor.rgb:
@@ -416,6 +448,7 @@ proc detectTermAttributes(term: Terminal) =
     term.formatmode = term.config.formatmode.get
   if term.config.altscreen.isSome:
     term.smcup = term.config.altscreen.get
+  term.mincontrast = term.config.mincontrast
 
 proc start*(term: Terminal, infile: File) =
   term.infile = infile
diff --git a/src/ips/serialize.nim b/src/ips/serialize.nim
index 2114cec0..9de0e374 100644
--- a/src/ips/serialize.nim
+++ b/src/ips/serialize.nim
@@ -5,6 +5,7 @@ import streams
 import tables
 
 import buffer/cell
+import config/bufferconfig
 import io/request
 import js/regex
 import types/buffersource
@@ -178,6 +179,9 @@ proc swrite*(stream: Stream, source: BufferSource) =
   stream.swrite(source.location)
   stream.swrite(source.contenttype)
 
+proc swrite*(stream: Stream, bconfig: BufferConfig) =
+  stream.swrite(bconfig.userstyle)
+
 template sread*[T](stream: Stream, o: T) =
   stream.read(o)
 
@@ -307,3 +311,6 @@ proc sread*(stream: Stream, source: var BufferSource) =
     stream.sread(source.fd)
   stream.sread(source.location)
   stream.sread(source.contenttype)
+
+proc sread*(stream: Stream, bconfig: var BufferConfig) =
+  stream.sread(bconfig.userstyle)
diff --git a/src/types/color.nim b/src/types/color.nim
index 9fc00edc..9d3994ff 100644
--- a/src/types/color.nim
+++ b/src/types/color.nim
@@ -32,7 +32,6 @@ func `==`*(color1, color2: CellColor): bool =
 
 const defaultColor* = CellColor(rgb: false, color: 0)
 
-const ANSIFGBlack* = CellColor(rgb: false, color: 38)
 const ColorsANSIFg* = [
   CellColor(rgb: false, color: 30), # black
   CellColor(rgb: false, color: 31), # red