mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-05 07:27:46 +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]
|
[lib]
|
||||||
path="src/lib/lib.rs"
|
path="src/lib/lib.rs"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members=["src/uucore_procs"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dunce = "1.0.0"
|
dunce = "1.0.0"
|
||||||
getopts = "<= 0.2.21"
|
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…
Add table
Add a link
Reference in a new issue