Guile Ncurses Has a Live Editor!

February 02, 2020

curses is a commandline user interface creation library that allows programmers to make really useful TUI programs (like nano, cmus, and top). ncurses is the modern, more robust, still-maintained successor to curses.

guile-ncurses is a set of ncurses bindings for GNU Guile that I admittedly haven't used until this morning. Thankfully, the bindings have some solid documentation (guile-gl could learn a few things from it!)


Hello, World!

The bindings blend in with Guile's syntax perfectly. So far I have absolutely no gripes with it. Check out this "Hello World" program to see what I mean:

;; Hello World in Guile ncurses.
(use-modules (ncurses curses)) ;Use the curses bindings.

(define stdscr (initscr)) ;Initialize the window.
(addstr stdscr "Hello, World!") ;Add text to our window.
(refresh stdscr) ;Refresh to actually draw the text.
(getch stdscr) ;Wait for user input.
(endwin) ;End curses mode and exit the program

If you compare it with the C version below, you'll notice that they mirror eachother gracefully:

/*Hello World in C using ncurses.*/
#include <ncurses.h>

int
main()
{
        initscr(); /* Start curses mode. */
        printw("hello world!"); /* Print some text. */
        refresh(); /* Draw the text to the screen
        getch(); /* Wait for user input. */
        endwin(); /* end curses mode. */
        return 0; /* No errors here! */
}

I haven't run any extensive unit tests, but guile-ncurses 3.0 feels very solid.


Guile Ncurses' Live REPL

What I was most surprised by is the built-in live editor for guile-ncurses. Running the command guile-ncurses-shell starts the guile-ncurses interpreter (which is a regular Guile REPL that runs alongside a connected terminal window) Here's an example, starring lyrics from Strangers in the Night:

[muto@kahlua]$ guile-ncurses-shell
scheme@(guile-user)> (define my-scr (initscr))
scheme@(guile-user)> (define msg "Love was just a glance away")
scheme@(guile-user)> (define max-row (getmaxx my-scr))
scheme@(guile-user)> (define max-col (getmaxy my-scr))

scheme@(guile-user)> (move my-scr
                      (round (/ max-row 2))
                      (round (/ (- max-col
                                   (string-length msg)) 2)))

scheme@(guile-user)> (addstr my-scr msg)
scheme@(guile-user)> (addstr my-scr
                      (format #f "A warm, embracing dance away")
                      max-row
                      max-col
                      #:y (- max-row 2)
                      #:x 0)

scheme@(guile-user)> (refresh my-scr)

The above code snippet, if run in the guile-ncurses-shell REPL, will display the lyric "Love was just a glance away" in the center of the connected terminal, and "A warm, embracing dance away" at the bottom left.


Final Thoughts

I really enjoyed playing around with guile-ncurses and I'm surprised at how complete it feels. Not too many people create CLI programs anymore, in fact, it's treated like a niche! Anyway, I'm going to continue using these bindings and ncurses in general, I just really needed to advertise guile-ncurses for a moment. Thanks for reading!

(Also, today is 02/02/2020 which is the same backwards. Crazy stuff.)