Skip to content

Commit

Permalink
add ;decant and ;defuse commands for dealing with stderr
Browse files Browse the repository at this point in the history
  • Loading branch information
geremachek committed Oct 28, 2021
1 parent f6628c0 commit 507c52f
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "merlin"
version = "2.0.1"
version = "2.1.0"
authors = ["geremachek <[email protected]>"]
edition = "2018"

Expand Down
52 changes: 38 additions & 14 deletions src/commands/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,37 @@ use std::{
io::Write,
};

// wait for, and capture of a child process, dealing with all of the errors
// wait for, and capture an output stream of a child process, dealing with all of the errors

macro_rules! capture_output {
($command:ident) => {
($command:ident, $stream:ident) => {
String::from_utf8($command.wait_with_output()
.or(Err(MerlinError::InvalidExternal))?.stdout)
.or(Err(MerlinError::InvalidExternal))?.$stream)
.or(Err(MerlinError::InvalidExternal))
}
}

// run an external command and capture its output
// make a "*cant" command: run a command and capture either stdout or stderr

pub fn incant(script: &str) -> Result<String, MerlinError> {
let command = make_command(script, Stdio::inherit())?;
capture_output!(command)
macro_rules! make_incant {
($name:ident, $out:expr, $err:expr, $stream:ident) => {
pub fn $name(script: &str) -> Result<String, MerlinError> {
let command = make_command(script,
Stdio::inherit(),
$out,
$err)?;

capture_output!(command, $stream)
}
}
}

// send text to an external command
make_incant!(incant, Stdio::piped(), Stdio::inherit(), stdout);
make_incant!(decant, Stdio::inherit(), Stdio::piped(), stderr);

pub fn infuse(input: &str, script: &str) -> Result<String, MerlinError> {
let mut command = make_command(script, Stdio::piped())?;
// send text to an external command

fn send_and_receive(command: &mut Child, input: &str) -> Result<(), MerlinError> {
// send data to stdin

let mut stdin = command.stdin.take()
Expand All @@ -45,19 +54,34 @@ pub fn infuse(input: &str, script: &str) -> Result<String, MerlinError> {
"couldn't write to stdin")
}).or(Err(MerlinError::InvalidExternal))?;

capture_output!(command)
Ok(())
}

macro_rules! make_infuse {
($name:ident, $out:expr, $err:expr, $stream:ident) => {
pub fn $name(input: &str, script: &str) -> Result<String, MerlinError> {
let mut command = make_command(script, Stdio::piped(), $out, $err)?;
send_and_receive(&mut command, input)?;

capture_output!(command, $stream)
}
}
}

make_infuse!(infuse, Stdio::piped(), Stdio::inherit(), stdout);
make_infuse!(defuse, Stdio::inherit(), Stdio::piped(), stderr);

// "make" a command from arguments, changing how it deals with io

fn make_command(script: &str, sio: Stdio) -> Result<Child, MerlinError> {
fn make_command(script: &str, stdin: Stdio, stdout: Stdio, stderr: Stdio) -> Result<Child, MerlinError> {
let args: Vec<&str> = script.split_whitespace().collect();

Command::new(&args[0])
.args(&args[1..])
.envs(env::vars_os())
.stdin(sio)
.stdout(Stdio::piped())
.stdin(stdin)
.stdout(stdout)
.stderr(stderr)
.spawn()
.or(Err(MerlinError::InvalidExternal))
}
8 changes: 6 additions & 2 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ pub enum Command {
Volume,
Volumes,
Incant,
Decant,
Infuse,
Defuse,
Spot,
Span,
Pin,
Expand Down Expand Up @@ -58,7 +60,9 @@ impl FromStr for Command {
"spine" => Ok(Command::Spine),
"carved" => Ok(Command::Carved),
"incant" => Ok(Command::Incant),
"decant" => Ok(Command::Decant),
"infuse" => Ok(Command::Infuse),
"defuse" => Ok(Command::Defuse),
"shelve" => Ok(Command::Shelve),
"focus" => Ok(Command::Focus),
"volume" => Ok(Command::Volume),
Expand Down Expand Up @@ -130,8 +134,8 @@ impl Command {
Command::Volumes | Command::Carved | Command::Atoms => 0,
Command::Focus | Command::Traverse | Command::Appear | Command::Shave | Command::Shelve | Command::Inscribe | Command::Trample | Command::Incant |
Command::Summon | Command::Dub | Command::Spellbook | Command::Shift | Command::Infix | Command::Spine | Command::Merlin | Command::Disenchant |
Command::Smash => 1,
Command::Infuse | Command::Peer | Command::Fray => 2,
Command::Smash | Command::Decant => 1,
Command::Infuse | Command::Peer | Command::Fray | Command::Defuse => 2,
Command::Genesis => choose_mm(1, 0),
};

Expand Down
2 changes: 2 additions & 0 deletions src/plane/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ impl Plane {
Command::Genesis => if data.len() > 0 { self.genesis(&data[0]); } else { self.genesis(""); },
Command::Spine => return Ok(Some(self.spine(parse_pos::<usize>(&data[0])?)?)),
Command::Incant => return Ok(Some(commands::incant(&data[0])?)),
Command::Decant => return Ok(Some(commands::decant(&data[0])?)),
Command::Infuse => return Ok(Some(commands::infuse(&data[0], &data[1])?)),
Command::Defuse => return Ok(Some(commands::defuse(&data[0], &data[1])?)),
Command::Molecule => self.stack.molecule(),
Command::Pen => self.stack.pen(),
Command::Orbit => self.stack.orbit()?,
Expand Down

0 comments on commit 507c52f

Please sign in to comment.