Jumplist Database Program in Nim

Tag: PROGRAM
Edit
Created: 2019/10/24
Updated: 2020/2/27

This is a nim port of the Go jumplist manager. It can be used in a similar fashion, after installing nim, and compiling the following file with nim -c jumplist.nim which will produce a jumplist.exe that functions identically to the go jumplist manager.

jumplist.nim


import os
import sequtils
import strutils
import tables

const ASCII_RECORD_SEPERATOR = 30.chr
const ASCII_UNIT_SEPERATOR = 31.chr

proc ensureFileExists(path: string) =
    if not existsFile(path):
        echo ".jumpdb doesn't exist in %HOME%, creating it."
        writeFile(path, "")

proc LoadKVFile*(path: string): OrderedTableRef[string, string] =
    let data = readFile(path)
    if data.len == 0:
        result = newOrderedTable[string, string]()
        return

    result = newOrderedTable[string, string]()
    for row in data.split(ASCII_RECORD_SEPERATOR):
        if row.len == 0: continue
        var cols: seq[string] = row.split(ASCII_UNIT_SEPERATOR)
        if cols.len != 2:
            raise newException(ValueError, "Row needs exactly two columns!")
        result[cols[0]] = cols[1]

proc SaveKVFile*(path: string, entries: OrderedTableRef[string, string]) =
    var f = open(path, fmWrite)
    defer: f.close()
    for k in entries.keys:
        f.write(k)
        f.write(ASCII_UNIT_SEPERATOR)
        f.write(entries[k])
        f.write(ASCII_RECORD_SEPERATOR)

proc dbPath(): string =
    var home = os.getHomeDir()
    return joinPath(home, ".jumpdb")

proc emitSet(store: OrderedTableRef[string, string] ) =
    var maxLen = foldl(toSeq(store.keys), max(a, len(b)), 1)
    for key in store.keys:
        stdout.write(key.alignLeft(maxLen, ' '))
        stdout.write(" -> ")
        stdout.writeLine(store[key])

proc dispatch() =
    var cmd = os.paramStr(1)
    # Make sure the file exists
    ensureFileExists(dbPath())
    var store = LoadKVFile(dbPath())
    # Used for debugging, not for other stuff.
    # for i in countup(0,paramCount()):
    #     stdout.write(paramStr(i))
    #     stdout.write(" ")
    # stdout.writeLine("")

    case cmd:
        of "-add": 
            if os.paramCount() < 2: 
                echo "Need at least one argument to the -add flag"
                return
            var key = os.paramStr(2)
            var value = os.getCurrentDir()
            store[key]= value
        of "-rm": 
            if os.paramCount() < 2: 
                echo "Need at least one argument to the -rm flag"
                return
            store.del(os.paramStr(2))
        of "-ls": emitSet(store)
        else:
            var key = os.paramStr(1)
            if key in store:
                var value = store[key]
                echo value
            else:
                echo "."
    SaveKVFile(dbPath(), store)

proc main() =
    if os.paramCount() > 0:
        dispatch()
    else:
        echo "Not enough args!"
    return

main()