DEV Community

vindarel
vindarel

Posted on

Common Lisp: a command-line interactive terminal application in 2 lines

The quicker to a MVP the better, right?

Suppose you have a working Lisp function:

(defun play (file &optional (player (ensure-player)))
  "Play this file or directory in the background.

  Return the PLAYER instance.

  See also:

    TOGGLE-PLAY/PAUSE, STOP, QUIT, PLAYLIST-NEXT/PREVIOUS."

  ;; Play!
  (with-accessors ((p process)) player
    ;; but stop the current process if it's alive.
    (when (and p (uiop:process-alive-p p))
      (stop player))
    ;; If we get a pathname, get the file name as string.
    (setf p (uiop:launch-program (mpv-command (uiop:native-namestring file)))))
  player)
Enter fullscreen mode Exit fullscreen mode

It works in the Common Lisp REPL. It works in the Lem editor. How can we make it work (fast) on the terminal?

Quickload the replic library (based on cl-readline).

Create a file run.lisp:

;; run.lisp
(load "media-player.lisp") ;; your library

(in-package :media-player)

;; TODO: yes, next step is to set-up a proper.asd system definition.
(eval-when (:compile-toplevel :load-toplevel :execute)
  ;; Load helper libraries (you need quicklisp).
  (ql:quickload "replic"))

;; The exported functions of :media-player will be available
;; in the readline prompt.
;; TAB-completion works to write them.
(replic.completion:functions-to-commands :media-player)

;; Start the readline command loop:
(replic:repl)
Enter fullscreen mode Exit fullscreen mode

and that's it: 2 lines.

Run it:

$ sbcl --load run.lisp
> play "~/zique/2000\ -\ Jorge\ Aragão\ Ao\ Vivo\ 2/"
> toggle-pause 
> toggle-pause 
> stop
> 
Do you want to quit ? [Y]/n : 
Enter fullscreen mode Exit fullscreen mode

(it's even easier to run a file on the terminal, with batteries included, with CIEL)

This gives you:

  • TAB-completion for the player commands (play, stop, toggle-pause…)
  • dialog confirmation for quit

We could do more, like specifying what to TAB-complete for each different command, but that's our MVP, we can now have fun with the application on the terminal. For example (see replic's README), if we had a hello <name> command, we'd register every name, and the goodby <name> command would get TAB-completion of names. Other commands are unaffected.

How interesting is that to you?

What replic saved you is: reading cl-readline's documentation, writing readline boilerplate to start the command loop, writing boilerplate to say what to TAB-complete. You can now easily use your Lisp program from outside of the editor.

This was for the Lem editor

The Lem editor is really good. I assembled this media player (all the heavy lifting is done by mpv) to see how it fits in Lem.

Find the code here:

Top comments (0)