summaryrefslogtreecommitdiff
path: root/tui/widget/widget.ha
diff options
context:
space:
mode:
Diffstat (limited to 'tui/widget/widget.ha')
-rw-r--r--tui/widget/widget.ha151
1 files changed, 147 insertions, 4 deletions
diff --git a/tui/widget/widget.ha b/tui/widget/widget.ha
index 77b6f88..dbbfa11 100644
--- a/tui/widget/widget.ha
+++ b/tui/widget/widget.ha
@@ -1,35 +1,178 @@
use fmt;
use unix::tty;
use io;
+use strings;
+use memio;
+use os;
+use strconv;
export type coords = (u16, u16);
export type printfn = fn(w: *widget) void;
export type resizefn = fn(w: *widget, ttysize: tty::ttysize) void;
-export type nosize = void;
-export type widgetsize = (tty::ttysize | nosize);
+export type widgetsize = (tty::ttysize | void);
+
+export type color = enum uint {
+ BLACKFG = 30,
+ REDFG = 31,
+ GREENFG = 32,
+ BROWNFG = 33,
+ BLUEFG = 34,
+ MAGENTAFG = 35,
+ CYANFG = 36,
+ WHITEFG = 37,
+ DEFAULTFG = 39,
+
+ BLACKBG = 40,
+ REDBG = 41,
+ GREENBG = 42,
+ BROWNBG = 43,
+ BLUEBG = 44,
+ MAGENTABG = 45,
+ CYANBG = 46,
+ WHITEBG = 47,
+ DEFAULTBG = 49,
+};
export type style = struct {
border: bool,
+ colorfg: color,
+ colorbg: color,
};
export def DEFAULT_STYLE: style = style {
border = false,
+ colorfg = color::DEFAULTFG,
+ colorbg = color::DEFAULTBG,
};
export type widget = struct {
out: io::file,
print: *printfn,
resize: *resizefn,
+ buf: str,
pos: coords,
sz: widgetsize,
- style: style,
+ style: (*style | void),
};
def gotoroot: str = "\x1B[1;1H";
-export fn print(out: io::file, s: str, pos: coords) void = {
+def UNDERLINE: str = "\x1B[4m";
+def NOUNDERLINE: str = "\x1B[0m";
+
+def OVERLINE: rune = '\u0305';
+def NOOVERLINE: str = "\x1B[0m";
+
+// Must free return value
+fn underline(s: str) str = {
+ return strings::concat(UNDERLINE, s, NOUNDERLINE);
+};
+
+// Must free return value
+fn overline(s: str) str = {
+ const st = memio::dynamic();
+ defer io::close(&st)!;
+ let iter = strings::iter(s);
+ for (let r: rune => strings::next(&iter)) {
+ const char = strings::fromrunes([r, OVERLINE]);
+ defer free(char);
+ memio::concat(&st, char)!;
+ };
+ return strings::dup(memio::string(&st)!);
+};
+
+fn minrows(out: io::file, x: u16, y: widgetsize) (u16 | tty::error) = {
+ const y = match (y) {
+ case let y: tty::ttysize =>
+ yield y;
+ case void =>
+ yield tty::winsize(out)?;
+ };
+ return if (x < y.rows) x else y.rows;
+};
+
+// Must free return string
+fn color_to_str(color: color) str = fmt::asprintf("\x1B[{}m", strconv::utos(color));
+
+export fn print(w: *widget) void = {
+ fmt::fprintf(w.out, "\x1B[{};{}H", w.pos.0, w.pos.1)!;
+
+ let s = truncate_to_size(w);
+
+ let sstyle = match (w.style) {
+ case let st: *style =>
+ defer free(s);
+ let sborder = if (st.border) {
+ yield border(s);
+ } else {
+ yield strings::dup(s);
+ };
+ defer free(sborder);
+ const scolor = color_to_str(st.colorfg);
+ defer free(scolor);
+ const defcolor = color_to_str(color::DEFAULTFG);
+ defer free(defcolor);
+ yield strings::concat(scolor, sborder, defcolor);
+ case void =>
+ yield s;
+ };
+
+ defer free(sstyle);
+
+ fmt::fprint(w.out, sstyle)!;
+};
+
+// Truncates the text of the widget to the widget's size (rows and columns) and
+// returns the resulting string.
+fn truncate_to_size(w: *widget) str = {
+ let spl = strings::split(w.buf, "\n");
+ const st = memio::dynamic();
+ defer io::close(&st)!;
+ for (let i = 0z; i < minrows(w.out, len(spl): u16, w.sz)!; i += 1) {
+ const line = spl[i];
+ let item = match (w.sz) {
+ case let sz: tty::ttysize =>
+ const s = if (len(line) > sz.columns) strings::sub(line, 0z, sz.columns) else line;
+ yield strings::rpad(s, ' ', sz.columns);
+ case void =>
+ yield strings::dup(line);
+ };
+ defer free(item);
+ memio::concat(&st, item)!;
+ if (i < len(spl) - 1) {
+ memio::concat(&st, "\n")!;
+ };
+ };
+ return strings::dup(memio::string(&st)!);
+};
+
+fn border(s: str) str = {
+ let st = memio::dynamic();
+ defer io::close(&st)!;
+ let spl = strings::split(s, "\n");
+ for (let i = 0z; i < len(spl); i += 1) {
+ const s = strings::concat("|", spl[i], "|");
+ //const s = strings::dup(spl[i]);
+ defer free(s);
+ if (i == 0) {
+ s = overline(s);
+ };
+ if (i == len(spl) - 1) {
+ s = underline(s);
+ };
+ //memio::concat(&st, "|", s, "|")!;
+ memio::concat(&st, s)!;
+
+ if (i < len(spl) - 1) {
+ memio::concat(&st, "\n")!;
+ };
+ };
+ return strings::dup(memio::string(&st)!);
+};
+
+export fn prints(out: io::file, s: str, pos: coords) void = {
fmt::fprintf(out, "\x1B[{};{}H", pos.0, pos.1)!;
fmt::fprint(out, s)!;
};