diff --git a/.changes/pr256.md b/.changes/pr256.md new file mode 100644 index 00000000..d236459b --- /dev/null +++ b/.changes/pr256.md @@ -0,0 +1,13 @@ +--- +"cargo-packager": "patch" +"@crabnebula/packager": "patch" +--- + +Automatically add an Exec arg (field code) in the `.desktop` file. + +This adds an `{exec_arg}` field to the default `main.desktop` template. +This field is populated with a sane default value, based on the +`deep_link_protocols` or `file_associations` in the `Config` struct. + +This allows an installed Debian package to be invoked by other +applications with URLs or files as arguments, as expected. diff --git a/bindings/packager/nodejs/schema.json b/bindings/packager/nodejs/schema.json index a7692a50..ee823dfe 100644 --- a/bindings/packager/nodejs/schema.json +++ b/bindings/packager/nodejs/schema.json @@ -785,7 +785,7 @@ } }, "desktopTemplate": { - "description": "Path to a custom desktop file Handlebars template.\n\nAvailable variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.\n\nDefault file contents: ```text [Desktop Entry] Categories={{categories}} {{#if comment}} Comment={{comment}} {{/if}} Exec={{exec}} Icon={{icon}} Name={{name}} Terminal=false Type=Application {{#if mime_type}} MimeType={{mime_type}} {{/if}} ```", + "description": "Path to a custom desktop file Handlebars template.\n\nAvailable variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.\n\nDefault file contents: ```text [Desktop Entry] Categories={{categories}} {{#if comment}} Comment={{comment}} {{/if}} Exec={{exec}} {{exec_arg}} Icon={{icon}} Name={{name}} Terminal=false Type=Application {{#if mime_type}} MimeType={{mime_type}} {{/if}} ```\n\nThe `{{exec_arg}}` will be set to: * \"%F\", if at least one [Config::file_associations] was specified but no deep link protocols were given. * The \"%F\" arg means that your application can be invoked with multiple file paths. * \"%U\", if at least one [Config::deep_link_protocols] was specified. * The \"%U\" arg means that your application can be invoked with multiple URLs. * If both [Config::file_associations] and [Config::deep_link_protocols] were specified, the \"%U\" arg will be used, causing the file paths to be passed to your app as `file://` URLs. * An empty string \"\" (nothing) if neither are given. * This means that your application will never be invoked with any URLs or file paths.\n\nTo specify a custom `exec_arg`, just use plaintext directly instead of `{{exec_arg}}`: ```text Exec={{exec}} %u ```\n\nSee more here: .", "type": [ "string", "null" diff --git a/crates/packager/schema.json b/crates/packager/schema.json index a7692a50..ee823dfe 100644 --- a/crates/packager/schema.json +++ b/crates/packager/schema.json @@ -785,7 +785,7 @@ } }, "desktopTemplate": { - "description": "Path to a custom desktop file Handlebars template.\n\nAvailable variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.\n\nDefault file contents: ```text [Desktop Entry] Categories={{categories}} {{#if comment}} Comment={{comment}} {{/if}} Exec={{exec}} Icon={{icon}} Name={{name}} Terminal=false Type=Application {{#if mime_type}} MimeType={{mime_type}} {{/if}} ```", + "description": "Path to a custom desktop file Handlebars template.\n\nAvailable variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.\n\nDefault file contents: ```text [Desktop Entry] Categories={{categories}} {{#if comment}} Comment={{comment}} {{/if}} Exec={{exec}} {{exec_arg}} Icon={{icon}} Name={{name}} Terminal=false Type=Application {{#if mime_type}} MimeType={{mime_type}} {{/if}} ```\n\nThe `{{exec_arg}}` will be set to: * \"%F\", if at least one [Config::file_associations] was specified but no deep link protocols were given. * The \"%F\" arg means that your application can be invoked with multiple file paths. * \"%U\", if at least one [Config::deep_link_protocols] was specified. * The \"%U\" arg means that your application can be invoked with multiple URLs. * If both [Config::file_associations] and [Config::deep_link_protocols] were specified, the \"%U\" arg will be used, causing the file paths to be passed to your app as `file://` URLs. * An empty string \"\" (nothing) if neither are given. * This means that your application will never be invoked with any URLs or file paths.\n\nTo specify a custom `exec_arg`, just use plaintext directly instead of `{{exec_arg}}`: ```text Exec={{exec}} %u ```\n\nSee more here: .", "type": [ "string", "null" diff --git a/crates/packager/src/config/mod.rs b/crates/packager/src/config/mod.rs index 1a022b2c..65b44a8e 100644 --- a/crates/packager/src/config/mod.rs +++ b/crates/packager/src/config/mod.rs @@ -194,7 +194,7 @@ pub struct DebianConfig { /// {{#if comment}} /// Comment={{comment}} /// {{/if}} - /// Exec={{exec}} + /// Exec={{exec}} {{exec_arg}} /// Icon={{icon}} /// Name={{name}} /// Terminal=false @@ -203,6 +203,23 @@ pub struct DebianConfig { /// MimeType={{mime_type}} /// {{/if}} /// ``` + /// + /// The `{{exec_arg}}` will be set to: + /// * "%F", if at least one [Config::file_associations] was specified but no deep link protocols were given. + /// * The "%F" arg means that your application can be invoked with multiple file paths. + /// * "%U", if at least one [Config::deep_link_protocols] was specified. + /// * The "%U" arg means that your application can be invoked with multiple URLs. + /// * If both [Config::file_associations] and [Config::deep_link_protocols] were specified, + /// the "%U" arg will be used, causing the file paths to be passed to your app as `file://` URLs. + /// * An empty string "" (nothing) if neither are given. + /// * This means that your application will never be invoked with any URLs or file paths. + /// + /// To specify a custom `exec_arg`, just use plaintext directly instead of `{{exec_arg}}`: + /// ```text + /// Exec={{exec}} %u + /// ``` + /// + /// See more here: . #[serde(alias = "desktop-template", alias = "desktop_template")] pub desktop_template: Option, /// Define the section in Debian Control file. See : @@ -243,7 +260,7 @@ impl DebianConfig { /// {{#if comment}} /// Comment={{comment}} /// {{/if}} - /// Exec={{exec}} + /// Exec={{exec}} {{exec_arg}} /// Icon={{icon}} /// Name={{name}} /// Terminal=false diff --git a/crates/packager/src/package/deb/main.desktop b/crates/packager/src/package/deb/main.desktop index 721648d0..a5f72023 100644 --- a/crates/packager/src/package/deb/main.desktop +++ b/crates/packager/src/package/deb/main.desktop @@ -3,7 +3,7 @@ Categories={{categories}} {{#if comment}} Comment={{comment}} {{/if}} -Exec={{exec}} +Exec={{exec}} {{exec_arg}} Icon={{icon}} Name={{name}} Terminal=false diff --git a/crates/packager/src/package/deb/mod.rs b/crates/packager/src/package/deb/mod.rs index 8390cf43..3c3f29f6 100644 --- a/crates/packager/src/package/deb/mod.rs +++ b/crates/packager/src/package/deb/mod.rs @@ -96,8 +96,8 @@ fn generate_desktop_file(config: &Config, data_dir: &Path) -> crate::Result<()> .join("usr/share/applications") .join(desktop_file_name); - // For more information about the format of this file, see - // https://developer.gnome.org/integration-guide/stable/desktop-files.html.en + // For more information about the format of this file, see: + // let file = &mut util::create_file(&desktop_file_path)?; let mut handlebars = Handlebars::new(); @@ -117,14 +117,22 @@ fn generate_desktop_file(config: &Config, data_dir: &Path) -> crate::Result<()> categories: &'a str, comment: Option<&'a str>, exec: &'a str, + exec_arg: Option<&'a str>, icon: &'a str, name: &'a str, mime_type: Option, } + // Set the argument code at the end of the `Exec` key. + // See the docs for `DebianConfig::desktop_template` for more details. + let mut exec_arg = None; + let mut mime_type: Vec = Vec::new(); if let Some(associations) = &config.file_associations { + if !associations.is_empty() { + exec_arg = Some("%F"); + } mime_type.extend( associations .iter() @@ -133,6 +141,11 @@ fn generate_desktop_file(config: &Config, data_dir: &Path) -> crate::Result<()> } if let Some(protocols) = &config.deep_link_protocols { + if !protocols.is_empty() { + // Use "%U" even if file associations were already provided, + // as it can also accommodate file names in addition to URLs. + exec_arg = Some("%U"); + } mime_type.extend( protocols .iter() @@ -152,6 +165,7 @@ fn generate_desktop_file(config: &Config, data_dir: &Path) -> crate::Result<()> .unwrap_or(""), comment: config.description.as_deref(), exec: &bin_name, + exec_arg, icon: &bin_name, name: config.product_name.as_str(), mime_type,