trivial-toplevel-commands

2024-10-12

Trivial Toplevel Commands allows to define toplevel commands available on most implementations in a portable fashion.

Upstream URL

github.com/aartaka/trivial-toplevel-commands

Author

Artyom Bologov

License

BSD-3 Clause
README

Most CL implementations provide convenient toplevel commands, like

  ;; ECL command to load a Lisp file
  :ld file.lisp

These commands tend to start with a colon and end with a newline, possibly including space-separated arguments. Such commands are too similar to not want a portable way to define them. Trivial Toplevel Commands is such a portability layer. It allows to define and remove toplevel commands on SBCL, CCL, ECL, ABCL, CLISP, and Allegro CL.

Couple of caveats:

There are no toplevel commands on SBCL
there are only debuggercommands. Trivial Toplevel Commands only defines debugger command tonot interfere with default SBCL REPL. If you want to access definedcommands, enter the debugger by signaling some condition ((break),at least) or contribute a more involved REPL to SBCL directly.
  • You can also (require "sb-aclrepl") to enable an Allegro-likeREPL. Trivial Toplevel Commands supports it.
CCL commands only accept evaluated arguments
macro-like commandsare thus not possible. If you want to have maximum portability, onlyuse define-toplevel-command/eval or constant arguments. Contributea new REPL to CCL if you want to change that.
ECL /read and /string commands remove a layer of quotes from strings
I.e. ""hello"hello" will be read as "hello hello". Plan accordingly. /evalcommands are unaffected.
Help with making it work on CLASP, CMUCL, and LispWorks
I don'thave access to these implementations. Like, at all. Thanks.

1Getting Started

Clone the Git repository:
  git clone --recursive https://github.com/aartaka/trivial-toplevel-commands ~/common-lisp/

And then load :trivial-toplevel-commands in the REPL:

  (asdf:load-system :trivial-toplevel-commands)
  ;; or, if you use Quicklisp
  (ql:quickload :trivial-toplevel-commands)

You can also install Trivial Toplevel Commands via Guix, using the bundled guix.scm file:

  guix package -f guix.scm

2Examples

A simple shell-invoking command mimicking ruricolist/cmd. Obviously quite primitive:

  (tpl-cmds:define-command/eval (:cmd :!) (command)
    "Shell invocation shortcut."
    (uiop:launch-program command))

  ;; Used like:
  :! "touch ~/cmd-test.txt"

  ;; With an apparent result
  (uiop:file-exists-p #p"~/cmd-test.txt")
  ;; => #P"~/cmd-test.txt"

A much more involved command processing raw string argument, say, for your MP3 player setup:

  (tpl-cmds:define-command/string (:list-mp3s :lm) (path)
    "Recursively list all MP3 files in PATH, be it directory or file."
    (labels ((ls (file)
               (cond
                 ((uiop:directory-pathname-p file)
                  (format t "~&Directory ~a..." file)
                  (mapc #'ls (uiop:subdirectories file))
                  (mapc #'ls (uiop:directory-files file)))
                 ((equalp "mp3" (pathname-type file))
                  (format t "~&File ~a..." file)))))
      (ls (uiop:merge-pathnames* (uiop:parse-native-namestring path) (uiop:getcwd)))))

  ;; Used like:
  :list-mp3s /path/to/your/mp3/files
  ;; or
  :lm /path/to/your/mp3/files

  ;; Directory ...
  ;; Directory ...
  ;; File ...
  ;; Directory ...
  ;; Directory ...
  ;; File ...
  ;; File ...
  ;; File ...
  ;; File ...

You can also undefine previously defined commands with remove-command:

  ;; By alias:
  (tpl-cmds:remove-command :lm)
  ;; Or by full name:
  (tpl-cmds:remove-command :list-mp3s)

Most of the information for command is accessible too, via helper functions:

Command char for implementation (setf-able)
command-char.
Command alias by name
command-alias.
And vice versa
command-name.
The handler function for the command
command-handler.
  • Documentation for the command can be fetched with (documentation (command-handler :command) 'function).

You can also see the practical uses for commands in my config.

3Similar Libraries

Peder Klingenberg's commands.lisp
CMUCL-specific, could possiblywork on SBCL.
Paul Foley's Toplevel
CMUCL-specific.

Dependencies (0)

    Dependents (0)

      • GitHub
      • Quicklisp