File encoder/decoder in Nim
As long as the encoding and decoding are so similar you could use a template

template doCmd(gp: untyped, encdec: untyped, msg: string): void =
    let key = gp()
    let newContent = encdec(existingContent, key)
    write(newContent)
    notify(msg)


and then:

of "open":
    doCmd getpass, xxtea.decrypt, "Decoded"
of "close":
    doCmd getpass2, xxtea.encrypt, "Encoded"


You can also use a proc that accepts proc as arguments, more safe for checking the types of arguments passed, but at that point either getpass and getpass2 are declared with the same arguments or you have to pass an argument for each variant.

To pass a function as an argument just use proc and{.closure}

proc doCmd(gp: proc(m: string = "Password: "): string {.closure}, encdec: proc(b: string, k: string): string {.closure}, msg: string): void =
    let key = gp()