nc plugin: ncurses bindings for SpiderApe


The ncurses plugin (formerly named 'nc') provides a JavaScript wrapper around the venerable ncurses C API. ncurses, for those who aren't familiar with it, is a library to assist with writing text-based user interfaces. While that might sound archaic, text-based user interfaces are rather common in system-level applications and come in especially useful when one must run applications over remote logins (where graphical applications cannot always be run). More information about ncurses can be found on its official home page: http://invisible-island.net/ncurses/ncurses.html.

This plugin wraps over 150 ncurses functions, providing access to nearly every feature of the C API (including mouse support). The "panels" library is also supported, but the "menu" and "form" libraries are not. This plugin's main claim to fame it allows very fast authoring (or prototyping) of ncurses applications - several times faster than doing so in C because the whole compile/link phases of the application development process disappear. JavaScript also matches up perfectly to ncurses' event handling mechanism, making it simple to attach arbitrary JS handler code to keyboard events.

This plugin is partially documented in the plugins manual, but a guide to the ncurses C API (or equivalent experience) will also be required (it's called "curses!" for a reason!). The ncurses man pages are quite informative, and i can highly recommend Dan Gookin's Programmer's Guide to nCurses as a great tutorial and overall reference guide. 95% or more of what's covered in Dan's book can be done with this plugin (plus the plugin supports libpanels, which that book doesn't cover).

Demo

Here's a trivial demonstration of what ncurses code in SpiderApe looks like:
assert(open_dll('nc'));

nc_initscr();
nc_capture_cout(stdscr);
nc_scrollok(stdscr,true);
nc_noecho();
var sub = nc_subwin(stdscr,3,4,5,6);
nc_wbkgd( sub, ncurses["-"] | nc_color("white","red"));
// print(ncurses.toSource());
nc_wmove(stdscr,12,0);
print("nc_getparyx(sub) ==",nc_getparyx(sub).toSource());
print("nc_getparyx(sub).y ==",nc_getparyx(sub).y);
print("nc_getpary(sub) ==",nc_getpary(sub));
print("nc_getparx(sub) ==",nc_getparx(sub));

print('ncurses.MOUSE_VERSION ==',ncurses.MOUSE_VERSION);
if( ncurses.MOUSE_VERSION ) {
	print("Play with the mouse. Tap 'q' to quit.");
	var key = 0;
	while( ascii('q') != (key = nc_getch()) ) {
		if( key == ncurses.KEY_MOUSE ) {
			var evt = nc_getmouse();
			print( "mouse :",key,evt.toSource() );
		}
	}
}

print("Tap any key to exit.");
nc_getch();
nc_delwin(sub);
nc_endwin();

And that code generates something like this...
ncdemo.png