./dtcw createTask exportNotion
Extending docToolchain: Custom Tasks and Monkey-Patching
docToolchain ships every task as a self-contained Groovy script. You can use the same mechanism in your own project — to add a task or to change one that docToolchain already provides. Neither needs a fork, a build step, or an edit to a registry.
|
Note
|
This is a v4 feature (the Gradle-free runtime driven by dtcw/dtcw4).
The older v3 customTasks config entry belongs to the Gradle build and does not
apply here.
|
How task resolution works
When you run ./dtcw <task>, the wrapper looks for the task script in two
places, the project first, the installation second:
-
scripts/<task>.groovyin your project (the project scripts directory) -
<task>.groovyin the installed docToolchain (~/.doctoolchain/docToolchain-<version>/scripts/)
A file counts as a task only if it carries the marker // @task within its
first five lines — exactly the rule used by the built-in tasks. This is how a
project script can be discovered without you registering it anywhere.
The project scripts directory defaults to scripts/ under your project root.
Override it with the environment variable DTC_PROJECT_SCRIPTS_DIR.
|
Note
|
In the docker environment the project is mounted at a fixed location
inside the container, so DTC_PROJECT_SCRIPTS_DIR must be a path relative to
the project root. An absolute value cannot be reached inside the container, so
project tasks would not be found there (resolution falls back to the installed
task).
|
Adding a custom task
Create a skeleton with createTask and edit it:
This writes scripts/exportNotion.groovy with the // @task marker already in
place. Add your logic, then run it:
./dtcw exportNotion
It also shows up in the task list, under its own heading:
./dtcw tasks
You can of course create the file by hand instead — the only requirement is the
// @task marker near the top.
Reusing docToolchain’s helpers
A custom task can reuse the bundled helpers (for example DtcConfig to read
docToolchainConfig.groovy). They live in the installation, not your project,
and dtcw tells your script where via the dtc.scriptsHome system property:
def docDir = System.getProperty('docDir', '.')
def configFile = System.getProperty('mainConfigFile', 'docToolchainConfig.groovy')
def scriptsHome = System.getProperty('dtc.scriptsHome')
def gcl = new GroovyClassLoader(this.class.classLoader)
def DtcConfig = gcl.parseClass(new File(scriptsHome, 'lib/DtcConfig.groovy'))
def config = DtcConfig.load(docDir, configFile).getRaw()
println "inputPath is ${config.inputPath}"
The skeleton created by createTask already contains this pattern.
Monkey-patching an installed task
To change what a shipped task does, copy it into your project and edit the copy:
./dtcw copyTask generateHTML
This copies the installed generateHTML.groovy to scripts/generateHTML.groovy
in your project. Because the project copy has the same name as an installed
task, it overrides it: from now on ./dtcw generateHTML runs your copy.
docToolchain makes the override visible so you never patch by accident:
-
./dtcw generateHTMLprints a note to stderr that the installed task is being overridden by your project file. -
./dtcw taskslistsgenerateHTMLasoverridden by scripts/generateHTML.groovy.
The copy keeps working even though it now lives in your project: its bundled
helpers and resources still resolve from the installation via dtc.scriptsHome.
To return to the shipped behaviour, simply delete your copy.
|
Warning
|
A monkey-patched task is pinned to the version you copied. After upgrading docToolchain, re-copy the task if you want to pick up upstream changes. |
Security note
Project tasks are Groovy code that runs with your privileges — the same trust
level that docToolchainConfig.groovy already has, since it too is executable
Groovy. Opening someone else’s project and running dtcw runs their scripts.
Treat a project’s scripts/ directory with the same care as its config.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.