textwrap_macros_impl/
lib.rs

1extern crate proc_macro;
2extern crate syn;
3extern crate textwrap;
4
5use proc_macro::TokenStream;
6use quote::ToTokens;
7use syn::parse::Parse;
8use syn::parse::ParseStream;
9use syn::parse::Result as ParseResult;
10use syn::parse_macro_input;
11
12// ---------------------------------------------------------------------------
13
14struct DedentInput {
15    lit: syn::LitStr,
16}
17
18impl Parse for DedentInput {
19    fn parse(input: ParseStream) -> ParseResult<Self> {
20        Ok(Self {
21            lit: input.parse()?,
22        })
23    }
24}
25
26#[proc_macro_hack::proc_macro_hack]
27pub fn dedent(tokens: TokenStream) -> TokenStream {
28    let input = parse_macro_input!(tokens as DedentInput);
29    let newstr = textwrap::dedent(&input.lit.value());
30
31    syn::LitStr::new(&newstr, input.lit.span())
32        .into_token_stream()
33        .into()
34}
35
36// ---------------------------------------------------------------------------
37
38struct FillInput {
39    lit: syn::LitStr,
40    width: syn::LitInt,
41}
42
43impl Parse for FillInput {
44    fn parse(input: ParseStream) -> ParseResult<Self> {
45        let lit = input.parse()?;
46        input.parse::<syn::Token![,]>()?;
47        let width = input.parse()?;
48        Ok(Self { lit, width })
49    }
50}
51
52#[proc_macro_hack::proc_macro_hack]
53pub fn fill(tokens: TokenStream) -> TokenStream {
54    let input = parse_macro_input!(tokens as FillInput);
55    let width: usize = input.width.base10_parse().expect("could not parse number");
56    let newstr = textwrap::fill(&input.lit.value(), width);
57
58    syn::LitStr::new(&newstr, input.lit.span())
59        .into_token_stream()
60        .into()
61}
62
63// ---------------------------------------------------------------------------
64
65struct RefillInput {
66    lit: syn::LitStr,
67    width: syn::LitInt,
68}
69
70impl Parse for RefillInput {
71    fn parse(input: ParseStream) -> ParseResult<Self> {
72        let lit = input.parse()?;
73        input.parse::<syn::Token![,]>()?;
74        let width = input.parse()?;
75        Ok(Self { lit, width })
76    }
77}
78
79#[proc_macro_hack::proc_macro_hack]
80pub fn refill(tokens: TokenStream) -> TokenStream {
81    let input = parse_macro_input!(tokens as RefillInput);
82    let width: usize = input.width.base10_parse().expect("could not parse number");
83    let newstr = textwrap::refill(&input.lit.value(), width);
84
85    syn::LitStr::new(&newstr, input.lit.span())
86        .into_token_stream()
87        .into()
88}
89
90// ---------------------------------------------------------------------------
91
92struct UnfillInput {
93    lit: syn::LitStr,
94}
95
96impl Parse for UnfillInput {
97    fn parse(input: ParseStream) -> ParseResult<Self> {
98        Ok(Self {
99            lit: input.parse()?,
100        })
101    }
102}
103
104#[proc_macro_hack::proc_macro_hack]
105pub fn unfill(tokens: TokenStream) -> TokenStream {
106    let input = parse_macro_input!(tokens as UnfillInput);
107    let newstr = textwrap::unfill(&input.lit.value()).0;
108
109    syn::LitStr::new(&newstr, input.lit.span())
110        .into_token_stream()
111        .into()
112}
113
114// ---------------------------------------------------------------------------
115
116struct IndentInput {
117    lit: syn::LitStr,
118    prefix: syn::LitStr,
119}
120
121impl Parse for IndentInput {
122    fn parse(input: ParseStream) -> ParseResult<Self> {
123        let lit = input.parse()?;
124        input.parse::<syn::Token![,]>()?;
125        let prefix = input.parse()?;
126        Ok(Self { lit, prefix })
127    }
128}
129
130#[proc_macro_hack::proc_macro_hack]
131pub fn indent(tokens: TokenStream) -> TokenStream {
132    let input = parse_macro_input!(tokens as IndentInput);
133    let newstr = textwrap::indent(&input.lit.value(), &input.prefix.value());
134
135    syn::LitStr::new(&newstr, input.lit.span())
136        .into_token_stream()
137        .into()
138}
139
140// ---------------------------------------------------------------------------
141
142struct WrapInput {
143    lit: syn::LitStr,
144    width: syn::LitInt,
145}
146
147impl Parse for WrapInput {
148    fn parse(input: ParseStream) -> ParseResult<Self> {
149        let lit = input.parse()?;
150        input.parse::<syn::Token![,]>()?;
151        let width = input.parse()?;
152        Ok(Self { lit, width })
153    }
154}
155
156#[proc_macro_hack::proc_macro_hack]
157pub fn wrap(tokens: TokenStream) -> TokenStream {
158    let input = parse_macro_input!(tokens as WrapInput);
159    let width: usize = input.width.base10_parse().expect("could not parse number");
160
161    let elems = textwrap::wrap(&input.lit.value(), width)
162        .iter()
163        .map(|s| syn::Lit::from(syn::LitStr::new(&s, input.lit.span())))
164        .map(|lit| {
165            syn::Expr::Lit(syn::ExprLit {
166                lit,
167                attrs: Vec::new(),
168            })
169        })
170        .collect();
171    let array = syn::ExprArray {
172        elems,
173        attrs: Vec::new(),
174        bracket_token: Default::default(),
175    };
176    let expr = syn::ExprReference {
177        attrs: Vec::new(),
178        and_token: Default::default(),
179        raw: Default::default(),
180        mutability: None,
181        expr: Box::new(syn::Expr::Array(array)),
182    };
183
184    expr.into_token_stream().into()
185}