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