1 | //! This internal library provides the procedural macros needed by the crate [`color-print`]. |
2 | //! |
3 | //! [`color-print`]: https://crates.io/crates/color-print |
4 | |
5 | extern crate proc_macro; |
6 | |
7 | #[macro_use ] |
8 | mod util; |
9 | #[cfg (not(feature = "terminfo" ))] |
10 | mod ansi; |
11 | #[cfg (not(feature = "terminfo" ))] |
12 | mod ansi_constants; |
13 | mod color_context; |
14 | mod error; |
15 | mod format_args; |
16 | mod parse; |
17 | #[cfg (feature = "terminfo" )] |
18 | mod terminfo; |
19 | mod untagged; |
20 | |
21 | use proc_macro::TokenStream; |
22 | use quote::{quote, ToTokens}; |
23 | |
24 | /// The same as `format!()`, but parses color tags. |
25 | /// |
26 | /// #### Example |
27 | /// |
28 | /// ``` |
29 | /// # use color_print_proc_macro::cformat; |
30 | /// let s: String = cformat!("A <g>green</> word, {}" , "placeholders are allowed" ); |
31 | /// assert_eq!(s, "A \u{1b}[32mgreen \u{1b}[39m word, placeholders are allowed" ); |
32 | /// ``` |
33 | #[proc_macro ] |
34 | #[cfg (not(feature = "terminfo" ))] |
35 | pub fn cformat(input: TokenStream) -> TokenStream { |
36 | get_macro(macro_name:"format" , input) |
37 | } |
38 | |
39 | /// The same as `format!()`, but parses color tags. |
40 | #[proc_macro ] |
41 | #[cfg (feature = "terminfo" )] |
42 | pub fn cformat(input: TokenStream) -> TokenStream { |
43 | get_macro("format" , input) |
44 | } |
45 | |
46 | /// The same as `print!()`, but parses color tags. |
47 | /// |
48 | /// #### Example |
49 | /// |
50 | /// ``` |
51 | /// # use color_print_proc_macro::cprint; |
52 | /// cprint!("A <g>green</> word, {}" , "placeholders are allowed" ); |
53 | /// ``` |
54 | #[proc_macro ] |
55 | #[cfg (not(feature = "terminfo" ))] |
56 | pub fn cprint(input: TokenStream) -> TokenStream { |
57 | get_macro(macro_name:"print" , input) |
58 | } |
59 | |
60 | /// The same as `print!()`, but parses color tags. |
61 | #[proc_macro ] |
62 | #[cfg (feature = "terminfo" )] |
63 | pub fn cprint(input: TokenStream) -> TokenStream { |
64 | get_macro("print" , input) |
65 | } |
66 | |
67 | /// The same as `println!()`, but parses color tags. |
68 | /// |
69 | /// #### Example |
70 | /// |
71 | /// ``` |
72 | /// # use color_print_proc_macro::cprintln; |
73 | /// cprintln!("A <g>green</> word, {}" , "placeholders are allowed" ); |
74 | /// ``` |
75 | #[proc_macro ] |
76 | #[cfg (not(feature = "terminfo" ))] |
77 | pub fn cprintln(input: TokenStream) -> TokenStream { |
78 | get_macro(macro_name:"println" , input) |
79 | } |
80 | |
81 | /// The same as `println!()`, but parses color tags. |
82 | #[proc_macro ] |
83 | #[cfg (feature = "terminfo" )] |
84 | pub fn cprintln(input: TokenStream) -> TokenStream { |
85 | get_macro("println" , input) |
86 | } |
87 | |
88 | /// Colorizes a string literal, without formatting the `format!`-like placeholders. |
89 | /// |
90 | /// * Accepts only one argument; |
91 | /// * Will panic if feature `terminfo` is activated. |
92 | /// |
93 | /// #### Example |
94 | /// |
95 | /// ``` |
96 | /// # use color_print_proc_macro::cstr; |
97 | /// let s: &str = cstr!("A <g>green</> word" ); |
98 | /// assert_eq!(s, "A \u{1b}[32mgreen \u{1b}[39m word" ); |
99 | /// ``` |
100 | #[cfg (not(feature = "terminfo" ))] |
101 | #[proc_macro ] |
102 | pub fn cstr(input: TokenStream) -> TokenStream { |
103 | crateTokenStream::ansi::get_cstr(input) |
104 | .unwrap_or_else(|err: SpanError| err.to_token_stream()) |
105 | .into() |
106 | } |
107 | |
108 | /// Removes all the color tags from the given string literal. |
109 | /// |
110 | /// Accepts only one argument. |
111 | /// |
112 | /// #### Example |
113 | /// |
114 | /// ``` |
115 | /// # use color_print_proc_macro::untagged; |
116 | /// let s: &str = untagged!("A <g>normal</> word" ); |
117 | /// assert_eq!(s, "A normal word" ); |
118 | /// ``` |
119 | #[proc_macro ] |
120 | pub fn untagged(input: TokenStream) -> TokenStream { |
121 | crateTokenStream::untagged::get_untagged(input) |
122 | .unwrap_or_else(|err: SpanError| err.to_token_stream()) |
123 | .into() |
124 | } |
125 | |
126 | /// Colorizes a string literal, without formatting the `format!`-like placeholders. |
127 | /// |
128 | /// * Accepts only one argument; |
129 | /// * Will panic if feature `terminfo` is activated. |
130 | #[cfg (feature = "terminfo" )] |
131 | #[proc_macro ] |
132 | pub fn cstr(_: TokenStream) -> TokenStream { |
133 | panic!("Macro cstr!() cannot be used with terminfo feature" ) |
134 | } |
135 | |
136 | /// Renders a whole processed macro. |
137 | fn get_macro(macro_name: &str, input: TokenStream) -> TokenStream { |
138 | #[cfg (not(feature = "terminfo" ))] |
139 | let format_args: Result = crate::ansi::get_format_args(input); |
140 | #[cfg (feature = "terminfo" )] |
141 | let format_args = crate::terminfo::get_format_args(input); |
142 | |
143 | let format_args: TokenStream = format_args.unwrap_or_else(|err: SpanError| err.to_token_stream()); |
144 | let macro_name: Ident = util::ident(macro_name); |
145 | (quote! { #macro_name!(#format_args) }).into() |
146 | } |
147 | |