nekoprint 0.1.6

nekoprint is a powerful procedural macro for Rust that automatically generates printing methods for a struct's fields and the entire struct itself. It lets you create fluid, asynchronous logs with different severity levels using a simple, chained syntax. This library is ideal for debugging, monitoring, and diagnostics in Rust applications, especially those using async/await.
Documentation

nekoprint

Crates.io Docs.rs License GitHub top language GitHub stars GitHub forks Tests Crates.io downloads GitHub last commit

nekoprint is a powerful procedural macro for Rust that automatically generates printing methods for a struct's fields and the entire struct itself. It lets you create fluid, asynchronous logs with different severity levels using a simple, chained syntax.

This library is ideal for debugging, monitoring, and diagnostics in Rust applications, especially those using async/await.


✨ Features

  • Automatic Generation: Creates methods like print_field() and print() for every decorated struct.
  • Customizable Transporters: Define your own message transport logic using the #[transporter] attribute.
  • Integrated Log Levels: Built-in support for the following fluid log levels:
    • .err()
    • .info()
    • .success()
    • .warning()
    • .critical()
    • .panic()
    • .rust() (useful for standard debug logs)
  • Personalized Messages: Add specific log messages to each call with the .message() method.
  • async/await Compatible: Fully integrated with the tokio ecosystem.

⚙️ Installation

Add nekoprint to your Cargo.toml:

cargo add nekoprint

Make sure the nekoprint macro is in scope.


🚀 Usage

Defining Your Struct

Decorate your struct with #[derive(NekoPrint)] and use the #[transporter] attribute to define how the log message will be processed. The transporter is an async function that takes a message variable (a CString).

use nekoprint::NekoPrint;

#[derive(Debug, NekoPrint, Default, Clone)]
#[transporter(async fn procedure() {
    println!("{message}");
    let m = message.to_string();
    assert!(
        m.contains("message")
    );
})]
pub struct User {
    id: i32,
    name: String,
    friend: Friend,
}

#[derive(Debug, NekoPrint, Default, Clone)]
#[transporter(async fn procedure() {
    println!("{message}");
    let m = message.to_string();
    assert!(
        m.contains("message")
    );
})]
pub struct Friend {
    id: i32,
    name: String,
}

Full Usage Example

The NekoPrint macro generates methods like print_id(), print_name(), and print() for the User and Friend structs. You can then chain the .message() and .level() methods to customize the output.

#[tokio::test]
async fn test_print_user() {
    let user = User {
        id: 1,
        name: "name".into(),
        friend: Friend {
            id: 1,
            name: "name".into(),
        },
    };

    // Print the `id` field with different log levels
    user.print_id().message("custom message for id").err().await;
    user.print_id().message("info id message").info().await;
    user.print_id().message("success id message").success().await;
    user.print_id().message("warning id message").warning().await;
    user.print_id().message("critical id message").critical().await;
    user.print_id().message("panic id message").panic().await;
    user.print_id().message("rust debug id message").rust().await;

    // Print the `name` field with different log levels
    user.print_name().message("custom message for name").err().await;
    user.print_name().message("info name message").info().await;
    user.print_name().message("success name message").success().await;
    user.print_name().message("warning name message").warning().await;
    user.print_name().message("critical name message").critical().await;
    user.print_name().message("panic name message").panic().await;
    user.print_name().message("rust debug name message").rust().await;

    // Print the entire struct with different log levels
    user.print().message("custom message for all").err().await;
    user.print().message("custom message for all").info().await;
    user.print().message("custom message for all").success().await;
    user.print().message("custom message for all").warning().await;
    user.print().message("custom message for all").panic().await;
    user.print().message("custom message for all").critical().await;
    user.print().message("custom message for all").rust().await;
}