diff options
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/cl | 296 |
1 files changed, 296 insertions, 0 deletions
@@ -0,0 +1,296 @@ +#!/bin/sh +set -eu + + +uuid() { + od -xN20 /dev/urandom | + head -n1 | + awk '{OFS="-"; print $2$3,$4,$5,$6,$7$8$9}' +} + +tmpname() { + echo "${TMPDIR:-/tmp}/cl.tmpfile.$(uuid)" +} + +mkstemp() { + name="$(tmpname)" + touch "$name" + echo "$name" +} + +escape_name() { + printf '%s' "$1" | + sed 's|"|\\"|g' | + printf '(load "%s")\n' "$(cat -)" +} + + +IMPLEMENTATIONS=' +abcl +allegro +ccl +clasp +clisp +cmucl +ecl +jscl +mkcl +sbcl +' + +usage() { + cat <<-'EOF' + Usage: + cl [-e EXP] [-f FILE] [-p] [-M IMAGE] [-I IMPL] [-n] [-v] [FILE...] + cl -l + cl -h + EOF +} + +help() { + cat <<-'EOF' + + + Options: + -e EXP an sexp to be evaluated (can be given more than once) + -f FILE FIXME + -p print the value of the last given expression + -M IMAGE load the given Lisp image + -m disable looking for the default image under $XDG_DATA_HOME + -I IMPL use the given implementation (default: $LISP_CLI_IMPL) + -n skip loading the implementation's init file + -v verbose mode + -l list the known types of implementations + -h, --help show this message + + FILE FIXME + + + Lauch the desired Lisp implementation, properly adapting the given + CLI options. + + When the implementation is not explicited on the command line, and + the $LISP_CLI_IMPL environment variable in unset, implementations are + searched for alphabetically in $PATH, untill one is found, otherwise + an error is emitted. + + The supported implementations are: + EOF + + + for i in $IMPLEMENTATIONS; do + printf '%s\n' "$i" + done + + cat <<-'EOF' + + + Examples: + + Launch CLISP REPL, when $LISP_CLI_IMPL is set to 'clisp': + + $ cl + + + Lauch SBCL REPL, with the given Lisp image loaded, skipping the + loading of the '.sbclrc' file: + + $ cl -n -Isbcl sbcl.image + + + Run file1.lisp with ABCL: + + $ cl -Iabcl file1.lisp + + + Process STDIN: + + $ cat <<-EOS > process.lisp + + EOS + $ cat f1.txt f2.txt | cl -p process.lisp + + + Print a value on all types of implementations: + + $ for i in `cl -l`; do cl -I$i -pe 'call-arguments-list'; done + EOF +} + + +for flag in "$@"; do + case "$flag" in + --) + break + ;; + --help) + usage + help + exit + ;; + *) + ;; + esac +done + +NO_RC=false +SCRIPT="$(mkstemp)" +LISP_CLI_RC="${XDG_CONFIG_HOME:-$HOME/.config}/lisp-cli/init.lisp" +VERBOSE=false +IMAGE='' +SKIP_DEFAULT_IMAGE=false +IMPL="${LISP_CLI_IMPL:-}" +while getopts 'e:f:pM:mI:nvlh' flag; do + case "$flag" in + e) + printf '%s\n' "$OPTARG" >> "$SCRIPT" + ;; + f) + escape_name "$OPTARG" >> "$SCRIPT" + ;; + M) + IMAGE="$OPTARG" + ;; + m) + SKIP_DEFAULT_IMAGE=true + ;; + I) + IMPL="$OPTARG" + ;; + n) + NO_RC=true + ;; + v) + VERBOSE=true + ;; + h) + usage + help + exit + ;; + *) + usage >&2 + exit 2 + ;; + esac +done +shift $((OPTIND - 1)) + +INTERACTIVE=true +for f in "$@"; do + INTERACTIVE=false + escape_name "$f" >> "$SCRIPT" +done + +MAIN="$(mkstemp)" +if [ "$NO_RC" = false ] && [ -e "$LISP_CLI_RC" ]; then + escape_name "$LISP_CLI_RC" > "$MAIN" +fi + +if [ "$INTERACTIVE" = true ]; then + escape_name "$SCRIPT" >> "$MAIN" +else + cat <<-EOF >> "$MAIN" + (handler-case + (progn + (load "$SCRIPT" + :verbose NIL + :print NIL) + (uiop:quit 0)) + (error (e) + (format *error-output* "~&~%ERROR: ~a" e) + (uiop:quit 1))) + EOF +fi + +if [ -z "$IMPL" ]; then + for i in $IMPLEMENTATIONS; do + if command -v "$i" > /dev/null; then + IMPL="$i" + break + fi + done + if [ -z "$IMPL" ]; then + printf 'Could not find any implementation in $PATH.\n' >&2 + exit 2 + fi +fi + +DEFAULT_IMAGE="${XDG_DATA_HOME:-$HOME/.local/share}/lisp-cli/$IMPL.image" +if [ "$SKIP_DEFAULT_IMAGE" = false ] && [ -z "$IMAGE" ] && + [ -e "$DEFAULT_IMAGE" ]; then + IMAGE="$DEFAULT_IMAGE" +fi + +case "$IMPL" in + abcl) + exit 4 + ;; + allegro) + exit 4 + ;; + ccl) + exit 4 + ;; + clasp) + exit 4 + ;; + clisp) + ARGS="-ansi -i $MAIN" + if [ -n "$IMAGE" ]; then + set -- -M "$IMAGE" + fi + if [ "$NO_RC" = true ]; then + ARGS="$ARGS -norc" + fi + if [ "$VERBOSE" = false ]; then + ARGS="$ARGS -q -q" + else + set -x + fi + exec clisp $ARGS "$@" + ;; + cmucl) + exit 4 + ;; + ecl) + exit 4 + ;; + jscl) + exit 4 + ;; + mkcl) + exit 4 + ;; + sbcl) + ARGS="--disable-debugger --script $MAIN" + if [ "$VERBOSE" = false ]; then + ARGS="$ARGS --noinform" + fi + if [ "$NO_RC" = true ]; then + ARGS="$ARGS --no-sysinit --no-userinit" + fi + if [ -n "$IMAGE" ]; then + set -- --core "$IMAGE" + fi + exec sbcl $ARGS "$@" + ;; + *) + printf 'Unsupported implementation: "%s".\n\n' "$IMPL" >&2 + usage >&2 + exit 2 + ;; +esac + +exit + +# https://www.cliki.net/cl-launch +# buildapp +# https://github.com/memleaks/clbuild +# https://www.cliki.net/roswell +# https://github.com/shinmera/cl-all +# https://fare.livejournal.com/184127.html +# https://github.com/rolpereira/trivial-dump-core +# FIXME: enable readline from CL itself +when competing with roswell, add completion +FIXME: implement the example from help string |