#Create a macro that uses a library

31 messages · Page 1 of 1 (latest)

ember relic
#

Hello, I want to do something simple. I want to create a macro like this one:

#[macro_export]
macro_rules! print_info {
    ($($arg:tt)*) => {
        use colored::Colorize;

        println!(
        "{} {}",
        "Info:".yellow().bold(),
        $($arg)*);
    };
}

However I get the following error:

the name `Colorize` is defined multiple times `Colorize` must be defined only once in the type namespace of this block

Is there any simple way to import Colorize just one time even if I use the macro multiple times?

open schooner
#

How about

#[macro_export]
macro_rules! print_info {
    ($($arg:tt)*) => {{
        use colored::Colorize;

        println!(
        "{} {}",
        "Info:".yellow().bold(),
        $($arg)*);
    }};
}
#

Or you could use the trait method as a function. Also, if you want it to work like the std format macros, you can use format_args.

#[macro_export]
macro_rules! print_info {
    ($fmt:expr, $($arg:tt)*) => {

        println!(
            "{} {}",
            color::Colorize::bold(color::Colorize::yellow("Info:")),
            format_args!($fmt:expr, $($arg)*)
        );
    };
}
```Otherwise it doesn't really make sense to use multiple `tt` since you can only put one thing there. Just use one `expr` token.
```rust
#[macro_export]
macro_rules! print_info {
    ($arg:expr) => {

        println!(
            "{} {}",
            color::Colorize::bold(color::Colorize::yellow("Info:")),
            $arg
        );
    };
}
ember relic
open schooner
#

Then the format_args one is what you want

ember relic
# open schooner Then the `format_args` one is what you want

I modified it because I think there are some errors:

#[macro_export]
macro_rules! print_info {
    ($fmt:expr, $($arg:tt)*) => {

        println!(
            "{} {}",
            colored::Colorize::bold(colored::Colorize::yellow("Info:")),
            format_args!($fmt, $($arg)*)
        );
    };
}
#

However, I have a new error:
unexpected end of macro invocation missing tokens in macro arguments

open schooner
#

You probably need to add a format string:

print_info!("{}", message);
ember relic
#

Maybe I should check println! internal code?

#

Okay, I think this works:

#[macro_export]
macro_rules! print_info {
    ($($arg:tt)*) => {

        println!(
            "{} {}",
            colored::Colorize::bold(colored::Colorize::yellow("Info:")),
            format!($($arg)*)
        );
    }
}
open schooner
#

This will only work for string literals

#

it also makes a String unecessarily, which is what format_args avoids

#

You can either only allow one argument, or you can allow multiple, but require the format string.

ember relic
#

Then how println! works? There is 1 macro for just 1 argument and another one for multiple?

#

Something like this?

#[macro_export]
macro_rules! print_info {
    ($arg:expr) => {

        println!(
            "{} {}",
            colored::Colorize::bold(colored::Colorize::yellow("Info:")),
            $arg
        );
    };
    ($fmt:expr, $($arg:tt)*) => {

        println!(
            "{} {}",
            colored::Colorize::bold(colored::Colorize::yellow("Info:")),
            format_args!($fmt, $($arg)*)
        );
    };
}
open schooner
#

It always requires a format string

cedar nexus
open schooner
#

No, actually it does have a branch for a single arg. It's still expr for some reason though.

ember relic
open schooner
#

jk that's only format_args... idk why they're different

#

yeah

ember relic
#

At least it is working 🙂

#

Now I am trying to do a similar one but with panic!

#

And I get this error:
trailing semicolon in macro used in expression position
this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

#

Okay sorry, this is because I am using the macro inside a match

#

Maybe I should open a new post asking the best way to do this

open schooner
#

Here's the print_info but cleaned up

#[macro_export]
macro_rules! print_info {
    ($($arg:tt)*) => {

        println!(
            "{} {}",
            colored::Colorize::bold(colored::Colorize::yellow("Info:")),
            format_args!($($arg)*)
        );
    };
}
#

Panic should be basically the same

ember relic
#

Thank you very much!

ember relic