commit 18bb4f889430b5f59936ce12aa199e8bc37df527
parent 3354f41adc477539f2763576bb3140071dd9b7d6
Author: Byron Torres <b@torresjrjr.com>
Date: Tue, 9 Jan 2024 00:41:52 +0000
cmd_write(): impl ! shell commands
Diffstat:
M | Makefile | | | 1 | + |
M | command.ha | | | 96 | ++++++++++++++++++++++++++++++------------------------------------------------- |
A | file.ha | | | 52 | ++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | util.ha | | | 12 | ------------ |
4 files changed, 89 insertions(+), 72 deletions(-)
diff --git a/Makefile b/Makefile
@@ -7,6 +7,7 @@ source=\
buffer.ha \
command.ha \
execute.ha \
+ file.ha \
global.ha \
interaction.ha \
parse.ha \
diff --git a/command.ha b/command.ha
@@ -179,38 +179,11 @@ fn cmd_delete(s: *Session, cmd: *Command) (void | Error) = {
};
fn cmd_edit(s: *Session, cmd: *Command) (void | Error) = {
- assert_noaddrs(s, cmd.linenums)?;
-
- if (s.buf.modified && !s.warned) {
- s.warned = true;
- return WarnBufferModified;
- };
-
- const fname = filename(s, cmd, true)?;
- const h = os::open(fname)?; defer io::close(h)!;
-
- buf_deleteall(s.buf);
- const (sz, _) = buf_read(s.buf, h, 0)?;
-
- if (!s.suppressmode)
- fmt::println(sz)!;
-
- s.buf.cursor = len(s.buf.lines) - 1;
+ edit(s, cmd, false)?;
};
fn cmd_edit_forced(s: *Session, cmd: *Command) (void | Error) = {
- assert_noaddrs(s, cmd.linenums)?;
-
- const fname = filename(s, cmd, true)?;
- const h = os::open(fname)?; defer io::close(h)!;
-
- buf_deleteall(s.buf);
- const (sz, _) = buf_read(s.buf, h, 0)?;
-
- if (!s.suppressmode)
- fmt::println(sz)!;
-
- s.buf.cursor = len(s.buf.lines) - 1;
+ edit(s, cmd, true)?;
};
fn cmd_filename(s: *Session, cmd: *Command) (void | Error) = {
@@ -448,15 +421,13 @@ fn cmd_read(s: *Session, cmd: *Command) (void | Error) = {
const n = get_linenum(cmd.linenums, addr_lastline(s.buf));
- const h: io::handle =
+ const rd: io::handle =
if (!strings::hasprefix(cmd.arg1, "!")) {
const fname = filename(s, cmd, false)?;
yield os::open(fname)?;
} else {
- // TODO: handle '!'s
- let shcmd = exec::cmd(
- "sh", "-c", strings::cut(cmd.arg1, "!").1
- )?;
+ let shcmdline = strings::cut(cmd.arg1, "!").1;
+ let shcmd = exec::cmd("sh", "-c", shcmdline)?;
let pipe = exec::pipe();
exec::addfile(&shcmd, os::stdout_file, pipe.1);
let proc = exec::start(&shcmd)?;
@@ -464,9 +435,9 @@ fn cmd_read(s: *Session, cmd: *Command) (void | Error) = {
exec::wait(&proc)?;
yield pipe.0;
};
- defer io::close(h)!;
+ defer io::close(rd)!;
- const (sz, _) = buf_read(s.buf, h, n)?;
+ const (sz, _) = buf_read(s.buf, rd, n)?;
if (!s.suppressmode)
fmt::println(sz)!;
@@ -578,21 +549,25 @@ fn cmd_write(s: *Session, cmd: *Command) (void | Error) = {
)?;
assert_nonzero(s, a)?;
- const fname = filename(s, cmd, false)?;
- const h = match (os::open(fname, fs::flag::WRONLY)) {
- case let err: fs::error =>
- yield match (err) {
- case errors::noentry =>
- yield os::create(fname, 0o644)?: io::handle;
- case =>
- return err;
+ let proc: (void | exec::process) = void;
+ const wr: io::handle =
+ if (!strings::hasprefix(cmd.arg1, "!")) {
+ yield openwritefile(filename(s, cmd, false)?)?;
+ } else {
+ let shcmdline = strings::cut(cmd.arg1, "!").1;
+ let shcmd = exec::cmd("sh", "-c", shcmdline)?;
+ let pipe = exec::pipe();
+ exec::addfile(&shcmd, os::stdin_file, pipe.0);
+ proc = exec::start(&shcmd)?;
+ yield pipe.1;
};
- case let h: io::file =>
- yield h: io::handle;
- };
- defer io::close(h)!;
- const sz = buf_write(s.buf, h, a, b)?;
+ const sz = buf_write(s.buf, wr, a, b)?;
+ io::close(wr)!;
+
+ // XXX: create a stdout pipe and copy it out here instead?
+ if (proc is exec::process)
+ exec::wait(&(proc as exec::process))?;
if (!s.suppressmode)
fmt::println(sz)!;
@@ -657,20 +632,21 @@ fn cmd_shellescape(s: *Session, cmd: *Command) (void | Error) = {
};
let shcmdline = memio::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)?;
- io::close(pipe.1)!;
-
- exec::wait(&proc)?;
-
if (preview)
fmt::println(shcmdline)!;
- io::copy(os::stdout, pipe.0)!;
- io::close(pipe.0)!;
+ let rd: io::handle = {
+ let shcmd = exec::cmd("sh", "-c", shcmdline)?;
+ let pipe = exec::pipe();
+ exec::addfile(&shcmd, os::stdout_file, pipe.1);
+ let proc = exec::start(&shcmd)?;
+ io::close(pipe.1)!;
+ exec::wait(&proc)?;
+ yield pipe.0;
+ };
+ defer io::close(rd)!;
+
+ io::copy(os::stdout, rd)!;
if (!s.suppressmode)
fmt::println("!")!;
diff --git a/file.ha b/file.ha
@@ -0,0 +1,52 @@
+use errors;
+use fmt;
+use fs;
+use io;
+use os;
+use strings;
+
+fn edit(s: *Session, cmd: *Command, forced: bool) (void | Error) = {
+ assert_noaddrs(s, cmd.linenums)?;
+
+ if (!forced && s.buf.modified && !s.warned) {
+ s.warned = true;
+ return WarnBufferModified;
+ };
+
+ const fname = filename(s, cmd, true)?;
+ const rd = os::open(fname)?; defer io::close(rd)!;
+
+ buf_deleteall(s.buf);
+ const (sz, _) = buf_read(s.buf, rd, 0)?;
+
+ if (!s.suppressmode)
+ fmt::println(sz)!;
+
+ s.buf.cursor = len(s.buf.lines) - 1;
+};
+
+fn filename(s: *Session, cmd: *Command, remember: bool) (str | NoFilename) = {
+ if (cmd.arg1 != "") {
+ if (remember || s.buf.filename == "")
+ s.buf.filename = strings::dup(cmd.arg1);
+ return cmd.arg1;
+ };
+ if (s.buf.filename != "")
+ return s.buf.filename;
+
+ return NoFilename;
+};
+
+fn openwritefile(fname: str) (io::file | fs::error) = {
+ match (os::open(fname, fs::flag::WRONLY)) {
+ case let h: io::file =>
+ return h;
+ case let e: fs::error =>
+ match (e) {
+ case errors::noentry =>
+ return os::create(fname, 0o644)?;
+ case =>
+ return e;
+ };
+ };
+};
diff --git a/util.ha b/util.ha
@@ -82,15 +82,3 @@ fn printlistln(text: str) (size | io::error) = {
sz += fmt::println('$')?;
return sz;
};
-
-fn filename(s: *Session, cmd: *Command, remember: bool) (str | NoFilename) = {
- if (cmd.arg1 != "") {
- if (remember || s.buf.filename == "")
- s.buf.filename = strings::dup(cmd.arg1);
- return cmd.arg1;
- };
- if (s.buf.filename != "")
- return s.buf.filename;
-
- return NoFilename;
-};