place_macro/lib.rs
1//! # Place-macro
2//! Macros you wish you had while you were writing your non-proc macro.
3//!
4//! This library privides some macros that make writing regural non-proc
5//! macros much simpler, readable and with less dirty tricks.
6//!
7//! The main macro of this library is `place`. It is able to expand the macros
8//! in this library in reverse expansion order.
9//!
10//! Every time I'm missing a proc macro while creating macro, I will add it
11//! here :).
12//!
13//! ## Macros
14//! + `place`: expands the following macros in reverse order, see below
15//! - `ignore`: expands to nothing
16//! - `identity`: expands to what is given, it bypasses the reverse order in
17//! the `place` macro
18//! - `dollar`: expands to dollar sign `$`
19//! - `string`: concats the contents into single string, see the doc
20//! - `identifier`: concats the contents into sintle identifier in the same way
21//! asstring
22//! - `head`: expands to the first token
23//! - `tail`: expands to all but the first token
24//! - `start`: expands to all but the last token
25//! - `last`: expands to the last token
26//! - `reverse`: expands to the tokens in reverse order
27//! - `stringify`: expands to string of the input
28//! - `replace_newline`: replaces all newlines and folowing whitespace in
29//! literal with the given literal
30//! - `str_replace`: replace in string literal
31//! - `to_case`: change the case of a identifier
32//!
33//! ### The macro `place`
34//! Expands the other macros inside in reverse order. The macros inside that
35//! will be expanded are used with a different sintax: instead of calling a
36//! macro as `string!("hello" "there")` you call it as
37//! `__string__("hello" "there")`. One exception is the macro `dollar` that is
38//! called without the parenthesis: `__dollar__` instead of `__dollar__()`.
39//!
40//! For some of the macros there are also shorter names:
41//! - `__identity__` - `__id__`
42//! - `__string__` - `__str__`
43//! - `__dollar__` - `__s__`
44//! - `__identifier__` - `__ident__`
45//! - `__stringify__` - `__strfy__`
46//! - `__replace_newline__` - `__repnl__`
47//! - `__str_replace__` - `__repstr__`
48//!
49//! The macro `to_case` has simplified usage, the case of the macro call will
50//! determine the case to which convert (e.g. `__ToCase__(my_ident)` will
51//! expand to `MyIdent`). Possible variants:
52//! - `__TOCASE__`
53//! - `__tocase__`
54//! - `__toCase__`
55//! - `__ToCase__`
56//! - `__to_case__`
57//! - `__TO_CASE__`
58//! - `__To_Case__`
59//!
60//! #### Example
61//! The following passes:
62//! ```rust
63//! use place_macro::place;
64//!
65//! let res = place!(__string__(1 __string__(2 __identity__(3 __string__(4)))));
66//! assert_eq!(res, "123__string__4");
67//! ```
68//!
69//! Why is this useful?
70//!
71//! - You can generate identifiers in your macros:
72//! ```rust
73//! use place_macro::place;
74//!
75//! macro_rules! my_cool_macro {
76//! ($name:ident -> $t:ty, $body:expr) => {
77//! place! {
78//! fn __identifier__(cool_ $name)() -> $t {
79//! $body
80//! }
81//! }
82//! };
83//! }
84//!
85//! my_cool_macro! { foo -> &'static str, "cool!" }
86//! // Expands to:
87//! // ```
88//! // fn cool_foo() -> &'static str {
89//! // "cool!"
90//! // }
91//! // ```
92//! ```
93//! - You can generate strings as macro parameters in your macros:
94//! ```rust
95//! use place_macro::place;
96//!
97//! macro_rules! my_cool_macro {
98//! ($name:ident -> $t:ty, $body:expr) => {
99//! place! {
100//! #[doc =
101//! __string__(
102//! "cool function called " $name ". Returns `"
103//! __stringify__($t) "`."
104//! )
105//! ]
106//! fn __identifier__(cool_ $name)() -> $t {
107//! $body
108//! }
109//! }
110//! };
111//! }
112//!
113//! my_cool_macro! { foo -> &'static str, "cool!" }
114//! // Expands to:
115//! // ```
116//! // #[doc = "cool function called foo. Returns `&'static str`."]
117//! // fn cool_foo() -> &'static str {
118//! // "cool!"
119//! // }
120//! // ```
121//! ```
122//! - Or you can even generate macros in your macros
123//! ```rust
124//! use place_macro::place;
125//!
126//! macro_rules! my_cooler_macro {
127//! ($t:ident) => {
128//! place! {
129//! macro_rules! __identifier__(my_ $t _macro) {
130//! (__dollar__ name:ident -> __dollar__ t:ty, __dollar__ body:expr) => {
131//! place! {
132//! #[doc =
133//! __identity__(__string__)(
134//! $t " function called " __dollar__ name ". Returns `"
135//! __identity__(__stringify__)(__dollar__ t) "`."
136//! )
137//! ]
138//! fn __identity__(__identifier__)($t __dollar__ name)() -> __dollar__ t {
139//! __dollar__ body
140//! }
141//! }
142//! };
143//! }
144//! }
145//! };
146//! }
147//!
148//! my_cooler_macro! { cool };
149//! my_cool_macro! { foo -> &'static str, "cool!" }
150//! // now you have the same function as in the previous example
151//! ```
152//! The last example was a little less readable, but you can see that you can do
153//! a lot with this macro.
154//!
155//! ## Links
156//! - **Author:** [BonnyAD9](https://github.com/BonnyAD9)
157//! - **GitHub repository:** [BonnyAD/place_macro](https://github.com/BonnyAD9/place_macro)
158//! - **Package:** [crates.io](https://crates.io/crates/place_macro)
159//! - **Documentation:** [docs.rs](https://docs.rs/place_macro/latest/place_macro/)
160//! - **My Website:** [bonnyad9.github.io](https://bonnyad9.github.io/)
161
162/// Ignores all the input, as if there was nothing
163///
164/// # Examples
165/// ```
166/// use place_macro::ignore;
167///
168/// let mut i = 5;
169/// ignore!(i = 10);
170/// assert_eq!(i, 5);
171/// ```
172pub use place_macro_proc::ignore;
173
174/// Returns exactly the given input
175///
176/// # Examples
177/// ```
178/// use place_macro::identity;
179///
180/// let mut i = 5;
181/// identity!(i = 10);
182/// assert_eq!(i, 10);
183/// ```
184pub use place_macro_proc::identity;
185
186/// Expands to a single dollar sign, this has no use when it is used alone,
187/// but it can be used in the `place` macro
188pub use place_macro_proc::dollar;
189
190/// Converts the input to string literal, literals are interpreted as their
191/// values, punctuation and brackets are ignored and the rest is stringified.
192///
193/// # Examples
194/// ```
195/// use place_macro::string;
196///
197/// let s = string!("hello" + , ", " {(agent)} ' ' 0x2F);
198/// assert_eq!(s, "hello, agent 47");
199/// ```
200pub use place_macro_proc::string;
201
202/// Expans to the first token if present
203///
204/// # Examples
205/// ```
206/// use place_macro::head;
207///
208/// let n = head!(5 + 3 + 2);
209/// assert_eq!(n, 5);
210///
211/// let n = head!((5 + 3) + 2);
212/// assert_eq!(n, (5 + 3));
213///
214/// // expands to nothing
215/// head!();
216/// ```
217pub use place_macro_proc::head;
218
219/// Expands to all but the first token
220///
221/// # Examples
222/// ```
223/// use place_macro::tail;
224///
225/// let n = tail!(-5);
226/// assert_eq!(n, 5);
227///
228/// let n = tail!((5 + 3) - 5);
229/// assert_eq!(n, -5);
230///
231/// // expands to nothing
232/// tail!((-5));
233/// ```
234pub use place_macro_proc::tail;
235
236/// Expands to all but the last token
237///
238/// # Examples
239/// ```
240/// use place_macro::start;
241///
242/// let n = start!(5 + 3 +);
243/// assert_eq!(n, 5 + 3);
244///
245/// // expands to nothing
246/// start!();
247/// ```
248pub use place_macro_proc::start;
249
250/// Expands to the last token
251///
252/// # Examples
253/// ```
254/// use place_macro::last;
255///
256/// let n = last!(5 + 3 + 2);
257/// assert_eq!(n, 2);
258///
259/// // expands to nothing
260/// last!();
261/// ```
262pub use place_macro_proc::last;
263
264/// Reverses the passed tokens
265///
266/// # Examples
267/// ```
268/// use place_macro::reverse;
269///
270/// let n = reverse!(5 - 3);
271/// assert_eq!(n, -2);
272///
273/// let n = reverse!((2 + 3) - 2);
274/// assert_eq!(n, -3);
275/// ```
276pub use place_macro_proc::reverse;
277
278/// Creates a identifier in the same way as the string macro creates string
279/// literals.
280///
281/// # Example
282/// ```
283/// use place_macro::identifier;
284///
285/// let my = 5;
286/// let var = 10;
287/// let myvar = 1;
288/// let n = identifier!(my + var);
289/// assert_eq!(n, myvar);
290/// ```
291pub use place_macro_proc::identifier;
292
293/// Should be same to the rust macro stringify
294///
295/// # Example
296/// ```
297/// use place_macro;
298///
299/// let a = place_macro::stringify!("hello" + , ", " {(agent)} ' ' 0x2F);
300/// let b = stringify!("hello" + , ", " {(agent)} ' ' 0x2F);
301/// assert_eq!(a, b);
302/// ```
303pub use place_macro_proc::stringify;
304
305/// Replaces newlines and follwing whitespace in string literal with another
306/// string.
307///
308/// # Example
309/// ```
310/// use place_macro::replace_newline;
311///
312/// let v = replace_newline!("hello
313/// every body
314/// ", ", ");
315/// assert_eq!(v, "hello, every body, ");
316/// ```
317pub use place_macro_proc::replace_newline;
318
319/// Replaces in string literal
320///
321/// # Examples
322/// ```
323/// use place_macro::str_replace;
324///
325/// let s = str_replace!("hello runtime replace", "runtime", "compile-time");
326/// assert_eq!(s, "hello compile-time replace");
327/// ```
328pub use place_macro_proc::str_replace;
329
330/// Converts the given identifier to the given case. Second argument is the
331/// identifier and the first is string literal representing the target case.
332/// The target case can be one of:
333/// - `"TOCASE"`
334/// - `"tocase"`
335/// - `"toCase"`
336/// - `"ToCase"`
337/// - `"to_case"`
338/// - `"TO_CASE"`
339/// - `"To_Case"`
340///
341/// # Examples
342/// ```
343/// use place_macro::to_case;
344///
345/// let my_var = 5;
346/// let MyVar = 10;
347/// let n = to_case!("ToCase", my_var);
348/// assert_eq!(n, MyVar);
349/// ```
350pub use place_macro_proc::to_case;
351
352/// Evaluates the macros in this crate in reverse order
353///
354/// to minimize conflicts, the macros are refered to as `__macro__` where
355/// macro is the name of the macro. Special case is the macro `dollar` that
356/// doesn't have any arguments.
357/// # Examples
358/// ```
359/// use place_macro::place;
360///
361/// place! {
362/// pub fn __identifier__(my "_function")() -> bool {
363/// true
364/// }
365/// }
366/// assert!(my_function());
367///
368/// place! {
369/// macro_rules! mac {
370/// (__dollar__ var: literal) => {
371/// __dollar__ var
372/// }
373/// }
374/// }
375/// assert_eq!("hi", mac!("hi"));
376///
377/// let res = place!(__string__(1 __string__(2 __identity__(3 __string__(4)))));
378/// assert_eq!(res, "123__string__4");
379/// ```
380pub use place_macro_proc::place;
381
382#[cfg(test)]
383mod tests {
384 #[test]
385 fn test0() {
386 super::place!(let __to_case__(Hello) = 5;);
387 }
388}