src/niprefs

Source   Edit  

niprefs is a simple way to manage your application preferences (or configuration) using TOML.

TOML Syntax

A config file format for humans.

# This is a TOML document

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00

[database]
enabled = true
ports = [ 8000, 8001, 8002 ]
data = [ ["delta", "phi"], [3.14] ]
temp_targets = { cpu = 79.5, case = 72.0 }

[servers]

[servers.alpha]
ip = "10.0.0.1"
role = "frontend"

[servers.beta]
ip = "10.0.0.2"
role = "backend"

Basic usage

A Prefs object requires a path and a default preferences. A TOML file is created at path with default whenever it's not found, if it exists it will read it. To access the actual preferences (not the default) you may want to use Prefs.content and at the end of your program call Prefs.save() to update the preferences file.

toToml is a helpful macro to define your default preferences. Instead of having to write:

{"a": [1.newTInt(), 2.newTInt()].newTArray()}.newTTable()
Using the toToml it's just as easy as writing:

toToml {a: [1, 2]}

Example:

import src/niprefs
let prefs = initPrefs(
  path = "prefs.toml", 
  default = toToml {
    "lang": "en", # Keys do not require quotes when using toToml macro.
    dark: true,
    keybindings: {:},
    scheme: {
      background: "#000000",
      font: {
        size: 15,
        family: "UbuntuMono",
        color: "#73D216"
      }
    }
  }
)

After the above example, a new prefs.toml file should be created:

  lang="en"
  dark=true
  scheme.background="#000000"
  scheme.font.color="#73D216"
  scheme.font.family="UbuntuMono"
  scheme.font.size=15
[keybindings]

Reading

You can access prefs.content

assert prefs.content["lang"] == "en"
But Prefs has some helper procedures to access content so you don't need to write prefs.content[] you can just prefs[]:

assert prefs["lang"] == "en"
To read a nested key you can use the {} operator:

assert prefs{"scheme", "font", "family"} == "UbuntuMono" # This acceses prefs.content
assert prefs["scheme"]["font"]["family"] == "UbuntuMono" # This acceses prefs.content

Writing

prefs["lang"] = "es" # Same as prefs.content["lang"] = "es"
assert prefs["lang"] == "es"
Same with nested keys:

prefs{"scheme", "font", "size"} = 20
assert prefs{"scheme", "font", "size"} == 20

prefs["scheme"]["font"]["size"] = 10
assert prefs["scheme"]["font"]["size"] == 10

Removing

assert "lang" in prefs

prefs.delete("lang")

assert "lang" notin prefs
## Overwriting To reset a key to its default value or reset the whole preferences use Prefs.overwrite():

assert prefs["lang"] == "en"
prefs["lang"] = "es"
prefs.overwrite("lang")
assert prefs["lang"] == "en"
Nested key:

assert prefs{"scheme", "font", "size"} == 15
prefs{"scheme", "font", "size"} = 20
prefs.overwrite(["scheme", "font", "size"])
assert prefs{"scheme", "font", "size"} == 15
Whole file:

prefs["lang"] = "es"
prefs["dark"] = false

prefs.overwrite()

assert prefs["lang"] == "en"
assert prefs["dark"] == true

Types

Prefs = object
  path*: string
  content*: TomlValueRef
Source   Edit  

Procs

proc `$`(prefs: Prefs): string {....raises: [ValueError, Exception],
                                 tags: [RootEffect], forbids: [].}
Instead of printing the prefs object, print it's content

Example:

var prefs = initPrefs("prefs.toml", toToml({"lang": "en", "theme": "dark"}))

prefs.overwrite() # Ignore this line

assert $prefs == "{\"lang\": \"en\", \"theme\": \"dark\"}"
Source   Edit  
proc `[]`(prefs: Prefs; key: string): TomlValueRef {....raises: [KeyError],
    tags: [], forbids: [].}
Source   Edit  
proc `[]=`(prefs: Prefs; key: string; val: TomlValueRef) {....raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc `[]=`[T: not TomlValueRef](prefs: Prefs; key: string; val: T)
Source   Edit  
proc contains(prefs: Prefs; key: string): bool {....raises: [], tags: [],
    forbids: [].}

Example:

var prefs = initPrefs("prefs.toml", toToml({"lang": "en", "theme": "dark"}))

prefs.overwrite() # Ignore this line

assert "lang" in prefs
Source   Edit  
proc default(prefs: Prefs): TomlValueRef {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc delete(prefs: Prefs; key: string) {....raises: [], tags: [], forbids: [].}

Example:

var prefs = initPrefs("prefs.toml", toToml({"lang": "en", "theme": "dark"}))

prefs.overwrite() # Ignore this line

prefs.delete("theme")

assert "theme" notin prefs
Source   Edit  
proc hasKey(prefs: Prefs; key: string): bool {....raises: [], tags: [], forbids: [].}

Example:

var prefs = initPrefs("prefs.toml", toToml({"lang": "en", "theme": "dark"}))

prefs.overwrite() # Ignore this line

assert prefs.hasKey("lang")
Source   Edit  
proc hasKey(prefs: Prefs; keys: varargs[string]): bool {....raises: [KeyError],
    tags: [], forbids: [].}

Example:

var prefs = initPrefs("prefs.toml", toToml({"scheme": {"font": "UbuntuMono"}}))

prefs.overwrite() # Ignore this line

assert prefs.hasKey("scheme", "font")
Source   Edit  
proc initPrefs(path: string; default: TomlValueRef): Prefs {....raises: [Exception,
    OSError, IOError, IOError, TomlError, SerializationError],
    tags: [RootEffect, ReadDirEffect, WriteDirEffect, ReadIOEffect], forbids: [].}
Create a Prefs object and load the content from path if it exists otherwise create it with default. Source   Edit  
proc len(prefs: Prefs): int {....raises: [], tags: [], forbids: [].}

Example:

var prefs = initPrefs("prefs.toml", toToml({"lang": "en", "theme": "dark"}))

prefs.overwrite() # Ignore this line

assert prefs.len == 2
Source   Edit  
proc overwrite(prefs: Prefs; key: string) {....raises: [KeyError], tags: [],
    forbids: [].}
Overwrites key in the niprefs file with it's default value from prefs.default.

Example:

var prefs = initPrefs("prefs.toml", toToml({"lang": "es", "theme": "dark"}))

prefs.overwrite() # Ignore this line

prefs["lang"] = "en"
prefs["theme"] = "light"

prefs.overwrite("lang")

assert prefs["lang"] == "es" # "es" is the default value
assert prefs["theme"] == "light" # "theme" was not overwritten
Source   Edit  
proc overwrite(prefs: Prefs; keys: openArray[string]) {....raises: [KeyError],
    tags: [], forbids: [].}
Traverses the node and overwrites the given value with it's default value from prefs.default.

Example:

var prefs = initPrefs("prefs.toml", toToml({"scheme": {"font": "UbuntuMono"}}))

prefs.overwrite() # Ignore this line

prefs{"scheme", "font"} = "ProggyClean Vector"

prefs.overwrite(["scheme", "font"])

assert prefs{"scheme", "font"} == "UbuntuMono" # "UbuntuMono" is the default value
Source   Edit  
proc overwrite(prefs: var Prefs; table: TomlValueRef = prefs.default) {.
    ...raises: [Exception], tags: [RootEffect], forbids: [].}
Overwrites the whole niprefs file with table.

Example:

var prefs = initPrefs("prefs.toml", toToml({lang: "es", theme: "dark"}))

prefs.overwrite() # Ignore this line

prefs.content["lang"] = "en"
prefs.content["theme"] = "light"

prefs.overwrite()

assert prefs["lang"] == "es" # "es" is the default value
assert prefs["theme"] == "dark" # "dark" is the default value
Source   Edit  
proc remove(prefs: Prefs) {....raises: [OSError],
                            tags: [ReadDirEffect, WriteDirEffect], forbids: [].}
Deletes the niprefs file if it exists. Source   Edit  
proc save(prefs: Prefs) {....raises: [OSError, IOError, IOError, Exception],
                          tags: [WriteDirEffect, ReadDirEffect, RootEffect],
                          forbids: [].}
Source   Edit  
proc `{}`(prefs: Prefs; keys: varargs[string]): TomlValueRef {....raises: [],
    tags: [], forbids: [].}
Source   Edit  
proc `{}=`(prefs: Prefs; keys: varargs[string]; val: TomlValueRef) {.
    ...raises: [KeyError], tags: [], forbids: [].}
Source   Edit  
proc `{}=`[T: not TomlValueRef](prefs: Prefs; keys: varargs[string]; val: T)
Source   Edit