use tui; use tui::widget; use io; use unix::tty; use memio; use strings; export type scrolllist = struct { widget: widget::widget, items: []str, frame: frame, cursor: u16, }; // Return an instance of list. out is the tty file, pos the starting position, // sz is the size of the widget (if void is used, the maximum possible // size is used), items is the slice of items of the list. export fn newscrolllist(state: *tui::tui, pos: widget::coords, sz: widget::widgetsize, style: (*widget::style | void), items: str...) (scrolllist | tty::error) = { const tsz = tty::winsize(state.out)?; let end = match (sz) { case let sz: tty::ttysize => yield if (tsz.rows < sz.rows) tsz.rows else sz.rows; case void => yield tsz.rows; }; if (end > len(items)) { end = len(items): u16; }; return scrolllist { widget = widget::widget { state = state, print = &printscrolllist, resize = &resizescrolllist, finish = &finishscrolllist, pos = pos, sz = sz, style = style, damage = widget::damageall, ... }, items = items, frame = frame { start = 0, end = end, }, cursor = 0u16, }; }; 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 = memio::string(&st)!; widget::print(list); }; fn resizescrolllist(widget: *widget::widget, ttysize: tty::ttysize) void = { return; }; fn finishscrolllist(widget: *widget::widget) void = { widget::finish(widget); }; export fn down(li: *scrolllist) void = { if (li.cursor == li.frame.end - 1) { framedown(li); }; if (li.cursor < len(li.items) - 1) { li.cursor += 1; }; }; export fn up(li: *scrolllist) void = { if (li.cursor == li.frame.start) { frameup(li); }; if (li.cursor > 0) { li.cursor -= 1; }; }; export fn frameup(li: *scrolllist) void = { if (li.frame.start > 0) { li.frame.start -= 1; li.frame.end -= 1; }; }; export fn framedown(li: *scrolllist) void = { if (li.frame.end < len(li.items)) { li.frame.start += 1; li.frame.end += 1; }; }; export fn top(li: *scrolllist) void = { const sz = li.frame.end - li.frame.start; li.cursor = 0; li.frame.end = sz; li.frame.start = 0; }; export fn bottom(li: *scrolllist) void = { const sz = li.frame.end - li.frame.start; li.cursor = len(li.items): u16 - 1; li.frame.end = len(li.items): u16; li.frame.start = len(li.items): u16 - sz; };