Various utilities for tasks in NimScript.
The library itself is written in Nim, so it can be used in regular Nim code.
The main motivation is to see whether it is possible to import external packages in Nimble scripts.
It is technically possible, but the external packages must be installed manually
before running the Nimble script. Indeed, the script has to be verified by the
compiler first, the requires statements only occur after, at runtime.
This becomes quite inconvenient when installing the package associated with the script.
The experimented solution with this project is to:
- Move the code that depends on external packages out in regular NimScript files.
- Write Nimble tasks that execute the corresponding scripts.
This project plays the role of an imported external package.
nimble install 'https://github.com/thenjip/taskutils'nim>=1.4.0
Examples of integration with Nimble project files can be found here.
# NimScriptimport pkg/taskutils/[cmdline, fileiters]
import std/[os]
for file ingetCurrentDir().relativeFiles("rst"):
["rst2html", file.quoteShell()].cmdLine().selfExec()
for test in"tests".absoluteNimModules():
["c", "-r", test.quoteShell()].cmdLine().selfExec()A few extensions of std/options
# NimScriptimport pkg/taskutils/[optional]
import std/[sugar]
let i =0doAssert(i.some().boxedType() is i.typeof())
doAssert(i.some().ifSome(i => i, () =>-1) == i)
doAssert(i.some().ifNone(() =>-1, i =>1) ==1)It is mainly used to make dealing with errors part of the API.
# NimScriptimport pkg/taskutils/[cmdline, result, unit]
import std/[strformat, strutils, sugar]
typeShellCmdSuccess=tuple
output: stringShellCmdFailure=tuple
cmd: string
exitCode: intShellCmdResult=Result[ShellCmdSuccess, ShellCmdFailure]
funcshellCmdSuccess (output: string): ShellCmdResult=
(output, ).success(ShellCmdFailure)
funcshellCmdFailure (cmd: string; exitCode: int): ShellCmdResult=
(cmd, exitCode).failure(ShellCmdSuccess)
procexecInShell (cmd, input: string): ShellCmdResult=let (output, exitCode) = cmd.gorgeEx(input)
if exitCode ==QuitSuccess:
output.shellCmdSuccess()
else:
cmd.shellCmdFailure(exitCode)
procexecInShell (cmd: string): ShellCmdResult=
cmd.execInShell("")
procpipe (self: ShellCmdResult; cmd: string): ShellCmdResult=
self.flatMap((previous: ShellCmdSuccess) => cmd.execInShell(previous.output))
["echo", "\"hello\""]
.cmdLine()
.execInShell()
.pipe(["grep", "-so", $'l'].cmdLine())
.ifSuccess(
proc (success: auto): Unit=echo(success.output)
,
proc (failure: auto): Unit=
[fmt"Command failed: {failure.cmd}", fmt"Exit code: {failure.exitCode}"]
.join($'\n')
.echo()
).ignore()# NimScriptimport pkg/taskutils/[envtypes, optional, parseenv, result, unit]
import std/[strformat, strutils, sugar]
typeNimOptimize {.pure.} =enumNoneSpeedSizefuncenvNimOptimize (): EnvVarName="NIM_OPTIMIZE"funcparseNimOptimize (value: EnvVarValue): ParseEnvResult[NimOptimize] =procinvalidValue (): refParseEnvError=envNimOptimize().parseEnvError(fmt"Invalid optimization type: {value}")
case value:
of"speed":
NimOptimize.Speed.success(result.failureType())
of"size":
NimOptimize.Size.success(result.failureType())
of"none":
NimOptimize.None.success(result.failureType())
else:
invalidValue.failure(result.successType())
procgetEnvOrEmpty (name: EnvVarName): EnvVarValue=
name.getEnv()
proctryGetEnv (name: EnvVarName): Optional[EnvVarValue] =
name.findValue(existsEnv, getEnvOrEmpty)
proctryParseNimOptimize (): Optional[ParseEnvResult[NimOptimize]] =envNimOptimize().tryParse(tryGetEnv, parseNimOptimize)
tryParseNimOptimize()
.ifSome(
parseResult =>
parseResult.ifSuccess(
proc (optimization: NimOptimize): Unit=echo(fmt"optimization: {optimization}")
,
proc (failure: () ->refParseEnvError): Unit=echo(failure().msg)
)
,
proc (): Unit=echo(fmt"{envNimOptimize()} not set.")
).ignore()