Fix NimScriptApi builtins. Implement before/after hooks for NimS.
This commit is contained in:
parent
c4639fc145
commit
5d55a5f7a2
5 changed files with 95 additions and 19 deletions
|
|
@ -12,6 +12,13 @@ srcDir = "src"
|
|||
|
||||
requires "nim >= 0.11.2"
|
||||
|
||||
before tasks:
|
||||
echo("About to list tasks!")
|
||||
return true
|
||||
|
||||
after tasks:
|
||||
echo("Listed tasks!")
|
||||
|
||||
task tests, "Run the Nimble tester!":
|
||||
withDir "tests":
|
||||
exec "nim c -r tester"
|
||||
|
|
@ -856,12 +856,23 @@ proc listTasks(options: Options) =
|
|||
let nimbleFile = findNimbleFile(getCurrentDir(), true)
|
||||
nimscriptsupport.listTasks(nimbleFile, options)
|
||||
|
||||
proc execHook(options: Options, before: bool): bool =
|
||||
## Returns whether to continue.
|
||||
result = true
|
||||
let nimbleFile = findNimbleFile(getCurrentDir(), true)
|
||||
# TODO: Optimise this, there are two (three?) calls to readPackageInfo.
|
||||
if nimbleFile.isNimScript(options):
|
||||
let actionName = ($options.action.typ)[6 .. ^1]
|
||||
let res = execHook(nimbleFile, actionName, before, options)
|
||||
result = res.retVal
|
||||
|
||||
proc doAction(options: Options) =
|
||||
if not existsDir(options.getNimbleDir()):
|
||||
createDir(options.getNimbleDir())
|
||||
if not existsDir(options.getPkgsDir):
|
||||
createDir(options.getPkgsDir)
|
||||
|
||||
if not execHook(options, true): return
|
||||
case options.action.typ
|
||||
of actionUpdate:
|
||||
update(options)
|
||||
|
|
@ -898,7 +909,6 @@ proc doAction(options: Options) =
|
|||
of actionCustom:
|
||||
# Custom command. Attempt to call a NimScript task.
|
||||
let nimbleFile = findNimbleFile(getCurrentDir(), true)
|
||||
## TODO: Optimise this, there are two calls to readPackageInfo here.
|
||||
if not nimbleFile.isNimScript(options):
|
||||
writeHelp()
|
||||
|
||||
|
|
@ -910,6 +920,8 @@ proc doAction(options: Options) =
|
|||
if execResult.command.normalize == "nop":
|
||||
echo("WARNING: Using `setCommand 'nop'` is not necessary.")
|
||||
return
|
||||
if not execHook(options, false):
|
||||
return
|
||||
if execResult.hasTaskRequestedCommand():
|
||||
var newOptions = initOptions()
|
||||
newOptions.config = options.config
|
||||
|
|
@ -921,6 +933,9 @@ proc doAction(options: Options) =
|
|||
parseFlag(flag, val, newOptions)
|
||||
doAction(newOptions)
|
||||
|
||||
if options.action.typ != actionCustom:
|
||||
discard execHook(options, false)
|
||||
|
||||
when isMainModule:
|
||||
when defined(release):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,17 @@ proc requires*(deps: varargs[string]) =
|
|||
## package.
|
||||
for d in deps: requiresData.add(d)
|
||||
|
||||
template before*(action: untyped, body: untyped): untyped =
|
||||
## Defines a block of code which is evaluated before ``action`` is executed.
|
||||
proc `action Before`*(): bool =
|
||||
result = false
|
||||
body
|
||||
|
||||
template after*(action: untyped, body: untyped): untyped =
|
||||
## Defines a block of code which is evaluated after ``action`` is executed.
|
||||
proc `action After`*(): bool =
|
||||
body
|
||||
|
||||
template builtin = discard
|
||||
|
||||
proc getPkgDir*(): string =
|
||||
|
|
|
|||
|
|
@ -12,18 +12,21 @@ import
|
|||
|
||||
from compiler/scriptconfig import setupVM
|
||||
from compiler/idents import getIdent
|
||||
from compiler/astalgo import strTableGet
|
||||
from compiler/astalgo import strTableGet, `$`
|
||||
import compiler/options as compiler_options
|
||||
|
||||
import compiler/renderer
|
||||
|
||||
import nimbletypes, version, options, packageinfo
|
||||
import os, strutils, strtabs, times, osproc
|
||||
|
||||
type
|
||||
ExecutionResult* = object
|
||||
ExecutionResult*[T] = object
|
||||
success*: bool
|
||||
command*: string
|
||||
arguments*: seq[string]
|
||||
flags*: StringTableRef
|
||||
retVal*: T
|
||||
|
||||
const
|
||||
internalCmd = "NimbleInternal"
|
||||
|
|
@ -174,18 +177,20 @@ proc setupVM(module: PSym; scriptName: string,
|
|||
proc findNimscriptApi(options: Options): string =
|
||||
## Returns the directory containing ``nimscriptapi.nim``
|
||||
var inPath = false
|
||||
let pkgs = getInstalledPkgsMin(options.getPkgsDir(), options)
|
||||
var pkg: PackageInfo
|
||||
if pkgs.findPkg(("nimble", newVRAny()), pkg):
|
||||
let pkgDir = pkg.getRealDir()
|
||||
if fileExists(pkgDir / "nimblepkg" / "nimscriptapi.nim"):
|
||||
result = pkgDir
|
||||
inPath = true
|
||||
# Try finding it in exe's path
|
||||
if fileExists(getAppDir() / "nimblepkg" / "nimscriptapi.nim"):
|
||||
result = getAppDir()
|
||||
inPath = true
|
||||
|
||||
if not inPath:
|
||||
# Try finding it in exe's path
|
||||
if fileExists(getAppDir() / "nimblepkg" / "nimscriptapi.nim"):
|
||||
result = getAppDir()
|
||||
inPath = true
|
||||
let pkgs = getInstalledPkgsMin(options.getPkgsDir(), options)
|
||||
var pkg: PackageInfo
|
||||
if pkgs.findPkg(("nimble", newVRAny()), pkg):
|
||||
let pkgDir = pkg.getRealDir()
|
||||
if fileExists(pkgDir / "nimblepkg" / "nimscriptapi.nim"):
|
||||
result = pkgDir
|
||||
inPath = true
|
||||
|
||||
if not inPath:
|
||||
raise newException(NimbleError, "Cannot find nimscriptapi.nim")
|
||||
|
||||
|
|
@ -196,6 +201,8 @@ proc execScript(scriptName: string, flags: StringTableRef, options: Options) =
|
|||
if "nimblepkg/nimscriptapi" notin compiler_options.implicitIncludes:
|
||||
compiler_options.implicitIncludes.add("nimblepkg/nimscriptapi")
|
||||
|
||||
let pkgName = scriptName.splitFile.name
|
||||
|
||||
# Ensure that "nimblepkg/nimscriptapi" is in the PATH.
|
||||
let nimscriptApiPath = findNimscriptApi(options)
|
||||
appendStr(searchPaths, nimscriptApiPath)
|
||||
|
|
@ -219,10 +226,10 @@ proc execScript(scriptName: string, flags: StringTableRef, options: Options) =
|
|||
|
||||
# Setup builtins defined in nimscriptapi.nim
|
||||
template cbApi(name, body) {.dirty.} =
|
||||
vm.globalCtx.registerCallback "stdlib.system." & astToStr(name),
|
||||
vm.globalCtx.registerCallback pkgName & "." & astToStr(name),
|
||||
proc (a: VmArgs) =
|
||||
body
|
||||
# TODO: This doesn't work.
|
||||
|
||||
cbApi getPkgDir:
|
||||
setResult(a, "FOOBAR")
|
||||
|
||||
|
|
@ -318,7 +325,7 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options,
|
|||
cleanup()
|
||||
|
||||
proc execTask*(scriptName, taskName: string,
|
||||
options: Options): ExecutionResult =
|
||||
options: Options): ExecutionResult[void] =
|
||||
## Executes the specified task in the specified script.
|
||||
##
|
||||
## `scriptName` should be a filename pointing to the nimscript file.
|
||||
|
|
@ -347,6 +354,44 @@ proc execTask*(scriptName, taskName: string,
|
|||
|
||||
cleanup()
|
||||
|
||||
proc execHook*(scriptName, actionName: string, before: bool,
|
||||
options: Options): ExecutionResult[bool] =
|
||||
## Executes the specified action's hook. Depending on ``before``, either
|
||||
## the "before" or the "after" hook.
|
||||
##
|
||||
## `scriptName` should be a filename pointing to the nimscript file.
|
||||
result.success = true
|
||||
result.flags = newStringTable()
|
||||
compiler_options.command = internalCmd
|
||||
let hookName =
|
||||
if before: actionName.toLower & "Before"
|
||||
else: actionName.toLower & "After"
|
||||
echo("Attempting to execute hook ", hookName, " in ", scriptName)
|
||||
|
||||
execScript(scriptName, result.flags, options)
|
||||
# Explicitly execute the task procedure, instead of relying on hack.
|
||||
let idx = fileInfoIdx(scriptName)
|
||||
let thisModule = getModule(idx)
|
||||
assert thisModule.kind == skModule
|
||||
let prc = thisModule.tab.strTableGet(getIdent(hookName))
|
||||
if prc.isNil:
|
||||
# Procedure not defined in the NimScript module.
|
||||
result.success = false
|
||||
return
|
||||
let returnVal = vm.globalCtx.execProc(prc, [])
|
||||
case returnVal.kind
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
result.retVal = returnVal.intVal == 1
|
||||
else: assert false
|
||||
|
||||
# Read the command, arguments and flags set by the executed task.
|
||||
result.command = compiler_options.command
|
||||
result.arguments = @[]
|
||||
for arg in compiler_options.gProjectName.split():
|
||||
result.arguments.add(arg)
|
||||
|
||||
cleanup()
|
||||
|
||||
proc getNimScriptCommand(): string =
|
||||
compiler_options.command
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ type
|
|||
of actionUpdate:
|
||||
optionalURL*: string # Overrides default package list.
|
||||
of actionInstall, actionPath, actionUninstall:
|
||||
optionalName*: seq[string] # \
|
||||
# When this is @[], installs package from current dir.
|
||||
packages*: seq[PkgTuple] # Optional only for actionInstall.
|
||||
of actionSearch:
|
||||
search*: seq[string] # Search string.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue