format-attr 0.2.1

a custom derive to implement Debug/Display easy
Documentation
use format_attr::{DebugAttr, DisplayAttr};

// Test: {field} syntax - inline field names in format string
#[derive(DisplayAttr, DebugAttr)]
#[fmt("Point({x}, {y})")]
struct Point {
    x: i32,
    y: i32,
}

// Test: {field} with format specifiers
#[derive(DisplayAttr, DebugAttr)]
#[fmt("Name: {name}, Age: {age:?}")]
struct Person {
    name: String,
    age: u32,
}

// Test: {field} with method call in explicit arg
#[derive(DisplayAttr, DebugAttr)]
#[fmt("Name: {name} (upper: {})", self.name.to_uppercase())]
struct Employee {
    name: String,
}

// Test: {field} with width and alignment
#[derive(DisplayAttr, DebugAttr)]
#[fmt("{name:>10} | {value:<5}")]
struct Item {
    name: String,
    value: i32,
}

// Test: separate fmt_display and fmt_debug with {field}
#[derive(DisplayAttr, DebugAttr)]
#[fmt_display("User: {name}")]
#[fmt_debug("User {{ name: {name}, age: {age} }}")]
struct User {
    name: String,
    age: u32,
}

// Test: Generic struct with {field}
#[derive(DisplayAttr, DebugAttr)]
#[fmt("Wrapper({value})")]
struct Wrapper<T: std::fmt::Display> {
    value: T,
}

// Test: Multiple {field} references
#[derive(DisplayAttr, DebugAttr)]
#[fmt("{first} {last}")]
struct FullName {
    first: String,
    last: String,
}

// Test: Escaped braces should work
#[derive(DisplayAttr, DebugAttr)]
#[fmt("{{ {name} }}")]
struct BracedName {
    name: String,
}

// Test: Empty {} still works with explicit args
#[derive(DisplayAttr, DebugAttr)]
#[fmt("Value: {}", value)]
struct SimpleValue {
    value: i32,
}

#[test]
fn test_point_inline_fields() {
    let p = Point { x: 10, y: 20 };
    assert_eq!(format!("{}", p), "Point(10, 20)");
    assert_eq!(format!("{:?}", p), "Point(10, 20)");
}

#[test]
fn test_person_with_format_spec() {
    let p = Person {
        name: "Alice".to_string(),
        age: 30,
    };
    assert_eq!(format!("{}", p), "Name: Alice, Age: 30");
}

#[test]
fn test_employee_mixed_syntax() {
    let e = Employee {
        name: "Bob".to_string(),
    };
    assert_eq!(format!("{}", e), "Name: Bob (upper: BOB)");
}

#[test]
fn test_item_with_width_alignment() {
    let i = Item {
        name: "Apple".to_string(),
        value: 42,
    };
    assert_eq!(format!("{}", i), "     Apple | 42   ");
}

#[test]
fn test_user_separate_inline() {
    let u = User {
        name: "Charlie".to_string(),
        age: 35,
    };
    assert_eq!(format!("{}", u), "User: Charlie");
    assert_eq!(format!("{:?}", u), "User { name: Charlie, age: 35 }");
}

#[test]
fn test_wrapper_inline() {
    let w = Wrapper { value: 100 };
    assert_eq!(format!("{}", w), "Wrapper(100)");
}

#[test]
fn test_full_name() {
    let n = FullName {
        first: "John".to_string(),
        last: "Doe".to_string(),
    };
    assert_eq!(format!("{}", n), "John Doe");
}

#[test]
fn test_escaped_braces() {
    let b = BracedName {
        name: "test".to_string(),
    };
    assert_eq!(format!("{}", b), "{ test }");
}

#[test]
fn test_empty_brace_with_explicit_arg() {
    let v = SimpleValue { value: 42 };
    assert_eq!(format!("{}", v), "Value: 42");
}