all repos — pls @ 0d65fab59329bbad1e86d1c23429541d2a7550a1

A polite but determined task runner.

Removed support for local projects; added auto-update.
h3rald h3rald@h3rald.com
Mon, 04 Oct 2021 08:56:02 +0200
commit

0d65fab59329bbad1e86d1c23429541d2a7550a1

parent

810e0f2b279ad97acb8c4b6c59819999c9c782e7

4 files changed, 74 insertions(+), 111 deletions(-)

jump to
M src/pls.nimsrc/pls.nim

@@ -29,14 +29,12 @@

Options: --help, -h Displays this message. --force, -f Do not ask for confirmation when executing the specified task. - --global, -g Execute task within the global project instead of the local one. --log, -l Specifies the log level (debug|info|notice|warn|error|fatal). Default: info --version, -h Displays the version of the application. """ % [pkgTitle, pkgVersion, pkgDescription, pkgAuthor] var force = false -var global = false # Helper Methods

@@ -74,7 +72,7 @@ obj[prop.key] = prop.value

done = not confirm("Do you want to add/remove more properties?") proc addTaskDefinition(parentObj: JsonNode, name = ""): tuple[key: string, value: JsonNode] = - # TODO: validate name of task definition! (not _syntax or _description, etc.) + # TODO: validate name of task definition! (not $syntax or $description, etc.) if name == "": result.key = editValue("Task Definition Matcher") else:

@@ -82,8 +80,6 @@ printValue(" Task Definition Matcher", name)

result.key = name result.value = newJObject() result.value["cmd"] = addProperty(parentObj[name], "cmd").value - result.value["pwd"] = addProperty(parentObj[name], "pwd").value - # TODO: delete task definition matcher if all properties are null. proc addTaskDefinitions(obj: var JsonNode) = var done = false

@@ -99,13 +95,13 @@ if newv.value != newJNull():

printAdded(newv.label, $newv.value) return confirm("Confirm change?") -proc updateDefinitions(prj: var PlsProject): bool = +proc update(PROJECT: var PlsProject, sysProject: JsonNode): bool {.discardable.} = result = false - let sysTasks = plsTpl.parseJson["tasks"] + let sysTasks = sysProject["tasks"] for k, v in sysTasks.pairs: - if prj.tasks.hasKey(k): + if PROJECT.tasks.hasKey(k): let sysTask = sysTasks[k] - var prjTask = prj.tasks[k] + var prjTask = PROJECT.tasks[k] for prop, val in sysTask.pairs: let sysProp = sysTask[prop] var prjProp = newJNull()

@@ -127,7 +123,7 @@ else:

result = true # Adding new task printAdded(k, $sysTasks[k]) - prj.tasks[k] = sysTasks[k] + PROJECT.tasks[k] = sysTasks[k] ### MAIN ###

@@ -141,8 +137,6 @@ of cmdLongOption, cmdShortOption:

case key: of "force", "f": force = true - of "global", "g": - global = true of "log", "l": var val = val setLogLevel(val)

@@ -157,35 +151,31 @@ discard

else: discard -var localPrj = newPlsProject(getCurrentDir()) -var globalPrj: PlsProject +var PROJECT: PlsProject if defined(windows): - globalPrj = newPlsProject(getenv("USERPROFILE")) + PROJECT = newPlsProject(getenv("USERPROFILE")) if not defined(windows): - globalPrj = newPlsProject(getenv("HOME")) + PROJECT = newPlsProject(getenv("HOME")) -if not globalPrj.configured: - globalPrj.init() +if not PROJECT.configured: + PROJECT.init() -globalPrj.load() - -var prj = localPrj - -if global: - prj = globalPrj +PROJECT.load() +let sysProject = plsTpl.parseJson() +let version = sysProject["version"].getInt +if PROJECT.version < version: + notice "Updating pls.json file..." + PROJECT.update(sysProject) + PROJECT.version = version + PROJECT.save() + notice "Done." if args.len == 0: echo usage quit(0) case args[0]: - of "init": - if prj.configured: - fatal "Project already configured." - quit(2) - prj.init() - notice "Project initialized." of "def": if args.len < 3: fatal "No alias specified."

@@ -196,12 +186,11 @@ var props = newJObject()

if not ["target", "task"].contains(kind): fatal "Unknown definition type $1" % kind quit(6) - prj.load if kind == "target": - if prj.targets.hasKey(alias): + if PROJECT.targets.hasKey(alias): notice "Redefining existing target: " & alias warn "Specify properties for target '$1':" % alias - props = prj.targets[alias] + props = PROJECT.targets[alias] for k, v in props.mpairs: if k == "name": continue

@@ -213,14 +202,14 @@ else:

notice "Definining new target: " & alias warn "Specify properties for target '$1':" % alias addProperties(props) - prj.defTarget(alias, props) + PROJECT.defTarget(alias, props) else: # task - if prj.tasks.hasKey(alias): + if PROJECT.tasks.hasKey(alias): notice "Redefining existing task: " & alias warn "Specify properties for task '$1':" % alias - props = prj.tasks[alias] + props = PROJECT.tasks[alias] for k, v in props.mpairs: - if ["_syntax", "_description"].contains(k): + if ["$syntax", "$description"].contains(k): let prop = addProperty(props, k) props[prop.key] = prop.value else:

@@ -229,10 +218,10 @@ props[prop.key] = prop.value

if confirm "Do you want to add/remove more task definitions?": addTaskDefinitions(props) else: - props["_syntax"] = addProperty(props, "_syntax").value - props["_description"] = addProperty(props, "_description").value + props["$syntax"] = addProperty(props, "$syntax").value + props["$description"] = addProperty(props, "$description").value addTaskDefinitions(props) - prj.defTask(alias, props) + PROJECT.defTask(alias, props) of "undef": if args.len < 3: fatal "No alias specified."

@@ -242,75 +231,61 @@ let alias = args[2]

if not ["target", "task"].contains(kind): fatal "Unknown definition type $1" % kind quit(6) - prj.load if kind == "target": - if not prj.targets.hasKey(alias): + if not PROJECT.targets.hasKey(alias): fatal "Target '$1' not defined." % [alias] quit(4) if force or confirm("Remove definition for target '$1'?" % alias): - prj.undefTarget(alias) + PROJECT.undefTarget(alias) else: # task - if not prj.tasks.hasKey(alias): + if not PROJECT.tasks.hasKey(alias): fatal "Task '$1' not defined." % [alias] quit(4) if force or confirm("Remove definition for task '$1'?" % alias): - prj.undefTask(alias) + PROJECT.undefTask(alias) of "info": - prj.load if args.len < 2: - for t, props in prj.targets.pairs: + for t, props in PROJECT.targets.pairs: echo "$1:" % [t] for k, v in props.pairs: echo " - $1:\t$2" % [k, $v] else: let alias = args[1] - if not prj.targets.hasKey(alias): + if not PROJECT.targets.hasKey(alias): fatal "Target '$1' not defined." % [alias] quit(4) - let data = prj.targets[alias] + let data = PROJECT.targets[alias] for k, v in data.pairs: echo "$1:\t$2" % [k, $v] - of "update": - prj.load - if updateDefinitions(prj): - prj.save of "help": echo "" if args.len < 2: - var sortedKeys = toSeq(prj.help.keys) + var sortedKeys = toSeq(PROJECT.help.keys) sortedKeys.sort(cmp[string]) for k in sortedKeys: - printGreen " pls $1" % prj.help[k]["_syntax"].getStr - echo "\n $1\n" % prj.help[k]["_description"].getStr + printGreen " pls $1" % PROJECT.help[k]["$syntax"].getStr + echo "\n $1\n" % PROJECT.help[k]["$description"].getStr else: let cmd = args[1] - let help = prj.help[cmd] - if not prj.help.hasKey(cmd): + let help = PROJECT.help[cmd] + if not PROJECT.help.hasKey(cmd): fatal "Task '$1' is not defined." % cmd quit(5) - printGreen " pls " & help["_syntax"].getStr - echo "\n $1\n" % help["_description"].getStr + printGreen " pls " & help["$syntax"].getStr + echo "\n $1\n" % help["$description"].getStr else: if args.len < 1: echo usage quit(1) if args.len < 2: - prj.load - var targets = toSeq(prj.targets.pairs) + var targets = toSeq(PROJECT.targets.pairs) if targets.len == 0: warn "No targets defined - nothing to do." quit(0) - for key, val in prj.targets.pairs: - prj.execute(args[0], key) + for key, val in PROJECT.targets.pairs: + PROJECT.execute(args[0], key) else: try: - prj.execute(args[0], args[1]) + PROJECT.execute(args[0], args[1]) except: - # Fallback to global project - if prj == localPrj: - try: - globalPrj.execute(args[0], args[1]) - except: - warn getCurrentExceptionMsg() - else: - warn getCurrentExceptionMsg() + warn getCurrentExceptionMsg()
M src/plspkg/help.jsonsrc/plspkg/help.json

@@ -1,22 +1,18 @@

{ "help": { - "_syntax": "help [<task>]", - "_description": "Display help on the specified task (or all tasks)." + "$syntax": "help [<task>]", + "$description": "Display help on the specified task (or all tasks)." }, "info": { - "_syntax": "info [<target>]", - "_description": "Displays information on <target> (or all targets)." - }, - "init": { - "_syntax": "init", - "_description": "Initializes a project in the current directory." + "$syntax": "info [<target>]", + "$description": "Displays information on <target> (or all targets)." }, "def": { - "_syntax": "def (task|target) <alias>", - "_description": "Configures a new or existing task or target <alias>." + "$syntax": "def (task|target) <id>", + "$description": "Configures a new or existing task or target <id>." }, "undef": { - "_syntax": "undef (task|target) <alias>", - "_description": "Unmaps the previously-mapped task or target <alias>." + "$syntax": "undef (task|target) <id>", + "$description": "Unmaps the previously-mapped task or target <id>." } }
M src/plspkg/pls.jsonsrc/plspkg/pls.json

@@ -1,4 +1,13 @@

{ - "tasks": {}, + "version": 1633326634, + "tasks": { + "go": { + "$syntax": "go <target>", + "$description": "Goes to the folder identified by <target>.", + "folder": { + "cmd": "cd \"{{folder}}\"" + } + } + }, "targets": {} }
M src/plspkg/project.nimsrc/plspkg/project.nim

@@ -8,10 +8,10 @@ pegs

type PlsProject* = object + version*: int dir*: string tasks*: JsonNode targets*: JsonNode - tasklists*: JsonNode type PlsError = ref object of ValueError

@@ -39,6 +39,7 @@ if not prj.configFile.fileExists:

fatal "Project not initialized - configuration file not found." quit(10) let cfg = prj.configFile.parseFile + prj.version = cfg["version"].getInt prj.tasks = cfg["tasks"] prj.targets = cfg["targets"] if cfg.hasKey("dir"):

@@ -51,16 +52,17 @@ prj.load

for k, v in systemHelp.parseJson.pairs: result[k] = v for k, v in prj.tasks.pairs: - if v.hasKey("_syntax") and v.hasKey("_description"): + if v.hasKey("$syntax") and v.hasKey("$description"): result[k] = (""" { - "_syntax": "$1", - "_description": "$2" + "$$syntax": "$1", + "$$description": "$2" } - """ % [v["_syntax"].getStr, v["_description"].getStr]).parseJson + """ % [v["$syntax"].getStr, v["$description"].getStr]).parseJson proc save*(prj: PlsProject) = var o = newJObject() + o["version"] = %prj.version o["tasks"] = %prj.tasks o["targets"] = %prj.targets prj.configFile.writeFile(o.pretty)

@@ -69,7 +71,6 @@ proc defTarget*(prj: var PlsProject, alias: string, props: var JsonNode) =

for k, v in props.mpairs: if v == newJNull(): props.delete(k) - prj.load if not prj.targets.hasKey alias: notice "Adding target '$1'..." % alias prj.targets[alias] = newJObject()

@@ -84,7 +85,6 @@ prj.save

notice "Target '$1' saved." % alias proc undefTarget*(prj: var PlsProject, alias: string) = - prj.load prj.targets.delete(alias) prj.save notice "Target '$1' removed." % alias

@@ -97,7 +97,6 @@ elif v.kind == JObject:

for kk, vv in v.pairs: if vv == newJNull(): v.delete(kk) - prj.load if not prj.tasks.hasKey alias: notice "Adding task '$1'..." % alias prj.tasks[alias] = newJObject()

@@ -124,7 +123,7 @@ var cmds = prj.tasks[task]

var score = 0 # Cycle through task definitions for key, val in cmds: - if key == "_syntax" or key == "_description": + if key == "$syntax" or key == "$description": continue var params = key.split("+") # Check if all params are available

@@ -163,19 +162,3 @@ result = execShellCmd cmd

else: debug "Task '$1' not available for target '$2'" % [task, alias] setCurrentDir(prj.dir) - -proc executeRec*(prj: var PlsProject, task, alias: string) = - prj.load - let pwd = getCurrentDir() - var dir = alias - if (execute(prj, task, alias) != 0): - return - if prj.targets[alias].hasKey("dir"): - dir = prj.targets[alias]["dir"].getStr - var childProj = newPlsProject(pwd/prj.dir/dir) - if childProj.configured: - childProj.load() - setCurrentDir(childProj.dir) - for key, val in childProj.targets.pairs: - childProj.executeRec(task, key) - setCurrentDir(pwd)