Max Schillinger: 1 Add actions histtokup and histtokdown 4 files changed, 53 insertions(+), 0 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.d2evs.net/~ecs/public-inbox/patches/50/mbox | git am -3Learn more about email & git
These actions complete the current command line with the last token of the previous/next command in history. They are bound to "Alt+." and "Alt+>"/"Alt+" (which is "Alt+Shift+." on QWERTY/QWERTZ). Example: % echo "hello world" % folder=/tmp/folder % mkdir $folder % cd $folder % mv ~/Downloads/x . % echo folder=$folder % echo [Alt+.] On pressing "Alt+." multiple times, the current command line will be completed to % echo folder=$folder % echo . % echo $folder % echo hello world The duplicate $folder token will be skipped. "folder=/tmp/folder" will be skipped as well (because there are no arguments). "hello world" will be considered one token (using made::split_sh). Possible TODO's: - "hello world" it is inserted without quotes. made::sh_escape could be used to escape the space but this would also escape the "$" in "$folder". Maybe made::split_sh can be modified to optionally return tokens including surrounding quotes. - IMO, these actions should iterate over all arguments not only the last one of every command. This would require to modify made::split_sh to optionally return a token with a requested index. --- made/actions.ha | 47 +++++++++++++++++++++++++++++++++++++++++++++++ made/hist.ha | 1 + made/line.ha | 4 ++++ made/types.ha | 1 + 4 files changed, 53 insertions(+) diff --git a/made/actions.ha b/made/actions.ha index 10f8021..dea1b2f 100644 --- a/made/actions.ha +++ b/made/actions.ha @@ -2,6 +2,7 @@ use bufio; use io; use strings; use sort; +use crypto; // Pull new lines from other madeline instances into the in-memory history fn update_hist(s: *state) (void | error) = { @@ -53,6 +54,52 @@ fn histdown(s: *state) (void | error) = { }; }; +fn histtokenup(s: *state) (void | error) = { + update_hist(s)?; + let h = &s.ctx.hist; + if (s.mode == mode::NORMAL) { + if (len(h.our_hist) == 0) return; + h.htokidx = len(h.our_hist); + s.buftyped = s.buf; + }; + if (s.mode == mode::SEARCH) return; + s.mode = mode::HIST; + for (h.htokidx > 0) { + h.htokidx -= 1; + let (token, count) = s.ctx.split.split(h.our_hist[h.htokidx]); + if (count == 0) continue; // command only, no arguments + let tempbuf = strings::concat(strings::fromutf8(s.buftyped)!, token); + defer free(tempbuf); + let newbufutf8 = strings::toutf8(strings::dup(tempbuf)); + if (crypto::compare(s.buf, newbufutf8)) continue; + s.buf = newbufutf8; + s.pos = len(s.buf); + break; + }; +}; + +fn histtokendown(s: *state) (void | error) = { + if (s.mode != mode::HIST) return; + update_hist(s)?; + let h = &s.ctx.hist; + for (h.htokidx < len(h.our_hist) - 1) { + h.htokidx += 1; + let (token, count) = s.ctx.split.split(h.our_hist[h.htokidx]); + if (count == 0) continue; // command only, no arguments + let tempbuf = strings::concat(strings::fromutf8(s.buftyped)!, token); + defer free(tempbuf); + let newbufutf8 = strings::toutf8(strings::dup(tempbuf)); + if (crypto::compare(s.buf, newbufutf8)) continue; + // update command line with new token + s.buf = newbufutf8; + s.pos = len(s.buf); + return; + }; + s.buf = s.buftyped; + s.pos = len(s.buf); + s.mode = mode::NORMAL; +}; + fn complete(s: *state) void = { freecompletions(s); s.completions = s.ctx.complete(s.ctx, s.buf, s.pos); diff --git a/made/hist.ha b/made/hist.ha index 7f867bd..04ddaf4 100644 --- a/made/hist.ha +++ b/made/hist.ha @@ -13,6 +13,7 @@ export type history = struct { hist: []str, our_hist: []str, hidx: size, + htokidx: size, }; // Stores [[history]] in memory without a backing handle. diff --git a/made/line.ha b/made/line.ha index a66600d..ebbfebd 100644 --- a/made/line.ha +++ b/made/line.ha @@ -138,6 +138,10 @@ export fn line(ctx: *context) (str | void | io::EOF | error) = { kill(&s, &prevword, false); case 'y' => // alt+y unkill(&s, false); + case '.' => // alt+. + histtokenup(&s)?; + case '>', ':' => // alt+shift+. + histtokendown(&s)?; case '\x0a', '\x0d' => // alt+enter appendstr(&s, "\n"); case => void; diff --git a/made/types.ha b/made/types.ha index 8359903..15cad42 100644 --- a/made/types.ha +++ b/made/types.ha @@ -20,6 +20,7 @@ type state = struct { in: io::file, out: io::handle, buf: []u8, + buftyped: []u8, // typed manually, without token completion pos: size, mode: mode, completions: (str, [](str, str)), -- 2.42.0