Skip to main content

easy_macros_helpers/
context.rs

1#[doc(hidden)]
2pub use context_internal::{context_internal, context_internal2};
3
4#[macro_export]
5/// Creates a closure that generates context strings for error handling with automatic file and line information.
6///
7/// This macro provides a convenient way to add context to errors when using the [anyhow](https://crates.io/crates/anyhow)
8/// crate's `.with_context()` method. It automatically prepends the current file name and line number to your
9/// context message, making error tracking much easier during debugging.
10///
11/// The macro supports the same syntax as the standard [`format!`] macro, allowing for formatted context messages
12/// with placeholders and arguments. When no arguments are provided, it creates a simple context with just
13/// file and line information.
14///
15/// # Syntax
16///
17/// ```ignore
18/// context!()                          // Just file:line info
19/// context!("message")                 // Static message with file:line
20/// context!("format {}", arg)          // Formatted message with file:line
21/// context!("multiple {} {}", a, b)    // Multiple format arguments
22/// context!("multiple {a} {b}")        // All things that format! supports are supported here too
23/// ```
24///
25/// # Returns
26///
27/// Returns a closure of type `impl FnOnce() -> String` that can be passed directly to
28/// anyhow's `.with_context()` method or called manually to get the formatted context string.
29///
30/// # Output Format
31///
32/// The context macro produces strings in the following exact formats:
33///
34/// - **With no message:** `"src/file.rs:line_number"`  
35///   Example: `"src/main.rs:42"`
36///
37/// - **With message:** `"src/file.rs:line_number\r\nYour custom message here"`  
38///   Example: `"src/main.rs:42\r\nOperation failed"`
39///
40/// The file path includes the `src/` prefix and the line number is automatically determined
41/// at compile time using the [`file!`] and [`line!`] macros. Messages are separated from
42/// the location info with a carriage return + line feed (`\r\n`) sequence.
43///
44/// # Examples
45///
46/// ## Basic Usage
47///
48#[doc = docify::embed!("src/examples.rs", context_basic_usage_example)]
49///
50/// ## With Custom Messages
51///
52#[doc = docify::embed!("src/examples.rs", context_with_custom_message_example)]
53///
54/// ## With Formatted Messages
55///
56#[doc = docify::embed!("src/examples.rs", context_with_formatted_message_example)]
57///
58/// ## Chaining Multiple Context Levels
59///
60#[doc = docify::embed!("src/examples.rs", context_chaining_multiple_levels_example)]
61///
62/// ## Manual Context Generation
63///
64#[doc = docify::embed!("src/examples.rs", context_manual_generation_example)]
65///
66/// # See Also
67///
68/// - [`anyhow::Context`](https://docs.rs/anyhow/latest/anyhow/trait.Context.html) - The trait that provides the `.with_context()` method
69/// - [`format!`] - The standard formatting macro that this macro's syntax is based on
70/// - [`file!`] and [`line!`] - The macros used internally to get location information
71macro_rules! context {
72    () => {
73        || {
74            $crate::context_internal!()
75        }
76    };
77    ($($arg:tt)*) => {
78        || {
79            // Adds syntax checking from format! macro
80            let _ = || {
81                let _ = format!($($arg)*);
82            };
83            $crate::context_internal!($($arg)*)
84        }
85    };
86}