# Notcurses: blingful TUIs and character graphics **What it is**: a library facilitating complex TUIs on modern terminal emulators, supporting vivid colors, multimedia, threads, and Unicode to the maximum degree possible. [Things](https://www.youtube.com/watch?v=dcjkezf1ARY) can be done with Notcurses that simply can't be done with NCURSES. It is furthermore fast as shit. **What it is not**: a source-compatible X/Open Curses implementation, nor a replacement for NCURSES on existing systems.
for more information, see [dankwiki](https://nick-black.com/dankwiki/index.php/Notcurses) and the [man pages](https://notcurses.com). in addition, there is [Doxygen](https://notcurses.com/html/) output. To subscribe to the [mailing list](https://groups.google.com/forum/#!forum/notcurses), send an email to notcurses+subscribe@googlegroups.com (the email contents don't matter). i wrote a coherent [guidebook](https://nick-black.com/htp-notcurses.pdf), which is available for free download (or [paperback purchase](https://amazon.com/dp/B086PNVNC9)). i've not yet added many documented examples, but [src/poc/](https://github.com/dankamongmen/notcurses/tree/master/src/poc) and [src/pocpp/](https://github.com/dankamongmen/notcurses/tree/master/src/pocpp) contain many small C and C++ programs respectively. `notcurses-demo` covers most of the functionality of Notcurses. **If you're running Notcurses applications in a Docker, please consult "[Environment notes](#environment-notes)" below.** ![Linux](https://img.shields.io/badge/-Linux-grey?logo=linux) ![FreeBSD](https://img.shields.io/badge/-FreeBSD-grey?logo=freebsd) ![Windows](https://img.shields.io/badge/-Windows-grey?logo=windows) ![macOS](https://img.shields.io/badge/-macOS-grey?logo=macos) [![Linux](https://github.com/dankamongmen/notcurses/actions/workflows/ubuntu_test.yml/badge.svg?branch=master)](https://github.com/dankamongmen/notcurses/actions/workflows/ubuntu_test.yml?query=branch%3Amaster) [![macOS](https://github.com/dankamongmen/notcurses/actions/workflows/macos_test.yml/badge.svg?branch=master)](https://github.com/dankamongmen/notcurses/actions/workflows/macos_test.yml?query=branch%3Amaster) [![Windows](https://github.com/dankamongmen/notcurses/actions/workflows/windows_test.yml/badge.svg?branch=master)](https://github.com/dankamongmen/notcurses/actions/workflows/windows_test.yml?query=branch%3Amaster) [![pypi_version](https://img.shields.io/pypi/v/notcurses?label=pypi)](https://pypi.org/project/notcurses) [![crates.io](https://img.shields.io/crates/v/libnotcurses-sys.svg)](https://crates.io/crates/libnotcurses-sys) [![Matrix](https://img.shields.io/matrix/notcursesdev:matrix.org?label=matrixchat)](https://app.element.io/#/room/#notcursesdev:matrix.org) [![Sponsor](https://img.shields.io/badge/-Sponsor-red?logo=github)](https://github.com/sponsors/dankamongmen) ## Introduction Notcurses abandons the X/Open Curses API bundled as part of the Single UNIX Specification. For some necessary background, consult Thomas E. Dickey's superb and authoritative [NCURSES FAQ](https://invisible-island.net/ncurses/ncurses.faq.html#xterm_16MegaColors). As such, Notcurses is not a drop-in Curses replacement. Wherever possible, Notcurses makes use of the Terminfo library shipped with NCURSES, benefiting greatly from its portability and thoroughness. Notcurses opens up advanced functionality for the interactive user on workstations, phones, laptops, and tablets, possibly at the expense of e.g. some industrial and retail terminals. Fundamentally, Curses assumes the minimum and allows you (with effort) to step up, whereas Notcurses assumes the maximum and steps down (by itself) when necessary. The latter approach probably breaks on some older hardware, but the former approach results in new software looking like old hardware. Why use this non-standard library? * Thread safety, and efficient use in parallel programs, has been a design consideration from the beginning. * A more orderly surface than that codified by X/Open: Exported identifiers are prefixed to avoid common namespace collisions. Where reasonable, `static inline` header-only code is used. This facilitates compiler optimizations, and reduces loader time. Notcurses can be built without its multimedia functionality, requiring a significantly lesser set of dependencies. * All APIs natively support the Universal Character Set (Unicode). The `nccell` API is based around Unicode's [Extended Grapheme Cluster](https://unicode.org/reports/tr29/) concept. * Visual features including images, fonts, video, high-contrast text, sprites, and transparent regions. All APIs natively support 24-bit color, quantized down as necessary for the terminal. * Portable support for bitmapped graphics, using Sixel, Kitty, and even the Linux framebuffer console. * Support for unambiguous [keyboard protocols](https://sw.kovidgoyal.net/kitty/keyboard-protocol/). * "TUI mode" facilitates high-performance, non-scrolling, full-screen applications. "CLI mode" supports scrolling output for shell utilities, but with the full power of Notcurses. * It's Apache2-licensed in its entirety, as opposed to the [drama in several acts](https://invisible-island.net/ncurses/ncurses-license.html) that is the NCURSES license (the latter is [summarized](https://invisible-island.net/ncurses/ncurses-license.html#issues_freer) as "a restatement of MIT-X11"). Much of the above can be had with NCURSES, but they're not what NCURSES was *designed* for. On the other hand, if you're targeting industrial or critical applications, or wish to benefit from time-tested reliability and portability, you should by all means use that fine library. ## Requirements Minimum versions generally indicate the oldest version I've tested with; it may well be possible to use still older versions. Let me know of any successes! * (build) CMake 3.14.0+ and a C11 compiler * (OPTIONAL) (OpenImageIO, testing, C++ bindings): A C++17 compiler * (build+runtime) From [NCURSES](https://invisible-island.net/ncurses/announce.html): terminfo 6.1+ * (build+runtime) GNU [libunistring](https://www.gnu.org/software/libunistring/) 0.9.10+ * (OPTIONAL) (build+runtime) [libgpm](https://www.nico.schottelius.org/software/gpm/) 1.20+ * (OPTIONAL) (build+runtime) From QR-Code-generator: [libqrcodegen](https://github.com/nayuki/QR-Code-generator) 1.5.0+ * (OPTIONAL) (build+runtime) From [FFmpeg](https://www.ffmpeg.org/): libswscale 5.0+, libavformat 57.0+, libavutil 56.0+ * (OPTIONAL) (build+runtime) [OpenImageIO](https://github.com/OpenImageIO/oiio) 2.15.0+, requires C++ * (OPTIONAL) (testing) [Doctest](https://github.com/onqtam/doctest) 2.3.5+ * (OPTIONAL) (documentation) [pandoc](https://pandoc.org/index.html) 1.19.2+ * (OPTIONAL) (python bindings): Python 3.7+, [CFFI](https://pypi.org/project/cffi/) 1.13.2+, [pypandoc](https://pypi.org/project/pypandoc/) 1.5+ * (runtime) Linux 2.6+, FreeBSD 11+, DragonFly BSD 5.9+, Windows 10 v1093+, or macOS 11.4+ More information on building and installation is available in [INSTALL.md](INSTALL.md). ### Wrappers If you wish to use a language other than C to work with Notcurses, numerous wrappers are available. Several are included in this repository, while others are external. | Language | Lead(s) | Repository | | -------- | ----------------------------- | ---------- | | Ada | Jeremy Grosser | [JeremyGrosser/notcursesada](https://github.com/JeremyGrosser/notcursesada) | | C++ | Marek Habersack, nick black | internal | | Python | nick black | internal | | Python | igo95862 | internal | | Rust | José Luis Cruz | [dankamongmen/libnotcurses-sys](https://github.com/dankamongmen/libnotcurses-sys) | | Zig | Jakub Dundalek | [dundalek/notcurses-zig-example](https://github.com/dundalek/notcurses-zig-example) | ## Included tools Nine executables are installed as part of Notcurses: * `ncls`: an `ls` that displays multimedia in the terminal * `ncneofetch`: a [neofetch](https://github.com/dylanaraps/neofetch) ripoff * `ncplayer`: renders visual media (images/videos) * `nctetris`: a tetris clone * `notcurses-demo`: some demonstration code * `notcurses-info`: detect and print terminal capabilities/diagnostics * `notcurses-input`: decode and print keypresses * `notcurses-tester`: unit testing * `tfman`: a swank manual browser To run `notcurses-demo` from a checkout, provide the `data` directory via the `-p` argument. Demos requiring data files will otherwise abort. The base delay used in `notcurses-demo` can be changed with `-d`, accepting a floating-point multiplier. Values less than 1 will speed up the demo, while values greater than 1 will slow it down. `notcurses-tester` likewise requires that `data`, populated with the necessary data files, be specified with `-p`. It can be run by itself, or via `make test`. ## Documentation With `-DUSE_PANDOC=on` (the default), a full set of man pages and XHTML will be built from `doc/man`. The following Markdown documentation is included directly: * Per-release [News](NEWS.md) for packagers, developers, and users. * The `TERM` environment variable and [various terminal emulators](TERMINALS.md). * Notes on [contributing](doc/CONTRIBUTING.md) and [hacking](doc/HACKING.md). * There's a semi-complete [reference guide](USAGE.md). * A list of [other TUI libraries](doc/OTHERS.md). * Abbreviated [history](doc/HISTORY.md) and thanks. * [Differences from](doc/CURSES.md) Curses and adapting Curses programs. If you (understandably) want to avoid the large Pandoc stack, but still enjoy manual pages, I publish a tarball with generated man/XHTML along with each release. Download it, and install the contents as you deem fit. ## Environment notes * If your `TERM` variable is wrong, or that terminfo definition is out-of-date, you're going to have a very bad time. Use *only* `TERM` values appropriate for your terminal. If this variable is undefined, or Notcurses can't load the specified Terminfo entry, it will refuse to start, and you will [not be going to space today](https://xkcd.com/1133/). * Notcurses queries the terminal on startup, enabling some advanced features based on the determined terminal (and even version). Basic capabilities, however, are taken from Terminfo. So if you have, say, Kitty, but `TERM=vt100`, you're going to be able to draw RGBA bitmap graphics (despite such things being but a dream for a VT100), but *unable* to use the alternate screen (despite it being supported by every Kitty version). So `TERM` and an up-to-date Terminfo database remain important. * Ensure your `LANG` environment variable is set to a UTF8-encoded locale, and that this locale has been generated. This usually means `"[language]_[Countrycode].UTF-8"`, i.e. `en_US.UTF-8`. The first part (`en_US`) ought exist as a directory or symlink in `/usr/share/locales`. This usually requires editing `/etc/locale.gen` and running `locale-gen`. On Debian systems, this can be accomplished with `dpkg-reconfigure locales`, and enabling the desired locale. The default locale is stored somewhere like `/etc/default/locale`. * If your terminal has an option about default interpretation of "ambiguous-width characters" (this is actually a technical term from Unicode), ensure it is set to **Wide**, not narrow (if that doesn't work, ensure it is set to **Narrow**, heh). * If your terminal supports 3x8bit RGB color via `setaf` and `setbf` (most modern terminals), but exports neither the `RGB` nor `Tc` terminfo capability, you can export the `COLORTERM` environment variable as `truecolor` or `24bit`. Note that some terminals accept a 24-bit specification, but map it down to fewer colors. RGB is unconditionally enabled whenever [most modern terminals](TERMINALS.md) are identified. ### Fonts Glyph width, and indeed whether a glyph can be displayed at all, is dependent in part on the font configuration. Ideally, your font configuration has a glyph for every Unicode EGC, and each glyph's width matches up with the POSIX function's `wcswidth()` result for the EGC. If this is not the case, you'll likely get blanks or � (U+FFFD, REPLACEMENT CHARACTER) for missing characters, and subsequent characters on the line may be misplaced. It is worth knowing that several terminals draw the block characters directly, rather than loading them from a font. This is generally desirable. Quadrants and sextants are not the place to demonstrate your design virtuosity. To inspect your environment's rendering of drawing characters, run `notcurses-info`. The desired output ought look something like this:## FAQs If things break or seem otherwise lackluster, **please** consult the [Environment Notes](#environment-notes) section! You **need** correct `TERM` and `LANG` definitions, and might want `COLORTERM`.
NCOPTION_CLI_MODE
flag (an alias for several
real flags; see notcurses_init(1)
for more information). You still must explicitly render.
-DUSE_MULTIMEDIA=none
.
notcurses_core_init()
or
ncdirect_core_init()
in place of notcurses_init()
/
ncdirect_init()
, and link with -lnotcurses-core
.
Your application will likely start a few milliseconds faster;
more importantly, it will link against minimal Notcurses installations.
notcurses-demo
(and maybe a few other programs).
Use -DUSE_CXX=off
.
TERM
value, many hardware terminals are
supported. In general, if the terminfo database entry indicates mandatory
delays, Notcurses will not currently support that terminal properly. It's
known that Notcurses can drive the VT320 and VT340, including Sixel graphics
on the latter.
NCBLIT_PIXEL
has been
requested. Likewise, sextants (NCBLIT_3x2
) won't be used without
Unicode 13 support, etc. ncvisual_blit()
will use the best blitter
available, unless NCVISUAL_OPTION_NODEGRADE
is provided (in
which case it will fail).
screen
.screen
doesn't support RGB colors (at least as of 4.08.00);
if you have COLORTERM
defined, you'll have a bad time.
If you have a screen
that was compiled with
--enable-colors256
, try exporting
TERM=screen-256color
as opposed to TERM=screen
.
mosh
.NC_ENTER
NCTYPE_RELEASE
event, and each keypress will typically result in at least two inputs.
NCKEY_RESIZE
until
I press some other key.SIGWINCH
in some thread,
and that thread is receiving the signal instead of the thread which called
notcurses_getc_blocking()
. As a result, the poll()
is not interrupted. Call pthread_sigmask()
before spawning any
threads.
NotCurses
destructor is run when I return from main()
?NotCurses
is scoped to main()
).
ncplane_move_yx()
, move it underneath an opaque plane with
ncplane_move_below()
, or move it off-pile with
ncplane_reparent()
.
ncplane_box_yx()
? Do you hate
orthogonality, you dullard?ncplane_box()
and friends
already have far too many arguments, you monster.
graphics/qr-code-generator
.cmake -DCMAKE_REQUIRED_INCLUDES=/usr/local/include
.
This is passed by bsd.port.mk
.
LANG
environment variable is underdefined or incorrectly
defined, or the necessary locale is not present on your machine (it is also
possible that you explicitly supplied NCOPTION_INHIBIT_SETLOCALE
,
but never called setlocale(3)
, in which case don't do that).
ncplane
when using a
nccell
. Why doesn't the latter hold a pointer to the former?
nccell
needs to
remain as small as possible, and you almost always have the ncplane
handy if you've got a reference to a valid nccell
anyway.
valgrind
/ASAN, and
it shows memory leaks from libtinfo.so
, what's up with that?notcurses-demo
, but my table numbers don't match
the Notcurses banner numbers, you charlatan.notcurses-demo
renders several frames beyond the actual demos.
notcurses_stop()
/ncdirect_stop()
on all exit paths, including fatal signals (note that, by default, Notcurses
installs handlers for most fatal signals to do exactly this).
ncdirect_readline()
still exists,
though, and now actually works even without libreadline, though it is of
course not exactly libreadline. In any case, you'd probably be better off
using CLI mode with a ncreader
.
pkg-config --static --libs notcurses
(or --libs notcurses-core
) to discover them.
mintty
with -P on
arguments, or export MSYS=enable_pcon
before launching it.
COLORTERM=24bit
everywhere?SendEnv COLORTERM
to .ssh/config
, and
AcceptEnv COLORTERM
to sshd_config
on the remote
server. Yes, this will probably require root on the remote server.
Don't blame me, man; I didn't do it.
ncvisual
from RGBA memory using
ncvisual_from_rgba()
.
NCSTYLE_REVERSE
?ncchannels_reverse()
to correctly invert fore- and background colors.
ncsubproc
widget.
notcurses_refresh()
after notcurses_init()
returns successfully.