ed

[hare] The standard editor
Log | Files | Refs | README | LICENSE

commit 75577de0f5b81b5225c671403b12ea690a830346
parent 97ceeeaf3ef19e9c6481438f0eece7fbf645fee8
Author: Byron Torres <b@torresjrjr.com>
Date:   Sun, 19 Feb 2023 23:46:13 +0000

complete cmd_shellescape()

Diffstat:
Mcommand.ha | 53++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mmain.ha | 4++++
2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/command.ha b/command.ha @@ -6,6 +6,7 @@ use os; use os::exec; use regex; use strings; +use strio; type command = struct { addrs: []address, @@ -35,6 +36,7 @@ type error = !( | nofilename | buffermodified | nomatch + | noprevshcmd | regex::error | fs::error ); @@ -47,6 +49,8 @@ type nofilename = !void; type buffermodified = !void; +type noprevshcmd = !void; + fn lookupcmd(name: rune) commandfn = { switch (name) { case 'a' => return &cmd_append; @@ -536,7 +540,49 @@ fn cmd_linenumber(s: *session, cmd: *command) (void | error) = { }; fn cmd_shellescape(s: *session, cmd: *command) (void | error) = { - let shcmd = exec::cmd("sh", "-c", cmd.arg)!; + let iter = strings::iter(cmd.arg); + let new = strio::dynamic(); defer io::close(&new)!; + let preview = false; + + // handling '!!' + if (strings::next(&iter) == '!') { + match (s.prev_shcmd) { + case void => + return noprevshcmd; + case let s: str => + strio::concat(&new, s)!; + }; + preview = true; + } else { + strings::prev(&iter); + }; + + // handling '%' and '\%' + for (true) { + match (strings::next(&iter)) { + case void => + break; + case let r: rune => + switch (r) { + case '\\' => + match (strings::next(&iter)) { + case void => + break; + case let r: rune => + strio::appendrune(&new, r)!; + }; + case '%' => + strio::concat(&new, s.buf.filename)!; + preview = true; + case => + strio::appendrune(&new, r)!; + }; + }; + }; + + let shcmdline = strings::dup(strio::string(&new)); + + let shcmd = exec::cmd("sh", "-c", shcmdline)!; let pipe = exec::pipe(); exec::addfile(&shcmd, os::stdout_file, pipe.1); let proc = exec::start(&shcmd)!; @@ -546,10 +592,15 @@ fn cmd_shellescape(s: *session, cmd: *command) (void | error) = { io::close(pipe.0)!; exec::wait(&proc)!; + if (preview) { + fmt::println(shcmdline)!; + }; fmt::print(strings::fromutf8(data)!)!; if (!s.suppressmode) { fmt::println("!")!; }; + + s.prev_shcmd = shcmdline; }; fn cmd_null(s: *session, cmd: *command) (void | error) = { diff --git a/main.ha b/main.ha @@ -17,6 +17,7 @@ type session = struct { promptmode: bool, prompt: str, warned: bool, + prev_shcmd: (str | void), }; type mode = enum { @@ -41,6 +42,7 @@ export fn main() void = { ... }, prompt = "*", + prev_shcmd = void, ... }; @@ -148,6 +150,8 @@ fn errormsg(s: *session, err: error) error = { yield "Invalid destination"; case nomatch => yield "No match"; + case noprevshcmd => + yield "No previous shell command"; case let e: regex::error => yield regex::strerror(e); case let e: fs::error =>