Home

Awesome

mian: a Scheme Lisp task runner

ABOUT

mian enables Scheme developers to configure build tasks directly with Scheme code. This is a powerful advantage over the classic make utility. No longer do developers have to manage two completely different programming languages. With mian, Scheme devs have more expressiveness over their builds.

EXAMPLE

$ cd example

$ ./mian
Hello World!

$ ./mian test
Hello World!

SETUP

mian demonstrates a basic task runner in Scheme. This example specifically targets Chicken Scheme, though you may write similar task runners for other Scheme implementations.

Inside the example directory, we have a simple hello.scm application representing a Scheme project. At the same level of the project is a mian task runner script.

Create a mian Scheme script file at the top level of your project. Omit any file extensions. Ensure the file receives executable chmod bits.

Shebang

 #!/bin/sh
 #|
 exec csi -s "$0" "$@"
 |#

The complex shebang above provides a POSIX compliant way to load the Scheme interpreter and query CLI arguments.

Imports

(import (chicken process-context))

; chicken-install shell
(require-extension shell)

This example uses the process-context Chicken standard library module, as well as a shell egg module. Chicken Scheme eggs must be installed separately via chicken-install commands.

Create a task

(define test
 (lambda () (run (csi -s hello.scm))))

mian declares tasks in the form of simple Scheme functions.

Note the shell module run function, which takes a list of command and argument literals, and executes them as a subprocess.

This example merely executes the hello.scm script. You will likely want to alter your project's test task to trigger a unit test suite.

A more typical Chicken Scheme project may feature lint tasks to detect coding quirks, clean tasks to remove build artifacts, and/or a build task to trigger compilation commands.

Entrypoint

(let ((default-task 'test)
      (args (map string->symbol (command-line-arguments))))
 (if (= (length args) 0)
  ((eval default-task))
  (map (lambda (arg)
        ((eval arg)))
        args)))

Above, we have a Scheme entrypoint. The entrypoint declares the symbol 'test as the default task, simililar to the all default task convention in the make build system. You may choose another task symbol, whichever task is most relevant for your project.

When the user executes the shell command ./mian with no arguments, then the default task processes.

When the user supplies some task arguments like ./mian test, then the default task is ignored, and only the list of named tasks in the command line arguments will process.

Further Research

Use a Chicken Scheme parser to extract the function names from its own script, then generate a usage message as a help task.

Validate command line arguments against the list of task names.

SEE ALSO

🍜