cmd_proc_macro/
lib.rs

1#![doc=include_str!("../README.md")]
2
3use proc_macro::TokenStream;
4
5/// This macro will yield an expression of type `&'static [u8; N]` which is the output of the command.
6/// 
7/// ```rust, no_run
8/// let hash = cmd_execute!("git rev-parse --short HEAD"); // git rev-parse --short HEAD | tr -d '\n\r'
9/// let date = cmd_execute!("git log -1 --format=%cd");
10/// let latest_tag = cmd_execute!("git describe --tags --abbrev=0");
11/// let sub_version = cmd_execute!("git rev-list `git describe --tags --abbrev=0`..HEAD --count --first-parent");
12///
13/// println!("{}", String::from_utf8_lossy(hash).trim_end());
14///
15/// let cargo = cmd_execute!("cat Cargo.toml");
16/// let bytes = include_bytes!("../Cargo.toml");
17/// assert_eq!(cargo, bytes);
18/// ```
19#[proc_macro]
20pub fn cmd_execute(input: TokenStream) -> TokenStream {
21    let input: syn::LitStr = syn::parse(input).unwrap();
22
23    #[cfg(target_os="windows")]
24    let sh = "cmd";
25    #[cfg(not(target_os="windows"))]
26    let sh = "bash";
27
28    let mut cmd = std::process::Command::new(sh);
29
30    #[cfg(target_os="windows")]
31    cmd.arg("/c");
32    #[cfg(not(target_os="windows"))]
33    cmd.arg("-c");
34
35    cmd.arg(input.value());
36    let output = match cmd.output() {
37        Ok(out) => out,
38        Err(e) => panic!("{}", e),
39    };
40    // println!("output: {:?}", output);
41    if !output.status.success() {
42        panic!("The command's output is: {:?}", output);
43    }
44
45    let stdout = output.stdout;
46
47    quote::quote! {
48        &[
49            #(#stdout,)*
50        ]
51    }.into()
52}
53
54