use libtui; use libtui::widget; use libtui::widget::list; use libtui::layout; use encoding::utf8; use io; use fmt; use os; use strings; use unix::tty; use unix::signal; use unix::poll; use errors; let u: mainUI = mainUI {...}; let searchterm: str = ""; let searchforward: bool = true; type mainUI = struct { list: *list::listwidget, }; fn sighandler(sig: int, info: *signal::siginfo, ucontext: *void) void = { switch (sig) { case signal::SIGWINCH => let sz = libtui::getwinsize(u.list.widget.ui)!; //let rows: (u16 | size) = if (sz.rows - 2 < len(u.list.items)) { //yield sz.rows - 2; //} else { //yield len(u.list.items); //}; const oldsz = list::ttysize { rows = u.list.sz.rows, cols = u.list.sz.cols, }; list::setsize(u.list, tty::ttysize { rows = sz.rows - 1u16, columns = sz.columns, }); //u.list.sz.rows = rows: u16; //u.list.sz.cols = sz.columns; list::resize(u.list, oldsz); libtui::clear(u.list.widget.ui); list::print(u.list)!; case => yield; }; }; fn resize(list: *list::listwidget) void = { let sz = libtui::getwinsize(list.widget.ui)!; let rows: (u16 | size) = if (sz.rows - 1 < len(list.items)) { yield sz.rows - 1; } else { yield len(list.items); }; const oldsz = list::ttysize { rows = list.sz.rows, cols = list.sz.cols, }; let rows: (u16 | size) = if (sz.rows - 1u16 < len(list.items)) { yield sz.rows - 1u16; } else { yield len(list.items); }; list::setsize(list, tty::ttysize { rows = rows: u16, columns = sz.columns, }); list::resize(list, oldsz); }; export fn main() void = { let in = match (io::drain(os::stdin)) { case let in: []u8 => yield in; case let e: io::error => fmt::fatal(io::strerror(e)); }; defer free(in); let sin = strings::fromutf8(in); sin = strings::trim(sin, '\n'); let items = strings::split(sin, "\n"); // freed by list::finish itemscopy = strings::dupall(items); defer strings::freeall(itemscopy); let ui = libtui::init(); defer libtui::finish(&ui); let sz = libtui::getwinsize(ui)!; let rows: (u16 | size) = if (sz.rows - 1u16 < len(items)) { yield sz.rows - 1u16; } else { yield len(items); }; let l = list::newlistsz(ui, tty::ttysize { rows = rows: u16, columns = sz.columns, }, items...); libtui::addlistener(&ui, &globalrunehandler); widget::addlistener(&l, &runehandler); let layout = layout::newlayout(&l); defer layout::finishall(&layout); //defer free(searchterm); //libtui::clear(l.widget.ui); signal::block(signal::SIGWINCH); let sfd = match (signal::signalfd(signal::SIGWINCH)) { case let sfd: io::file => yield sfd; case let e: errors::error => fmt::fatal(errors::strerror(e)); }; defer io::close(sfd)!; const pollfds: [2]poll::pollfd = [poll::pollfd { fd = ui.f, events = poll::event::POLLIN, ... }, poll::pollfd { fd = sfd, events = poll::event::POLLIN, ... }]; for (true) { libtui::clear(l.widget.ui); match (layout::print(layout)) { case void => yield; case let e: io::error => fmt::fatal(io::strerror(e)); case let e: tty::error => fmt::fatal(tty::strerror(e)); }; let nb = match (poll::poll(pollfds, poll::INDEF)) { case let nb: uint => yield nb; case let e: errors::error => fmt::fatal(errors::strerror(e)); }; let readin = false; if (nb == 0) { continue; } else { if (pollfds[0].revents & poll::event::POLLIN != 0) { readin = true; }; if (pollfds[1].revents & poll::event::POLLIN != 0) { signal::read(pollfds[1].fd)!; resize(&l); }; }; if (readin) { let r = match (libtui::scan(ui)) { case let r: rune => yield r; case utf8::invalid => fmt::fprintln(os::stderr, "Invalid utf8 sequence")!; break; case io::EOF => fmt::fprintln(os::stderr, "EOF")!; break; case let e: io::error => fmt::fprintln(os::stderr, io::strerror(e))!; break; }; if (libtui::notify(&ui, r)) { break; }; if (list::notify(&l, r)) { break; }; }; }; }; @fini fn finish() void = { free(searchterm); };