How to run Cozenage¶
Cozenage provides both a file runner for evaluating code in external files and a fully-featured interactive REPL which allows for experimentation and quick discovery. These two methods of running Cozenage will be treated in order, after a short introduction to command-line flags which affect the operation of both.
Cozenage command line flags¶
-hand--helpDisplay short usage details to the screen, ie: print the information we are discussing here.
-Vand--versionPrint the version number of the currently running Cozenage binary, and print when it was compiled.
-land--libraryPreload Cozenage ‘base’ libraries at startup. Accepts a mandatory comma-delimited list of libraries to load. This is a convenience flag which is identical to manually loading libraries using the
(import (base foo))syntax. Valid arguments to this flag are:bits,cxr,file,math,random,system, andtime.
Using the file runner¶
To evaluate code in an external file, simply pass the filename as argument on the command line:
$ cozenage file.scm
By convention, Scheme source files typically use scm or ss suffixes. Cozenage will print a warning to the
standard error stream when it detects a file without one of these two suffixes, but will attempt to run the file
anyway. Cozenage will only run one external file at a time. If you want to run multiple unrelated files in sequential
order, use your shell’s facilities for this:
$ cozenage file1.scm && cozenage file2.scm && cozenage file3.scm
Or perhaps more idiomatically:
$ for file in file1.scm file2.scm file3.scm; do
cozenage ${file}
done
If you want to load definitions from one or more files for use in a final script, you can use the (load) procedure.
In your script file:
(load "file1.scm")
(load "file2.scm")
(load "file3.scm")
;;; ...and the rest of the script...
And now these definitions are available when you run the script:
$ cozenage script.scm
You can use the -l or --library flag as a convenience to pre-load libraries:
$ cozenage -l file,system script.scm
This is functionally equivalent to adding (import) expressions at the top of your source file:
(import (base file))
(import (base system))
;;; etc
Tip
Other than printing runtime errors to the standard error stream, file runner mode does not generate
any output that is not explicitly generated by the code in the source file itself. Success or failure
of the run can be determined by inspecting the output of echo $?.
You can pass flags and arguments to the source file you are running and these will be made available through the
(command-line) procedure which returns them as a list of strings. As an example, let’s say we have these
definitions in a file:
(write (command-line))
(newline)
Notice the results of running the file, given this invocation:
$ cozenage cli.scm -- --foo --bar --baz somefile.txt
("cli.scm" "--foo" "--bar" "--baz" "somefile.txt")
Note in particular, that you have to explicitly add ‘--’ AFTER the Scheme file name so that getopt() knows to
stop parsing the arguments as args to Cozenage itself, and ensure they are interpreted as flags and arguments to the
Scheme file.
Using the REPL¶
Most modern interpreted languages provide a REPL for interactive use. The idea of a REPL was first described by John McCarthy, the inventor of the original LISP language in his 1960 paper named “Recursive functions of symbolic expressions and their computation by machine”. The interactive loop he described is the direct ancestor of every REPL that exists today.
REPLs are a very powerful tool which allow for interactive ‘conversations’ with the interpreter, in order to experiment and try out various code expressions without the overhead of the edit-compile-test workflow required with most compiled languages.
Running Cozenage with no file arguments will start the program in REPL mode:
$ cozenage
Cozenage version 0.11.0
Press <Ctrl+d> or type '(exit)' to quit
-->
The ‘-->’ is the cozenage prompt, at which you can type in expressions to be immediately evaluated when you press enter. The REPL also provides multiline input using a simple heuristic that tracks if the parentheses are balanced. If there are more left parentheses than right parentheses in the current expression, pressing enter will continue on to the next line and print a secondary prompt: ‘…’. The secondary prompt will also be printed if you press enter while inside a string literal, that is, no closing quotation mark is detected.
--> (+ 2 4)
6
--> (define (fact n)
... (if (= n 1) 1
... (* n (fact (- n 1)))))
<lambda 'fact'>
--> (fact 5)
120
-->
Note that you can type multiple expressions in a single line, and they will be evaluated in sequence:
--> (import (scheme write))
#true
--> (display "Hello, World!") (newline)
"Hello, World!"
-->
REPL History¶
The REPL maintains a buffer containing the history of entered expressions. This history can be cycled through using the up and down arrow keys. Currently, the size of the buffer is fixed at 500 items, but at some point this will become a configurable option.
Upon closing Cozenage, the history will be written to a file for persistence between runs. On startup, the history is
read from the file to populate the runtime buffer. If the $XDG_STATE_HOME environment variable is set, the history
file will be located at $XDG_STATE_HOME/cozenage/history. If this variable is not set, the history will be written
to ~/.local/state/cozenage/history. This is a plain-text (UTF8) encoded file that can be inspected and edited with
any text editor.
Tab Completion¶
Cozenage provides tab-completion for convenience. There are two kinds of completions that will be deployed depending on context. If inside a string literal the filename completer will be activated, using filenames relative to the CWD. In all other contexts, Cozenage provides extended tab completion for all defined procedures and special forms at startup.
To use tab completion, simply type in the first few characters of the desired name. If there is no ambiguity, the rest of the name, or the rest of the name up until a point of ambiguity, will be auto-completed at the prompt immediately upon pressing the tab key. If there are multiple possible completions, pressing the tab key a second time will display the options to the screen.
--> (def[tab]ine ;;; The REPL auto-completes the 'define' special form
--> (make-[tab][tab]
make-bytevector make-list make-string make-vector
--> (make-b[tab]ytevector