mirror of
https://github.com/uutils/coreutils
synced 2024-11-17 02:08:09 +00:00
change ~ add proc-macros module (uucore_procs) with uucore_procs::main()
- `uucore_procs::main!(UUTIL_NAME)` allows simple, consistent instantiation of `main()` for uutils
This commit is contained in:
parent
503cc53014
commit
0432063479
3 changed files with 85 additions and 0 deletions
|
@ -18,6 +18,9 @@ travis-ci = { repository = "uutils/uucore" }
|
|||
[lib]
|
||||
path="src/lib/lib.rs"
|
||||
|
||||
[workspace]
|
||||
members=["src/uucore_procs"]
|
||||
|
||||
[dependencies]
|
||||
dunce = "1.0.0"
|
||||
getopts = "<= 0.2.21"
|
||||
|
|
18
src/uucore/src/uucore_procs/Cargo.toml
Normal file
18
src/uucore/src/uucore_procs/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "uucore_procs"
|
||||
version = "0.0.2"
|
||||
authors = []
|
||||
license = "MIT"
|
||||
description = "`uucore` proc-macros for use by various uutils projects"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = { version="1.0" } ## debug: use `features=["extra-traits"]` to add Debug traits to structs (for `println!("{:?}", ...)`)
|
||||
|
||||
[features]
|
||||
default = []
|
||||
debug = []
|
64
src/uucore/src/uucore_procs/src/lib.rs
Normal file
64
src/uucore/src/uucore_procs/src/lib.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
extern crate proc_macro;
|
||||
|
||||
// spell-checker:ignore () sigpipe uucore uumain
|
||||
|
||||
// ref: <https://dev.to/naufraghi/procedural-macro-in-rust-101-k3f> @@ <http://archive.is/Vbr5e>
|
||||
// ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ <http://archive.is/8YDua>
|
||||
|
||||
struct Tokens {
|
||||
expr: syn::Expr,
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for Tokens {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
Ok(Tokens {
|
||||
expr: input.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn main(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let Tokens { expr } = syn::parse_macro_input!(stream as Tokens);
|
||||
// eprintln!("expr={:?}", expr);
|
||||
let expr = match expr {
|
||||
syn::Expr::Lit(expr) => {
|
||||
// eprintln!("found Expr::Lit => {:?}", expr);
|
||||
match expr.lit {
|
||||
syn::Lit::Str(ref lit) => {
|
||||
let mut s = lit.value();
|
||||
if !s.ends_with("::uumain") {
|
||||
s += "::uumain";
|
||||
}
|
||||
syn::LitStr::new(&s, proc_macro2::Span::call_site())
|
||||
.parse()
|
||||
.unwrap()
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
syn::Expr::Path(expr) => {
|
||||
// eprintln!("found Expr::Path => {:?}", expr);
|
||||
// let i = &expr.path.segments.last().unwrap().ident;
|
||||
// eprintln!("... i => {:?}", i);
|
||||
if &expr.path.segments.last().unwrap().ident.to_string() != "uumain" {
|
||||
syn::parse_quote!( #expr::uumain )
|
||||
} else {
|
||||
expr
|
||||
}
|
||||
}
|
||||
_ => panic!(),
|
||||
};
|
||||
let f = quote::quote! { #expr(uucore::args().collect()) };
|
||||
// eprintln!("f = {:?}", f);
|
||||
let result = quote::quote! {
|
||||
fn main() {
|
||||
use std::io::Write;
|
||||
uucore::panic::install_sigpipe_hook();
|
||||
let code = #f;
|
||||
std::io::stdout().flush().expect("could not flush stdout");
|
||||
std::process::exit(code);
|
||||
}
|
||||
};
|
||||
proc_macro::TokenStream::from(result)
|
||||
}
|
Loading…
Reference in a new issue