GithubHelp home page GithubHelp logo

dankamongmen / notcurses Goto Github PK

View Code? Open in Web Editor NEW
3.3K 34.0 112.0 105.56 MB

blingful character graphics/TUI library. definitely not curses.

Home Page: https://nick-black.com/dankwiki/index.php/Notcurses

License: Other

CMake 0.81% C 82.35% C++ 14.86% Python 1.73% Shell 0.25%
terminal-emulators ncurses cli terminal c

notcurses's Introduction

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 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.

setting the standard (hype video)

for more information, see dankwiki and the man pages. in addition, there is Doxygen output. To subscribe to the mailing list, send an email to [email protected] (the email contents don't matter). i wrote a coherent guidebook, which is available for free download (or paperback purchase).

i've not yet added many documented examples, but src/poc/ and 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" below.

Packaging status

Linux FreeBSD Windows macOS

Linux macOS Windows

pypi_version crates.io

Matrix Sponsor

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. 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 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.

  • "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 that is the NCURSES license (the latter is summarized 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: terminfo 6.1+
  • (build+runtime) GNU libunistring 0.9.10+
  • (OPTIONAL) (build+runtime) libgpm 1.20+
  • (OPTIONAL) (build+runtime) From QR-Code-generator: libqrcodegen 1.5.0+
  • (OPTIONAL) (build+runtime) From FFmpeg: libswscale 5.0+, libavformat 57.0+, libavutil 56.0+, libavdevice 57.0+
  • (OPTIONAL) (build+runtime) OpenImageIO 2.15.0+, requires C++
  • (OPTIONAL) (testing) Doctest 2.3.5+
  • (OPTIONAL) (documentation) pandoc 1.19.2+
  • (OPTIONAL) (python bindings): Python 3.7+, CFFI 1.13.2+, 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.

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
C++ Marek Habersack, nick black internal
Dart Nelson Fernandez kascote/dart_notcurses
Julia Dheepak Krishnamurthy kdheepak/Notcurses.jl
Nim Michael S. Bradley, Jr. michaelsbradleyjr/nim-notcurses
Python nick black internal
Python igo95862 internal
Rust José Luis Cruz dankamongmen/libnotcurses-sys
Zig Jakub Dundalek 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 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:

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.

  • 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 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:

notcurses-info can be used to check Unicode drawing

FAQs

If things break or seem otherwise lackluster, please consult the Environment Notes section! You need correct TERM and LANG definitions, and might want COLORTERM.

Can I use Notcurses in my closed-source program? Notcurses is licensed under Apache2, a demonstration that I have transcended your petty world of material goods, fiat currencies, and closed sources. Implement Microsoft Bob in it. Charge rubes for it. Put it in your ballistic missiles so that you have a nice LED display of said missile's speed and projected yield; right before impact, scroll "FUCK YOU" in all the world's languages, and close it out with a smart palette fade. Carve the compiled objects onto bricks and mail them to Richard Stallman, taunting him through a bullhorn as you do so.
Can I write a CLI program (scrolling, fits in with the shell, etc.) with Notcurses? Yes! Use the NCOPTION_CLI_MODE flag (an alias for several real flags; see notcurses_init(1) for more information). You still must explicitly render.
Can I have Notcurses without this huge multimedia stack? Again yes! Build with -DUSE_MULTIMEDIA=none.
Can I build this individual Notcurses program without aforementioned multimedia stack? Almost unbelievably, yes! Use 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.
We're paying by the electron, and have no C++ compiler. Can we still enjoy Notcurses goodness? Some of it! You won't be able to build several executables, nor the NCPP C++ wrappers, nor can you build with the OpenImageIO multimedia backend (OIIO ships C++ headers). You'll be able to build the main library, though, as well as notcurses-demo (and maybe a few other programs). Use -DUSE_CXX=off.
Do I want ffmpeg or OpenImageIO? While OpenImageIO is a superb library for dealing with single-frame images, its video support is less than perfect (blame me; I've been promising Larry I'd rewrite it for several months), and in any case implemented atop...ffmpeg. ffmpeg is the preferred multimedia backend.
Does it work with hardware terminals? With the correct 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.
What happens if I try blitting bitmap graphics on a terminal which doesn't support them? Notcurses will not make use of bitmap protocols unless the terminal positively indicates support for them, even if 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).
Notcurses looks like absolute crap in 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.
Notcurses looks like absolute crap in mosh. Yeah it sure does. I'm not yet sure what's up.
Notcurses looks like absolute crap in Windows Terminal. Go to Language Setting, click "Administrative language settings", click "Change system locale", and check the "Beta: Use Unicode UTF-8 for worldwide language support" option. Restart the computer. That ought help a little bit. Try playing with fonts—Cascadia Code and Cascadia Mono both seem to work well (quadrants and Braille both work), whereas Consolas and Courier New both have definite problems.
I'm getting strange and/or duplicate inputs in Kitty/foot. Notcurses supports Kitty's powerful keyboard protocol, which includes things like key release events and modifier keypresses by themselves. This means, among other things, that a program in these terminals will usually immediately get an NC_ENTER NCTYPE_RELEASE event, and each keypress will typically result in at least two inputs.
Why didn't you just render everything to bitmaps? That's not a TUI; it's a slow and inflexible GUI. Many terminal emulators don't support bitmaps. They doesn't work well with mouse selection. Sixels have a limited color palette. With that said, both Sixel and the Kitty bitmap protocol are well-supported.
My multithreaded program doesn't see NCKEY_RESIZE until I press some other key. You've almost certainly failed to mask 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.
Using the C++ wrapper, how can I ensure that the NotCurses destructor is run when I return from main()? As noted in the C++ FAQ, wrap it in an artificial scope (this assumes your NotCurses is scoped to main()).
How do I hide a plane I want to make visible later? In order of least to most performant: move it offscreen using ncplane_move_yx(), move it underneath an opaque plane with ncplane_move_below(), or move it off-pile with ncplane_reparent().
Why isn't there an ncplane_box_yx()? Do you hate orthogonality, you dullard? ncplane_box() and friends already have far too many arguments, you monster.
Why doesn't Notcurses support 10- or 16-bit color? Notcurses supports 24 bits of color, spread across three eight-bit channels. You presumably mean 10-bit-per-channel color. I needed those six bits for other things. When terminals support it, Notcurses might support it.
The name is dumb. That's not a question?
I'm not finding qrcodegen on BSD, despite having installed graphics/qr-code-generator. Try cmake -DCMAKE_REQUIRED_INCLUDES=/usr/local/include. This is passed by bsd.port.mk.
Do you support musl? I try to! You'll need at least 1.20.
I only seem to blit in ASCII, and/or can't emit Unicode beyond ASCII in general. Your 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).
I pretty much always need an ncplane when using a nccell. Why doesn't the latter hold a pointer to the former? Besides the massive redundancy this would entail, 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.
I ran my Notcurses program under valgrind/ASAN, and it shows memory leaks from libtinfo.so, what's up with that? Yeah, the NCURSES Terminfo leaks memory unless compiled a special, non-standard way (see the NCURSES FAQ). It shouldn't be a substantial amount; you're advised not to worry overmuch about it.
I ran notcurses-demo, but my table numbers don't match the Notcurses banner numbers, you charlatan. notcurses-demo renders several frames beyond the actual demos.
When my program exits, I don't have a cursor, or text is invisible, or colors are weird, ad nauseam. Ensure you're calling 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).
How can I use Direct Mode in conjunction with libreadline? You can't anymore (you could up until 2.4.1, but the new input system is fundamentally incompatible with it). 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.
So is Direct Mode deprecated or what? It is not currently deprecated, and definitely receives bugfixes. You are probably better served using CLI mode (see above), which came about somewhat late in Notcurses development (the 2.3.x series), but is superior to Direct Mode in pretty much every way. The only reason to use Direct Mode is if you're going to have other programs junking up your display.
Direct Mode sounds fast! Since it's, like, direct. Direct mode is substantially slower than rendered mode. Rendered mode assumes it knows what's on the screen, and uses this information to generate optimized sequences of escapes and glyphs. Direct mode writes everything it's told to write. It is furthermore far less capable—all widgets etc. are available only to rendered mode, and will definitely not be extended to Direct Mode.
Will there ever be Java wrappers? I should hope not. If you want a Java solution, try @klamonte's Jexer. Autumn's a good woman, and thorough. We seem to have neatly partitioned the language space.
Given that the glyph channel is initialized as transparent for a plane, shouldn't the foreground and background be initialized as transparent, also? Probably (they are instead by default initialized to opaque). This would change some of the most longstanding behavior of Notcurses, though, so it isn't happening.
I get linker errors when statically linking. Are you linking all necessary libraries? Use pkg-config --static --libs notcurses (or --libs notcurses-core) to discover them.
Notcurses exits immediately in MSYS2/Cygwin. Notcurses requires the Windows ConPTY layer. This is available in Cygwin by default since 3.2.0, but is disabled by default in MSYS. Launch mintty with -P on arguments, or export MSYS=enable_pcon before launching it.
Can I avoid manually exporting COLORTERM=24bit everywhere? Sure. Add 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.
How about arbitrary image manipulation here functionality? I'm not going to beat ImageMagick et al. on image manipulation, but you can load an ncvisual from RGBA memory using ncvisual_from_rgba().
My program locks up during initialization. Notcurses interrogates the terminal. If the terminal doesn't reply to standard interrogations, file a Notcurses bug, send upstream a patch, or use a different terminal. No known terminal emulators exhibit this behavior.
How can I draw a large plane, and only make a portion of it visible? The simplest way is probably to create a plane of the same dimensions immediately above the plane, and keep a region of it transparent, and the rest opaque. If you want the visible area to stay in the same place on the display, but the portion being seen to change, try making a plane twice as large in each dimension as the original plane. Make the desired area transparent, and the rest opaque. Now move the original plane behind this plane so that the desired area lines up with the “hole”.
Why no NCSTYLE_REVERSE? It would consume a precious bit. You can use ncchannels_reverse() to correctly invert fore- and background colors.
How do I mix Rendered and Direct mode? You really don't want to. You can stream a subprocess to a plane with the ncsubproc widget.
How can I clear the screen on startup in Rendered mode when not using the alternate screen? Call notcurses_refresh() after notcurses_init() returns successfully.
Why do the stats show more Linux framebuffer bitmap bytes written than total bytes written to the terminal? And why don't Linux console graphics work when I ssh? Linux framebuffer graphics aren't implemented via terminal writes, but rather writes directly into a memory map. This memory map isn't available on remote machines, and these writes aren't tracked by the standard statistics.
What is the possessive form of Notcurses? Notcurses'. I cite Garner's Modern English Usage in its third edition: "POSSESSIVES. A. Singular Possessives.…Biblical and Classical names that end with a /zəs/ or /eez/ sound take only the apostrophe." Some ask: is Notcurses then Biblical, or is it Classical? Truly, it is both.
I just want to display a bitmap on my terminal. Your library is complex and stupid. You are simple and stupid. If you're willing to call a binary, use ncplayer to put an image, with desired scaling, anywhere on the screen and call it a day. Otherwise, call notcurses_init(), ncvisual_from_file(), ncvisual_blit(), notcurses_render(), and notcurses_stop(). It's not too tough. And thanks—your thoughtful comments and appreciative tone are why I work on Free Software.

Useful links

“Our fine arts were developed, their types and uses were established, in times very different from the present, by men whose power of action upon things was insignificant in comparison with ours. But the amazing growth of our techniques, the adaptability and precision they have attained, the ideas and habits they are creating, make it a certainty that profound changes are impending in the ancient craft of the Beautiful.” —Paul Valéry

notcurses's People

Contributors

alexhsamuel avatar barracuda156 avatar christianparpart avatar cjtenny avatar dankamongmen avatar data-man avatar db48x avatar dcantrell avatar dnkl avatar ericonr avatar gmiz avatar grendello avatar hkatzdev avatar igo95862 avatar initramfs avatar joeyslalom avatar joseluis avatar kdheepak avatar kristofferc avatar magiblot avatar masflam avatar michaelsbradleyjr avatar mukundan314 avatar mulle-nat avatar sikfeng avatar spinicist avatar spritetm avatar timgates42 avatar tinmarino avatar tomek-szczesny avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

notcurses's Issues

Support attributes beyond color

Where supported, we ought make available the various WA_* attributes (though probably not any marked color-incompatible by the no_color_video terminfo property).

Quantize colors down

Our color interfaces are defined in terms of 3x8-bit channels, RGB. On many terminals, this won't fly. We need operate with at least the following:

  • fixed, recoverable 3x8 256-index palette
  • fixed, recoverable 3x8 88-index palette
  • fixed, recoverable 3x8 8-index palette
  • configurable versions of each of these

To do this properly is the problem of color quantization. For a fixed image, there are well-known algorithms available. For colors thrown at us on the fly, we can keep the raw inputs, and requantize as the image changes. For a fixed palette, we can probably just do a fixed conversion; there's a known O(1) one, and several that trade greater complexity for better results.

Multibyte UTF-8 isn't being rendered properly

When we send UTF-8 outside the 7-bit clean ASCII single-byte baby encodings, we get the nastyglyph: �

We're PoCing with single-byte write(2) calls, which obviously isn't our endgame. Does translation occur where exactly?

wide string on demo intro isn't centered

│ΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔ│ 
│ΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔ│
│ΔΔΔΔΔ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ █ ▇ ▆ ▅ ▄ ▃ ▂▁ ΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔ│ 
│ΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔ│ 
│ΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔ│
│ΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔ Die Welt ist alles, was der Fall ist. ΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔ│
│ΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔ│
│ΔΔΔΔΔΔΔΔΔ Wovon man nicht sprechen kann, darüber muss man schweigen. ΔΔΔΔΔΔΔ│
│ΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔ│ 
│ΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔΔ│

what's this crap

Print wide characters in uniblock demo

We currently skip wide characters in uniblock despite having resolved #6. We ought be able to display these, and just make the block a bit bigger. It's not critical right now, but it would be good to have done soon.

Background colors aren't working properly

When I run notcurses-demo, I'm seeing two problems:

  • The background color for the first screen seems to be chosen almost at random
  • The background color for the widecolor demo is the same for the entire page

ncplane_erase() is crashing

In the grid demo, if I enable an ncplane_erase() at the start of each of the three sections, we crash. If I don't have them there, we do not see the crash, nor any valgrind complaints throughout.

Port panelreels over from outcurses

I built up the panelreel abstraction as part of outcurses last week. We now need it in notcurses. Once we have z-index support working (#1), move 'em over.

Disable cursor by default

That cursor is really fucking with me on the unicodeblock demo, and it slows down our drawing. Turn it off with the civis capability.

Spacing-combining characters aren't handled properly

The widecolors demo always manages to incompletely fill the screen. More precisely, I think, the widecolors demo fills up a bit more than the screen, scrolling its message back (if the amount moved back from [2,2] is equal to the amount unfilled, that's definitely our problem). This could very well come from failing to account for multicolumn Asian characters (see #6), so we would just need to pipe that down.

repair damage done to ublock demo by RTLs

right to left scripts fuck up our uniblock demo. i'd like to undo the damage, if possible.

damaged blocks include:

  • Cyrillic, Cyrillic Supplement, Armenian, Hebrew -- hebrew only
  • Arabic, Syriac, Arabic Supplement - all but first line
  • Samaritan, Mandaic, Devanagari, Bengali
  • Supplemental Punctuation, CJK Radicals
  • Cuneiform
  • Cuneiform (cont.)
  • Byzantine Musical Symbols, Musical Symbols
  • Mahjong Tiles, Domino Tiles, Playing Cards -- breakage starts halfway down
  • Enclosed Ideographic Supplement, Miscellaneous Symbols
    (everything after that)

Speed up bulk render operations

When I maximize my terminal (239x64 here at home) and render a screen which changes the color/style at every coordinate, we're entirely too slow. We still need to do some pretty basic damage-oriented optimizations in notcurses_render() for sure, but that won't help in this kind of worst case. We simply need to take less time:

491 renders, 41.6s total (0.062s min, 2.4s max, 0.085s avg)

2.4s! Abominable and unacceptable. The first problem is gonna be that tputs(3) from libtinfo wants to call back to us and have us emit a character at a time. We're currently doing that with a write():

static int
erpchar(int c){
  if(write(STDOUT_FILENO, &c, 1) == 1){
    return c;
  }
  return EOF;
}

so this already sucks because we don't get a user context, and are just hoping STDOUT_FILENO is good. we should probably use a thread-specific datum there. so tputs(3) seems to rely on this behavior to insert delays etc., but it's fundamentally bad for us. We could stack this output up in a garbage buffer acquired via TSD (or just a global for now even), whether that was a POSIX memstream or whatever, but at that point we might as well skip tputs(3) entirely....which I'd rather not do, if possible...

libav tests are blowing up inside drone CI

Since merging #53 for #35 , we're failing in Drone:

[----------] 2 tests from LibavTest
[ RUN ] LibavTest.LoadImage
/drone/src/github.com/dankamongmen/notcurses/tests/libav.cpp:10: Failure
Expected: (nullptr) != (nc_), actual: (nullptr) vs NULL
[ FAILED ] LibavTest.LoadImage (0 ms)
[ RUN ] LibavTest.LoadVideo
/drone/src/github.com/dankamongmen/notcurses/tests/libav.cpp:10: Failure
Expected: (nullptr) != (nc_), actual: (nullptr) vs NULL
[ FAILED ] LibavTest.LoadVideo (0 ms)
[----------] 2 tests from LibavTest (0 ms total)
[----------] 16 tests from NcplaneTest

I wonder if we're perhaps missing codecs on there or something? Urk.

Clear out invalidated cells

Currently, our output doesn't release the resources held by a cell they're blowing away. These need to be dropped from the egcpool.

Need palette fades on planes

With notcurses, palette fades were trivial, since we had an actual palette. With directcolor, it'll be a bit more complex. First, I think we'll have to manually redraw and refresh the region. Secondly, we'd need modify the actual colors associated with each touched cell.

I think we might have an easy way out, though -- once we get alpha blending working, can a fade not just be a scaled alpha, independent of the actual colors? I would think so, except that alpha applies to both foreground and background, and we might only want to do one. Think about it.

Add a panel demo

With #26 and friends done, we need a good demo to show off ncplanes. Do a sliding puzzle, and sex it up a little.

implement ncplane_resize() and ncplane_move()

Now that we can create and destroy ncplanes, let's add the functionality necessary to move and resize them. For moving, it's fine to just accept a new origin point (perhaps relative to either the screen or some other ncplane). For resize, rather than ncurses's wresize(), which takes new dimensions but applies them from the origin, i want to accept a new subsection of the ncplane, which will be left where it is (even if the resize is a growth, and it's now partially offscreen). move moves, resize resizes, and the resize is general.

actually, a fully general resize would require:

  • section of current ncplane to keep,
  • where it ought be RELATIVE TO new ncplane, and
  • new dimensions of ncplane

where the new section must be wholly within the new ncplane, but the ncplane can be beyond the screen. note that move is still distinct: in this sceme, the resize is "anchored" by the subsection that we keep.

if you want to resize or move, but don't care about keeping any of it, i guess it can apply to the origin. so to resize down and to the right by 2, currently at yoff/xoff with dimensions ylen/xlen, it would be

ncplane_resize(zero-area section, {0,0}, {ylen + 2, xlen + 2})

and to resize by 2 but put the current origin at the lower right, it would be:

ncplane_resize(zero-area section, {ylen + 2 - 1, xlen + 2 - 1}, {ylen + 2, xlen + 2})

and to resize by 2 to the up and left, it would be:

ncplane_resize(zero-area section, {2, 2}, {ylen + 2, xlen + 2}

in the first example, you get two new empty rows and two new empty columns, retaining all current data. in the second, you lose all data, and have a window with its lower-right corner where the upper-left corner was. in the third, you have two new empty rows and two new empty columns, retaining all current data, but they're above and to the left of you. yeah, i like that.

you still can't implement move() via resize(), which i like. resize() is fundamentally a data-rearranging operation within the ncplane, whereas move() is rearranging data at the notcurses level.

Fill out drawing API

I've added most of the necessary declarations to notcurses.h. We now need implementations.

Implement notcurses_render()

notcurses_render() is a fundamental API point which updates the physical screen to match the virtual screen (this has nothing to do with "alternative screens" as mentioned in #3). It needs be implemented atop the data structure defined in #1 (the cell plane).

For the first pass, blit the entirety of the virtual buffer to the physical screen, using a 1bpc changemask (don't replace character cells that haven't been touched; notcurses_clear() and friends touch all cells). This will validate the basics of our framebuffer.

Next, take advantage of advanced terminal blitting capabilities (clear-to-eol, etc.) if they're available.

Next, ensure we're not emitting more escape sequences than are necessary. Avoiding two passes over the buffer will require keeping some metadata about how far foward a state applies.

Missing ass-end of rendered frames

Since speeding up our rendering in #41 , we lost a few characters off our last line.

On the intro screen of the demo, we don't lose anything until we print the welcome message. so maybe it depends on the total number of characters present somehow?

Apply gradients in hline/vline/box()

If the user indicates that they want it, lines in boxes ought be able to be colored along a gradient from one endpoint to the other. In order to do so, ncplane_box() needs to instruct ncplane_hline() etc. of the same. Perhaps hline/vline could accept two styles, and gradient between them? To avoid said gradient, just supply the same styles on either side....nah, probably make it explicit.

But this would be pimp!

Render AVFrames

Now that we're able to extract AVFrames from video and images, it's time to render them down. We're first looking for the quality level of e.g. mpv -vo tct, but then we ought be able to use better drawing characters, better palette matching, and better dithering to improve on it.

Data structure representing virtual z-layers

If we want to do libpanelw-like stuff, the first thing we'll need is a good data structure for maintaining multiple virtual screens along a z axis. Each cell must be able to hold its own wchar_t and attributes, including color of some depth.

Glyphs aren't printed unless both fg and bg are explicitly set

I'm having some weird problems with things not rendering until I give them some explicit styling. This seems to happen for ncplane_box(), for instance. Without styling the individual cells, we don't see the output, even if the plane has a current color.

Widecolor demo renders summary text at the wrong location

When we run the modified widecolor demo, the summary text ought always be at (2, 2). This is indeed where it gets rendered in the notcurses equivalent. In our four pages, however, it keeps moving to the left. I assume this is due to prior characters occupying more than one column (though we ought be printing the same characters at the same locations each time through, no)?

Need be able to acquire input

We'll need some way to return a composed keypress from stdin, one which ideally natively handles wide characters and e.g. keypad movement.

monospace wide characters

// array due to the possibility of combining characters), a foreground color,

If data structures make cells index'able then please consider that many monospace characters take up multiple cells.

TEST(strwidth, testCjkWidesAndCombiningLowLines_withThompsonPikeEncoding) {
  /*───────────────────────────────────────────────────┬─*/
  EXPECT_EQ(20, strwidth(/**/ "𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷▒▒▒▒▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(20, strwidth(/**/ "(╯°□°)╯𐄻︵ ̲┻̲━̲┻▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(20, strwidth(/**/ "ちゃぶ台返し▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(20, strclen(/*─*/ "𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷▒▒▒▒▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(22, strclen(/*─*/ "(╯°□°)╯𐄻︵ ̲┻̲━̲┻▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(14, strclen(/*─*/ "ちゃぶ台返し▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(68, strlen(/*──*/ "𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷▒▒▒▒▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(56, strlen(/*──*/ "(╯°□°)╯𐄻︵ ̲┻̲━̲┻▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(42, strlen(/*──*/ "ちゃぶ台返し▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(20, wcswidth(/**/ L"Table flip▒▒▒▒▒▒▒▒▒▒" /*│*/, -1));
  EXPECT_EQ(20, wcswidth(/**/ L"(╯°□°)╯︵ ̲┻̲━̲┻▒▒▒▒▒▒▒" /*│*/, -1));
  EXPECT_EQ(20, wcswidth(/**/ L"ちゃぶ台返し▒▒▒▒▒▒▒▒" /*│*/, -1));
  EXPECT_EQ(20, wcslen(/*──*/ L"Table flip▒▒▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(22, wcslen(/*──*/ L"(╯°□°)╯︵ ̲┻̲━̲┻▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(14, wcslen(/*──*/ L"ちゃぶ台返し▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(20, strwidth16(/**/ u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷▒▒▒▒▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(20, strwidth16(/**/ u"(╯°□°)╯𐄻︵ ̲┻̲━̲┻▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(20, strwidth16(/**/ u"ちゃぶ台返し▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(20, strclen16(/*─*/ u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷▒▒▒▒▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(22, strclen16(/*─*/ u"(╯°□°)╯𐄻︵ ̲┻̲━̲┻▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(14, strclen16(/*─*/ u"ちゃぶ台返し▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(28, strlen16(/*──*/ u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷▒▒▒▒▒▒▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(23, strlen16(/*──*/ u"(╯°□°)╯𐄻︵ ̲┻̲━̲┻▒▒▒▒▒▒" /*│*/));
  EXPECT_EQ(14, strlen16(/*──*/ u"ちゃぶ台返し▒▒▒▒▒▒▒▒" /*│*/));
  /*───────────────────────────────────────────────────┴─*/
}

Register a signal handler by default, allow it to be disabled

By default, we ought register a signal handler for most fatal signals, and use it to restore the terminal. We should make this optional via a new member of notcurses_opts. This handler ought remember the previously configured action, and invoke it.

Horrible corruption issue in egcpool upon realloc

ugh, when we get to a certain size in our egcpool, we're corrupting the hell out of it. see the lengthy details in #57. in widecolors-demo, we ought see output like this:

[00/00] [В]
[00/01] [о]
[00/02] [й]
[00/03] [н]
[00/04] [а]
[00/05] [и]
[00/06] [м]
[00/07] [и]
[00/08] [р]
[00/09] [Б]
[00/10] [р]
[00/11] [а́]
[00/12] [т]
[00/13] [ь]
[00/14] [я]
[00/15] [К]
[00/16] [а]

but instead we're seeing

[00/00] [Вλ]
[00/01] [оа]
[00/02] [йⱏ]
[00/03] [нн]
[00/04] [аⰸ]
[00/05] [ид]
[00/06] [мⰺ]
[00/07] [их]
[00/08] [рλ]
[00/09] [Бэ]
[00/10] [р]
[00/11] [а́ⰿ]
[00/12] [тд]
[00/13] [ьα]

despite extracting everything out all nice

Add routine to render a QR code

I've seen it claimed that a QR code can be emitted as Unicode box drawing characters, and be successfully scanned. Too cool. We obviously need such functionality.

Linux virtual console doesn't support smcup/rmcup

Neither the smcup nor the rmcup capabilities are advertised by the linux terminfo type as of ncurses 6.1. We error out if either is not supported. I think we can just skip them in that case instead?

drawing box from lower right coord segfaults

I've already fixed this, but in the box demo, I had forgotten to move the cursor back up to the next box in. When I created a box from where the previous perimeter had left us, we segfaulted out. See if this can't be reproduced and locked down.

Properly implement default colors

The "default colors" are achieved by using the op terminfo capability, which on my terminal maps to 39 and 49:

39	Default foreground color	implementation defined (according to standard)
49	Default background color	implementation defined (according to standard)

so when the default bits are active (or rather the "not default" bits are not active), we need be using this. I don't seem to see a terminfo capability for doing these distinctly.

memu=\Em, oc=\E]104\007, op=\E[39;49m, rc=\E8, rev=\E[7m,

Unit test for column output of multibyte characters

We need some unit testing to ensure we're reporting:

  • the number of bytes copied out for cell_load(), BUT
  • the number of columns written for putstr/printf

I'm pretty sure we're doing the first one right, or other things wouldn't work. Not sure about the second, nor how much we can trust e.g. wcwidth().

Copy nonspacing characters into EGC cell

In utf8_gce_len(), we currently only take the first multibyte character. We want an entire EGC, and indeed we must properly account for this to get general layout working (see #25 ). Loop forward on wcwidth() == 0 in this function.

Support PrintScreen to dump rendering to a file

When printscreen is pushed, render the current virtual buffer to a file (the physical on-screen buffer can be grabbed any number of ways). Provide an option to disable this behavior, and probably also allow it to be remapped.

Avoid invalidating standard plane on resize

There seems no fundamental reason to invalidate the standard plane on a resize, as we claim to do. Just use the existing ncplane structure, and realloc() the framebuffer. Easy enough.

Too many visible symbols

We ought be using -fvisibility=hidden so we only export symbols we want to. Right now we're making available things like egcpool_grow() etc.

Uniblock demo renders black background for text instead of default

In the uniblock demo, I get a big nasty trail of black empty cells following the name line. This is presumably due to us clearing the remainder of the line (so as not to retain cruft from longer names), but it should be transparent, as I've not set a background.

Implement transparent planes

With #1, we have a z-buffer and a first-order drawable plane. We ought be able to use this together with the idea of a default color to have transparent plane backgrounds. These cells ought show the next non-transparent layer's background, and if there is no such layer, show the underlying desktop.

In the case where an image is being rendered below, things get complicated, because there we're going to be using unicode fill characters to fake higher resolutions. With a foreground character, though, this can't be done. For a first-order solution, choose the most prominent color. A better solution would add dithering, methinks.

We probably ought generalize this to a full alpha channel, at least for backgrounds.

Don't send unnecessary color change sequences

We're writing a color escape for every cell on the screen in notcurses_render(). We only need to write it if it's changed from the previous cell. This will reduce the bandwidth sent to the terminal substantially.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.