aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--handlers.ha200
-rw-r--r--libui/widget/list/list.ha12
-rw-r--r--main.ha183
3 files changed, 215 insertions, 180 deletions
diff --git a/handlers.ha b/handlers.ha
new file mode 100644
index 0000000..ef374ef
--- /dev/null
+++ b/handlers.ha
@@ -0,0 +1,200 @@
+use libui;
+use libui::widget;
+use libui::widget::list;
+use sort;
+use slices;
+use encoding::utf8;
+use fmt;
+use bufio;
+use os;
+use regex;
+use io;
+use strings;
+use unix::tty;
+
+let itemscopy: []str = [];
+
+fn globalrunehandler(ui: *libui::ttyui, r: rune) bool = {
+ if (r == 'q') {
+ return true;
+ };
+ return false;
+};
+
+fn runehandler(l: *widget::widget, r: rune) bool = {
+ const l = l: *list::listwidget;
+ switch (r) {
+ case 'j' =>
+ list::down(l);
+ case 'k' =>
+ list::up(l);
+ case 'd' =>
+ list::pagedown(l);
+ case 'u' =>
+ list::pageup(l);
+ case 'l' =>
+ // to print properly suspend the ui, print, then resume
+ libui::suspend(&l.ui);
+ //fmt::println(l.items[l.cursor])!;
+ match (list::selected(*l)) {
+ case let s: str =>
+ fmt::println(s)!;
+ case let s: []str =>
+ defer free(s);
+ const out = strings::join("\n", s...);
+ defer free(out);
+ fmt::println(out)!;
+ };
+ libui::resume(&l.ui);
+ return true;
+ case 'g' =>
+ list::top(l);
+ case 'G' =>
+ list::bottom(l);
+ case 'n' =>
+ if (searchforward) {
+ list::search(l, searchterm);
+ } else {
+ list::rsearch(l, searchterm);
+ };
+ case 'N' =>
+ if (searchforward) {
+ list::rsearch(l, searchterm);
+ } else {
+ list::search(l, searchterm);
+ };
+ case '?' =>
+ // TODO add commandline support maybe
+ libui::suspend(&l.ui);
+ fmt::fprint(l.ui.f, '?')!;
+ let line = match (bufio::scanline(l.ui.f)) {
+ case let s: []u8 =>
+ yield s;
+ case io::EOF =>
+ fmt::fprintln(os::stderr, "EOF")!;
+ return true;
+ case let e: io::error =>
+ fmt::fprintln(os::stderr, io::strerror(e))!;
+ return true;
+ };
+ //defer free(line);
+ searchterm = strings::fromutf8(line);
+ searchforward = false;
+ let c = l.cursor;
+ list::rsearch(l, searchterm);
+ libui::resume(&l.ui);
+ case '/' =>
+ // TODO add commandline support maybe
+ libui::suspend(&l.ui);
+ fmt::fprint(l.ui.f, '/')!;
+ let line = match (bufio::scanline(l.ui.f)) {
+ case let s: []u8 =>
+ yield s;
+ case io::EOF =>
+ fmt::fprintln(os::stderr, "EOF")!;
+ return true;
+ case let e: io::error =>
+ fmt::fprintln(os::stderr, io::strerror(e))!;
+ return true;
+ };
+ //defer free(line);
+ searchterm = strings::fromutf8(line);
+ searchforward = true;
+ let c = l.cursor;
+ list::search(l, searchterm);
+ libui::resume(&l.ui);
+ case 'o' =>
+ // order
+ sort::strings(l.items);
+ case 'O' =>
+ // reverse order
+ sort::strings(l.items);
+ slices::reverse(l.items: []void, size(str));
+ case 'p' =>
+ list::setitems(l, itemscopy...);
+ case 's' =>
+ // TODO add commandline support maybe
+ libui::suspend(&l.ui);
+ fmt::fprint(l.ui.f, "s: ")!;
+ let line = match (bufio::scanline(l.ui.f)) {
+ case let s: []u8 =>
+ yield s;
+ case io::EOF =>
+ fmt::fprintln(os::stderr, "EOF")!;
+ return true;
+ case let e: io::error =>
+ fmt::fprintln(os::stderr, io::strerror(e))!;
+ return true;
+ };
+ defer free(line);
+ list::containsmark(l, strings::fromutf8(line));
+ libui::resume(&l.ui);
+ case 'S' =>
+ // TODO add commandline support maybe
+ libui::suspend(&l.ui);
+ fmt::fprint(l.ui.f, "S: ")!;
+ let line = match (bufio::scanline(l.ui.f)) {
+ case let s: []u8 =>
+ yield s;
+ case io::EOF =>
+ fmt::fprintln(os::stderr, "EOF")!;
+ return true;
+ case let e: io::error =>
+ fmt::fprintln(os::stderr, io::strerror(e))!;
+ return true;
+ };
+ defer free(line);
+ list::fnmatchmark(l, strings::fromutf8(line));
+ libui::resume(&l.ui);
+ case 'r' =>
+ // TODO add commandline support maybe
+ libui::suspend(&l.ui);
+ fmt::fprint(l.ui.f, "r: ")!;
+ let line = match (bufio::scanline(l.ui.f)) {
+ case let s: []u8 =>
+ yield s;
+ case io::EOF =>
+ fmt::fprintln(os::stderr, "EOF")!;
+ return true;
+ case let e: io::error =>
+ fmt::fprintln(os::stderr, io::strerror(e))!;
+ return true;
+ };
+ defer free(line);
+ match (regex::compile(strings::fromutf8(line))) {
+ case let re: regex::regex =>
+ list::regexmark(l, &re);
+ regex::finish(&re);
+ case let e: regex::error =>
+ fmt::fprintln(os::stderr, regex::strerror(e))!;
+ };
+ libui::resume(&l.ui);
+ case ' ' =>
+ list::tmark(l);
+ list::down(l);
+ case 'c' =>
+ list::clearmarked(l);
+ case '\n' =>
+ // For some reason enter doesn't send r == '\n'
+ fmt::fprintln(os::stderr, "This is not detected")!;
+ yield;
+ case =>
+ let us = utf8::encoderune(r);
+ if (len(us) > 0 && us[0] == 13u8) {
+ fmt::fprintln(os::stderr, "newline")!;
+ };
+ yield;
+ };
+ libui::clear(l.ui);
+ match (list::print(l)) {
+ case void =>
+ yield;
+ case let e: io::error =>
+ fmt::fprintln(os::stderr, io::strerror(e))!;
+ return true;
+ case let e: tty::error =>
+ fmt::fprintln(os::stderr, tty::strerror(e))!;
+ return true;
+ };
+ return false;
+};
diff --git a/libui/widget/list/list.ha b/libui/widget/list/list.ha
index 8500482..efed759 100644
--- a/libui/widget/list/list.ha
+++ b/libui/widget/list/list.ha
@@ -79,6 +79,18 @@ export fn finish(list: *widget::widget) void = {
widget::finishcommon(list);
};
+// Set the list's items. If the length of the given items is smaller than the
+// list's current items, the cursor will be set to 0z and [[reframe]] will be
+// called to reset the frame.
+export fn setitems(list: *listwidget, items: str...) void = {
+ const reset = len(items) < len(list.items);
+ list.items = strings::dupall(items);
+ if (reset) {
+ list.cursor = 0z;
+ reframe(list);
+ };
+};
+
// Add a listener to the given list.
//export fn addlistener(list: *listwidget, l: listener) void = {
//append(list.listeners, l);
diff --git a/main.ha b/main.ha
index 1af7662..298087d 100644
--- a/main.ha
+++ b/main.ha
@@ -9,8 +9,6 @@ use os;
use strings;
use unix::tty;
use unix::signal;
-use bufio;
-use regex;
let u: mainUI = mainUI {...};
@@ -21,182 +19,6 @@ type mainUI = struct {
list: *list::listwidget,
};
-fn globalrunehandler(ui: *libui::ttyui, r: rune) bool = {
- if (r == 'q') {
- return true;
- };
- return false;
-};
-
-fn runehandler(l: *widget::widget, r: rune) bool = {
- const l = l: *list::listwidget;
- switch (r) {
- case 'j' =>
- list::down(l);
- case 'k' =>
- list::up(l);
- case 'd' =>
- list::pagedown(l);
- case 'u' =>
- list::pageup(l);
- case 'l' =>
- // to print properly suspend the ui, print, then resume
- libui::suspend(&l.ui);
- //fmt::println(l.items[l.cursor])!;
- match (list::selected(*l)) {
- case let s: str =>
- fmt::println(s)!;
- case let s: []str =>
- defer free(s);
- const out = strings::join("\n", s...);
- defer free(out);
- fmt::println(out)!;
- };
- libui::resume(&l.ui);
- return true;
- case 'g' =>
- list::top(l);
- case 'G' =>
- list::bottom(l);
- case 'n' =>
- if (searchforward) {
- list::search(l, searchterm);
- } else {
- list::rsearch(l, searchterm);
- };
- case 'N' =>
- if (searchforward) {
- list::rsearch(l, searchterm);
- } else {
- list::search(l, searchterm);
- };
- case '?' =>
- // TODO add commandline support maybe
- libui::suspend(&l.ui);
- fmt::fprint(l.ui.f, '?')!;
- let line = match (bufio::scanline(l.ui.f)) {
- case let s: []u8 =>
- yield s;
- case io::EOF =>
- fmt::fprintln(os::stderr, "EOF")!;
- return true;
- case let e: io::error =>
- fmt::fprintln(os::stderr, io::strerror(e))!;
- return true;
- };
- //defer free(line);
- searchterm = strings::fromutf8(line);
- searchforward = false;
- let c = l.cursor;
- list::rsearch(l, searchterm);
- libui::resume(&l.ui);
- case '/' =>
- // TODO add commandline support maybe
- libui::suspend(&l.ui);
- fmt::fprint(l.ui.f, '/')!;
- let line = match (bufio::scanline(l.ui.f)) {
- case let s: []u8 =>
- yield s;
- case io::EOF =>
- fmt::fprintln(os::stderr, "EOF")!;
- return true;
- case let e: io::error =>
- fmt::fprintln(os::stderr, io::strerror(e))!;
- return true;
- };
- //defer free(line);
- searchterm = strings::fromutf8(line);
- searchforward = true;
- let c = l.cursor;
- list::search(l, searchterm);
- libui::resume(&l.ui);
- case 's' =>
- // TODO add commandline support maybe
- libui::suspend(&l.ui);
- fmt::fprint(l.ui.f, "s: ")!;
- let line = match (bufio::scanline(l.ui.f)) {
- case let s: []u8 =>
- yield s;
- case io::EOF =>
- fmt::fprintln(os::stderr, "EOF")!;
- return true;
- case let e: io::error =>
- fmt::fprintln(os::stderr, io::strerror(e))!;
- return true;
- };
- defer free(line);
- list::containsmark(l, strings::fromutf8(line));
- libui::resume(&l.ui);
- case 'S' =>
- // TODO add commandline support maybe
- libui::suspend(&l.ui);
- fmt::fprint(l.ui.f, "S: ")!;
- let line = match (bufio::scanline(l.ui.f)) {
- case let s: []u8 =>
- yield s;
- case io::EOF =>
- fmt::fprintln(os::stderr, "EOF")!;
- return true;
- case let e: io::error =>
- fmt::fprintln(os::stderr, io::strerror(e))!;
- return true;
- };
- defer free(line);
- list::fnmatchmark(l, strings::fromutf8(line));
- libui::resume(&l.ui);
- case 'r' =>
- // TODO add commandline support maybe
- libui::suspend(&l.ui);
- fmt::fprint(l.ui.f, "r: ")!;
- let line = match (bufio::scanline(l.ui.f)) {
- case let s: []u8 =>
- yield s;
- case io::EOF =>
- fmt::fprintln(os::stderr, "EOF")!;
- return true;
- case let e: io::error =>
- fmt::fprintln(os::stderr, io::strerror(e))!;
- return true;
- };
- defer free(line);
- match (regex::compile(strings::fromutf8(line))) {
- case let re: regex::regex =>
- list::regexmark(l, &re);
- regex::finish(&re);
- case let e: regex::error =>
- fmt::fprintln(os::stderr, regex::strerror(e))!;
- };
- libui::resume(&l.ui);
- case ' ' =>
- list::tmark(l);
- list::down(l);
- case 'c' =>
- list::clearmarked(l);
- case '\n' =>
- // For some reason enter doesn't send r == '\n'
- fmt::fprintln(os::stderr, "This is not detected")!;
- yield;
- case =>
- let us = utf8::encoderune(r);
- if (len(us) > 0 && us[0] == 13u8) {
- fmt::fprintln(os::stderr, "newline")!;
- };
- yield;
- };
- libui::clear(l.ui);
- match (list::print(l)) {
- case void =>
- yield;
- case let e: io::error =>
- fmt::fprintln(os::stderr, io::strerror(e))!;
- return true;
- case let e: tty::error =>
- fmt::fprintln(os::stderr, tty::strerror(e))!;
- return true;
- };
- return false;
-};
-
fn sighandler(sig: int, info: *signal::siginfo, ucontext: *void) void = {
switch (sig) {
case signal::SIGWINCH =>
@@ -221,7 +43,9 @@ export fn main() void = {
defer free(in);
let sin = strings::fromutf8(in);
sin = strings::trim(sin, '\n');
- let items = strings::split(sin, "\n");
+ let items = strings::split(sin, "\n"); // freed by list::finish
+ itemscopy = strings::dupall(items);
+ defer strings::freeall(itemscopy);
let ui = libui::init();
defer libui::finish(&ui);
@@ -230,7 +54,6 @@ export fn main() void = {
widget::addlistener(&l, &runehandler);
let layout = layout::newlayout(&l);
-
defer layout::finishall(&layout);
//defer free(searchterm);