about summary refs log blame commit diff stats
path: root/src/config/config.nim
blob: ff4f0b45888850786b20cf076c0f92aa857e73c8 (plain) (tree)
1
2
3
4
5
6
7
8
9
             
              
         
              
 
                  
                  
                  
                   
 
    


                                           
                                   
                         
                     
                    
                     
                       
                    
                           



                                   
                            
                       
 
                                      
                   
                 
              




                  
                
                  
                                
              
                                   
                 
                                   
                 


                                
                      
              


                      
         

                     



                                  
           
                  

                  

                

              
                                                                                     















                                             
 
                                                    












                                      
                                                             

                

                          























                                                               




                                                      

























                                                              




                                           
 
                                                               

                                            
                                                           

                                             



                                                        
 
                                        
 
                                              

                                             
                               
 


                                                          
           
 
                                                         

                            
           
 


                            
                      

                                              
import tables
import options
import os
import streams

import buffer/cell
import config/toml
import types/color
import utils/twtstr

type
  ColorMode* = enum
    MONOCHROME, ANSI, EIGHT_BIT, TRUE_COLOR
  FormatMode* = set[FormatFlags]
  ActionMap = Table[string, string]
  Config* = ref ConfigObj
  ConfigObj* = object
    nmap*: ActionMap
    lemap*: ActionMap
    stylesheet*: string
    startup*: string
    ambiguous_double*: bool
    hlcolor*: RGBAColor
    headless*: bool
    colormode*: Option[ColorMode]
    formatmode*: Option[FormatMode]
    altscreen*: Option[bool]
    mincontrast*: float

func getRealKey(key: string): string =
  var realk: string
  var control = 0
  var meta = 0
  var skip = false
  for c in key:
    if c == '\\':
      skip = true
    elif skip:
      realk &= c
      skip = false
    elif c == 'M' and meta == 0:
      inc meta
    elif c == 'C' and control == 0:
      inc control
    elif c == '-' and control == 1:
      inc control
    elif c == '-' and meta == 1:
      inc meta
    elif meta == 1:
      realk &= 'M' & c
      meta = 0
    elif control == 1:
      realk &= 'C' & c
      control = 0
    else:
      if meta == 2:
        realk &= '\e'
        meta = 0
      if control == 2:
        realk &= getControlChar(c)
        control = 0
      else:
        realk &= c
  if control == 1:
    realk &= 'C'
  if meta == 1:
    realk &= 'M'
  return realk

func constructActionTable*(origTable: Table[string, string]): Table[string, string] =
  var strs: seq[string]
  for k in origTable.keys:
    let realk = getRealKey(k)
    var teststr = ""
    for c in realk:
      teststr &= c
      strs.add(teststr)

  for k, v in origTable:
    let realk = getRealKey(k)
    var teststr = ""
    for c in realk:
      teststr &= c
      if strs.contains(teststr):
        result[teststr] = "client.feedNext()"
    result[realk] = v

proc readUserStylesheet(dir, file: string): string =
  if file.len == 0:
    return ""
  if file[0] == '~' or file[0] == '/':
    var f: File
    if f.open(expandPath(file)):
      result = f.readAll()
      f.close()
  else:
    var f: File
    if f.open(dir / file):
      result = f.readAll()
      f.close()

proc parseConfig(config: Config, dir: string, t: TomlValue) =
  for k, v in t:
    case k
    of "startup":
      config.startup = v.s
    of "headless":
      config.headless = v.b
    of "page":
      for k, v in v:
        config.nmap[getRealKey(k)] = v.s
    of "line":
      for k, v in v:
        config.lemap[getRealKey(k)] = v.s
    of "css":
      for k, v in v:
        case k
        of "include":
          case v.vt
          of VALUE_STRING:
            config.stylesheet &= readUserStylesheet(dir, v.s)
          of VALUE_ARRAY:
            for child in v.a:
              config.stylesheet &= readUserStylesheet(dir, v.s)
          else: discard
        of "inline":
          config.stylesheet &= v.s
    of "display":
      for k, v in v:
        case k
        of "alt-screen":
          if v.vt == VALUE_BOOLEAN:
            config.altscreen = some(v.b)
          elif v.vt == VALUE_STRING and v.s == "auto":
            config.altscreen = none(bool)
        of "color-mode":
          case v.s
          of "auto": config.colormode = none(ColorMode)
          of "monochrome": config.colormode = some(MONOCHROME)
          of "ansi": config.colormode = some(ANSI)
          of "8bit": config.colormode = some(EIGHT_BIT)
          of "24bit": config.colormode = some(TRUE_COLOR)
        of "format-mode":
          if v.vt == VALUE_STRING and v.s == "auto":
            config.formatmode = none(FormatMode)
          elif v.vt == VALUE_ARRAY:
            var mode: FormatMode
            for v in v.a:
              case v.s
              of "bold": mode.incl(FLAG_BOLD)
              of "italic": mode.incl(FLAG_ITALIC)
              of "underline": mode.incl(FLAG_UNDERLINE)
              of "reverse": mode.incl(FLAG_REVERSE)
              of "strike": mode.incl(FLAG_STRIKE)
              of "overline": mode.incl(FLAG_OVERLINE)
              of "blink": mode.incl(FLAG_BLINK)
            config.formatmode = some(mode)
        of "highlight-color":
          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))

proc parseConfig*(config: Config, dir: string, s: string) =
  config.parseConfig(dir, newStringStream(s))

proc staticReadConfig(): ConfigObj =
  var config = new(Config)
  config.parseConfig("res", staticRead"res/config.toml")
  return config[]

const defaultConfig = staticReadConfig()

proc readConfig(config: Config, dir: string) =
  let fs = newFileStream(dir / "config.toml")
  if fs != nil:
    config.parseConfig(dir, fs)

proc getNormalAction*(config: Config, s: string): string =
  if config.nmap.hasKey(s):
    return config.nmap[s]
  return ""

proc getLinedAction*(config: Config, s: string): string =
  if config.lemap.hasKey(s):
    return config.lemap[s]
  return ""

proc readConfig*(): Config =
  new(result)
  result[] = defaultConfig
  when defined(debug):
    result.readConfig(getCurrentDir() / "res")
  result.readConfig(getConfigDir() / "chawan")