Skip to content

Commit

Permalink
move parsing into cmdrun instead of in main
Browse files Browse the repository at this point in the history
  • Loading branch information
tomeichlersmith committed Sep 17, 2024
1 parent 3534867 commit bb5ea5c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 98 deletions.
106 changes: 53 additions & 53 deletions src/cmdrun.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use mdbook::book::Book;
use mdbook::book::Chapter;
use mdbook::preprocess::{Preprocessor, PreprocessorContext};

use clap::value_parser;

use crate::utils::map_chapter;

pub struct CmdRun;
Expand Down Expand Up @@ -159,62 +161,24 @@ impl CmdRun {

// This method is public for unit tests
pub fn run_cmdrun(command: String, working_dir: &str, inline: bool) -> Result<String> {
let (command, correct_exit_code): (String, Option<i32>) = if let Some(first_word) =
command.split_whitespace().next()
{
if first_word.starts_with('-') {
if first_word.starts_with("--") {
// double-tick long form
match first_word {
"--strict" => (
command
.split_whitespace()
.skip(1)
.collect::<Vec<&str>>()
.join(" "),
Some(0),
),
"--expect-return-code" => {
if let Some(second_word) = command.split_whitespace().nth(1) {
(
command
.split_whitespace()
.skip(2)
.collect::<Vec<&str>>()
.join(" "),
Some(second_word.parse()?),
)
} else {
// no second word after return code, print error
return Ok(format!("**cmdrun error**: No return code after '--expect-return-code' for command {command}."));
}
}
some_other_word => {
// unrecognized flag, print error
return Ok(format!("**cmdrun error**: Unrecognized cmdrun flag {some_other_word} in 'cmdrun {command}'"));
}
}
} else {
// single-tick short form
let (_, exit_code) = first_word.rsplit_once('-').unwrap_or(("", "0"));
(
command
.split_whitespace()
.skip(1)
.collect::<Vec<&str>>()
.join(" "),
Some(exit_code.parse()?),
)
}
} else {
(command, None)
}
let parser = make_cmdrun_parser();
let matches = parser.try_get_matches_from(command.split_whitespace())?;

let cmd : Vec<_> = matches
.try_get_many::<String>("cmd")
.expect("able to parse a command and not get Err")
.expect("able to parse a command and not get None")
.map(|s| s.as_str())
.collect();
let correct_exit_code = if matches.get_flag("strict") {
Some(&0)
} else {
(command, None)
matches.try_get_one("expect-return-code")?
};

let output = Command::new(LAUNCH_SHELL_COMMAND)
.args([LAUNCH_SHELL_FLAG, &command])
.args([LAUNCH_SHELL_FLAG])
.args(cmd)
.current_dir(working_dir)
.output()
.with_context(|| "Fail to run shell")?;
Expand All @@ -223,7 +187,7 @@ impl CmdRun {
match (output.status.code(), correct_exit_code) {
(None, _) => Ok(format!("'{command}' was ended before completing.")),
(Some(code), Some(correct_code)) => {
if code != correct_code {
if code != *correct_code {
Ok(
format!(
"**cmdrun error**: '{command}' returned exit code {code} instead of {correct_code}.\n{0}\n{1}", String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr))
Expand All @@ -241,3 +205,39 @@ impl CmdRun {
}
}
}


fn make_cmdrun_parser() -> clap::Command {
clap::Command::new("cmdrun")
.about("test run a command before putting it in a book")
.arg(
clap::Arg::new("expect-return-code")
.help("require the specific return code N")
.long("expect-return-code")
.conflicts_with("strict")
// .conflicts_with("exit-code-short")
.num_args(1)
.value_name("N")
.value_parser(value_parser!(i32))
).arg(
clap::Arg::new("strict")
.help("require command to return the successful exit code 0")
.long("strict")
.conflicts_with("expect-return-code")
// .conflicts_with("exit-code-short")
.action(clap::ArgAction::SetTrue)
// ).arg(
// Arg::new("exit-code-short")
// .help("require the specific exit code N")
// .conflicts_with("expect-return-code")
// .conflicts_with("strict")
// .value_name("-N")
// .allow_negative_numbers(true)
// .value_parser(..=0)
).arg(
clap::Arg::new("cmd")
.help("command whose output will be injected into book")
.num_args(1..)
.trailing_var_arg(true)
)
}
55 changes: 10 additions & 45 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clap::{Arg, ArgMatches, Command, value_parser};
use clap::{Arg, ArgMatches, Command};
use mdbook::errors::Error;
use mdbook::preprocess::CmdPreprocessor;
use mdbook::preprocess::Preprocessor;
Expand All @@ -16,14 +16,13 @@ fn main() {
if let Some(sub_args) = matches.subcommand_matches("supports") {
handle_supports(sub_args);
} else if let Some(sub_args) = matches.subcommand_matches("cmdrun") {
let cmd = sub_args.try_get_many::<String>("cmd");
let correct_exit_code = if sub_args.get_flag("strict") {
Ok(Some(&0))
} else {
sub_args.try_get_one("expect-return-code")
};
println!("{:?} {:?}", correct_exit_code, cmd)
//CmdRun::run_cmdrun(sub_args, ".", false);
let text : String = sub_args
.try_get_many::<String>("text")
.expect("able to parse a command and not get Err")
.expect("able to parse a command and not get None")
.map(|s| s.as_str())
.collect();
println!("{}", CmdRun::run_cmdrun(text, ".", false).unwrap());
} else if let Err(e) = handle_preprocessing() {
eprintln!("{e}");
process::exit(1);
Expand All @@ -33,41 +32,6 @@ fn main() {
}
}

fn make_cmdrun_parser() -> Command {
Command::new("cmdrun")
.about("test run a command before putting it in a book")
.arg(
Arg::new("expect-return-code")
.help("require the specific return code N")
.long("expect-return-code")
.conflicts_with("strict")
// .conflicts_with("exit-code-short")
.num_args(1)
.value_name("N")
.value_parser(value_parser!(i32))
).arg(
Arg::new("strict")
.help("require command to return the successful exit code 0")
.long("strict")
.conflicts_with("expect-return-code")
// .conflicts_with("exit-code-short")
.action(clap::ArgAction::SetTrue)
// ).arg(
// Arg::new("exit-code-short")
// .help("require the specific exit code N")
// .conflicts_with("expect-return-code")
// .conflicts_with("strict")
// .value_name("-N")
// .allow_negative_numbers(true)
// .value_parser(..=0)
).arg(
Arg::new("cmd")
.help("command whose output will be injected into book")
.num_args(1..)
.trailing_var_arg(true)
)
}

fn make_app() -> Command {
Command::new("mdbook-cmdrun")
.about("mdbook preprocessor to run arbitrary commands and replace the stdout of these commands inside the markdown file.")
Expand All @@ -76,7 +40,8 @@ fn make_app() -> Command {
.arg(Arg::new("renderer").required(true))
.about("Check whether a renderer is supported by this preprocessor"),
).subcommand(
make_cmdrun_parser()
Command::new("cmdrun")
.arg(Arg::new("text").num_args(1..).trailing_var_arg(true))
)
}

Expand Down

0 comments on commit bb5ea5c

Please sign in to comment.