custom_print/macros/
define.rs

1/// Defines multiple `print`-like and `dbg`-like macros.
2///
3/// The first argument braced in curly braces and contains
4/// comma-seperated macro template names and optionally their custom macro names.
5/// See the [`define_macro`] declaration for the list of available templates.
6/// The rest tokens specified in `$($args)*` are used as input for [`define_writer`] macro.
7///
8/// Depending on the specified templates, the macro uses
9/// [`define_print`], [`define_println`], [`define_dbg`], [`define_flush`],
10/// [`define_try_print`], [`define_try_println`], [`define_try_dbg`] or [`define_try_flush`]
11/// for each generated macro.
12///
13/// If you need to define a single `print`-like or `dbg`-like macro, use [`define_macro`].
14///
15/// # Macro ambiguity
16///
17/// When using std-prelude, std macros cannot be replaced in [textual scope] using this macro.
18/// This is a consequence of the ambiguous precedence between
19/// a macro-expanded macro and a macro from the outer scope.
20/// Use alternative names like `cprint`, `ceprint`, `cprintln`, `ceprintln`, `cdbg`,
21/// and then override std macros using proxy macro or use declaration.
22///
23/// Overriding with a proxy macro is a better way because
24/// it overrides macros in [textual scope] and accordingly in all submodules:
25/// ```
26/// custom_print::define_macros!({ cprint, cprintln }, once: crate::write);
27/// macro_rules! print { ($($args:tt)*) => { cprint!($($args)*); } }
28/// macro_rules! println { ($($args:tt)*) => { cprintln!($($args)*); } }
29/// # fn main() {}
30/// mod submodule { /* println is already defined in all submodules */ }
31/// ```
32///
33/// Alternatively, use can rebind macro from the [textual scope] to the [path-based scope],
34/// but then it will be necessary not to forget to import macro into submodules scope:
35/// ```
36/// custom_print::define_macros!({ cprint, cprintln }, once: crate::write);
37/// use cprint as print;
38/// use cprintln as println;
39/// # fn main() {}
40/// mod submodule { use crate::{print, println}; /* ... */ }
41/// ```
42///
43/// # Examples
44///
45/// An example with a simple string writer:
46/// ```rust
47/// use core::fmt::Write;
48/// let mut string = String::new();
49/// custom_print::define_macros!({ cprint, cprintln }, &mut string);
50///
51/// assert_eq!(cprintln!("first"), ());
52/// assert_eq!(string, "first\n");
53/// assert_eq!(cprint!("second"), ());
54/// assert_eq!(string, "first\nsecond");
55/// ```
56///
57/// An example with an extern functions that takes a UTF-8 chars pointer and byte length
58/// and works in `no_std` context:
59#[cfg_attr(feature = "alloc", doc = "```rust")]
60#[cfg_attr(not(feature = "alloc"), doc = "```rust,compile_fail")]
61/// #![no_std]
62/// extern crate std;
63///
64/// # pub mod ffi {
65/// #     #[no_mangle] pub extern "C" fn console_log(_: *const u8, _: usize) {}
66/// #     #[no_mangle] pub extern "C" fn console_warn(_: *const u8, _: usize) {}
67/// # }
68/// #
69/// custom_print::define_macros!({ print, println },
70///     concat, extern "C" fn console_log(_: *const u8, _: usize));
71/// custom_print::define_macros!({ eprint, eprintln, dbg },
72///     concat, extern "C" fn console_warn(_: *const u8, _: usize));
73///
74/// fn main() {
75///     println!("println");
76///     print!("print");
77///     eprintln!("eprintln");
78///     eprint!("eprint");
79///     dbg!("dbg");
80/// }
81/// ```
82///
83/// An example with a closure that takes an [`str`] reference in `no_std` and `no_alloc`:
84#[cfg_attr(feature = "std", doc = " ```rust")]
85#[cfg_attr(not(feature = "std"), doc = " ```rust,compile_fail")]
86/// #![no_std]
87/// custom_print::define_macros!({ print, println }, fmt, |_value: &str| { /* ... */ });
88///
89/// fn main() {
90///     println!("println");
91///     print!("print");
92/// }
93/// ```
94///
95/// An example with a function that takes a [`c_char`] pointer and overriding
96/// [`std::print`] and [`std::println`] functions:
97#[cfg_attr(feature = "std", doc = "```rust")]
98#[cfg_attr(not(feature = "std"), doc = "```rust,compile_fail")]
99/// fn write(_value: *const std::os::raw::c_char) { /* ... */ }
100///
101/// custom_print::define_macros!({ cprint, cprintln }, concat, crate::write);
102/// macro_rules! print { ($($args:tt)*) => { cprint!($($args)*); } }
103/// macro_rules! println { ($($args:tt)*) => { cprintln!($($args)*); } }
104///
105/// fn main() {
106///     println!("println");
107///     print!("print");
108/// }
109/// ```
110///
111/// An example with `LineWriter` and flushing.
112/// ```rust
113/// use std::io::{self, LineWriter, Write};
114/// use std::sync::Mutex;
115///
116/// let written: Mutex<Vec<u8>> = Mutex::default();
117///
118/// #[derive(Clone, Debug)]
119/// struct CustomWriter<'a>(&'a Mutex<Vec<u8>>);
120///
121/// impl Write for CustomWriter<'_> {
122///     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
123///         let mut written = self.0.lock().unwrap();
124///         written.extend_from_slice(buf);
125///         Ok(buf.len())
126///     }
127///
128///     fn flush(&mut self) -> io::Result<()> {
129///         Ok(())
130///     }
131/// }
132///
133/// let custom_writer = CustomWriter(&written);
134/// let mut line_writer = LineWriter::new(custom_writer);
135///
136/// custom_print::define_macros!({cprint, flush}, line_writer);
137///
138/// assert_eq!(cprint!("first,"), ());
139/// assert_eq!(*written.lock().unwrap(), b"");
140/// assert_eq!(cprint!("second\nthird,"), ());
141/// assert_eq!(*written.lock().unwrap(), b"first,second\n");
142/// assert_eq!(flush!(), ());
143/// assert_eq!(*written.lock().unwrap(), b"first,second\nthird,");
144/// ```
145///
146/// [`c_char`]: https://doc.rust-lang.org/std/os/raw/type.c_char.html
147/// [textual scope]: https://doc.rust-lang.org/nightly/reference/macros-by-example.html#scoping-exporting-and-importing
148/// [path-based scope]: https://doc.rust-lang.org/nightly/reference/macros-by-example.html#scoping-exporting-and-importing
149/// [`define_macro`]: macro.define_macro.html
150/// [`define_writer`]: macro.define_writer.html
151/// [`define_print`]: macro.define_print.html
152/// [`define_println`]: macro.define_println.html
153/// [`define_dbg`]: macro.define_dbg.html
154/// [`define_flush`]: macro.define_flush.html
155/// [`define_try_print`]: macro.define_try_print.html
156/// [`define_try_println`]: macro.define_try_println.html
157/// [`define_try_dbg`]: macro.define_try_dbg.html
158/// [`define_try_flush`]: macro.define_try_flush.html
159#[macro_export]
160macro_rules! define_macros {
161    (
162        $( #[$meta1:meta] )*
163        { $( $( #[$meta2:meta] )* $template:ident $(as $name:ident)? ),* $(,)? },
164        $( $args:tt )*
165    ) => {
166        $crate::_define_macros_impl!(
167            $( #[$meta1] )*
168            { $( $( #[$meta2] )* $template $( as $name )? ),* },
169            $( $args )*
170        );
171    };
172}
173
174#[doc(hidden)]
175#[macro_export]
176macro_rules! _define_macros_impl {
177    (
178        $( #[$meta1:meta] )*
179        { $( #[$meta2:meta] )* $template:ident $(as $name:ident)? $(, $($rest:tt)* )? },
180        $( $args:tt )*
181    ) => {
182        $crate::define_macro!(
183            $( #[$meta1] )*
184            $( #[$meta2] )*
185            $template $(as $name)?, $($args)*
186        );
187        $crate::_define_macros_impl!(
188            $( #[$meta1] )*
189            { $($($rest)*)? }, $($args)*
190        );
191    };
192    ( $( #[$meta1:meta] )* { $(,)? } $(, $( $args:tt )* )? ) => {};
193}
194
195/// Defines custom `print`-like and `dbg`-like macro.
196///
197/// The first argument contains the macro name by which its template is determined,
198/// or both the template name and the macro name using the syntax `template as name`.
199/// The rest tokens specified in `$($args)*` are used as input for [`define_writer`] macro.
200///
201/// Depending on the specified template, the macro uses
202/// [`define_print`], [`define_println`], [`define_dbg`], [`define_flush`],
203/// [`define_try_print`], [`define_try_println`], [`define_try_dbg`] or [`define_try_flush`].
204///
205/// If you need to define multiple `print`-like and `dbg`-like macros, use [`define_macros`].
206///
207/// # Naming
208///
209/// The macros with the `try_` prefix are producing fallible write expressions.
210/// The macros with the `e` prefix are proposed to be used with `stderr`-like writers.
211/// The macros with the `c` prefix are proposed to be used
212/// instead of the standard macros
213/// or to shadow the standard macros in the following lines of code.
214///
215/// # Macro ambiguity
216///
217/// When using std-prelude, std macros cannot be replaced in [textual scope] using this macro.
218/// This is a consequence of the ambiguous precedence between
219/// a macro-expanded macro and a macro from the outer scope.
220/// Use alternative names like `cprint`, `ceprint`, `cprintln`, `ceprintln`, `cdbg`,
221/// and then override std macros using proxy macro or use declaration.
222///
223/// Overriding with a proxy macro is a better way because
224/// it overrides macros in [textual scope] and accordingly in all submodules:
225/// ```
226/// custom_print::define_macro!(cprintln, once: crate::write);
227/// macro_rules! println { ($($args:tt)*) => { cprintln!($($args)*); } }
228/// # fn main() {}
229/// mod submodule { /* println is already defined in all submodules */ }
230/// ```
231///
232/// Alternatively, use can override macro in the [path-based scope],
233/// but then it will be necessary not to forget to import macro into submodules scope:
234/// ```
235/// custom_print::define_macro!(cprintln, once: crate::write);
236/// use cprintln as println;
237/// # fn main() {}
238/// mod submodule { use crate::println; /* ... */ }
239/// ```
240///
241/// # Examples
242///
243/// An example with a simple string writer:
244/// ```rust
245/// use core::fmt::Write;
246/// let mut string = String::new();
247/// custom_print::define_macro!(cprint, &mut string);
248///
249/// assert_eq!(cprint!("value"), ());
250/// assert_eq!(string, "value");
251/// ```
252///
253/// An example with an extern functions that takes a UTF-8 chars pointer and byte length
254/// and works in `no_std` context:
255#[cfg_attr(feature = "alloc", doc = "```rust")]
256#[cfg_attr(not(feature = "alloc"), doc = "```rust,compile_fail")]
257/// #![no_std]
258/// extern crate std;
259///
260/// # pub mod ffi {
261/// #     #[no_mangle] pub extern "C" fn console_log(_: *const u8, _: usize) {}
262/// #     #[no_mangle] pub extern "C" fn console_warn(_: *const u8, _: usize) {}
263/// # }
264/// #
265/// custom_print::define_macro!(println,
266///     concat, extern "C" fn console_log(_: *const u8, _: usize));
267/// custom_print::define_macro!(eprintln,
268///     concat, extern "C" fn console_warn(_: *const u8, _: usize));
269///
270/// fn main() {
271///     println!("println");
272///     eprintln!("eprintln");
273/// }
274/// ```
275///
276/// An example with a closure that takes an [`str`] reference in `no_std` and `no_alloc`:
277#[cfg_attr(feature = "std", doc = " ```rust")]
278#[cfg_attr(not(feature = "std"), doc = " ```rust,compile_fail")]
279/// #![no_std]
280/// custom_print::define_macro!(println, fmt, |_value: &str| { /* ... */ });
281///
282/// fn main() {
283///     println!("println");
284/// }
285/// ```
286///
287/// An example with a function that takes a [`c_char`] pointer and overriding
288/// [`std::println`] function:
289#[cfg_attr(feature = "std", doc = "```rust")]
290#[cfg_attr(not(feature = "std"), doc = "```rust,compile_fail")]
291/// fn write(_value: *const std::os::raw::c_char) { /* ... */ }
292///
293/// custom_print::define_macro!(cprintln, concat, crate::write);
294/// macro_rules! println { ($($args:tt)*) => { cprintln!($($args)*); } }
295///
296/// fn main() {
297///     println!("println");
298/// }
299/// ```
300///
301/// An example with `LineWriter` and flushing.
302/// ```rust
303/// use std::io::{self, LineWriter, Write};
304/// use std::sync::Mutex;
305///
306/// let written: Mutex<Vec<u8>> = Mutex::default();
307///
308/// #[derive(Clone, Debug)]
309/// struct CustomWriter<'a>(&'a Mutex<Vec<u8>>);
310///
311/// impl Write for CustomWriter<'_> {
312///     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
313///         let mut written = self.0.lock().unwrap();
314///         written.extend_from_slice(buf);
315///         Ok(buf.len())
316///     }
317///
318///     fn flush(&mut self) -> io::Result<()> {
319///         Ok(())
320///     }
321/// }
322///
323/// let custom_writer = CustomWriter(&written);
324/// let mut line_writer = LineWriter::new(custom_writer);
325///
326/// custom_print::define_macro!(cprint, line_writer);
327/// custom_print::define_macro!(flush, line_writer);
328///
329/// assert_eq!(cprint!("first,"), ());
330/// assert_eq!(*written.lock().unwrap(), b"");
331/// assert_eq!(cprint!("second\nthird,"), ());
332/// assert_eq!(*written.lock().unwrap(), b"first,second\n");
333/// assert_eq!(flush!(), ());
334/// assert_eq!(*written.lock().unwrap(), b"first,second\nthird,");
335/// ```
336///
337/// [`c_char`]: https://doc.rust-lang.org/std/os/raw/type.c_char.html
338/// [textual scope]: https://doc.rust-lang.org/nightly/reference/macros-by-example.html#scoping-exporting-and-importing
339/// [path-based scope]: https://doc.rust-lang.org/nightly/reference/macros-by-example.html#scoping-exporting-and-importing
340/// [`define_writer`]: macro.define_writer.html
341/// [`define_print`]: macro.define_print.html
342/// [`define_println`]: macro.define_println.html
343/// [`define_dbg`]: macro.define_dbg.html
344/// [`define_flush`]: macro.define_flush.html
345/// [`define_try_print`]: macro.define_try_print.html
346/// [`define_try_println`]: macro.define_try_println.html
347/// [`define_try_dbg`]: macro.define_try_dbg.html
348/// [`define_try_flush`]: macro.define_try_flush.html
349#[macro_export]
350macro_rules! define_macro {
351    ( $( #[$meta:meta] )* print       as $name:ident, $( $args:tt )* ) => {
352        $crate::define_print!      ( $( #[$meta] )* $name, $( $args )* )
353    };
354    ( $( #[$meta:meta] )* println     as $name:ident, $( $args:tt )* ) => {
355        $crate::define_println!    ( $( #[$meta] )* $name, $( $args )* )
356    };
357    ( $( #[$meta:meta] )* dbg         as $name:ident, $( $args:tt )* ) => {
358        $crate::define_dbg!        ( $( #[$meta] )* $name, $( $args )* )
359    };
360    ( $( #[$meta:meta] )* flush       as $name:ident, $( $args:tt )* ) => {
361        $crate::define_flush!      ( $( #[$meta] )* $name, $( $args )* )
362    };
363    ( $( #[$meta:meta] )* try_print   as $name:ident, $( $args:tt )* ) => {
364        $crate::define_try_print!  ( $( #[$meta] )* $name, $( $args )* )
365    };
366    ( $( #[$meta:meta] )* try_println as $name:ident, $( $args:tt )* ) => {
367        $crate::define_try_println!( $( #[$meta] )* $name, $( $args )* )
368    };
369    ( $( #[$meta:meta] )* try_dbg     as $name:ident, $( $args:tt )* ) => {
370        $crate::define_try_dbg!    ( $( #[$meta] )* $name, $( $args )* )
371    };
372    ( $( #[$meta:meta] )* try_flush   as $name:ident, $( $args:tt )* ) => {
373        $crate::define_try_flush!  ( $( #[$meta] )* $name, $( $args )* )
374    };
375
376    ( $( #[$meta:meta] )* print,        $( $args:tt )* ) => {
377        $crate::define_print!  ( $( #[$meta] )* print,        $( $args )* );
378    };
379    ( $( #[$meta:meta] )* eprint,       $( $args:tt )* ) => {
380        $crate::define_print!  ( $( #[$meta] )* eprint,       $( $args )* );
381    };
382    ( $( #[$meta:meta] )* cprint,       $( $args:tt )* ) => {
383        $crate::define_print!  ( $( #[$meta] )* cprint,       $( $args )* );
384    };
385    ( $( #[$meta:meta] )* ceprint,      $( $args:tt )* ) => {
386        $crate::define_print!  ( $( #[$meta] )* ceprint,      $( $args )* );
387    };
388    ( $( #[$meta:meta] )* println,      $( $args:tt )* ) => {
389        $crate::define_println!( $( #[$meta] )* println,      $( $args )* );
390    };
391    ( $( #[$meta:meta] )* eprintln,     $( $args:tt )* ) => {
392         $crate::define_println!( $( #[$meta] )* eprintln,     $( $args )* );
393    };
394    ( $( #[$meta:meta] )* cprintln,     $( $args:tt )* ) => {
395        $crate::define_println!( $( #[$meta] )* cprintln,     $( $args )* );
396    };
397    ( $( #[$meta:meta] )* ceprintln,    $( $args:tt )* ) => {
398        $crate::define_println!( $( #[$meta] )* ceprintln,    $( $args )* );
399    };
400    ( $( #[$meta:meta] )* dbg,          $( $args:tt )* ) => {
401        $crate::define_dbg!    ( $( #[$meta] )* dbg,          $( $args )* );
402    };
403    ( $( #[$meta:meta] )* edbg,         $( $args:tt )* ) => {
404        $crate::define_dbg!    ( $( #[$meta] )* edbg,         $( $args )* );
405    };
406    ( $( #[$meta:meta] )* cdbg,         $( $args:tt )* ) => {
407        $crate::define_dbg!    ( $( #[$meta] )* cdbg,         $( $args )* );
408    };
409    ( $( #[$meta:meta] )* flush,        $( $args:tt )* ) => {
410        $crate::define_flush!  ( $( #[$meta] )* flush,        $( $args )* );
411    };
412    ( $( #[$meta:meta] )* eflush,       $( $args:tt )* ) => {
413        $crate::define_flush!  ( $( #[$meta] )* eflush,       $( $args )* );
414    };
415
416    ( $( #[$meta:meta] )* try_print,    $( $args:tt )* ) => {
417        $crate::define_try_print!  ( $( #[$meta] )* try_print,    $( $args )* );
418    };
419    ( $( #[$meta:meta] )* try_eprint,   $( $args:tt )* ) => {
420        $crate::define_try_print!  ( $( #[$meta] )* try_eprint,   $( $args )* );
421    };
422    ( $( #[$meta:meta] )* try_println,  $( $args:tt )* ) => {
423        $crate::define_try_println!( $( #[$meta] )* try_println,  $( $args )* );
424    };
425    ( $( #[$meta:meta] )* try_eprintln, $( $args:tt )* ) => {
426        $crate::define_try_println!( $( #[$meta] )* try_eprintln, $( $args )* );
427    };
428    ( $( #[$meta:meta] )* try_dbg,      $( $args:tt )* ) => {
429        $crate::define_try_dbg!    ( $( #[$meta] )* try_dbg,      $( $args )* );
430    };
431    ( $( #[$meta:meta] )* try_edbg,     $( $args:tt )* ) => {
432        $crate::define_try_dbg!    ( $( #[$meta] )* try_edbg,     $( $args )* );
433    };
434    ( $( #[$meta:meta] )* try_flush,    $( $args:tt )* ) => {
435        $crate::define_try_flush!  ( $( #[$meta] )* try_flush,    $( $args )* );
436    };
437    ( $( #[$meta:meta] )* try_eflush,   $( $args:tt )* ) => {
438        $crate::define_try_flush!  ( $( #[$meta] )* try_eflush,   $( $args )* );
439    };
440}