summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tui/widget/list/list.ha18
-rw-r--r--tui/widget/list/scrolllist.ha39
-rw-r--r--tui/widget/text/text.ha9
-rw-r--r--tui/widget/widget.ha114
4 files changed, 97 insertions, 83 deletions
diff --git a/tui/widget/list/list.ha b/tui/widget/list/list.ha
index 23127ac..61ab22d 100644
--- a/tui/widget/list/list.ha
+++ b/tui/widget/list/list.ha
@@ -56,22 +56,10 @@ style: (*widget::style | void), items: str...) (list | tty::error) = {
export fn printlist(widget: *widget::widget) void = {
const list = widget: *list;
- let st = memio::dynamic();
- defer io::close(&st)!;
- for (let i = list.frame.start; i < list.frame.end; i += 1) {
- //let item = match (list.widget.sz) {
- //case let sz: tty::ttysize =>
- // yield strings::sub(list.items[i], 0z, sz.columns);
- //case widget::nosize =>
- // yield list.items[i];
- //};
- //memio::concat(&st, item)!;
- memio::concat(&st, list.items[i])!;
- if (i != list.frame.end - 1) {
- memio::concat(&st, "\n")!;
- };
+ list.widget.buf = widget::linesbuf {
+ lines = list.items[list.frame.start..list.frame.end],
+ styles = null,
};
- list.widget.buf = memio::string(&st)!;
widget::print(list);
};
diff --git a/tui/widget/list/scrolllist.ha b/tui/widget/list/scrolllist.ha
index 55cee9a..5057116 100644
--- a/tui/widget/list/scrolllist.ha
+++ b/tui/widget/list/scrolllist.ha
@@ -53,28 +53,10 @@ style: (*widget::style | void), items: str...) (scrolllist | tty::error) = {
fn printscrolllist(widget: *widget::widget) void = {
const list = widget: *scrolllist;
- let st = memio::dynamic();
- defer io::close(&st)!;
- for (let i = list.frame.start; i < list.frame.end; i += 1) {
- //let item = match (list.widget.sz) {
- //case let sz: tty::ttysize =>
- // yield strings::sub(list.items[i], 0z, sz.columns);
- //case widget::nosize =>
- // yield list.items[i];
- //};
- //memio::concat(&st, item)!;
- if (i == list.cursor) {
- memio::concat(&st, "\x1B[7m")!;
- };
- memio::concat(&st, list.items[i])!;
- if (i == list.cursor) {
- memio::concat(&st, "\x1B[27m")!;
- };
- if (i != list.frame.end - 1) {
- memio::concat(&st, widget::NEWLINE)!;
- };
+ list.widget.buf = widget::linesbuf {
+ lines = list.items[list.frame.start..list.frame.end],
+ styles = &stylesscrolllist,
};
- list.widget.buf = memio::string(&st)!;
widget::print(list);
};
@@ -131,3 +113,18 @@ export fn bottom(li: *scrolllist) void = {
li.frame.end = len(li.items): u16;
li.frame.start = len(li.items): u16 - sz;
};
+
+fn stylesscrolllist(widget: *widget::widget, txt: str, idx: size) str = {
+ const list = widget: *scrolllist;
+ const idx = idx + list.frame.start;
+ let st = memio::dynamic();
+ defer io::close(&st)!;
+ if (idx == list.cursor) {
+ memio::concat(&st, "\x1B[7m")!;
+ };
+ memio::concat(&st, txt)!;
+ if (idx == list.cursor) {
+ memio::concat(&st, "\x1B[27m")!;
+ };
+ return strings::dup(memio::string(&st)!);
+};
diff --git a/tui/widget/text/text.ha b/tui/widget/text/text.ha
index 0a30eb0..40b3f58 100644
--- a/tui/widget/text/text.ha
+++ b/tui/widget/text/text.ha
@@ -2,7 +2,6 @@ use io;
use unix::tty;
use tui;
use tui::widget;
-use strings;
export type text = struct {
widget: widget::widget,
@@ -19,7 +18,7 @@ export fn newtext(state: *tui::tui, txt: str, pos: widget::coords, style: (*widg
pos = pos,
sz = void,
style = style,
- damage = widget::all,
+ damage = widget::damageall,
...
},
txt = txt,
@@ -28,8 +27,10 @@ export fn newtext(state: *tui::tui, txt: str, pos: widget::coords, style: (*widg
fn printtext(widget: *widget::widget) void = {
const widget = widget: *text;
- widget.widget.buf = strings::dup(widget.txt);
- defer free(widget.widget.buf);
+ widget.widget.buf = widget::linesbuf {
+ lines = [widget.txt],
+ ...
+ };
widget::print(widget);
};
diff --git a/tui/widget/widget.ha b/tui/widget/widget.ha
index 8422932..eadc773 100644
--- a/tui/widget/widget.ha
+++ b/tui/widget/widget.ha
@@ -25,12 +25,23 @@ export type damageitem = damagerow;
export type damage = (damagenone | damageall | []damageitem);
+export type stylesfn = fn(w: *widget, txt: str, idx: size) str;
+
+//export type line = struct {
+// txt: str,
+//};
+
+export type linesbuf = struct {
+ lines: []str,
+ styles: nullable *stylesfn,
+};
+
export type widget = struct {
state: *tui::tui,
print: *printfn,
resize: *resizefn,
finish: *finishfn,
- buf: str,
+ buf: linesbuf,
pos: coords,
sz: widgetsize,
style: (*style | void),
@@ -153,15 +164,33 @@ export fn print(w: *widget) void = {
defer free(clear);
let s = truncate_to_size(w);
- defer free(s);
+ defer strings::freeall(s);
let sstyle = applystyles(w.style, s);
- defer free(sstyle);
+ defer strings::freeall(sstyle);
//const clear = if (w.state.clear) "\x1B[2J" else "";
+
+ let st = memio::dynamic();
+ defer io::close(&st)!;
+
+ for(let i = 0z; i < len(sstyle); i += 1) {
+ const line = match (w.buf.styles) {
+ case let f: *stylesfn =>
+ yield f(w, sstyle[i], i);
+ case null =>
+ yield strings::dup(sstyle[i]);
+ };
+ defer free(line);
+ memio::concat(&st, line, NEWLINE)!;
+ };
+
+ const joined = memio::string(&st)!;
+
let seekpos = fmt::asprintf("{}\x1B[{};{}H", clear, w.pos.0, w.pos.1);
defer free(seekpos);
- const sout = strings::concat(seekpos, sstyle);
+
+ const sout = strings::concat(seekpos, joined);
defer free(sout);
fmt::fprint(w.state.out, sout)!;
@@ -169,36 +198,40 @@ export fn print(w: *widget) void = {
w.state.clear = false;
};
-// Applies styling (style) to the given string
-fn applystyles(st: (*style | void), s: str) str = {
+// Applies styling (style) to the given string.
+fn applystyles(st: (*style | void), s: []str) []str = {
return match (st) {
case let st: *style =>
let sborder = if (st.border) {
yield border(s);
} else {
- yield strings::dup(s);
+ yield strings::dupall(s);
};
- defer free(sborder);
+ //defer strings::freeall(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);
+ const sb = strings::concat(scolor, sborder[0]);
+ free(sborder[0]);
+ sborder[0] = sb;
+ const endidx = len(sborder) - 1;
+ const sb = strings::concat(sborder[endidx], defcolor);
+ free(sborder[endidx]);
+ sborder[endidx] = sb;
+ yield sborder;
case void =>
- yield strings::dup(s);
+ yield strings::dupall(s);
};
};
// 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 = splitstr(w.buf, NEWLINE);
- defer free(spl);
- const st = memio::dynamic();
- defer io::close(&st)!;
- const nbrows = minrows(w.state.out, len(spl): u16, w.sz)!;
+// returns the resulting lines. Must call [[strings::freeall]] on the result.
+fn truncate_to_size(w: *widget) []str = {
+ let lines: []str = [];
+ const nbrows = minrows(w.state.out, len(w.buf.lines): u16, w.sz)!;
for (let i = 0z; i < nbrows; i += 1) {
- const line = spl[i];
+ const line = w.buf.lines[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;
@@ -206,39 +239,34 @@ fn truncate_to_size(w: *widget) str = {
case void =>
yield strings::dup(line);
};
+ append(lines, item);
//fmt::println(item)!;
- defer free(item);
- memio::concat(&st, item)!;
- memio::concat(&st, NEWLINE)!;
};
- return strings::dup(memio::string(&st)!);
+ return lines;
};
-// Add a border around a string
-fn border(s: str) str = {
- let st = memio::dynamic();
- defer io::close(&st)!;
- //let spl = strings::split(s, NEWLINE);
- let spl = splitstr(s, NEWLINE);
- defer free(spl);
- 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);
+// Add a border around a slice of strings. Must call [[strings::freeall]] on the
+// result.
+fn border(s: []str) []str = {
+ let lines: []str = [];
+ for (let i = 0z; i < len(s); i += 1) {
+ const si = strings::concat("|", s[i], "|");
+ si = if (i == 0) {
+ defer free(si);
+ yield overline(si);
+ } else {
+ yield si;
};
- if (i == len(spl) - 1) {
- s = underline(s);
+ si = if (i == len(s) - 1) {
+ defer free(si);
+ yield underline(si);
+ } else {
+ yield si;
};
- //memio::concat(&st, "|", s, "|")!;
- memio::concat(&st, s)!;
- if (i < len(spl) - 1) {
- memio::concat(&st, NEWLINE)!;
- };
+ append(lines, si);
};
- return strings::dup(memio::string(&st)!);
+ return lines;
};
export fn prints(out: io::file, s: str, pos: coords) void = {