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
5extern crate proc_macro;
6
7#[macro_use]
8mod util;
9#[cfg(not(feature = "terminfo"))]
10mod ansi;
11#[cfg(not(feature = "terminfo"))]
12mod ansi_constants;
13mod color_context;
14mod error;
15mod format_args;
16mod parse;
17#[cfg(feature = "terminfo")]
18mod terminfo;
19mod untagged;
20
21use proc_macro::TokenStream;
22use 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"))]
35pub 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")]
42pub 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"))]
56pub 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")]
63pub 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"))]
77pub 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")]
84pub 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]
102pub 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]
120pub 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]
132pub fn cstr(_: TokenStream) -> TokenStream {
133 panic!("Macro cstr!() cannot be used with terminfo feature")
134}
135
136/// Renders a whole processed macro.
137fn 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