summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-07-30 20:22:36 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-07-30 20:22:46 +0200
commit9e41cdfb69532c51be5a241c975cec023b8d858b (patch)
tree23df34492edaa4eb23e11472958f801cace33166
parent5a4f8de935872076e71c124de599ff88026e550d (diff)
Implement EXIT.
-rw-r--r--src/main.rs40
1 files changed, 29 insertions, 11 deletions
diff --git a/src/main.rs b/src/main.rs
index 408a69b..61f6663 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -40,14 +40,14 @@ fn main() -> Result<()> {
let Ok(CommandReceivers {
stdout,
stderr,
- exit_status,
+ status,
}) = command.run()
else {
eprintln!("unimplemented command: {}", line);
continue;
};
- // print stdout, stderr interleaved until exit_status produces something
+ // print stdout, stderr interleaved until status produces something
let stdout_writer = spawn(move || {
loop {
let Ok(bytes) = stdout.recv() else {
@@ -75,9 +75,14 @@ fn main() -> Result<()> {
stdout_writer.join().expect("stdout writer thread failed");
stderr_writer.join().expect("stderr writer thread failed");
- let _exit_status = exit_status
+ let command_result = status
.recv()
.expect("failed to receive exit status from command");
+
+ match command_result {
+ CommandStatus::ExitShell => break,
+ CommandStatus::Code(_) => {}
+ }
}
Ok(())
@@ -176,16 +181,22 @@ enum Command {
Empty,
}
+#[derive(Debug)]
+enum CommandStatus {
+ Code(u16),
+ ExitShell,
+}
+
struct CommandReceivers {
stdout: Receiver<Vec<u8>>,
stderr: Receiver<Vec<u8>>,
- exit_status: Receiver<u16>,
+ status: Receiver<CommandStatus>,
}
struct CommandSenders {
stdout: SyncSender<Vec<u8>>,
stderr: SyncSender<Vec<u8>>,
- exit_status: SyncSender<u16>,
+ status: SyncSender<CommandStatus>,
}
struct CommandContext {
@@ -203,12 +214,12 @@ impl CommandContext {
senders: CommandSenders {
stdout: sout,
stderr: serr,
- exit_status: sexit,
+ status: sexit,
},
receivers: CommandReceivers {
stdout: rout,
stderr: rerr,
- exit_status: rexit,
+ status: rexit,
},
}
}
@@ -222,30 +233,35 @@ impl Command {
pub(crate) fn run(&self) -> Result<CommandReceivers> {
use crate::BuiltinCommand::*;
use crate::Command::*;
+ use crate::CommandStatus::*;
let (senders, receivers) = CommandContext::new().split();
let CommandSenders {
stdout,
stderr,
- exit_status,
+ status: status,
} = senders;
match self {
Empty => {
- exit_status.send(0)?;
+ status.send(Code(0))?;
}
Builtin(EchoText { message }) => {
stdout.send(message.bytes().collect())?;
stdout.send(b"\n".into())?;
- exit_status.send(0)?;
+ status.send(Code(0))?;
}
Builtin(Cls) => {
let mut stdout_handle = io::stdout();
execute!(stdout_handle, terminal::Clear(terminal::ClearType::All))?;
execute!(stdout_handle, cursor::MoveTo(0, 0))?;
- exit_status.send(0)?;
+ status.send(Code(0))?;
+ }
+
+ Builtin(Exit) => {
+ status.send(ExitShell)?;
}
_ => bail!("Command::run not implemented for {:?}", self),
@@ -423,6 +439,8 @@ impl Command {
"CLS" => Ok(Builtin(Cls)),
+ "EXIT" => Ok(Builtin(Exit)),
+
_ => Err(eyre::eyre!("parse not implemented for {:?}", input)),
}
}