Or see the list of project sponsors.
Documentation | 🥺 |
Docstrings | 🤨 |
Tests | 🥺 |
Examples | 😀 |
RepositoryActivity | 🤨 |
CI | 🤨 |
Two days ago I reviewed the cl-ncurses. CL-Charms
is also a binding to ncurses
, but uses more universal and portable CFFI instead of UFFI.
By the way, LEM (Common Lisp Emacs) uses cl-charms
for it's console backend.
CL-Charms
provides a high-level API besides a low level. I've ported my previous echo
program to it:
(defun main (&rest argv)
(declare (ignorable argv))
(with-curses ()
(enable-raw-input)
(enable-extra-keys *standard-window*)
(disable-echoing)
(write-string-at-cursor *standard-window*
"Type any character to see it in bold:
")
(let ((ch (get-char *standard-window*)))
(cond
((eql ch (code-char 265))
(write-string-at-cursor *standard-window*
"F1 Key pressed"))
(t
(write-string-at-cursor *standard-window*
"The pressed key is ")
(cl-charms/low-level:attron cl-charms/low-level:a_bold)
(write-string-at-cursor *standard-window*
(format nil "~A~%" ch))
(cl-charms/low-level:attroff cl-charms/low-level:a_bold)))
(get-char *standard-window*))))
Interesting that cl-charms/low-level
package can be used as a drop-in replacement for cl-ncurses
and my second example worked without any changes except a change in the use clause.
I must admit, that working with such kind of bindings can be problematic. For example, I haven't any problems using neither cl-ncurses
nor cl-charms
on OSX, but there was a problem with starting an example program on Ubuntu Bionic.
On Ubuntu cl-ncurses
is unable to find libncurses.so
and you have to load it manually like that:
;; These paths are harcoded in the cl-ncurses:
(defvar *ncurses-search-paths*
#-win32'("/usr/local/lib64/" "/usr/local/lib/" "/lib64/" "/lib/" "/usr/lib64/" "/usr/lib/")
#+win32'("/users/jacob/src/pdc31dll/"))
;; On Ubuntu Bionic you have to add this
;; before cl-ncurses initscr call:
(uffi:load-foreign-library "/lib/x86_64-linux-gnu/libncurses.so.5.9"
:module "cl-ncurses")
CL-Charms
has another problem. It requires the libncurses5-dev
package to be installed on Ubuntu. Without that, it has problem when compiling the CFFI Grovel's files:
; cc -o /root/.cache/common-lisp/sbcl-1.5.6-linux-x64/root/.roswell/lisp/quicklisp/dists/quicklisp/software/cl-charms-20200218-git/src/low-level/curses-grovel__grovel-tmpBF3HHBTQ.o -c -g -Wall -Wundef -Wsign-compare -Wpointer-arith -O3 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wunused-parameter -fno-omit-frame-pointer -momit-leaf-frame-pointer -fno-pie -fPIC -I/root/.roswell/lisp/quicklisp/dists/quicklisp/software/cffi_0.21.0/ /root/.cache/common-lisp/sbcl-1.5.6-linux-x64/root/.roswell/lisp/quicklisp/dists/quicklisp/software/cl-charms-20200218-git/src/low-level/curses-grovel__grovel.c
/root/.cache/common-lisp/sbcl-1.5.6-linux-x64/root/.roswell/lisp/quicklisp/dists/quicklisp/software/cl-charms-20200218-git/src/low-level/curses-grovel__grovel.c:6:10: fatal error: ncurses.h: No such file or directory
#include <ncurses.h>
^~~~~~~~~~~
compilation terminated.
Unhandled CFFI-GROVEL:GROVEL-ERROR in thread #<error printing a SB-THREAD:THREAD: #<PRINT-NOT-READABLE {10042938A3}>>: Subprocess #<UIOP/LAUNCH-PROGRAM::PROCESS-INFO {100428DCF3}>
with command ("cc" "-o" "/root/.cache/common-lisp/sbcl-1.5.6-linux-x64/root/.roswell/lisp/quicklisp/dists/quicklisp/software/cl-charms-20200218-git/src/low-level/curses-grovel__grovel-tmpBF3HHBTQ.o" "-c" "-g" "-Wall" "-Wundef" "-Wsign-compare" "-Wpointer-arith" "-O3" "-D_LARGEFILE_SOURCE" "-D_LARGEFILE64_SOURCE" "-D_FILE_OFFSET_BITS=64" "-Wunused-parameter" "-fno-omit-frame-pointer" "-momit-leaf-frame-pointer" "-fno-pie" "-fPIC" "-I/root/.roswell/lisp/quicklisp/dists/quicklisp/software/cffi_0.21.0/" "/root/.cache/common-lisp/sbcl-1.5.6-linux-x64/root/.roswell/lisp/quicklisp/dists/quicklisp/software/cl-charms-20200218-git/src/low-level/curses-grovel__grovel.c")
exited with error code 1
Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {10004F04C3}>
0: (SB-DEBUG::DEBUGGER-DISABLED-HOOK #<CFFI-GROVEL:GROVEL-ERROR "~a" {1004291F73}> #<unused argument> :QUIT T)
1: (SB-DEBUG::RUN-HOOK *INVOKE-DEBUGGER-HOOK* #<CFFI-GROVEL:GROVEL-ERROR "~a" {1004291F73}>)
2: (INVOKE-DEBUGGER #<CFFI-GROVEL:GROVEL-ERROR "~a" {1004291F73}>)
3: (ERROR CFFI-GROVEL:GROVEL-ERROR :FORMAT-CONTROL "~a" :FORMAT-ARGUMENTS (#<UIOP/RUN-PROGRAM:SUBPROCESS-ERROR {10042917F3}>))
4: (CFFI-GROVEL:GROVEL-ERROR "~a" #<UIOP/RUN-PROGRAM:SUBPROCESS-ERROR {10042917F3}>)
5: ((FLET "THUNK" :IN CFFI-GROVEL:PROCESS-GROVEL-FILE))
Probably, @borodust's claw and bodge-blobs-support can solve these issues?