Markwardt.TaskRunner
1.2.0
dotnet add package Markwardt.TaskRunner --version 1.2.0
NuGet\Install-Package Markwardt.TaskRunner -Version 1.2.0
<PackageReference Include="Markwardt.TaskRunner" Version="1.2.0" />
<PackageVersion Include="Markwardt.TaskRunner" Version="1.2.0" />
<PackageReference Include="Markwardt.TaskRunner" />
paket add Markwardt.TaskRunner --version 1.2.0
#r "nuget: Markwardt.TaskRunner, 1.2.0"
#:package Markwardt.TaskRunner@1.2.0
#addin nuget:?package=Markwardt.TaskRunner&version=1.2.0
#tool nuget:?package=Markwardt.TaskRunner&version=1.2.0
Task Runner
Task Runner is a small cross-platform automation system built around a purpose-built scripting
language, the task language. Scripts are written in plain text .task files, edited with a
dedicated syntax-highlighting editor, and executed by a runner application that shows each script's
live status and output.
Solution layout
| Project | Type | Purpose |
|---|---|---|
Core |
Class library | Parses .task documents and executes them. No UI dependency. |
Tests |
xUnit test project | Unit tests for Core. |
Editor |
Avalonia desktop app | A text editor for .task files: tabbed multi-file editing with task-language syntax highlighting. |
Runner |
Avalonia desktop app | Takes a .task file path as its only command line argument, runs it immediately, and shows each script's live output. |
All four projects live under the base namespace Markwardt.TaskRunner and are collected in the
TaskRunner.slnx solution.
Building and running
dotnet build TaskRunner.slnx
dotnet test Tests/Tests.csproj
# Edit .task files
dotnet run --project Editor/Editor.csproj
# Run a .task file
dotnet run --project Runner/Runner.csproj -- path/to/script.task
Releases
Pushing a tag matching a version number (for example 1.0.0) triggers the Release GitHub Actions
workflow, which tests the solution, then builds and uploads three assets to a GitHub release for
that tag: the Core NuGet package, and self-contained single-file Runner executables for
Windows and Linux (x64).
The task language
A .task file is plain text, structured entirely by indentation and line breaks; there is no
punctuation to terminate a statement. If a line is indented more deeply than the line before it, it
begins a new block nested under that line. This nesting is recursive: a block's lines can themselves
be the start of a further-nested block.
Any line whose first non-whitespace character is # is a comment and is ignored completely,
wherever it appears (including inside an instruction's indented block), the same as a blank line.
There is no syntax for a trailing comment at the end of a line with other content on it.
Top-level declarations
At the top level (no indentation), every line is one of two kinds of declaration:
var MyVariable = hello
script MyScript
. hello from MyScript
var Name = Valuedefines a variable with a value. The value is everything after the first=on the line.script Namedefines a script block. Every line indented beneath it is an instruction that belongs to that script, run in order. The name is optional; a barescriptline defines a nameless script, which simply cannot be referenced by another script'safterinstruction.
When a document declares multiple script blocks, they all start running simultaneously when
the document is run; scripts do not wait on each other unless a script explicitly uses the after
instruction.
Each script reports its own live status while it runs:
- Running: actively executing an instruction.
- Waiting: paused on a
wait,after, orqueryinstruction. - Completed: every instruction ran successfully.
- Failed: an instruction raised an error; the script stopped at that point.
Each script also has its own output log, a running console-style transcript: every instruction is
announced as soon as it starts, before it executes, as a line of the form > label argument (for
example > wait 5), so long-running instructions like wait appear in the log immediately rather
than only once they finish. In the runner's output window, the label portion of each
announcement is colored blue. The . instruction is the one exception: its announcement omits the
label, appearing as > argument (for example > hello world) with no coloring, even if the
argument happens to start with a word that matches an instruction's label. Instructions can add
further, unprefixed entries to the log as they run (run's command output, read's file content,
error reporting).
The trace off instruction turns off the > label argument announcements described above, along
with run's command output, for the rest of the script (or until a later trace on). Output that
an instruction generates explicitly rather than as an announcement, such as . and read, is
unaffected and keeps appearing either way. Tracing is on by default.
Instructions and arguments
Every line inside a script block is an instruction: a label, followed by its arguments.
script Build
. Starting the build
run npm install
If an instruction line is followed by a further-indented block, every line in that block is treated as additional, literal lines of the instruction's argument (appended after anything written inline on the instruction's own line), preserving each line's indentation relative to the block. This is how you write a multi-line message or a multi-line shell script:
script Build
run
echo starting
npm install
npm run build
is equivalent to a single run instruction whose command text is the three lines joined together.
Variable insertion
A previously defined variable can be inserted anywhere in the value of another variable definition,
in a script's name, or in an instruction's argument, using {VariableName}:
var Version = 1.2.3
script Publish{Version}
. Publishing version {Version}
Because { introduces a variable insertion, write {{ to insert a literal { character instead.
Inside a script block, two special variables are always available in addition to any var
declarations:
{Script}: the running script's own name.{Location}: the script's current working directory (see theswitchinstruction below). It starts out as the folder containing the.taskfile being run.
The query instruction (see below) sets a variable at runtime from user input, scoped to the
script that ran it; it overrides a var declaration of the same name, and is available to every
instruction after it in that script.
Instructions
Every path argument, unless it is already an absolute path, is resolved relative to the script's
current {Location}.
| Instruction | Arguments | Behavior |
|---|---|---|
wait |
seconds | Pauses the script for the given number of seconds. |
run |
command | Runs the command string in the local shell, in the script's current location. The command's standard output and error are streamed into the script's log. The instruction fails if the command exits with a non-zero code. |
. |
message | Writes the message to the script's output log; the instruction has no further effect beyond its own > message announcement. |
after |
script name | Waits until the named script finishes (whether it completed or failed) before continuing. |
delete |
path | Deletes the file or folder at the path, including all of its contents if it is a folder. Does nothing if nothing exists at the path. |
clean |
path | Deletes every file and folder inside the given folder, leaving the folder itself in place. Does nothing if the folder doesn't exist. |
switch |
path | Changes the script's current location ({Location}) to the given folder for every instruction that follows. |
move |
source, destination | Moves a file or folder to a new path, creating any missing intermediate directories. If something already exists at the destination, it is deleted first. |
copy |
source, destination | Copies a file or folder (recursively) to a new path, creating any missing intermediate directories. If something already exists at the destination, it is deleted first. The source is left in place. |
rename |
path, new name | Renames a file or folder in place, within its existing parent directory. If something already exists at the resulting path, it is deleted first. |
file |
path, optional content | Creates a file with the given content (empty if omitted). If a file or folder already exists at the path, it is deleted and replaced. Missing intermediate directories are created. |
append |
path, content | Appends the content to the end of the file at the path. If the file doesn't exist, it is created with that content. Missing intermediate directories are created. |
folder |
path | Creates a folder at the path, including any missing intermediate directories. Does nothing if a folder already exists there. |
read |
path | Writes the file's content to the script's output log. Does nothing if the file doesn't exist. |
trace |
on or off |
Turns instruction-announcement output (see above) on or off for the rest of the script. |
query |
message, variable name | Shows a popup with the message and a text box, pausing the script until the user submits it, then stores the submitted text in the named script variable (see Variable insertion). |
Instructions that take two path-like arguments (move, copy, rename) separate them by
whitespace; wrap a path in double quotes if it needs to contain a space. Instructions that take a
single free-form argument (., run, and the content of file/append) take the rest of the
line (plus any indented block beneath it) as one literal value, with no need for quoting. query
also takes two whitespace-separated arguments, in the same style as rename; wrap the message in
double quotes if it needs to contain a space, which it usually does.
The editor
Editor is a tabbed text editor for .task files, with syntax highlighting specific to the task
language. Right-clicking anywhere on a tab (not just its label) opens a menu with New, Open, Save
As, Run, and Close actions for that tab; double-clicking a tab runs it directly. Highlighting is
purely positional: it is based on where a piece of text sits in the document's structure, never on
whether it merely happens to match a keyword or name elsewhere. For example, a word that matches an
instruction label is only colored as one when it actually starts an instruction line inside a
script block; the same text appearing inside an argument stays plain.
- Blue: the
varandscriptkeywords, recognized instruction labels, and the=character in a variable definition. - Orange: a variable's name in its
vardefinition, every{Name}variable insertion (wherever it legally appears), and the variable name argument of aqueryinstruction. - Green: a script's name, both in its
script Namedeclaration and as the argument of anafterinstruction. - Comment green: a whole comment line (see below).
- White: everything else.
The runner
Runner takes exactly one command line argument: the path to a .task file. It loads and parses
the file, then immediately starts running every script simultaneously. Its window shows one output
panel per script, each with the script's name, live status, and output log, updating in real time as
the scripts run.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.