Skip to content

Commit a9b0424

Browse files
committed
Create a separate treesap-macros crate
1 parent 8ec1fb6 commit a9b0424

File tree

6 files changed

+105
-90
lines changed

6 files changed

+105
-90
lines changed

Cargo.lock

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[workspace]
2-
members = ["treesap"]
2+
members = ["treesap", "treesap/macros"]
33

44
[package]
55
name = "sap"

treesap/Cargo.toml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,9 @@ name = "treesap"
33
version = "0.1.0"
44
edition = "2024"
55

6-
[lib]
7-
proc-macro = true
8-
96
[dependencies]
10-
darling = "0.21.3"
11-
quote = "1.0.41"
12-
syn = { version = "2.0.108", features = ["full"] }
7+
sap = { version = "0.0.7", path = ".." }
8+
treesap-macros = { version = "0.1.0", path = "macros" }
139

1410
[dev-dependencies]
1511
anyhow = "1.0.100"
16-
sap = { path = ".." }

treesap/macros/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "treesap-macros"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[lib]
7+
proc-macro = true
8+
9+
[dependencies]
10+
darling = "0.21.3"
11+
quote = "1.0.41"
12+
syn = { version = "2.0.108", features = ["full"] }

treesap/macros/src/lib.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use proc_macro::TokenStream;
2+
use quote::quote;
3+
use syn::{Data, DataStruct, DeriveInput, parse_macro_input};
4+
5+
#[proc_macro_derive(Parser, attributes(arg, command))]
6+
pub fn derive_parser(input: TokenStream) -> TokenStream {
7+
let input = parse_macro_input!(input as DeriveInput);
8+
let ident = input.ident;
9+
10+
match input.data {
11+
Data::Struct(DataStruct { fields, .. }) => {
12+
let mut field_declarations = Vec::new();
13+
let mut field_setters = Vec::new();
14+
let mut field_getters = Vec::new();
15+
16+
for field in fields {
17+
let ident = field.ident.unwrap();
18+
let ty = field.ty;
19+
let option = ident.to_string();
20+
21+
field_declarations.push(quote! {
22+
let mut #ident: Option<#ty> = None;
23+
});
24+
25+
field_setters.push(quote! {
26+
sap::Argument::Long(#option) => { #ident = Some(true) }
27+
});
28+
29+
field_getters.push(quote! {
30+
#ident: #ident.unwrap()
31+
});
32+
}
33+
34+
quote! {
35+
impl #ident {
36+
const HELP: &str = "";
37+
38+
pub fn parse() -> ::sap::Result<Self> {
39+
use std::io::Write as _;
40+
41+
let mut arg_parser = sap::Parser::from_env()?;
42+
43+
#(#field_declarations)*
44+
45+
while let Some(arg) = arg_parser.forward()? {
46+
47+
match arg {
48+
// Long("version") => {
49+
// stdout
50+
// .write_all(
51+
// "wc (puppyutils) 0.0.1\nLicensed under the European Union Public Licence (EUPL) <https://eupl.eu/>\n"
52+
// .as_bytes(),
53+
// )?;
54+
// stdout.flush()?;
55+
// std::process::exit(0);
56+
// }
57+
// Long("help") => {
58+
// stdout
59+
// .write_all(
60+
// "Usage: wc [OPTION]... [FILE]...\nPrint newline, word, and byte counts for each FILE. A word is a nonempty \nsequence of non white space delimited by white space characters or by start \nor end of input.\n\n -c, --bytes print the byte counts\n -m, --chars print the character counts\n -l, --lines print the newline counts\n -w, --words print the word counts\n --help display this help and exit\n --version output version information and exit\n\nWith no FILE, or when FILE is -, read standard input.\n"
61+
// .as_bytes(),
62+
// )?;
63+
// stdout.flush()?;
64+
// std::process::exit(0);
65+
// }
66+
#(#field_setters),*
67+
arg => return Err(arg.into_error(None)),
68+
}
69+
}
70+
71+
Ok(Self { #(#field_getters),* })
72+
}
73+
}
74+
75+
}
76+
.into()
77+
}
78+
Data::Enum(_data_enum) => todo!(),
79+
Data::Union(_data_union) => todo!(),
80+
}
81+
}

treesap/src/lib.rs

Lines changed: 1 addition & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1 @@
1-
use proc_macro::TokenStream;
2-
use quote::quote;
3-
use syn::{Data, DataStruct, DeriveInput, parse_macro_input};
4-
5-
#[proc_macro_derive(Parser, attributes(arg, command))]
6-
pub fn derive_parser(input: TokenStream) -> TokenStream {
7-
let input = parse_macro_input!(input as DeriveInput);
8-
let ident = input.ident;
9-
10-
match input.data {
11-
Data::Struct(DataStruct { fields, .. }) => {
12-
let mut field_declarations = Vec::new();
13-
let mut field_setters = Vec::new();
14-
let mut field_getters = Vec::new();
15-
16-
for field in fields {
17-
let ident = field.ident.unwrap();
18-
let ty = field.ty;
19-
let option = ident.to_string();
20-
21-
field_declarations.push(quote! {
22-
let mut #ident: Option<#ty> = None;
23-
});
24-
25-
field_setters.push(quote! {
26-
sap::Argument::Long(#option) => { #ident = Some(true) }
27-
});
28-
29-
field_getters.push(quote! {
30-
#ident: #ident.unwrap()
31-
});
32-
}
33-
34-
quote! {
35-
impl #ident {
36-
const HELP: &str = "";
37-
38-
pub fn parse() -> ::sap::Result<Self> {
39-
use std::io::Write as _;
40-
41-
let mut arg_parser = sap::Parser::from_env()?;
42-
43-
#(#field_declarations)*
44-
45-
while let Some(arg) = arg_parser.forward()? {
46-
47-
match arg {
48-
// Long("version") => {
49-
// stdout
50-
// .write_all(
51-
// "wc (puppyutils) 0.0.1\nLicensed under the European Union Public Licence (EUPL) <https://eupl.eu/>\n"
52-
// .as_bytes(),
53-
// )?;
54-
// stdout.flush()?;
55-
// std::process::exit(0);
56-
// }
57-
// Long("help") => {
58-
// stdout
59-
// .write_all(
60-
// "Usage: wc [OPTION]... [FILE]...\nPrint newline, word, and byte counts for each FILE. A word is a nonempty \nsequence of non white space delimited by white space characters or by start \nor end of input.\n\n -c, --bytes print the byte counts\n -m, --chars print the character counts\n -l, --lines print the newline counts\n -w, --words print the word counts\n --help display this help and exit\n --version output version information and exit\n\nWith no FILE, or when FILE is -, read standard input.\n"
61-
// .as_bytes(),
62-
// )?;
63-
// stdout.flush()?;
64-
// std::process::exit(0);
65-
// }
66-
#(#field_setters),*
67-
arg => return Err(arg.into_error(None)),
68-
}
69-
}
70-
71-
Ok(Self { #(#field_getters),* })
72-
}
73-
}
74-
75-
}
76-
.into()
77-
}
78-
Data::Enum(_data_enum) => todo!(),
79-
Data::Union(_data_union) => todo!(),
80-
}
81-
}
1+
pub use treesap_macros::Parser;

0 commit comments

Comments
 (0)