mcparen / croatoan Goto Github PK
View Code? Open in Web Editor NEWCommon Lisp bindings for the ncurses terminal library.
License: Other
Common Lisp bindings for the ncurses terminal library.
License: Other
Since the upgrade to ncurses 6.2 the wbkgrnd function does not work properly any more.
More precisely, the wide-character background routine can not set anything but 7bit characters (0-127) as the window background.
A minimal example to reproduce the bug with SBCL/cffi:
(let ((scr (initscr)))
(cffi:with-foreign-objects ((ptr '(:struct cchar_t))
(wch 'wchar_t 5))
(dotimes (i 5)
(setf (cffi:mem-aref wch 'wchar_t i) 0))
;; 126 works 7bit
;; 161 doesnt work 8bit
(setf (cffi:mem-aref wch 'wchar_t 0) 126)
;;(setf (cffi:mem-aref wch 'wchar_t 0) #x2592)
(setcchar ptr wch 0 0 (cffi:null-pointer))
(wbkgrnd scr ptr)
(wrefresh scr)
(wgetch scr)
(endwin))))
The corresponding C function works for me, so I can not reproduce the Lisp bug in C:
#define _XOPEN_SOURCE_EXTENDED
#include <locale.h>
#include "/home/build/ncurses-6.2-20200328/include/curses.h"
int main()
{
cchar_t cch;
const wchar_t wch[2] = {L'\u2591', L'\0'};
setlocale(LC_ALL, "");
setcchar(&cch,
wch,
0,
0,
NULL);
initscr();
bkgrnd(&cch);
refresh();
getch();
endwin();
return 0;
}
The ncurses C function that does properly work with Lisp FFI: Link
The new version of the wkbgrnd function that does not work for 8bit and wide chars: Link
Is anybody knowlegeable enough about C or ncurses internals to identify the cause of this bug?
@McParen - I've been using cl-charms, but your library seems much nicer!
I've spent some effort trying to get swank to keep the repl going while a curses app is being worked on. In particular, I run a swank server and connect to it from emacs... I then call a function inside the main loop that keeps REPL interactive. During development, I often separate initialization, main loop iteration and termination; that way I can stop in the middle of the main loop - with the display active - and fix some functionality (obviously, can't always do that unless you indirect compiled calls in some places).
If you are interested I could put together a pull request.
I am also very curious about how you work with it. Do you run a swank server? Do you have a way of interactive development that is different from what I do?
Instead of drawing the last char of the choice string to the choice, why not draw something like .. or give a choice to what the last char drawn will be so that menu choices will look better.
Hey there :-)
Working on an adventure game, I noticed that when I hold down an arrow key for any length of time, the player character will continue travelling for quite some distance after I let go of the key. It seems to me that the act of holding down the key emits key events at a high frequency, and that these are stored in some sort of a stream until they can be processed by the program. Of course, this kind of "inertia" is no good for a game, and I would like to get rid of it. Is there currently a way to limit the maximum frequency at which key events are generated?
* To load "croatoan":
Load 1 ASDF system:
croatoan
; Loading "croatoan"
; in: DEFUN T03C
; (CLEAR SCR)
;
; caught STYLE-WARNING:
; undefined function: CLEAR
; (REFRESH SCR)
;
; caught STYLE-WARNING:
; undefined function: REFRESH
; (SCR :INPUT-ECHOING NIL :INPUT-BLOCKING T)
;
; caught STYLE-WARNING:
; undefined function: SCR
; (WITH-SCREEN (SCR :INPUT-ECHOING NIL :INPUT-BLOCKING T) (CLEAR SCR)
; (PRINC "Type chars. Type q to quit." SCR) (REFRESH SCR)
; (LOOP FOR CH = (READ-CHAR SCR)
; WHILE (NOT (EQUAL CH #\q))
; DO (PRINC CH SCR))
; (PRINC "You pressed q. Now press any char to quit." SCR) (READ-CHAR SCR))
;
; caught STYLE-WARNING:
; undefined function: WITH-SCREEN
;
; compilation unit finished
; Undefined functions:
; CLEAR REFRESH SCR WITH-SCREEN
; caught 4 STYLE-WARNING conditions
This is produced by evaluating the following code in emacs + slime, test t03c, with my code as follow
(ql:quickload :croatoan)
(defparameter scr nil)
(defun t03c ()
(with-screen (scr :input-echoing nil :input-blocking t)
(clear scr)
(princ "Type chars. Type q to quit." scr)
(refresh scr)
(loop for ch = (read-char scr)
while (not (equal ch #\q))
do (princ ch scr))
(princ "You pressed q. Now press any char to quit." scr)
(read-char scr)))
Hi,
I do not know if just me but after upgraded to sbcl 2.0.3 the support for widechar seems gone and, fir unicode characters, nothing is printed instead; to reproduce just run the test ut01
.
Bye!
C.
Hi!
I can see you are improving the library, thank you!
I have a little request: I need to use the function key_name
and, after checking the code, i found the file src/util.lisp
that in not in the ASDF file (please correct my if i am wrong). This file contains a little function: key-to-string
that i think could be useful even if it is just syntactic sugar. Moreover i can see in the same file some CFFI stuff that overlap with definitions in ncurses/util.lisp
; are the C functions src/util.lisp
be commented out if the latter file is included in ASDF system definition?
If this is all is needed to export the function key-to-string
i think i could take care of that with a pull request as these appears to be really simple changes.
Bye!
C.
Hi,
I'd like to build a small CLI using croatoan with sbcl and would need a bit of help to know how to achieve that. my running environment is Debian and bash terminal
Goal : have a CLI program started from bash which react similarly like other interpreters (take python as example).
I launch my sbcl program with cl-launch which work fine, but then my standard input is in cooked mode . Because of this I use croatoan doing
(croatoan:with-screen (scr :input-buffering nil :process-control-chars t
...)
so I can get each char typed one by one (cbreak mode)to catch up and down arrows (for command history) and tab for autocompletion.
I have a few undesirable effect when I am in the with-screen macro :
my screen in cleared (I don't see the past bash command end past output before my sbcl program was started)
when I close the with-screen macro I get back the output from my terminal.
when I do a (format t "abc~%123")
it prints 123 one line under abc but it doesn't print 123 at position 0 in that line. so I have to do a (format t "~c~%" #\return)
for a new line + carriage return.
when I check the key value for the pressed arrow keys I get #\Esc
like when I press the Escape key on my keyboard.
So how should I use croatoan to use my terminal window without a new screen even if I want to be in cbreak mode.
how can I get the value of the arrow keys so I can propose command line history like most shells do.
Thanks.
Hello, I'm new to Common Lisp development, and I'd like to write an ncurses
application and learn that alongside CL itself. I'm especially interested in the interactive development workflow, so I checked out the example in the doc
directory.
I'm stumbling over the following problem (tried both slynk
and swank
):
sbcl --load src/main.lisp
with the example code in the doc
. This shows me a gray, empty ncurses application inside the terminal.slime-connect
(or sly-connect
).WARNING: redefining SWANK::SYMBOL-INDENTATION in DEFUN
WARNING: redefining SWANK::MACRO-INDENTATION in DEFUN
WARNING:
redefining THREAD-FOR-EVALUATION (#<STRUCTURE-CLASS SWANK::MULTITHREADED-CONNECTION>
#<SB-MOP:EQL-SPECIALIZER :FIND-EXISTING>) in DEFMETHOD
After that, anything I do with croatoan
, like add-string
or refresh
or clear
, kind of works; by that I mean that they are seemingly operating on the remaining area of the terminal without the warnings. If I (croatoan:submit ...)
anything that leads to an error or warning, these are "posted" to the ncurses screen as well, further limiting my usable screen space.
Do you have any advice on what I might be doing wrong and/or misunderstanding here? I guess it's probably something basic.
Thank you very much!
sbcl 1.3.15
using croatoan from quicklisp
(defvar exsyms)
(setq exsyms (loop for x being each external-symbol in :croatoan collect x))
(.items set-mouse-event menu-window ....)
(length exsyms)
83
(member 'get-wide-char exsyms)
nil
I am running xterm and st terminals with TERM=xterm-256color.
Possibly because of that I am unable to see any ACS characters (they come out as q's and such). Have you any thoughts on how to fix that?
Hello!
Please, dear developers, can you write some documentation, examples? Missing list of functions. How do ncurses and croatoan compare?
Thanks!
I don't want to be annoying, but please do.
I get this:
; READ error during COMPILE-FILE: The symbol "SETLOCALE" is not external in the DE.ANVI.NCURSES package.
Full log here: http://report.quicklisp.org/2020-04-08/failure-report/croatoan.html#croatoan
Line 111 in 8a36ee1
#\horizontal_ellipsis is not a standard character is common-lisp, so will not be recognize by some implementations and wil get an error.
replacing it by (code-char #x2026)
make it poratble for all implementations.
Maybe make clearer to read by defining
(defconstant *horizontal-ellipsis-char* (code-char #x2026))
and then use *horizontal-ellipsis-char*.
Hi!
I am trying to access mouse event using bind
but i can not understand how to get the mouse coordinates of the event,
i tried using a code similar to the one below:
(bind croatoan-window
:button-1-clicked
(lambda (w event) ; event contains just the keyword :button-1-clicked
(declare (ignore w event))
(format t "~a" (multiple-value-list (croatoan:get-mouse-event)
But the coordinates are always both 0.
Is there a way to get that information using bind or should i use an explicit event loop instead?
Edit:
I just modified the handle-events
function to allow getting the mouse events in bind using code like that:
(bind croatoan-window
:button-1-clicked
(lambda (w event mouse-x mouse-y))) ; event contains the keyword :button-1-clicked and coordinates (x, y)
This is the modified function:
EDIT2, modified function below
(defun handle-events (object args)
"Read a single event from the user, lookup a handler and apply it."
(multiple-value-bind (event mouse-x mouse-y)
(get-wide-event object)
(if event
;; t
(progn
(run-hook object 'before-event-hook)
(if (and mouse-x mouse-y)
(handle-event object event (append (list mouse-x mouse-y) args))
(handle-event object event args))
(run-hook object 'after-event-hook))
;; The nil (idle) event should be defined directly in the object's bindings/keymap.
;; It has to be handled separately to allow handling of chained events.
(let ((handler (get-event-handler object event)))
(when handler
(if (and mouse-x mouse-y)
(apply-handler handler object event (append (list mouse-x mouse-y) args))
(apply-handler handler object event args)))))))
I would propose this as a patch but i fear i likely i broke some other procedures with this changes, but if it is both harmless and useful, instead, i would happily propose this code as a pull request!
Thanks!
C.
Hello!
Thank you for this library, i can see this is the results of a lot of hard work!
Maybe i spotted a minor issue with the docstring of bind
(or i missed something, not sure :-) )
If a handler for the event :default is defined, it will handle all events for which
no specific event handler has been defined.
I think :default
should be t
instead, is it?
bye!
C.
Hi @McParen !
I think something changed in the way a message-text
is managed in a dialog window.
To show what i mean is sufficient to change these lines (example t19f
):
https://github.com/McParen/croatoan/blob/master/test/clos.lisp#L2592
(let* ((items (list "Yes" "No" "OK" 'cancel))
to:
(let* ((items (list "Yes" "No"))
and this one:
https://github.com/McParen/croatoan/blob/master/test/clos.lisp#L2599
:layout (list 1 4)
What we get here is that the message text is fitted (but with words truncated) at a with equal to the cumulative items length instead of fill the windows width.
I do not know if this is actually is a bug or intentional but i am quite sure this behaviour was added in one of the latest commits.
I investigated this a bit and i found that if in this line:
https://github.com/McParen/croatoan/blob/master/src/classes.lisp#L665
we substitute:
:width (* (cadr layout) item-length)))
with:
:width width
The message text expands to fill the window but is is still somehow truncated (something with pad i guess).
If this is indeed a bug i can submit a PR with the changes above, but i am reluctant because i do not think this is enough.
If this is a bug and you are OK to help me with suggestions i can try to get a proper fix.
Bye!
C.
Hi McParent
I am getting problems compiling my application because the compiler can not find the function mentioned in the subject.
Bye!
C.
Reason being you can't #'length a complex-string, which is what happens in the let form inside #'add-string.
At the moment, the simple croatoan class hierarchy looks like this:
widget --> window --> screen
--> sub-window
--> extended-window
--> pad --> sub-pad
--> panel
--> element --> field
--> button
--> label
--> checkbox --> menu-item
--> menu --> menu-window --> dialog-window
--> menu-panel
--> checklist
--> form --> form-window
For historical reasons, both window and element have separate slots and differently named accessors for the position, window-position and element-position, because just "position" is taken by cl:position, which is unfortunate.
I would like to fix that and have a single accessor for the position of all visible widgets, which would mean moving the y and x slots from element and window up to the parent widget class, but I am uncertain about what accessor name should be picked that would sound most "natural" for all visible objects.
Alternative 1: Use "widget-position" for everything. That would lead to calls like (widget-position win) and (widget-position field), etc., which is okay but for me doesnt sound "nice" and "natural" in this context.
Alternative 2: Add widget-position, but also keep using different accessors that accomplish the same, window-position, element-position, etc.
Alternative 3: Shadow cl:position and use the fully qualified name crt:position, which would be the cleanest solution, but which would lead to naming conflicts to everybody who :uses the whole package.
Any thoughts about this?
Hi,
I know it's not too common to use versioned tags and releases among Common Lisp projects but it would help to improve package distribution via Guix where it's pined to the latest commit which is not convenient to keep up-to-date.
How hard would it be to use versioned tag for the project?
Thanks,
Oleg
First off, thanks for the project, it looks really great.
Now, on to my question:
http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/forms.html
Just wondering if there was support or bindings for forms built in? Preferably in a CLOS or simplified manner?
If not, do you know if cl-charms supports it? (or, if there are low level cffi calls available, or would I need to run form.h through swig or something to generate bindings?)
Noticed this in my own program, confirmed with the (test1) example; about 1 in 5 keypresses don't get noticed by croatoan. This occurred while testing both the (event-case) loop and just (get-event). In all cases input-blocking is t.
Further testing revealed this only occurs when connecting from slime. Running straight from command-line sbcl behaves normally.
SBCL 1.4.5 Ubuntu 18.04
Hi @McParen !
Seems that there is some spurious code in croatoan.lisp here:
https://github.com/McParen/croatoan/blob/master/src/croatoan.lisp#L221
That prevents compilation, i commented the last form that starts with ((listp...
and everything to appears to work fine, then. But i am not sure if i did it well! ๐
Anyway let me wish you: seasons greetings!
C.
I get this:
Unhandled SB-EXT:SYMBOL-PACKAGE-LOCKED-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING {1002F276A3}>: Lock on package COMMON-LISP violated when defining ERROR as a constant while in package DE.ANVI.NCURSES.
http://report.quicklisp.org/2015-07-29/failure-report/croatoan.html#croatoan has a longer log.
There seems to be no way to check if close
(%delwin
) was called on a window.
As a workaround i wrap window
and set winptr
to nil
when close
is called. As this is a common use case, it would be a nice feature if it was added to croatoan.
Hi @McParen !
In all these months i wrote a few little functions that i found useful when working with complex-string
, i believe this code could be of general use, so i wonder if i could make a PR to include this functions into the library so that other people can use them.
The original program is licensed under GPLv3 or later but, as i am the only author of the following code i can re-license with MIT for this library.
The links to said function follows:
https://notabug.org/cage/tinmop/src/master/src/tui-utils.lisp#L94
https://notabug.org/cage/tinmop/src/master/src/tui-utils.lisp#L125
https://notabug.org/cage/tinmop/src/master/src/tui-utils.lisp#L127
https://notabug.org/cage/tinmop/src/master/src/tui-utils.lisp#L194
https://notabug.org/cage/tinmop/src/master/src/tui-utils.lisp#L261
As you can see they are quite simple, so i am not even sure if there was not a way to do this kind of text manipulation using existing functions in Croatoan
, if so just close this issue.
Looking forward to your comments!
Bye!
C.
Hi McParen,
i would like to use the 24bit RGB color on my application but i think the library coerce the 8 bit color to 6 bit color even if the terminal support color specified as 8 bit per channel.
I wonder if checking if a terminal support 24bit color and bypass the conversion 8bit to 6bit could suffice.
I have found this document to checks if a terminal support 24bit colors
https://gist.github.com/XVilka/8346728#true-color-detection
it is not perfect but should not give false positive, at least.
What do you think?
Bye!
C.
There is no curses library definition for MS Windows, so the build fails.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.