diff options
Diffstat (limited to 'libui/libui.ha')
| -rw-r--r-- | libui/libui.ha | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/libui/libui.ha b/libui/libui.ha new file mode 100644 index 0000000..0546d24 --- /dev/null +++ b/libui/libui.ha @@ -0,0 +1,110 @@ +use fmt; +use os; +use io; +use unix::tty; +use errors; +use bufio; +use encoding::utf8; +use strings; + + +// A listener on a rune input that returns if the ui needs to terminate or not +export type listener = *fn(ui: *ttyui, r: rune) bool; + +export type ttyui = struct { + term: tty::termios, + f: io::file, + listeners: []listener, +}; + +export fn init() ttyui = { + let f = match (tty::open()) { + case let f: io::file => + yield f; + case let e: tty::error => + fmt::fatal(tty::strerror(e)); + }; + if (!tty::isatty(f)) { + fmt::fatal("/dev/tty is not a tty"); + }; + let term = match (tty::termios_query(f)) { + case let t: tty::termios => + yield t; + case let e: errors::error => + fmt::fatal(errors::strerror(e)); + }; + tty::makeraw(&term)!; + tty::noecho(&term)!; + + return ttyui { + term = term, + f = f, + listeners = [], + }; +}; + +export fn getwinsize(ui: ttyui) (tty::ttysize | tty::error) = { + return tty::winsize(ui.f); +}; + +export fn suspend(ui: *ttyui) void = { + tty::termios_restore(&ui.term); +}; + +export fn resume(ui: *ttyui) void = { + tty::makeraw(&ui.term)!; +}; + +export fn finish(ui: *ttyui) void = { + tty::termios_restore(&ui.term); + io::close(ui.f)!; + free(ui.listeners); +}; + +export fn scan(ui: ttyui) (rune | utf8::invalid | io::EOF | io::error) = { + return bufio::scanrune(ui.f); +}; + +export fn notify(ui: *ttyui, r: rune) bool = { + for (let i = 0z; i < len(ui.listeners); i += 1) { + if (ui.listeners[i](ui, r)) { + return true; + }; + }; + return false; +}; + +fn loop(ui: *ttyui) void = { + for (true) { + let r = match (bufio::scanrune(ui.f)) { + case let r: rune => + yield r; + case utf8::invalid => + fmt::fatal("Invalid utf8 sequence found"); + case io::EOF => + fmt::fatal("EOF"); + case let e: io::error => + fmt::fatal(io::strerror(e)); + }; + for (let i = 0z; i < len(ui.listeners); i += 1) { + if (ui.listeners[i](ui, r)) { + return; + }; + }; + }; +}; + +export fn addlistener(ui: *ttyui, l: listener) void = { + append(ui.listeners, l); +}; + + +export fn print(ui: ttyui, arg: (str | rune)) void = { + fmt::fprintf(ui.f, "{}\r\n", arg)!; +}; + +export fn clear(ui: ttyui) void = { + fmt::fprintf(ui.f, "\x1B[2J\x1B[1;1H\r")!; +}; + +//export @symbol("wcwidth") fn wcwidth(r: rune) int; |
