# Macros for all your token pasting needs
[<img alt="github" src="https://img.shields.io/badge/github-as1100k/pastey-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/as1100k/pastey)
[<img alt="crates.io" src="https://img.shields.io/crates/v/pastey.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/pastey)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-pastey-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/pastey)
[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/as1100k/pastey/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/as1100k/pastey/actions?query=branch%master)
**_`pastey` is the fork of `paste` and is aimed to be a drop-in replacement with additional features for
`paste` crate_**
<details>
<summary>Migrating from <code>paste</code> crate</summary>
Migrating from `paste` crate to `pastey` is super simple, just change the following
in your `Cargo.toml`
```diff
[dependencies]
- paste = "1"
+ pastey = "*" # Or any specific version of pastey
```
Or even better way:
```diff
[dependencies]
- paste = "1"
+ paste = { package = "pastey", version = "*" }
```
</details>
## Quick Start
Add `pastey` as your dependency in `Cargo.toml`
```toml
[dependencies]
# TODO: Replace with latest version available on crates.io
pastey = "*"
```
This approach works with any Rust compiler 1.54+.
## Pasting identifiers
Within the `paste!` macro, identifiers inside `[<`...`>]` are pasted together to
form a single identifier.
```rust
use pastey::paste;
paste! {
// Defines a const called `QRST`.
const [<Q R S T>]: &str = "success!";
}
fn main() {
assert_eq!(
paste! { [<Q R S T>].len() },
8,
);
}
```
## More elaborate example
The next example shows a macro that generates accessor methods for some struct
fields. It demonstrates how you might find it useful to bundle a paste
invocation inside of a macro\_rules macro.
```rust
use pastey::paste;
macro_rules! make_a_struct_and_getters {
($name:ident { $($field:ident),* }) => {
// Define a struct. This expands to:
//
// pub struct S {
// a: String,
// b: String,
// c: String,
// }
pub struct $name {
$(
$field: String,
)*
}
// Build an impl block with getters. This expands to:
//
// impl S {
// pub fn get_a(&self) -> &str { &self.a }
// pub fn get_b(&self) -> &str { &self.b }
// pub fn get_c(&self) -> &str { &self.c }
// }
paste! {
impl $name {
$(
pub fn [<get_ $field>](&self) -> &str {
&self.$field
}
)*
}
}
}
}
make_a_struct_and_getters!(S { a, b, c });
fn call_some_getters(s: &S) -> bool {
s.get_a() == s.get_b() && s.get_c().is_empty()
}
```
## Case conversion
The `pastey` crate supports the following case modfiers:
| `$var:lower` | Lower Case |
| `$var:upper` | Upper Case |
| `$var:snake` | Snake Case |
| `$var:camel` or `$var:upper_camel` | Upper Camel Case |
| `$var:lower_camel` | Lower Camel Case [#4] |
| `$var:camel_edge` | Covers Edge cases of Camel Case. [#3] |
_**NOTE: The pastey crate is going to be a drop in replacement to paste crate,
and will not change the behaviour of existing modifier like `lower`, `upper`,
`snake` and `camel`. For modifying the behaviour new modifiers will be created,
like `camel_edge`**_
You can also use multiple of these modifers like `$var:snake:upper` would give you
`SCREAMING_SNAKE_CASE`.
Example
```rust
use pastey::paste;
paste! {
const [<LIB env!("CARGO_PKG_NAME"):snake:upper>]: &str = "libpastey";
let _ = LIBPASTEY;
}
```
The precise Unicode conversions are as defined by [`str::to_lowercase`] and
[`str::to_uppercase`].
[#3]: https://github.com/AS1100K/pastey/issues/3
[#4]: https://github.com/AS1100K/pastey/issues/4
[`str::to_lowercase`]: https://doc.rust-lang.org/std/primitive.str.html#method.to_lowercase
[`str::to_uppercase`]: https://doc.rust-lang.org/std/primitive.str.html#method.to_uppercase
## Replace modifier
The `replace` modifier allows you to perform string replacement on identifiers,
using the same semantics as [`str::replace`]. This is useful for transforming
identifiers by removing or substituting substrings.
[`str::replace`]: https://doc.rust-lang.org/std/primitive.str.html#method.replace
```rust
use pastey::paste;
macro_rules! m {
($(($command:ident, $from:ident)),+) => {
paste! {
$(pub struct $command {})*
pub enum Command {
$(
[< $command:replace($from, "") >] ( $command )
),*
}
}
}
}
m! {
(CommandFoo, Command),
(CommandBar, Command),
(HelloWorld, Hello)
}
let command_bar = Command::Bar(CommandBar {});
let command_foo = Command::Foo(CommandFoo {});
let command_hello = Command::World(HelloWorld {});
```
## Raw Identifier Generation
`pastey` now supports raw identifiers using a special raw mode. By prefixing a
token with `#` inside the paste syntax, it treats that token as a raw identifier.
```rust
use pastey::paste;
macro_rules! define_struct_and_impl {
($name:ident $(- $name_tail:ident)*) => {
paste!{
struct [< # $name:camel $( $name_tail)* >]; // '#' signals a raw identifier
impl [< # $name:camel $( $name_tail)* >] {
fn [< # $name:snake $( _ $name_tail:snake)* >]() {}
}
}
}
}
define_struct_and_impl!(loop);
define_struct_and_impl!(loop - xyz);
fn test_fn() {
let _ = Loop::r#loop();
let _ = Loopxyz::loop_xyz();
}
```
## Pasting documentation strings
Within the `paste!` macro, arguments to a #\[doc ...\] attribute are implicitly
concatenated together to form a coherent documentation string.
```rust
use pastey::paste;
macro_rules! method_new {
($ret:ident) => {
paste! {
#[doc = "Create a new `" $ret "` object."]
pub fn new() -> $ret { todo!() }
}
};
}
pub struct Pastey {}
method_new!(Pastey); // expands to #[doc = "Create a new `Paste` object"]
```
#### Credits
<sup>
This crate is the fork of <a href="https://github.com/dtolnay/paste"><code>paste</code></a>
and I appreciate the efforts of <a href="https://github.com/dtolnay">@dtolnay</a>
and other contributors.
</sup>
#### License
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>
<br>
<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
</sub>