Macro custom_print::define_macros[][src]

macro_rules! define_macros {
    ( { $( $template:ident $(as $name:ident)? ),* $(,)? }, $($args:tt)* ) => { ... };
}
Expand description

Defines multiple print-like and dbg-like macros.

The first argument braced in curly braces and contains comma-seperated macro template names and optionally their custom macro names. See the define_macro declaration for the list of available templates. The rest tokens specified in $($args)* are used as input for define_writer macro.

Depending on the specified templates, the macro uses define_print, define_println, define_dbg, define_flush, define_try_print, define_try_println, define_try_dbg or define_try_flush for each generated macro.

If you need to define a single print-like or dbg-like macro, use define_macro.

Macro ambiguity

When using std-prelude, std macros cannot be replaced in textual scope using this macro. This is a consequence of the ambiguous precedence between a macro-expanded macro and a macro from the outer scope. Use alternative names like cprint, ceprint, cprintln, ceprintln, cdbg, and then override std macros using proxy macro or use declaration.

Overriding with a proxy macro is a better way because it overrides macros in textual scope and accordingly in all submodules:

custom_print::define_macros!({ cprint, cprintln }, once: crate::write);
macro_rules! print { ($($args:tt)*) => { cprint!($($args)*); } }
macro_rules! println { ($($args:tt)*) => { cprintln!($($args)*); } }
mod submodule { /* println is already defined in all submodules */ }

Alternatively, use can rebind macro from the textual scope to the path-based scope, but then it will be necessary not to forget to import macro into submodules scope:

custom_print::define_macros!({ cprint, cprintln }, once: crate::write);
use cprint as print;
use cprintln as println;
mod submodule { use crate::{print, println}; /* ... */ }

Examples

An example with a simple string writer:

use core::fmt::Write;
let mut string = String::new();
custom_print::define_macros!({ cprint, cprintln }, &mut string);

assert_eq!(cprintln!("first"), ());
assert_eq!(string, "first\n");
assert_eq!(cprint!("second"), ());
assert_eq!(string, "first\nsecond");

An example with an extern functions that takes a UTF-8 chars pointer and byte length and works in no_std context:

#![no_std]
extern crate std;

custom_print::define_macros!({ print, println },
    concat, extern "C" fn console_log(_: *const u8, _: usize));
custom_print::define_macros!({ eprint, eprintln, dbg },
    concat, extern "C" fn console_warn(_: *const u8, _: usize));

fn main() {
    println!("println");
    print!("print");
    eprintln!("eprintln");
    eprint!("eprint");
    dbg!("dbg");
}

An example with a closure that takes an str reference in no_std and no_alloc:

#![no_std]
custom_print::define_macros!({ print, println }, fmt, |_value: &str| { /* ... */ });

fn main() {
   println!("println");
   print!("print");
}

An example with a function that takes a c_char pointer and overriding std::print and std::println functions:

fn write(_value: *const std::os::raw::c_char) { /* ... */ }

custom_print::define_macros!({ cprint, cprintln }, concat, crate::write);
macro_rules! print { ($($args:tt)*) => { cprint!($($args)*); } }
macro_rules! println { ($($args:tt)*) => { cprintln!($($args)*); } }

fn main() {
    println!("println");
    print!("print");
}

An example with LineWriter and flushing.

use std::io::{self, LineWriter, Write};
use std::sync::Mutex;

let written: Mutex<Vec<u8>> = Mutex::default();

#[derive(Clone, Debug)]
struct CustomWriter<'a>(&'a Mutex<Vec<u8>>);

impl Write for CustomWriter<'_> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut written = self.0.lock().unwrap();
        written.extend_from_slice(buf);
        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

let custom_writer = CustomWriter(&written);
let mut line_writer = LineWriter::new(custom_writer);

custom_print::define_macros!({cprint, flush}, line_writer);

assert_eq!(cprint!("first,"), ());
assert_eq!(*written.lock().unwrap(), b"");
assert_eq!(cprint!("second\nthird,"), ());
assert_eq!(*written.lock().unwrap(), b"first,second\n");
assert_eq!(flush!(), ());
assert_eq!(*written.lock().unwrap(), b"first,second\nthird,");