Friday 17 May 2024 Getting the terminal size in Clisp on FreeBSD ============================================= Recently I have been fooling around with lisp and ncurses. This is part of my quest to learn Lisp, I don't have much experience with Common Lisp, so this is one big adventure for me. Clisp and ncurses ----------------- Clisp, at least on FreeBSD, doesn't like cl-charms or croatoan, two more "modern" Common Lisp packages created for using ncurses. I read somewhere about a file "curses.lisp", and started looking for that. This is how I discovered "The Sewer Massacre" [1], which is available under the GPL license. The Git repo contains indeed a file `curses.lisp'. This file uses the `CFFI' package, "The Common Foreign Function Interface" to talk with the ncurses library. Swank ----- Emacs gives a Common Lisp REPL through SLIME. This works wonderful. However, using ncurses to interact with the terminal screen is not possible this way. In order to let Clisp interact with the terminal and still have a REPL, one has to use Swank. This is used to create a running Lisp that listens to a port (default 4005). The command `M-x slime-connect' starts an interface in Emacs to this port to provide a REPL, It turned out it wasn't that difficult to get a running Clisp that listens to port 4005. Hello world ----------- Using my fresh Swank daemon, I started playing with the `curses.lisp' file. After loading the lisp packages `CFFI' and `trivial-gray-streams', and changing the library name into `libncurses.so.6' in the code, Clisp printed the famous "hello world" message using ncurses. And There Was Much Rejoicing... LINES and COLS -------------- In the (very) past, I have toyed with ncurses from C and Perl. I remembered using `LINES' and `COLS' to get the actual screen size. Unfortunately, the `curses.lisp' file doesn't export some function to retrieve these two variables. I tried to add a Lisp function, using CFFI, to request these values from ncurses. Which resulted in a crashing Swank session :) Next, I created a Lisp function to use the getmaxyx ncurses function. This resulted in the values 0 and 14. Searching the internet I ran into posts from people running in these same values, using different languages to interface with ncurses, which gave me an excuse not to blame it on my Lisp function, and concluded that using getmaxyx was perhaps not the best path. Terminal size ------------- Trying to discover more, I ran into a small Common lisp project called "terminal-size" [2]. This is available under the MIT license. `terminal-size' also uses CFFI, but it doesn't use ncurses. terminal-size depends on the Common Lisp `osicat' package. After loading CFFI and osicat, the function `(size)' reports a terminal width and height of 182 and 60. Mission accomplished :) Final words ----------- Learning Lisp is a hobby project that only allows for brief sessions. A seemingly trivial task --to get the terminal dimensions-- as a start for a small Clisp application, took me several days. It has not been a waste of time, I learned a lot along the road. From this perspective, attempting to get things functioning with Clisp rather than SBCL was beneficial. The additional challenges I had to tackle as a result created numerous learning opportunities. Happy Lisping! [1]: http://common-lisp.net/project/lifp/sewers-src.zip [2]: https://github.com/eudoxia0/terminal-size.git Last edited: $Date: 2024/05/17 13:29:37 $