mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-08 15:49:03 -05:00
Initialize Readline on demand
Eliminate NCDIRECT_OPTION_NO_READLINE (it was only introduced in Notcurses 2.1.6). Add a new function, ncdirect_readline(). Upon first call to this function, initialize libreadline. Destroy libreadline in ncdirect_stop() iff we initialized it. Add hilodirect guessing game PoC from #1325. Rename notcurses_directmode.3 to notcurses_direct.3. Closes #1326.
This commit is contained in:
parent
5afa3f14a9
commit
b3569b6aef
4
NEWS.md
4
NEWS.md
@ -4,6 +4,10 @@ rearrangements of Notcurses.
|
||||
* 2.1.8 (not yet released):
|
||||
* The `notcurses-tetris` binary has been renamed `nctetris`.
|
||||
* The new function `channel_set_palindex()` has been added.
|
||||
* `NCDIRECT_OPTION_NO_READLINE` has been removed after a short life.
|
||||
* `ncdirect_readline()` has been added. The first time used, it initializes
|
||||
Readline. Readline will be destroyed by ncdirect_stop() if it was ever
|
||||
initialized.
|
||||
|
||||
* 2.1.7 (2021-01-21):
|
||||
* Notcurses has been split into two libraries, `notcurses-core` and
|
||||
|
@ -29,7 +29,7 @@ relies on the font. Patches to correct/complete this table are very welcome!
|
||||
| mlterm | ❌ |? |`TERM=mlterm-256color` | Do not set `COLORTERM`. `mlterm-direct` gives strange results. |
|
||||
| PuTTY | ❌ |❌ |`TERM=putty-256color` `COLORTERM=24bit` | |
|
||||
| rxvt | ? |? | | |
|
||||
| Sakura | ✅ |? |`TERM=vte-256color` `COLORTERM=24bit` | No terminfo entry? |
|
||||
| Sakura | ✅ |? |`TERM=vte-256color` `COLORTERM=24bit` | VTE-derived, no terminfo entry. |
|
||||
| GNU Screen | ❌ |? |`TERM=screen.OLDTERM` | Must be compiled with `--enable-256color`. `TERM` should typically be `screen.` suffixed by the appropriate `TERM` value for the true connected terminal, e.g. `screen.vte-256color`. See below. |
|
||||
| st ("suckless") | ✅ |? |`TERM=st-256color` `COLORTERM=24bit` | |
|
||||
| Terminator | ? |? | ? | |
|
||||
|
15
USAGE.md
15
USAGE.md
@ -334,11 +334,16 @@ struct ncdirect* ncdirect_core_init(const char* termtype, FILE* fp, uint64_t fla
|
||||
// prior to notcurses_init(), you should not set this bit. Even if you are
|
||||
// invoking setlocale(), this behavior shouldn't be an issue unless you're
|
||||
// doing something weird (setting a locale not based on LANG).
|
||||
#define NCDIRECT_OPTION_INHIBIT_SETLOCALE 0x0001ull
|
||||
#define NCDIRECT_OPTION_INHIBIT_SETLOCALE 0x0001ull
|
||||
|
||||
// *Don't* place the terminal into cbreak mode (see tcgetattr(3)). By default,
|
||||
// echo and line buffering are turned off.
|
||||
#define NCDIRECT_OPTION_INHIBIT_CBREAK 0x0002ull
|
||||
#define NCDIRECT_OPTION_INHIBIT_CBREAK 0x0002ull
|
||||
|
||||
// We typically install a signal handler for SIG{INT, SEGV, ABRT, QUIT} that
|
||||
// restores the screen, and then calls the old signal handler. Set to inhibit
|
||||
// registration of these signal handlers. Chosen to match fullscreen mode.
|
||||
#define NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS 0x0008ull
|
||||
|
||||
// Release 'nc' and any associated resources. 0 on success, non-0 on failure.
|
||||
int ncdirect_stop(struct ncdirect* nc);
|
||||
@ -348,6 +353,12 @@ This context must be destroyed using `ncdirect_stop()`. The following functions
|
||||
are available for direct mode:
|
||||
|
||||
```c
|
||||
// Read a (heap-allocated) line of text using the Readline library Initializes
|
||||
// Readline the first time it's called. For input to be echoed to the terminal,
|
||||
// it is necessary that NCDIRECT_OPTION_INHIBIT_CBREAK be provided to
|
||||
// ncdirect_init(). Returns NULL on error.
|
||||
API char* ncdirect_readline(struct ncdirect* nc, const char* prompt);
|
||||
|
||||
int ncdirect_fg_rgb(struct ncdirect* nc, unsigned rgb);
|
||||
int ncdirect_bg_rgb(struct ncdirect* nc, unsigned rgb);
|
||||
|
||||
|
@ -7,7 +7,7 @@ rendering; output is intended to appear immediately (subject to buffering). It
|
||||
is still necessary to have a valid `TERM` environment variable identifying a
|
||||
valid terminfo database entry for the running terminal.
|
||||
|
||||
The authoritative reference for direct mode is the `notcurses_directmode(3)`
|
||||
The authoritative reference for direct mode is the `notcurses_direct(3)`
|
||||
man page.
|
||||
|
||||
Enter direct mode with a call to `ncdirect_init()`. It takes three arguments:
|
||||
|
@ -44,7 +44,7 @@
|
||||
<a href="notcurses_cell.3.html">notcurses_cell</a>—operations on <tt>nccell</tt> objects<br/>
|
||||
<a href="notcurses_channels.3.html">notcurses_channels</a>—operations on the <tt>channel</tt> type<br/>
|
||||
<a href="notcurses_core.3.html">notcurses_core</a>—linking against a minimal Notcurses<br/>
|
||||
<a href="notcurses_directmode.3.html">notcurses_directmode</a>—minimal notcurses instances for styling text<br/>
|
||||
<a href="notcurses_direct.3.html">notcurses_direct</a>—minimal notcurses instances for styling text<br/>
|
||||
<a href="notcurses_fade.3.html">notcurses_fade</a>—fading and pulsing for <tt>ncplane</tt>s<br/>
|
||||
<a href="notcurses_fds.3.html">notcurses_fds</a>—dumping file descriptors/subprocesses to <tt>ncplane</tt>s<br/>
|
||||
<a href="notcurses_init.3.html">notcurses_init</a>—initialization<br/>
|
||||
|
@ -47,7 +47,7 @@ for the actual terminal must be available.
|
||||
**ncdirect_init(3)** makes available a very restricted subset of
|
||||
Notcurses functionality. This subset is intended to be interleaved with
|
||||
user-generated output, and is limited to coloring and styling. Direct mode is
|
||||
documented in **notcurses_directmode(3)**.
|
||||
documented in **notcurses_direct(3)**.
|
||||
|
||||
## Output
|
||||
|
||||
@ -165,7 +165,7 @@ order to turn most error returns into exceptions.
|
||||
**notcurses_capabilities(3)**,
|
||||
**notcurses_cell(3)**,
|
||||
**notcurses_channels(3)**,
|
||||
**notcurses_directmode(3)**,
|
||||
**notcurses_direct(3)**,
|
||||
**notcurses_fade(3)**,
|
||||
**notcurses_fds(3)**,
|
||||
**notcurses_init(3)**,
|
||||
|
@ -1,10 +1,10 @@
|
||||
% ncdirect_init(3)
|
||||
% notcurses_direct(3)
|
||||
% nick black <nickblack@linux.com>
|
||||
% v2.1.7
|
||||
|
||||
# NAME
|
||||
|
||||
ncdirect_init - minimal notcurses instances for styling text
|
||||
notcurses_direct - minimal notcurses instances for styling text
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
@ -13,7 +13,6 @@ ncdirect_init - minimal notcurses instances for styling text
|
||||
|
||||
#define NCDIRECT_OPTION_INHIBIT_SETLOCALE 0x0001ull
|
||||
#define NCDIRECT_OPTION_INHIBIT_CBREAK 0x0002ull
|
||||
#define NCDIRECT_OPTION_NO_READLINE 0x0004ull
|
||||
#define NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS 0x0008ull
|
||||
```
|
||||
|
||||
@ -85,6 +84,8 @@ ncdirect_init - minimal notcurses instances for styling text
|
||||
|
||||
**int ncdirect_render_image(struct ncdirect* ***n***, const char* ***filename***, ncblitter_e ***blitter***, ncscale_e ***scale***);**
|
||||
|
||||
**char* ncdirect_readline(struct ncdirect* ***n***, const char* ***prompt***);**
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
**ncdirect_init** prepares the **FILE** provided as **fp** for colorizing and
|
||||
@ -108,10 +109,6 @@ The following flags are defined:
|
||||
will place the terminal into cbreak mode (i.e. disabling echo and line
|
||||
buffering; see **tcgetattr(3)**).
|
||||
|
||||
* **NCDIRECT_OPTION_NO_READLINE**: Unless this flag is set, **ncdirect_init**
|
||||
will initialize GNU Readline so that it can be safely used together with
|
||||
direct mode. With this flag, no calls are made to GNU Readline.
|
||||
|
||||
* **NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS**: A signal handler will usually be
|
||||
installed for **SIGINT**, **SIGQUIT**, **SIGSEGV**, **SIGTERM**, and
|
||||
**SIGABRT**, cleaning up the terminal on such exceptions. With this flag,
|
||||
@ -141,6 +138,12 @@ output stream, taking effect immediately.
|
||||
Attempting to e.g. move up while on the top row will return 0, but have no
|
||||
effect.
|
||||
|
||||
**ncdirect_readline** uses the Readline library to read a (heap-allocated)
|
||||
line of arbitrary length, supporting line-editing controls. For more
|
||||
information, consult **readline(3)**. If you want input echoed to the
|
||||
terminal while using **ncdirect_readline**, **NCDIRECT_OPTION_INHIBIT_CBREAK**
|
||||
must be supplied to **ncdirect_init**.
|
||||
|
||||
# RETURN VALUES
|
||||
|
||||
**ncdirect_init** returns **NULL** on failure. Otherwise, the return value
|
@ -25,11 +25,6 @@ typedef struct ncplane ncdirectv;
|
||||
// echo and input's line buffering are turned off.
|
||||
#define NCDIRECT_OPTION_INHIBIT_CBREAK 0x0002ull
|
||||
|
||||
// We typically initialize the GNU Readline library in a way that works with
|
||||
// ncdirect. If you intend no use of GNU Readline, this flag will inhibit any
|
||||
// such setup/teardown.
|
||||
#define NCDIRECT_OPTION_NO_READLINE 0x0004ull
|
||||
|
||||
// We typically install a signal handler for SIG{INT, SEGV, ABRT, QUIT} that
|
||||
// restores the screen, and then calls the old signal handler. Set to inhibit
|
||||
// registration of these signal handlers. Chosen to match fullscreen mode.
|
||||
@ -48,6 +43,12 @@ API struct ncdirect* ncdirect_init(const char* termtype, FILE* fp, uint64_t flag
|
||||
// allowing for a svelter binary. Link with notcurses-core if this is used.
|
||||
API struct ncdirect* ncdirect_core_init(const char* termtype, FILE* fp, uint64_t flags);
|
||||
|
||||
// Read a (heap-allocated) line of text using the Readline library Initializes
|
||||
// Readline the first time it's called. For input to be echoed to the terminal,
|
||||
// it is necessary that NCDIRECT_OPTION_INHIBIT_CBREAK be provided to
|
||||
// ncdirect_init(). Returns NULL on error.
|
||||
API char* ncdirect_readline(struct ncdirect* nc, const char* prompt);
|
||||
|
||||
// Direct mode. This API can be used to colorize and stylize output generated
|
||||
// outside of notcurses, without ever calling notcurses_render(). These should
|
||||
// not be intermixed with standard Notcurses rendering.
|
||||
|
@ -309,7 +309,7 @@ detect_cursor_inversion_wrapper(ncdirect* n, int* y, int* x){
|
||||
|
||||
// no terminfo capability for this. dangerous--it involves writing controls to
|
||||
// the terminal, and then reading a response. many things can distupt this
|
||||
// non-atomic procedure.
|
||||
// non-atomic procedure, leading to unexpected results. a garbage function.
|
||||
int ncdirect_cursor_yx(ncdirect* n, int* y, int* x){
|
||||
struct termios termio, oldtermios;
|
||||
// this is only meaningful for real terminals
|
||||
@ -321,7 +321,7 @@ int ncdirect_cursor_yx(ncdirect* n, int* y, int* x){
|
||||
return -1;
|
||||
}
|
||||
memcpy(&oldtermios, &termio, sizeof(termio));
|
||||
// we should already be in cbreak mode from ncdirect_init(), but just in case
|
||||
// we might already be in cbreak mode from ncdirect_init(), but just in case
|
||||
// it got changed by the client code since then, duck into cbreak mode anew.
|
||||
termio.c_lflag &= ~(ICANON | ECHO);
|
||||
if(tcsetattr(n->ctermfd, TCSAFLUSH, &termio)){
|
||||
@ -597,7 +597,7 @@ static int
|
||||
ncdirect_stop_minimal(void* vnc){
|
||||
ncdirect* nc = static_cast<ncdirect*>(vnc);
|
||||
int ret = drop_signals(nc);
|
||||
if(!(nc->flags & NCDIRECT_OPTION_NO_READLINE)){
|
||||
if(nc->initialized_readline){
|
||||
rl_deprep_terminal();
|
||||
}
|
||||
if(nc->tcache.op && term_emit("op", nc->tcache.op, nc->ttyfp, true)){
|
||||
@ -673,13 +673,7 @@ ncdirect* ncdirect_core_init(const char* termtype, FILE* outfp, uint64_t flags){
|
||||
if(interrogate_terminfo(&ret->tcache, shortname_term)){
|
||||
goto err;
|
||||
}
|
||||
ret->channels = 0;
|
||||
ncdirect_set_styles(ret, 0);
|
||||
if(!(flags & NCDIRECT_OPTION_NO_READLINE)){
|
||||
rl_outstream = stderr;
|
||||
rl_instream = stdin;
|
||||
rl_prep_terminal(1); // 1 == read 8-bit input
|
||||
}
|
||||
return ret;
|
||||
|
||||
err:
|
||||
@ -701,6 +695,16 @@ int ncdirect_stop(ncdirect* nc){
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* ncdirect_readline(ncdirect* n, const char* prompt){
|
||||
if(!n->initialized_readline){
|
||||
rl_outstream = n->ttyfp;
|
||||
rl_instream = stdin;
|
||||
rl_prep_terminal(1); // 1 == read 8-bit input
|
||||
n->initialized_readline = true;
|
||||
}
|
||||
return readline(prompt);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ncdirect_style_emit(ncdirect* n, unsigned stylebits, FILE* out){
|
||||
int r = -1;
|
||||
|
@ -310,6 +310,7 @@ typedef struct ncdirect {
|
||||
// typical order. we detect it the first time ncdirect_cursor_yx() is called.
|
||||
bool detected_cursor_inversion; // have we performed inversion testing?
|
||||
bool inverted_cursor; // does the terminal return inverted coordinates?
|
||||
bool initialized_readline; // have we initialized Readline?
|
||||
uint64_t flags; // copied in ncdirect_init() from param
|
||||
} ncdirect;
|
||||
|
||||
|
39
src/poc/hilodirect.c
Normal file
39
src/poc/hilodirect.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include <limits.h>
|
||||
#include <notcurses/direct.h>
|
||||
|
||||
int main(void){
|
||||
srand(time(NULL)); // gross
|
||||
long guess, secret = random();
|
||||
struct ncdirect* n = ncdirect_core_init(NULL, stdout, NCDIRECT_OPTION_INHIBIT_CBREAK);
|
||||
if(n == NULL){
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
int r = 0;
|
||||
do{
|
||||
if(!(r |= (ncdirect_set_fg_default(n)))){
|
||||
if(!(r |= (printf("Guess the long: ") < 0))){
|
||||
if(!fflush(stdout)){
|
||||
int rargs = scanf("%ld", &guess); // super shitty to the max
|
||||
if(rargs != 1){
|
||||
fprintf(stderr, "Die, infidel!\n");
|
||||
ncdirect_stop(n);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
int offoom = labs(__builtin_clzl(guess) - __builtin_clzl(secret));
|
||||
if(guess > secret){
|
||||
r |= ncdirect_set_fg_rgb8(n, 0x40, 0x80, offoom * 6);
|
||||
r |= (printf("\tLOL jabronies guess %ld. Too high!\n", guess) < 0);
|
||||
}else if(guess < secret){
|
||||
r |= ncdirect_set_fg_rgb8(n, offoom * 6, 0x80, 0x40);
|
||||
r |= (printf("\tSpineless worm! %ld? Too low!\n", guess) < 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}while(guess != secret && !r);
|
||||
if(r || printf("You enjoy 20/20 vision into the minds of antimen!\n") < 0){
|
||||
ncdirect_stop(n);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return ncdirect_stop(n) ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user