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}