Rust Quasi-Quoting ================== [![Build Status](https://api.travis-ci.org/dtolnay/quote.svg?branch=master)](https://travis-ci.org/dtolnay/quote) [![Latest Version](https://img.shields.io/crates/v/quote.svg)](https://crates.io/crates/quote) [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/quote/) Quasi-quoting without a Syntex dependency, intended for use with [Macros 1.1](https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md). ```toml [dependencies] quote = "0.3" ``` ```rust #[macro_use] extern crate quote; ``` ## What is quasi-quoting? Quasi-quoting is a way of writing code and treating it as data, similar to writing code inside of a double-quoted string literal except more friendly to your text editor or IDE. It does not get in the way of syntax highlighting, brace matching, indentation, or autocompletion, all of which you would lose by writing code inside of double quotes. Check out [my meetup talk] on the topic to learn more about the use case. [my meetup talk]: https://github.com/dtolnay/talks#macros-11--syn--quote This crate is motivated by the Macros 1.1 use case, but is a general-purpose Rust quasi-quoting library and is not specific to procedural macros. ## Syntax The quote crate provides a `quote!` macro within which you can write Rust code that gets packaged into a `quote::Tokens` and can be treated as data. You should think of `quote::Tokens` as representing a fragment of Rust source code. Call `to_string()` or `as_str()` on a Tokens to get back the fragment of source code as a string. Within the `quote!` macro, interpolation is done with `#var`. Any type implementing the `quote::ToTokens` trait can be interpolated. This includes most Rust primitive types as well as most of the syntax tree types from [`syn`](https://github.com/dtolnay/syn). ```rust let tokens = quote! { struct SerializeWith #generics #where_clause { value: &'a #field_ty, phantom: ::std::marker::PhantomData<#item_ty>, } impl #generics serde::Serialize for SerializeWith #generics #where_clause { fn serialize(&self, s: &mut S) -> Result<(), S::Error> where S: serde::Serializer { #path(self.value, s) } } SerializeWith { value: #value, phantom: ::std::marker::PhantomData::<#item_ty>, } }; ``` Repetition is done using `#(...)*` or `#(...),*` very similar to `macro_rules!`: - `#(#var)*` - no separators - `#(#var),*` - the character before the asterisk is used as a separator - `#( struct #var; )*` - the repetition can contain other things - `#( #k => println!("{}", #v), )*` - even multiple interpolations Note that there is a difference between `#(#var ,)*` and `#(#var),*`—the latter does not produce a trailing comma. This matches the behavior of delimiters in `macro_rules!`. Tokens can be interpolated into other quotes: ```rust let t = quote! { /* ... */ }; return quote! { /* ... */ #t /* ... */ }; ``` For a great example making use of all of these features, check out [`DeepClone`] and [`deep-clone-derive`]. [`DeepClone`]: https://github.com/asajeffrey/deep-clone [`deep-clone-derive`]: https://github.com/asajeffrey/deep-clone/blob/master/deep-clone-derive/lib.rs --- The `quote!` macro relies on deep recursion so some large invocations may fail with "recursion limit reached" when you compile. If it fails, bump up the recursion limit by adding `#![recursion_limit = "128"]` to your crate. An even higher limit may be necessary for especially large invocations. You don't need this unless the compiler tells you that you need it. ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution 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.