affix-macro 1.0.0

Macros for affixing tokens to groups of other tokens.
Documentation
//! Macros for affixing tokens to groups of other tokens.
//!
//! The [MSRV](https://doc.rust-lang.org/cargo/reference/rust-version.html) is [Rust 1.31](https://releases.rs/docs/1.31.0/).
//! If this is increased, it will be a major version bump.
//!
//! See the documentation of each macro for usage details.

#![no_std]

use ::rustversion;

/// Prefixes tokens to groups of other tokens.
///
/// Optionally, a mapping macro can be provided to transform each resulting prefixed token group.
///
/// See also [`prefix_items!`] for a convenience wrapper around this macro for use with items.
///
/// ```rust no_run
/// # use ::affix_macro::prefix;
/// #
/// prefix! {
/// 	(foo)
/// 	[{bar 1}, {baz 2}, {qux 3}]
/// }
///
/// // Expands to:
/// // foo bar 1
/// // foo baz 2
/// // foo qux 3
/// ```
///
/// With mapping macro:
/// ```rust no_run
/// # use ::affix_macro::prefix;
/// #
/// macro_rules! wrap_in_parens {
/// 	($($tokens:tt)*) => {
/// 		( $($tokens)* )
/// 	};
/// }
///
/// prefix! {
/// 	{wrap_in_parens}
/// 	(foo)
/// 	[{bar 1}, {baz 2}, {qux 3}]
/// }
///
/// // Expands to:
/// // ( foo bar 1 )
/// // ( foo baz 2 )
/// // ( foo qux 3 )
/// ```
#[rustversion::attr(since(1.48), doc(alias = "prepend"))]
#[macro_export]
macro_rules! prefix {
	(
		{$map:path}
		($($prefix:tt)*)
		[$(,)? {$($next:tt)*} $($rest:tt)*]
	) => {
		$map! {
			$($prefix)*
			$($next)*
		}

		$crate::__prefix! {
			{$map}
			($($prefix)*)
			[$($rest)*]
		}
	};

	(
		($($prefix:tt)*)
		[$(,)? {$($next:tt)*} $($rest:tt)*]
	) => {
		$($prefix)*
		$($next)*

		$crate::__prefix! {
			($($prefix)*)
			[$($rest)*]
		}
	};

	(
		$({$map:path})?
		($($prefix:tt)*)
		[$(,)?]
	) => {};
}

// Workaround for https://github.com/rust-lang/rust/pull/52234
#[doc(hidden)]
pub use prefix as __prefix;

/// Suffixes tokens to groups of other tokens.
///
/// Optionally, a mapping macro can be provided to transform each resulting suffixed token group.
///
/// ```rust no_run
/// # use ::affix_macro::suffix;
/// #
/// suffix! {
/// 	(foo)
/// 	[{bar 1}, {baz 2}, {qux 3}]
/// }
///
/// // Expands to:
/// // bar 1 foo
/// // baz 2 foo
/// // qux 3 foo
/// ```
///
/// With mapping macro:
/// ```rust no_run
/// # use ::affix_macro::suffix;
/// #
/// macro_rules! wrap_in_parens {
/// 	($($tokens:tt)*) => {
/// 		( $($tokens)* )
/// 	};
/// }
///
/// suffix! {
/// 	{wrap_in_parens}
/// 	(foo)
/// 	[{bar 1}, {baz 2}, {qux 3}]
/// }
///
/// // Expands to:
/// // ( bar 1 foo )
/// // ( baz 2 foo )
/// // ( qux 3 foo )
/// ```
#[rustversion::attr(since(1.48), doc(alias = "append"))]
#[macro_export]
macro_rules! suffix {
	(
		{$map:path}
		($($suffix:tt)*)
		[$(,)? {$($next:tt)*} $($rest:tt)*]
	) => {
		$map ! {
			$($next)*
			$($suffix)*
		}

		$crate::__suffix! {
			{$map}
			($($suffix)*)
			[$($rest)*]
		}
	};

	(
		($($suffix:tt)*)
		[$(,)? {$($next:tt)*} $($rest:tt)*]
	) => {
		$($next)*
		$($suffix)*

		$crate::__suffix! {
			($($suffix)*)
			[$($rest)*]
		}
	};

	(
		$({$map:path})?
		($($suffix:tt)*)
		[$(,)?]
	) => {};
}

// Workaround for https://github.com/rust-lang/rust/pull/52234
#[doc(hidden)]
pub use suffix as __suffix;

/// [suffix!] and [prefix!] in a single operation.
///
/// ```rust no_run
/// # use ::affix_macro::circumfix;
/// #
/// circumfix! {
/// 	(<<)
/// 	(>>)
/// 	[{foo}, {bar}, {baz}]
/// }
///
/// // Expands to:
/// // << foo >>
/// // << bar >>
/// // << baz >>
/// ```
///
/// With mapping macro:
/// ```rust no_run
/// # use ::affix_macro::circumfix;
/// #
/// macro_rules! wrap_in_parens {
/// 	($($tokens:tt)*) => {
/// 		( $($tokens)* )
/// 	};
/// }
///
/// circumfix! {
/// 	{wrap_in_parens}
/// 	(<<)
/// 	(>>)
/// 	[{foo}, {bar}, {baz}]
/// }
///
/// // Expands to:
/// // ( << foo >> )
/// // ( << bar >> )
/// // ( << baz >> )
/// ```
#[rustversion::attr(since(1.48), doc(alias = "surround"))]
#[macro_export]
macro_rules! circumfix {
	(
		{$map:path}
		($($prefix:tt)*)
		($($suffix:tt)*)
		[$(,)? {$($next:tt)*} $($rest:tt)*]
	) => {
		$map ! {
			$($prefix)*
			$($next)*
			$($suffix)*
		}

		$crate::__circumfix! {
			{$map}
			($($prefix)*)
			($($suffix)*)
			[$($rest)*]
		}
	};

	(
		($($prefix:tt)*)
		($($suffix:tt)*)
		[$(,)? {$($next:tt)*} $($rest:tt)*]
	) => {
		$($prefix)*
		$($next)*
		$($suffix)*

		$crate::__circumfix! {
			($($prefix)*)
			($($suffix)*)
			[$($rest)*]
		}
	};

	(
		$({$map:path})?
		($($prefix:tt)*)
		($($suffix:tt)*)
		[$(,)?]
	) => {};
}

// Workaround for https://github.com/rust-lang/rust/pull/52234
#[doc(hidden)]
pub use circumfix as __circumfix;

/// Joins segments together.
///
/// Optionally, a mapping macro can be provided to transform the whole resulting joined token group.
///
/// ```rust no_run
/// # use ::affix_macro::join;
/// #
/// join! {
/// 	[{foo}, {bar}, {baz}]
/// }
///
/// // Expands to:
/// // foo bar baz
/// ```
///
/// With mapping macro:
/// ```rust no_run
/// # use ::affix_macro::join;
/// #
/// macro_rules! wrap_in_parens {
/// 	($($tokens:tt)*) => {
/// 		( $($tokens)* )
/// 	};
/// }
///
/// join! {
/// 	{wrap_in_parens}
/// 	[{foo}, {bar}, {baz}]
/// }
///
/// // Expands to:
/// // ( foo bar baz )
/// ```
#[rustversion::attr(since(1.48), doc(alias = "merge"))]
#[rustversion::attr(since(1.48), doc(alias = "concat"))]
#[rustversion::attr(since(1.48), doc(alias = "concatenate"))]
#[macro_export]
macro_rules! join {
	(
		{$map:path}
		[
			$(,)? $({$($segment:tt)*} $(,)?)*
		]
	) => {
		$map! {
			$($($segment)*)*
		}
	};

	(
		[
			$(,)? $({$($segment:tt)*} $(,)?)*
		]
	) => {
		$($($segment)*)*
	}
}

/// Prefixes tokens to items.
///
/// This is a convenience wrapper around [`prefix!`] for use with items. It takes the same arguments
/// as [`prefix!`], but transforms each item given into an individual token group.
///
/// ```rust no_run
/// # use ::affix_macro::prefix_items;
/// #
/// prefix_items! {
/// 	(
/// 		#[cfg(feature = "foo")]
/// 	)
/// 	{
/// 		fn foo() {}
/// 		fn bar() {}
/// 		fn baz() {}
/// 	}
/// }
///
/// // Expands to:
/// // #[cfg(feature = "foo")]
/// // fn foo() {}
/// // #[cfg(feature = "foo")]
/// // fn bar() {}
/// // #[cfg(feature = "foo")]
/// // fn baz() {}
/// ```
#[rustversion::attr(since(1.48), doc(alias = "prepend_items"))]
#[macro_export]
macro_rules! prefix_items {
	(
		$({$map:path})?
		($($prefix:tt)*)
		{$($item:item)*}
	) => {
		$crate::__prefix! {
			$({$map})?
			($($prefix)*)
			[$({$item})*]
		}
	};
}