Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: add from_cargo_metadata macro #208

Merged
merged 3 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/from_cargo_metadata_macro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"muda": "minor"
---

Added `about_metadata` module and `about_metadata::from_cargo_metadata` macro.
5 changes: 5 additions & 0 deletions .changes/from_cargo_metadata_removal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"muda": "minor"
---

**Breaking Change** Removed `AboutMetadata::from_cargo_metadata` and `AboutMetadataBuilder::with_cargo_metadata` which had incorrect implementation, use the new `about_metadata::from_cargo_metadata` macro instead.
65 changes: 34 additions & 31 deletions src/about_metadata.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Types and functions to create [`AboutMetadata`] for the [`PredefinedMenuItem::about`](crate::PredefinedMenuItem::about) dialog.

use crate::icon::Icon;

/// Application metadata for the [`PredefinedMenuItem::about`](crate::PredefinedMenuItem::about).
/// Application metadata for the [`PredefinedMenuItem::about`](crate::PredefinedMenuItem::about) dialog.
#[derive(Debug, Clone, Default)]
pub struct AboutMetadata {
/// Sets the application name.
Expand Down Expand Up @@ -70,43 +72,49 @@ impl AboutMetadata {
.unwrap_or_default()
))
}
}

/// Creates [`AboutMetadata`] from [Cargo metadata][cargo]. The following fields are set by this function.
///
/// - [`AboutMetadata::name`] (from `CARGO_PKG_NAME`)
/// - [`AboutMetadata::version`] (from `CARGO_PKG_VERSION`)
/// - [`AboutMetadata::short_version`] (from `CARGO_PKG_VERSION_MAJOR` and `CARGO_PKG_VERSION_MINOR`)
/// - [`AboutMetadata::authors`] (from `CARGO_PKG_AUTHORS`)
/// - [`AboutMetadata::comments`] (from `CARGO_PKG_DESCRIPTION`)
/// - [`AboutMetadata::license`] (from `CARGO_PKG_LICENSE`)
/// - [`AboutMetadata::website`] (from `CARGO_PKG_HOMEPAGE`)
///
/// [cargo]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates
pub fn from_cargo_metadata() -> Self {
/// Creates [`AboutMetadata`] from [Cargo metadata][cargo]. The following fields are set by this function.
///
/// - [`AboutMetadata::name`] (from `CARGO_PKG_NAME`)
/// - [`AboutMetadata::version`] (from `CARGO_PKG_VERSION`)
/// - [`AboutMetadata::short_version`] (from `CARGO_PKG_VERSION_MAJOR` and `CARGO_PKG_VERSION_MINOR`)
/// - [`AboutMetadata::authors`] (from `CARGO_PKG_AUTHORS`)
/// - [`AboutMetadata::comments`] (from `CARGO_PKG_DESCRIPTION`)
/// - [`AboutMetadata::license`] (from `CARGO_PKG_LICENSE`)
/// - [`AboutMetadata::website`] (from `CARGO_PKG_HOMEPAGE`)
///
/// [cargo]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates
#[macro_export]
#[doc(hidden)]
macro_rules! from_cargo_metadata {
() => {{
#[allow(unused_mut)]
let mut m = Self {
name: Some(env!("CARGO_PKG_NAME").into()),
version: Some(env!("CARGO_PKG_VERSION").into()),
short_version: Some(format!(
let mut m = $crate::about_metadata::AboutMetadata {
name: Some(::std::env!("CARGO_PKG_NAME").into()),
version: Some(::std::env!("CARGO_PKG_VERSION").into()),
short_version: Some(::std::format!(
"{}.{}",
env!("CARGO_PKG_VERSION_MAJOR"),
env!("CARGO_PKG_VERSION_MINOR"),
)),
..Default::default()
..::std::default::Default::default()
};

#[cfg(not(target_os = "macos"))]
{
let authors = env!("CARGO_PKG_AUTHORS")
.split(';')
.map(|a| a.trim().to_string())
.collect::<Vec<_>>();
.collect::<::std::vec::Vec<_>>();

m.authors = if !authors.is_empty() {
Some(authors)
} else {
None
};

#[inline]
fn non_empty(s: &str) -> Option<String> {
if !s.is_empty() {
Some(s.to_string())
Expand All @@ -115,15 +123,17 @@ impl AboutMetadata {
}
}

m.comments = non_empty(env!("CARGO_PKG_DESCRIPTION"));
m.license = non_empty(env!("CARGO_PKG_LICENSE"));
m.website = non_empty(env!("CARGO_PKG_HOMEPAGE"));
m.comments = non_empty(::std::env!("CARGO_PKG_DESCRIPTION"));
m.license = non_empty(::std::env!("CARGO_PKG_LICENSE"));
m.website = non_empty(::std::env!("CARGO_PKG_HOMEPAGE"));
}

m
}
}};
}

pub use from_cargo_metadata;

/// A builder type for [`AboutMetadata`].
#[derive(Clone, Debug, Default)]
pub struct AboutMetadataBuilder(AboutMetadata);
Expand All @@ -133,12 +143,6 @@ impl AboutMetadataBuilder {
Default::default()
}

/// Creates [`AboutMetadataBuilder`] with Cargo metadata.
/// See [`AboutMetadata::from_cargo_metadata`] for more details.
pub fn with_cargo_metadata() -> Self {
Self(AboutMetadata::from_cargo_metadata())
}

/// Sets the application name.
pub fn name<S: Into<String>>(mut self, name: Option<S>) -> Self {
self.0.name = name.map(|s| s.into());
Expand Down Expand Up @@ -235,11 +239,10 @@ impl AboutMetadataBuilder {

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_build_from_metadata() {
let m = AboutMetadata::from_cargo_metadata();
let m = from_cargo_metadata!();
assert_eq!(m.name, Some("muda".to_string()));
assert!(m.version.is_some());
assert!(m.short_version.is_some());
Expand Down
8 changes: 4 additions & 4 deletions src/accelerator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
//! Accelerators describe keyboard shortcuts for menu items.
//!
//! [`Accelerator`s](crate::accelerator::Accelerator) are used to define a keyboard shortcut consisting
//! of an optional combination of modifier keys (provided by [`Modifiers`](crate::accelerator::Modifiers)) and
//! one key ([`Code`](crate::accelerator::Code)).
//! of an optional combination of modifier keys (provided by [`Modifiers`]) and
//! one key ([`Code`]).
//!
//! # Examples
//! They can be created directly
Expand Down Expand Up @@ -46,8 +46,8 @@ pub enum AcceleratorParseError {
}

/// A keyboard shortcut that consists of an optional combination
/// of modifier keys (provided by [`Modifiers`](crate::accelerator::Modifiers)) and
/// one key ([`Code`](crate::accelerator::Code)).
/// of modifier keys (provided by [`Modifiers`] and
/// one key ([`Code`]).
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Accelerator {
Expand Down
4 changes: 2 additions & 2 deletions src/items/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl CheckMenuItem {
/// Create a new check menu item.
///
/// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
/// for this check menu item. To display a `&` without assigning a mnemenonic, use `&&`.
/// for this check menu item. To display a `&` without assigning a mnemenonic, use `&&`.
pub fn new<S: AsRef<str>>(
text: S,
enabled: bool,
Expand All @@ -60,7 +60,7 @@ impl CheckMenuItem {
/// Create a new check menu item with the specified id.
///
/// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
/// for this check menu item. To display a `&` without assigning a mnemenonic, use `&&`.
/// for this check menu item. To display a `&` without assigning a mnemenonic, use `&&`.
pub fn with_id<I: Into<MenuId>, S: AsRef<str>>(
id: I,
text: S,
Expand Down
4 changes: 2 additions & 2 deletions src/items/icon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl IconMenuItem {
/// Create a new icon menu item.
///
/// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
/// for this icon menu item. To display a `&` without assigning a mnemenonic, use `&&`.
/// for this icon menu item. To display a `&` without assigning a mnemenonic, use `&&`.
pub fn new<S: AsRef<str>>(
text: S,
enabled: bool,
Expand All @@ -64,7 +64,7 @@ impl IconMenuItem {
/// Create a new icon menu item with the specified id.
///
/// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
/// for this icon menu item. To display a `&` without assigning a mnemenonic, use `&&`.
/// for this icon menu item. To display a `&` without assigning a mnemenonic, use `&&`.
pub fn with_id<I: Into<MenuId>, S: AsRef<str>>(
id: I,
text: S,
Expand Down
4 changes: 2 additions & 2 deletions src/items/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl MenuItem {
/// Create a new menu item.
///
/// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
/// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`.
/// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`.
pub fn new<S: AsRef<str>>(text: S, enabled: bool, acccelerator: Option<Accelerator>) -> Self {
let item = crate::platform_impl::MenuChild::new(text.as_ref(), enabled, acccelerator, None);
Self {
Expand All @@ -43,7 +43,7 @@ impl MenuItem {
/// Create a new menu item with the specified id.
///
/// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
/// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`.
/// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`.
pub fn with_id<I: Into<MenuId>, S: AsRef<str>>(
id: I,
text: S,
Expand Down
4 changes: 2 additions & 2 deletions src/items/submenu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl Submenu {
/// Create a new submenu.
///
/// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
/// for this submenu. To display a `&` without assigning a mnemenonic, use `&&`.
/// for this submenu. To display a `&` without assigning a mnemenonic, use `&&`.
pub fn new<S: AsRef<str>>(text: S, enabled: bool) -> Self {
let submenu = crate::platform_impl::MenuChild::new_submenu(text.as_ref(), enabled, None);
Self {
Expand All @@ -49,7 +49,7 @@ impl Submenu {
/// Create a new submenu with the specified id.
///
/// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
/// for this submenu. To display a `&` without assigning a mnemenonic, use `&&`.
/// for this submenu. To display a `&` without assigning a mnemenonic, use `&&`.
pub fn with_id<I: Into<MenuId>, S: AsRef<str>>(id: I, text: S, enabled: bool) -> Self {
let id = id.into();

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
use crossbeam_channel::{unbounded, Receiver, Sender};
use once_cell::sync::{Lazy, OnceCell};

mod about_metadata;
pub mod about_metadata;
pub mod accelerator;
mod builders;
mod error;
Expand Down
8 changes: 4 additions & 4 deletions src/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@ impl Menu {
/// Adds this menu to a [`gtk::Window`]
///
/// - `container`: this is an optional paramter to specify a container for the [`gtk::MenuBar`],
/// it is highly recommended to pass a container, otherwise the menubar will be added directly to the window,
/// which is usually not the desired behavior.
/// If using a [`gtk::Box`] as a container, it is added using [`Box::pack_start(menubar, false, false, 0)`](gtk::prelude::BoxExt::pack_start) then
/// reordered to be the first child of [`gtk::Box`] using [`Box::reorder_child(menubar, 0)`](gtk::prelude::BoxExt::reorder_child).
/// it is highly recommended to pass a container, otherwise the menubar will be added directly to the window,
/// which is usually not the desired behavior.
/// If using a [`gtk::Box`] as a container, it is added using [`Box::pack_start(menubar, false, false, 0)`](gtk::prelude::BoxExt::pack_start) then
/// reordered to be the first child of [`gtk::Box`] using [`Box::reorder_child(menubar, 0)`](gtk::prelude::BoxExt::reorder_child).
///
/// ## Example:
/// ```no_run
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/windows/icon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl RgbaIcon {
let pixels =
unsafe { std::slice::from_raw_parts_mut(rgba.as_ptr() as *mut Pixel, pixel_count) };
for pixel in pixels {
and_mask.push(pixel.a.wrapping_sub(std::u8::MAX)); // invert alpha channel
and_mask.push(pixel.a.wrapping_sub(u8::MAX)); // invert alpha channel
pixel.convert_to_bgra();
}
assert_eq!(and_mask.len(), pixel_count);
Expand Down