mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04: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):
|
* 2.1.8 (not yet released):
|
||||||
* The `notcurses-tetris` binary has been renamed `nctetris`.
|
* The `notcurses-tetris` binary has been renamed `nctetris`.
|
||||||
* The new function `channel_set_palindex()` has been added.
|
* 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):
|
* 2.1.7 (2021-01-21):
|
||||||
* Notcurses has been split into two libraries, `notcurses-core` and
|
* 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. |
|
| mlterm | ❌ |? |`TERM=mlterm-256color` | Do not set `COLORTERM`. `mlterm-direct` gives strange results. |
|
||||||
| PuTTY | ❌ |❌ |`TERM=putty-256color` `COLORTERM=24bit` | |
|
| PuTTY | ❌ |❌ |`TERM=putty-256color` `COLORTERM=24bit` | |
|
||||||
| rxvt | ? |? | | |
|
| 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. |
|
| 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` | |
|
| st ("suckless") | ✅ |? |`TERM=st-256color` `COLORTERM=24bit` | |
|
||||||
| Terminator | ? |? | ? | |
|
| Terminator | ? |? | ? | |
|
||||||
|
11
USAGE.md
11
USAGE.md
@ -340,6 +340,11 @@ struct ncdirect* ncdirect_core_init(const char* termtype, FILE* fp, uint64_t fla
|
|||||||
// echo and line buffering are turned off.
|
// 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.
|
// Release 'nc' and any associated resources. 0 on success, non-0 on failure.
|
||||||
int ncdirect_stop(struct ncdirect* nc);
|
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:
|
are available for direct mode:
|
||||||
|
|
||||||
```c
|
```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_fg_rgb(struct ncdirect* nc, unsigned rgb);
|
||||||
int ncdirect_bg_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
|
is still necessary to have a valid `TERM` environment variable identifying a
|
||||||
valid terminfo database entry for the running terminal.
|
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.
|
man page.
|
||||||
|
|
||||||
Enter direct mode with a call to `ncdirect_init()`. It takes three arguments:
|
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_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_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_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_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_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/>
|
<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
|
**ncdirect_init(3)** makes available a very restricted subset of
|
||||||
Notcurses functionality. This subset is intended to be interleaved with
|
Notcurses functionality. This subset is intended to be interleaved with
|
||||||
user-generated output, and is limited to coloring and styling. Direct mode is
|
user-generated output, and is limited to coloring and styling. Direct mode is
|
||||||
documented in **notcurses_directmode(3)**.
|
documented in **notcurses_direct(3)**.
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ order to turn most error returns into exceptions.
|
|||||||
**notcurses_capabilities(3)**,
|
**notcurses_capabilities(3)**,
|
||||||
**notcurses_cell(3)**,
|
**notcurses_cell(3)**,
|
||||||
**notcurses_channels(3)**,
|
**notcurses_channels(3)**,
|
||||||
**notcurses_directmode(3)**,
|
**notcurses_direct(3)**,
|
||||||
**notcurses_fade(3)**,
|
**notcurses_fade(3)**,
|
||||||
**notcurses_fds(3)**,
|
**notcurses_fds(3)**,
|
||||||
**notcurses_init(3)**,
|
**notcurses_init(3)**,
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
% ncdirect_init(3)
|
% notcurses_direct(3)
|
||||||
% nick black <nickblack@linux.com>
|
% nick black <nickblack@linux.com>
|
||||||
% v2.1.7
|
% v2.1.7
|
||||||
|
|
||||||
# NAME
|
# NAME
|
||||||
|
|
||||||
ncdirect_init - minimal notcurses instances for styling text
|
notcurses_direct - minimal notcurses instances for styling text
|
||||||
|
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
|
|
||||||
@ -13,7 +13,6 @@ ncdirect_init - minimal notcurses instances for styling text
|
|||||||
|
|
||||||
#define NCDIRECT_OPTION_INHIBIT_SETLOCALE 0x0001ull
|
#define NCDIRECT_OPTION_INHIBIT_SETLOCALE 0x0001ull
|
||||||
#define NCDIRECT_OPTION_INHIBIT_CBREAK 0x0002ull
|
#define NCDIRECT_OPTION_INHIBIT_CBREAK 0x0002ull
|
||||||
#define NCDIRECT_OPTION_NO_READLINE 0x0004ull
|
|
||||||
#define NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS 0x0008ull
|
#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***);**
|
**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
|
# DESCRIPTION
|
||||||
|
|
||||||
**ncdirect_init** prepares the **FILE** provided as **fp** for colorizing and
|
**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
|
will place the terminal into cbreak mode (i.e. disabling echo and line
|
||||||
buffering; see **tcgetattr(3)**).
|
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
|
* **NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS**: A signal handler will usually be
|
||||||
installed for **SIGINT**, **SIGQUIT**, **SIGSEGV**, **SIGTERM**, and
|
installed for **SIGINT**, **SIGQUIT**, **SIGSEGV**, **SIGTERM**, and
|
||||||
**SIGABRT**, cleaning up the terminal on such exceptions. With this flag,
|
**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
|
Attempting to e.g. move up while on the top row will return 0, but have no
|
||||||
effect.
|
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
|
# RETURN VALUES
|
||||||
|
|
||||||
**ncdirect_init** returns **NULL** on failure. Otherwise, the return value
|
**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.
|
// echo and input's line buffering are turned off.
|
||||||
#define NCDIRECT_OPTION_INHIBIT_CBREAK 0x0002ull
|
#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
|
// 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
|
// restores the screen, and then calls the old signal handler. Set to inhibit
|
||||||
// registration of these signal handlers. Chosen to match fullscreen mode.
|
// 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.
|
// 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);
|
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
|
// Direct mode. This API can be used to colorize and stylize output generated
|
||||||
// outside of notcurses, without ever calling notcurses_render(). These should
|
// outside of notcurses, without ever calling notcurses_render(). These should
|
||||||
// not be intermixed with standard Notcurses rendering.
|
// 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
|
// no terminfo capability for this. dangerous--it involves writing controls to
|
||||||
// the terminal, and then reading a response. many things can distupt this
|
// 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){
|
int ncdirect_cursor_yx(ncdirect* n, int* y, int* x){
|
||||||
struct termios termio, oldtermios;
|
struct termios termio, oldtermios;
|
||||||
// this is only meaningful for real terminals
|
// this is only meaningful for real terminals
|
||||||
@ -321,7 +321,7 @@ int ncdirect_cursor_yx(ncdirect* n, int* y, int* x){
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(&oldtermios, &termio, sizeof(termio));
|
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.
|
// it got changed by the client code since then, duck into cbreak mode anew.
|
||||||
termio.c_lflag &= ~(ICANON | ECHO);
|
termio.c_lflag &= ~(ICANON | ECHO);
|
||||||
if(tcsetattr(n->ctermfd, TCSAFLUSH, &termio)){
|
if(tcsetattr(n->ctermfd, TCSAFLUSH, &termio)){
|
||||||
@ -597,7 +597,7 @@ static int
|
|||||||
ncdirect_stop_minimal(void* vnc){
|
ncdirect_stop_minimal(void* vnc){
|
||||||
ncdirect* nc = static_cast<ncdirect*>(vnc);
|
ncdirect* nc = static_cast<ncdirect*>(vnc);
|
||||||
int ret = drop_signals(nc);
|
int ret = drop_signals(nc);
|
||||||
if(!(nc->flags & NCDIRECT_OPTION_NO_READLINE)){
|
if(nc->initialized_readline){
|
||||||
rl_deprep_terminal();
|
rl_deprep_terminal();
|
||||||
}
|
}
|
||||||
if(nc->tcache.op && term_emit("op", nc->tcache.op, nc->ttyfp, true)){
|
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)){
|
if(interrogate_terminfo(&ret->tcache, shortname_term)){
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
ret->channels = 0;
|
|
||||||
ncdirect_set_styles(ret, 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;
|
return ret;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@ -701,6 +695,16 @@ int ncdirect_stop(ncdirect* nc){
|
|||||||
return ret;
|
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
|
static inline int
|
||||||
ncdirect_style_emit(ncdirect* n, unsigned stylebits, FILE* out){
|
ncdirect_style_emit(ncdirect* n, unsigned stylebits, FILE* out){
|
||||||
int r = -1;
|
int r = -1;
|
||||||
|
@ -310,6 +310,7 @@ typedef struct ncdirect {
|
|||||||
// typical order. we detect it the first time ncdirect_cursor_yx() is called.
|
// typical order. we detect it the first time ncdirect_cursor_yx() is called.
|
||||||
bool detected_cursor_inversion; // have we performed inversion testing?
|
bool detected_cursor_inversion; // have we performed inversion testing?
|
||||||
bool inverted_cursor; // does the terminal return inverted coordinates?
|
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
|
uint64_t flags; // copied in ncdirect_init() from param
|
||||||
} ncdirect;
|
} 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