use fmt; use tb = termbox2; def bg = tb::COLOR.DEFAULT; def fg = tb::COLOR.BLACK; def paint_colors = [ (tb::COLOR.BLACK, "BLACK "), (tb::COLOR.RED, "RED "), (tb::COLOR.GREEN, "GREEN "), (tb::COLOR.YELLOW, "YELLOW "), (tb::COLOR.BLUE, "BLUE "), (tb::COLOR.MAGENTA, "MAGENTA"), (tb::COLOR.CYAN, "CYAN "), ]; def help_text = [ "Left-click to paint", "Right-click to change color", "Press q to exit", ]; def exit_keys = [ tb::KEY.ESC, tb::KEY.CTRL_Z, tb::KEY.CTRL_C, tb::KEY.CTRL_D, ]; def exit_chars = [ 'q', 'Q', ]; let ii: size = 0; // Current color index fn handle_mouse_event(me: tb::mouse_event) bool = { switch (me.key) { case tb::KEY.MOUSE_LEFT => tb::set_cell(me.x, me.y, ' ', tb::COLOR.DEFAULT, paint_colors[ii].0)!; case tb::KEY.MOUSE_RIGHT => ii = (ii + 1) % len(paint_colors); case => return false; }; return false; }; fn is_exit_key(ke: tb::key_event) bool = { match (ke.key_or_ch) { case let key: tb::key => for (let k .. exit_keys) if (key == k) return true; case let ch: rune => for (let c .. exit_chars) if (ch == c) return true; }; return false; }; fn handle_events_and_exit() bool = { let e = tb::poll_event(); if (e is tb::err) return false; return match (e as tb::event) { case tb::resize_event => yield false; case let me: tb::mouse_event => yield handle_mouse_event(me); case let ke: tb::key_event => yield is_exit_key(ke); }; }; fn print_help_text() void = { let y = (tb::height()! - len(help_text)): int; let len0 = tb::print(0, y, fg, bg, help_text[0])!; let (c, ctext) = paint_colors[ii]; tb::print(len0: int + 1, y, c, bg, ctext)!; for (let i = 1z; i < len(help_text); i += 1) tb::print(0, y + i: int, fg, bg, help_text[i])!; }; export fn main() void = { let e = tb::init(); if (e is tb::err) fmt::fatalf(tb::strerror(e as tb::err)); defer tb::shutdown()!; tb::set_input_mode(tb::INPUT.ESC | tb::INPUT.MOUSE)!; tb::set_clear_attrs(fg, bg)!; for (true) { print_help_text(); tb::present()!; if (handle_events_and_exit()) break; }; return; };