Skip to content

NaturalIO/format-attr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

format-attr

document: https://docs.rs/format-attr

A Rust proc-macro crate that provides custom derive macros for implementing Display and Debug traits with custom format strings.

Features

  • DisplayAttr - Derive std::fmt::Display with a custom format string
  • DebugAttr - Derive std::fmt::Debug with a custom format string
  • DisplayAsDebug - Implement Display by delegating to the existing Debug implementation
  • Support for separate format strings via #[fmt_display(...)] and #[fmt_debug(...)]
  • Fallback to shared #[fmt(...)] attribute

Usage

Add this to your Cargo.toml:

[dependencies]
format-attr = "0"

Basic Example

use format_attr::{DisplayAttr, DebugAttr};

#[derive(DisplayAttr, DebugAttr)]
#[fmt("Point({}, {})", x, y)]  // `self.` prefix is optional for simple field access
struct Point {
    x: i32,
    y: i32,
}

let p = Point { x: 10, y: 20 };
assert_eq!(format!("{}", p), "Point(10, 20)");
assert_eq!(format!("{:?}", p), "Point(10, 20)");

Note: You can omit the self. prefix for simple field names. If you need to call methods or use complex expressions, you can still use self.field.method() syntax.

Inline Field Names

You can also use field names directly inside the format string:

use format_attr::{DisplayAttr, DebugAttr};

#[derive(DisplayAttr, DebugAttr)]
#[fmt("Point({x}, {y})")]  // {x} and {y} are automatically replaced with field values
struct Point {
    x: i32,
    y: i32,
}

let p = Point { x: 10, y: 20 };
assert_eq!(format!("{}", p), "Point(10, 20)");

Format specifiers are also supported:

use format_attr::DisplayAttr;

#[derive(DisplayAttr)]
#[fmt("Name: {name:>10}, Age: {age:?}")]
struct Person {
    name: String,
    age: u32,
}

let p = Person { name: "Alice".to_string(), age: 30 };
assert_eq!(format!("{}", p), "Name:      Alice, Age: 30");

Separate Format Strings

Use #[fmt_display(...)] and #[fmt_debug(...)] for different output:

use format_attr::{DisplayAttr, DebugAttr};

#[derive(DisplayAttr, DebugAttr)]
#[fmt_display("User: {}", name)]
#[fmt_debug("User {{ name: {}, age: {} }}", name, age)]
struct User {
    name: String,
    age: u32,
}

let u = User { name: "Alice".to_string(), age: 30 };
assert_eq!(format!("{}", u), "User: Alice");
assert_eq!(format!("{:?}", u), "User { name: Alice, age: 30 }");

DisplayAsDebug

When you want Display to use the same output as Debug:

use format_attr::DisplayAsDebug;

#[derive(Debug, DisplayAsDebug)]
struct Value(i32);

let v = Value(42);
assert_eq!(format!("{}", v), "Value(42)");
assert_eq!(format!("{:?}", v), "Value(42)");

Attribute Priority

Derive Macro Priority 1 Priority 2 (fallback)
DisplayAttr #[fmt_display(...)] #[fmt(...)]
DebugAttr #[fmt_debug(...)] #[fmt(...)]

License

MIT

About

a custom derive to impl Debug and Display more easily

Resources

Stars

Watchers

Forks