import lua, os, osproc # The nim object is pretty straight forward, we have three values, we only really need to use two. Two are strings (cstrings technicaly) and the other is an integer indexed table, so a sequence of strings in nim. type State = object `type`: string packages: seq[string] manager: string proc main()= # Load the Lua VM var L = newstate() openlibs(L) # Read in our state configuration if L.dofile("state.lua") != 0: let error = tostring(L, -1) echo "Error: ", $error pop(L, 1) # Instantiate an object to hold over configuration var state: State state.packages = @[] # and an empty seq for our package list # Get the global state table onto the stack L.getglobal("state") # Then the package table L.getfield(-1, "packages") # Stack: [state_table, packages_array] L.pushnil() # First key for iteration while L.next(-2) != 0: # -2 is the packages array # Stack: [state_table, packages_array, key, value] state.packages.add($L.tostring(-1)) # Read in the package, append it to the seq L.pop(1) # Pop value, keep key for next iteration L.pop(1) # Pop the packages array # note these two pops are different, one is to clean up the values in the packages array # the other is to clean up the reference to the array itself # It's a lot easier to fetch the value of manager, since it's just a simple string. L.getfield(-1, "manager") state.manager = $L.tostring(-1) L.pop(1) var pkgcheck = "" var pkgman = "" case $state.manager: of "apk": pkgcheck = "apk info --installed " pkgman = "apk add " of "snap": pkgcheck = "snap list | grep " pkgman = "snap install " for package in state.packages: let (check, code) = execCmdEx(pkgcheck & $package) if code == 1: let install = execCmdEx(pkgman & $package) echo "Installed " & $package else: echo $package & " is already installed" close(L) main()