madeline basically only works well with foot. Ember is working on
improving it but she's not there yet.
Also, I don't think that most of the value-add of madeline has anything
to offer to himitsu. For instance, we definitely wouldn't want to store
the input history anywhere.
This patch updates hiq to use madeline for interactive input. The result
is quite pleasant to use; the arrow keys and some other key combinations
work in the usual readline style.
On the downside, when piping lines into `hiq -a`, madeline still
exclusively reads from the tty, rather than stdin. As a result, madeline
ignores piped data, so I had to keep a conditional branch that uses the
previous non-madeline implementation when when stdin is not a tty.
I'm not sure if that last bit is appropriate. Should madeline itself
handle this situation? Or should I extract the 10 duplicate lines into a
function and just keep this conditional branch?
---
cmd/hiq/main.ha | 70 ++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 55 insertions(+), 15 deletions(-)
diff --git a/cmd/hiq/main.ha b/cmd/hiq/main.ha
index 0e42d44..5fa6ead 100644
--- a/cmd/hiq/main.ha+++ b/cmd/hiq/main.ha
@@ -6,6 +6,7 @@ use getopt;
use himitsu::client;
use himitsu::query;
use io;
+use made;use net::unix;
use net;
use os;
@@ -75,20 +76,31 @@ export fn main() void = {
if (op == client::operation::ADD && len(cmd.args) == 0) {
if (tty::isatty(os::stderr_file) && tty::isatty(os::stdin_file)) {
fmt::errorln("Enter new keys, one per line, then press ^d:")!;
- };- for (true) {- match (bufio::read_line(os::stdin)!) {- case io::EOF => break;- case let line: []u8 =>- // NB. Can't defer free(line), causes a- // use-after-free in fmt::fatal- const line = match (strings::fromutf8(line)) {- case let s: str =>- yield s;- case =>- free(line);- fmt::fatal("Error: Query is not valid UTF-8");- };++ let ctx = made::context {+ complete = &made::complete_none,+ hint = &made::hint_history,+ hist = &made::histmem(),+ prompt = &made::prompt_string(""),+ split = made::split_sh,+ cfg = match (made::config_default("hiq")) {+ case let cfg: made::config =>+ yield cfg;+ case let e: made::error =>+ fmt::fatal(made::strerror(e));+ },+ ...+ };+ defer made::config_free(ctx.cfg);+ defer made::ctx_finish(&ctx)!;++ for (true) match (made::line(&ctx)) {+ case io::EOF =>+ break;+ case void =>+ fmt::println("^C")!;+ case let line: str =>+ defer free(line); const query = match (query::parse_str(line)) {
case let q: query::query =>
yield q;
@@ -98,8 +110,36 @@ export fn main() void = {
fmt::fatal("Duplicate keys in query:", line);
};
defer query::finish(&query);
- free(line); send(conn, client::operation::ADD, &query, flags, field, one);
+ case let e: made::error =>+ fmt::fatal(made::strerror(e));+ };+ } else {+ for (false) {+ match (bufio::read_line(os::stdin)!) {+ case io::EOF => break;+ case let line: []u8 =>+ // NB. Can't defer free(line), causes a+ // use-after-free in fmt::fatal+ const line = match (strings::fromutf8(line)) {+ case let s: str =>+ yield s;+ case =>+ free(line);+ fmt::fatal("Error: Query is not valid UTF-8");+ };+ const query = match (query::parse_str(line)) {+ case let q: query::query =>+ yield q;+ case query::invalid =>+ fmt::fatal("Invalid query:", line);+ case query::dupkeys =>+ fmt::fatal("Duplicate keys in query:", line);+ };+ defer query::finish(&query);+ free(line);+ send(conn, client::operation::ADD, &query, flags, field, one);+ }; };
};
} else {
--
2.44.0