1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
use proc_macro::TokenStream;

/// Lazy format macro
///
/// The first form receives closure as the only one argument.
///
/// ```
/// # #![feature(proc_macro_hygiene)]
/// # use format_core as format;
/// # use format_macro::lazy_format;
/// let a = "a";
/// lazy_format!(|f| write!(f, "{}", a));
/// ```
///
/// The second form is syntax sugar of the first form which is a closure with
/// the only one [write](std::write) macro. Its syntax is identical to the
/// [format](std::fmt::format) syntax.
///
/// ```
/// # #![feature(proc_macro_hygiene)]
/// # use format_core as format;
/// # use format_macro::lazy_format;
/// let a = "a";
/// lazy_format!("{}", a);
/// ```
///
/// The second form inferences the output format.
///
/// Format inference rules:
///
/// - has only [Debug](core::fmt::Debug) formats - Debug
/// - has formats of only one kind from: [Binary](core::fmt::Binary),
///   [LowerExp](core::fmt::LowerExp), [LowerHex](core::fmt::LowerHex),
///   [Octal](core::fmt::Octal), [Pointer](core::fmt::Pointer),
///   [UpperExp](core::fmt::UpperExp) or [UpperHex](core::fmt::UpperHex) -
///   Binary, LowerExp, LowerHex, Octal, Pointer, UpperExp or UpperHex
///   respectively
/// - otherwise - Display
///
/// # Examples
///
/// Nested Debug help struct example
///
/// ```
/// #![feature(proc_macro_hygiene)]
///
/// # mod format {
/// #     pub use format_core::*;
/// #     pub use format_macro::lazy_format;
/// # }
/// # use std::format;
/// use core::fmt::{Debug, Formatter, Result};
/// use format::lazy_format;
///
/// struct Foo {
///     bar: [u32; 10],
/// }
///
/// impl Debug for Foo {
///     fn fmt(&self, f: &mut Formatter) -> Result {
///         let bar = lazy_format!(|f| f.debug_list().entries(&self.bar).finish());
///         f.debug_struct("Foo")
///             .field("bar", &format_args!("{}", bar))
///             .finish()
///     }
/// }
///
/// assert_eq!(
///     "Foo { bar: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] }",
///     format!("{:?}", Foo { bar: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] })
/// );
/// ```
///
/// Control flow example
///
/// ```
/// #![feature(proc_macro_hygiene)]
///
/// # mod format {
/// #     pub use format_core::*;
/// #     pub use format_macro::lazy_format;
/// # }
/// # use std::format;
/// use core::fmt::{Debug, Formatter, Result};
/// use format::lazy_format;
///
/// struct Foo(usize);
///
/// impl Debug for Foo {
///     fn fmt(&self, f: &mut Formatter) -> Result {
///         let alternate = f.alternate();
///         let bar = lazy_format!(|f| if alternate {
///             write!(f, "{:#x}", self.0)
///         } else {
///             write!(f, "{:x}", self.0)
///         });
///         f.debug_tuple("Foo")
///             .field(&format_args!("{}", bar))
///             .finish()
///     }
/// }
///
/// assert_eq!("Foo(75bcd15)", format!("{:?}", Foo(0123456789)));
/// assert_eq!("Foo(\n    0x75bcd15,\n)", format!("{:#?}", Foo(0123456789)));
/// ```
#[proc_macro]
pub fn lazy_format(input: TokenStream) -> TokenStream {
    lazy_format::proc_macro(input)
}

mod lazy_format;