affix_macro/lib.rs
1//! Macros for affixing tokens to groups of other tokens.
2//!
3//! The [MSRV](https://doc.rust-lang.org/cargo/reference/rust-version.html) is [Rust 1.31](https://releases.rs/docs/1.31.0/).
4//! If this is increased, it will be a major version bump.
5//!
6//! See the documentation of each macro for usage details.
7
8#![no_std]
9
10use ::rustversion;
11
12/// Prefixes tokens to groups of other tokens.
13///
14/// Optionally, a mapping macro can be provided to transform each resulting prefixed token group.
15///
16/// See also [`prefix_items!`] for a convenience wrapper around this macro for use with items.
17///
18/// ```rust no_run
19/// # use ::affix_macro::prefix;
20/// #
21/// prefix! {
22/// (foo)
23/// [{bar 1}, {baz 2}, {qux 3}]
24/// }
25///
26/// // Expands to:
27/// // foo bar 1
28/// // foo baz 2
29/// // foo qux 3
30/// ```
31///
32/// With mapping macro:
33/// ```rust no_run
34/// # use ::affix_macro::prefix;
35/// #
36/// macro_rules! wrap_in_parens {
37/// ($($tokens:tt)*) => {
38/// ( $($tokens)* )
39/// };
40/// }
41///
42/// prefix! {
43/// {wrap_in_parens}
44/// (foo)
45/// [{bar 1}, {baz 2}, {qux 3}]
46/// }
47///
48/// // Expands to:
49/// // ( foo bar 1 )
50/// // ( foo baz 2 )
51/// // ( foo qux 3 )
52/// ```
53#[rustversion::attr(since(1.48), doc(alias = "prepend"))]
54#[macro_export]
55macro_rules! prefix {
56 (
57 {$map:path}
58 ($($prefix:tt)*)
59 [$(,)? {$($next:tt)*} $($rest:tt)*]
60 ) => {
61 $map! {
62 $($prefix)*
63 $($next)*
64 }
65
66 $crate::__prefix! {
67 {$map}
68 ($($prefix)*)
69 [$($rest)*]
70 }
71 };
72
73 (
74 ($($prefix:tt)*)
75 [$(,)? {$($next:tt)*} $($rest:tt)*]
76 ) => {
77 $($prefix)*
78 $($next)*
79
80 $crate::__prefix! {
81 ($($prefix)*)
82 [$($rest)*]
83 }
84 };
85
86 (
87 $({$map:path})?
88 ($($prefix:tt)*)
89 [$(,)?]
90 ) => {};
91}
92
93// Workaround for https://github.com/rust-lang/rust/pull/52234
94#[doc(hidden)]
95pub use prefix as __prefix;
96
97/// Suffixes tokens to groups of other tokens.
98///
99/// Optionally, a mapping macro can be provided to transform each resulting suffixed token group.
100///
101/// ```rust no_run
102/// # use ::affix_macro::suffix;
103/// #
104/// suffix! {
105/// (foo)
106/// [{bar 1}, {baz 2}, {qux 3}]
107/// }
108///
109/// // Expands to:
110/// // bar 1 foo
111/// // baz 2 foo
112/// // qux 3 foo
113/// ```
114///
115/// With mapping macro:
116/// ```rust no_run
117/// # use ::affix_macro::suffix;
118/// #
119/// macro_rules! wrap_in_parens {
120/// ($($tokens:tt)*) => {
121/// ( $($tokens)* )
122/// };
123/// }
124///
125/// suffix! {
126/// {wrap_in_parens}
127/// (foo)
128/// [{bar 1}, {baz 2}, {qux 3}]
129/// }
130///
131/// // Expands to:
132/// // ( bar 1 foo )
133/// // ( baz 2 foo )
134/// // ( qux 3 foo )
135/// ```
136#[rustversion::attr(since(1.48), doc(alias = "append"))]
137#[macro_export]
138macro_rules! suffix {
139 (
140 {$map:path}
141 ($($suffix:tt)*)
142 [$(,)? {$($next:tt)*} $($rest:tt)*]
143 ) => {
144 $map ! {
145 $($next)*
146 $($suffix)*
147 }
148
149 $crate::__suffix! {
150 {$map}
151 ($($suffix)*)
152 [$($rest)*]
153 }
154 };
155
156 (
157 ($($suffix:tt)*)
158 [$(,)? {$($next:tt)*} $($rest:tt)*]
159 ) => {
160 $($next)*
161 $($suffix)*
162
163 $crate::__suffix! {
164 ($($suffix)*)
165 [$($rest)*]
166 }
167 };
168
169 (
170 $({$map:path})?
171 ($($suffix:tt)*)
172 [$(,)?]
173 ) => {};
174}
175
176// Workaround for https://github.com/rust-lang/rust/pull/52234
177#[doc(hidden)]
178pub use suffix as __suffix;
179
180/// [suffix!] and [prefix!] in a single operation.
181///
182/// ```rust no_run
183/// # use ::affix_macro::circumfix;
184/// #
185/// circumfix! {
186/// (<<)
187/// (>>)
188/// [{foo}, {bar}, {baz}]
189/// }
190///
191/// // Expands to:
192/// // << foo >>
193/// // << bar >>
194/// // << baz >>
195/// ```
196///
197/// With mapping macro:
198/// ```rust no_run
199/// # use ::affix_macro::circumfix;
200/// #
201/// macro_rules! wrap_in_parens {
202/// ($($tokens:tt)*) => {
203/// ( $($tokens)* )
204/// };
205/// }
206///
207/// circumfix! {
208/// {wrap_in_parens}
209/// (<<)
210/// (>>)
211/// [{foo}, {bar}, {baz}]
212/// }
213///
214/// // Expands to:
215/// // ( << foo >> )
216/// // ( << bar >> )
217/// // ( << baz >> )
218/// ```
219#[rustversion::attr(since(1.48), doc(alias = "surround"))]
220#[macro_export]
221macro_rules! circumfix {
222 (
223 {$map:path}
224 ($($prefix:tt)*)
225 ($($suffix:tt)*)
226 [$(,)? {$($next:tt)*} $($rest:tt)*]
227 ) => {
228 $map ! {
229 $($prefix)*
230 $($next)*
231 $($suffix)*
232 }
233
234 $crate::__circumfix! {
235 {$map}
236 ($($prefix)*)
237 ($($suffix)*)
238 [$($rest)*]
239 }
240 };
241
242 (
243 ($($prefix:tt)*)
244 ($($suffix:tt)*)
245 [$(,)? {$($next:tt)*} $($rest:tt)*]
246 ) => {
247 $($prefix)*
248 $($next)*
249 $($suffix)*
250
251 $crate::__circumfix! {
252 ($($prefix)*)
253 ($($suffix)*)
254 [$($rest)*]
255 }
256 };
257
258 (
259 $({$map:path})?
260 ($($prefix:tt)*)
261 ($($suffix:tt)*)
262 [$(,)?]
263 ) => {};
264}
265
266// Workaround for https://github.com/rust-lang/rust/pull/52234
267#[doc(hidden)]
268pub use circumfix as __circumfix;
269
270/// Joins segments together.
271///
272/// Optionally, a mapping macro can be provided to transform the whole resulting joined token group.
273///
274/// ```rust no_run
275/// # use ::affix_macro::join;
276/// #
277/// join! {
278/// [{foo}, {bar}, {baz}]
279/// }
280///
281/// // Expands to:
282/// // foo bar baz
283/// ```
284///
285/// With mapping macro:
286/// ```rust no_run
287/// # use ::affix_macro::join;
288/// #
289/// macro_rules! wrap_in_parens {
290/// ($($tokens:tt)*) => {
291/// ( $($tokens)* )
292/// };
293/// }
294///
295/// join! {
296/// {wrap_in_parens}
297/// [{foo}, {bar}, {baz}]
298/// }
299///
300/// // Expands to:
301/// // ( foo bar baz )
302/// ```
303#[rustversion::attr(since(1.48), doc(alias = "merge"))]
304#[rustversion::attr(since(1.48), doc(alias = "concat"))]
305#[rustversion::attr(since(1.48), doc(alias = "concatenate"))]
306#[macro_export]
307macro_rules! join {
308 (
309 {$map:path}
310 [
311 $(,)? $({$($segment:tt)*} $(,)?)*
312 ]
313 ) => {
314 $map! {
315 $($($segment)*)*
316 }
317 };
318
319 (
320 [
321 $(,)? $({$($segment:tt)*} $(,)?)*
322 ]
323 ) => {
324 $($($segment)*)*
325 }
326}
327
328/// Prefixes tokens to items.
329///
330/// This is a convenience wrapper around [`prefix!`] for use with items. It takes the same arguments
331/// as [`prefix!`], but transforms each item given into an individual token group.
332///
333/// ```rust no_run
334/// # use ::affix_macro::prefix_items;
335/// #
336/// prefix_items! {
337/// (
338/// #[cfg(feature = "foo")]
339/// )
340/// {
341/// fn foo() {}
342/// fn bar() {}
343/// fn baz() {}
344/// }
345/// }
346///
347/// // Expands to:
348/// // #[cfg(feature = "foo")]
349/// // fn foo() {}
350/// // #[cfg(feature = "foo")]
351/// // fn bar() {}
352/// // #[cfg(feature = "foo")]
353/// // fn baz() {}
354/// ```
355#[rustversion::attr(since(1.48), doc(alias = "prepend_items"))]
356#[macro_export]
357macro_rules! prefix_items {
358 (
359 $({$map:path})?
360 ($($prefix:tt)*)
361 {$($item:item)*}
362 ) => {
363 $crate::__prefix! {
364 $({$map})?
365 ($($prefix)*)
366 [$({$item})*]
367 }
368 };
369}