clap_version_flag/
macros.rs

1// Project: clap-version-flag
2// File: src/macros.rs
3// Author: Hadi Cahyadi <cumulus13@gmail.com>
4// Date: 2025-12-12
5// Description: Main and helper macros for clap-version-flag
6// License: MIT
7
8//! Macros for creating and working with `ColorfulVersion`
9//!
10//! This module contains the main `colorful_version!` macro and
11//! additional helper macros for ease of use.
12
13/// Main macro for easy creation of ColorfulVersion from Cargo.toml
14///
15/// **IMPORTANT**: This macro uses `env!()` which expands at the caller's location,
16/// so it will correctly pick up the caller's package information, not this library's.
17///
18/// # Examples
19/// ```
20/// use clap_version_flag::colorful_version;
21///
22/// // With default colors - gets info from YOUR Cargo.toml
23/// let version = colorful_version!();
24/// println!("{}", version); // Prints: your-app-name v1.0.0 by Your Name
25///
26/// // With custom hex colors
27/// let version = colorful_version!("#FFFFFF", "#AA00FF", "#FFFF00", "#00FFFF");
28/// ```
29#[macro_export]
30macro_rules! colorful_version {
31    () => {
32        // env!() expands at the CALLER's location, not here!
33        // This means it will read from the caller's Cargo.toml
34        $crate::ColorfulVersion::new(
35            env!("CARGO_PKG_NAME"),
36            env!("CARGO_PKG_VERSION"),
37            env!("CARGO_PKG_AUTHORS"),
38        )
39    };
40
41    ($name_fg:expr, $name_bg:expr, $version:expr, $author:expr) => {
42        $crate::ColorfulVersion::new(
43            env!("CARGO_PKG_NAME"),
44            env!("CARGO_PKG_VERSION"),
45            env!("CARGO_PKG_AUTHORS"),
46        )
47        .with_hex_colors($name_fg, $name_bg, $version, $author)
48        .unwrap_or_else(|e| panic!("clap-version-flag: Invalid hex color format: {}", e))
49    };
50}
51
52/// Macro to create a colorful version with complete configuration
53///
54/// # Examples
55///
56/// ## Create with custom values
57/// ```
58/// use clap_version_flag::colorful_version_full;
59///
60/// let version = colorful_version_full!("myapp", "1.0.0", "John Doe");
61/// assert_eq!(version.package_name(), "myapp");
62/// ```
63///
64/// ## Create with custom values and colors
65/// ```
66/// use clap_version_flag::colorful_version_full;
67///
68/// let version = colorful_version_full!(
69///     "myapp", "1.0.0", "John Doe",
70///     "#FFFFFF", "#AA00FF", "#FFFF00", "#00FFFF"
71/// );
72/// ```
73#[macro_export]
74macro_rules! colorful_version_full {
75    ($name:expr, $version:expr, $author:expr) => {
76        $crate::ColorfulVersion::new($name, $version, $author)
77    };
78
79    ($name:expr, $version:expr, $author:expr,
80     $name_fg:expr, $name_bg:expr, $version_color:expr, $author_color:expr) => {
81        $crate::ColorfulVersion::new($name, $version, $author)
82            .with_hex_colors($name_fg, $name_bg, $version_color, $author_color)
83            .expect("Invalid hex color format")
84    };
85}
86
87/// Macro to create a colorful version with RGB colors
88///
89/// # Examples
90/// ```
91/// use clap_version_flag::colorful_version_rgb;
92///
93/// let version = colorful_version_rgb!(
94///     (255, 255, 255),  // name foreground
95///     (170, 0, 255),    // name background
96///     (255, 255, 0),    // version color
97///     (0, 255, 255)     // author color
98/// );
99/// ```
100#[macro_export]
101macro_rules! colorful_version_rgb {
102    ($name_fg:expr, $name_bg:expr, $version:expr, $author:expr) => {
103        $crate::ColorfulVersion::new(
104            env!("CARGO_PKG_NAME"),
105            env!("CARGO_PKG_VERSION"),
106            env!("CARGO_PKG_AUTHORS"),
107        )
108        .with_rgb_colors($name_fg, $name_bg, $version, $author)
109    };
110}
111
112/*
113NOTE: derive_colorful_version macro is commented out for now.
114It requires more complex implementation with trait bounds.
115Will be added in future version if there's demand.
116
117/// Macro for derive helper to add colorful version to your CLI struct
118///
119/// This is useful if you want to add version functionality directly to your CLI struct.
120///
121/// # Examples
122/// ```ignore
123/// use clap::Parser;
124/// use clap_version_flag::derive_colorful_version;
125///
126/// #[derive(Parser)]
127/// struct Cli {
128///     name: String,
129/// }
130///
131/// derive_colorful_version!(Cli);
132///
133/// fn main() {
134///     let version = Cli::colorful_version();
135///     version.print();
136/// }
137/// ```
138#[macro_export]
139macro_rules! derive_colorful_version {
140    ($struct_name:ident) => {
141        impl $struct_name {
142            /// Get colorful version for this CLI application
143            ///
144            /// This method returns a `ColorfulVersion` instance using the
145            /// information from your `Cargo.toml` file.
146            pub fn colorful_version() -> $crate::ColorfulVersion {
147                $crate::colorful_version!()
148            }
149
150            /// Parse command with automatic colorful version handling
151            ///
152            /// This method combines parsing and version handling in one call.
153            /// If the user passes `--version` or `-V`, it will print the
154            /// colorful version and exit.
155            ///
156            /// # Errors
157            ///
158            /// Returns an error if clap fails to parse the arguments.
159            pub fn parse_with_colorful_version() -> Result<Self, clap::Error>
160            where
161                Self: clap::FromArgMatches + clap::CommandFactory,
162            {
163                let version = Self::colorful_version();
164                $crate::parse_with_version(Self::command(), &version)
165            }
166        }
167    };
168}
169*/
170
171#[cfg(test)]
172mod tests {
173    // use crate::ColorfulVersion;
174
175    #[test]
176    fn test_colorful_version_full_without_colors() {
177        let version = colorful_version_full!("testapp", "1.0.0", "Test Author");
178        assert_eq!(version.package_name(), "testapp");
179        assert_eq!(version.version(), "1.0.0");
180        assert_eq!(version.author(), "Test Author");
181    }
182
183    #[test]
184    fn test_colorful_version_full_with_colors() {
185        let version = colorful_version_full!(
186            "testapp",
187            "1.0.0",
188            "Test Author",
189            "#FFFFFF",
190            "#AA00FF",
191            "#FFFF00",
192            "#00FFFF"
193        );
194        assert_eq!(version.package_name(), "testapp");
195    }
196
197    #[test]
198    fn test_colorful_version_rgb() {
199        let version = colorful_version_rgb!((255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0));
200        // This will use env! so it gets the crate's own name in tests
201        assert_eq!(version.package_name(), env!("CARGO_PKG_NAME"));
202    }
203}