From c3a073e96fe036dc069f455e904b456ae3f3906b Mon Sep 17 00:00:00 2001 From: Frederic Martinsons Date: Thu, 3 Dec 2020 10:42:47 +0100 Subject: [PATCH] Add gio launch command to execute desktop file This command will try to execute a desktop file, before that it will load the input as a keyfile for checking its existence and its validity (as a keyfile). File arguments are allowed after the desktop file. Closes #54 Signed-off-by: Frederic Martinsons --- docs/reference/gio/gio.xml | 19 ++++++ gio/completion/gio | 2 +- gio/gio-tool-launch.c | 131 +++++++++++++++++++++++++++++++++++++ gio/gio-tool.c | 3 + gio/gio-tool.h | 1 + gio/meson.build | 1 + po/POTFILES.in | 1 + 7 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 gio/gio-tool-launch.c diff --git a/docs/reference/gio/gio.xml b/docs/reference/gio/gio.xml index 641b2228c..eecaac9a1 100644 --- a/docs/reference/gio/gio.xml +++ b/docs/reference/gio/gio.xml @@ -53,6 +53,12 @@ OPTION LOCATION + + gio + launch + DESKTOP-FILE + FILE-ARG + gio list @@ -273,6 +279,19 @@ + + + launch + DESKTOP-FILE + FILE-ARG + + + Launch a desktop file from any location given. + The launch command extends the behavior of the open command by allowing + any desktop file to be launched, not only those registered as file handlers. + + + list diff --git a/gio/completion/gio b/gio/completion/gio index 75473d255..989befedd 100644 --- a/gio/completion/gio +++ b/gio/completion/gio @@ -105,7 +105,7 @@ __gio_location() { __gio() { # Complete subcommands if (( ${COMP_CWORD} == 1 )); then - COMPREPLY=($(compgen -W "help version cat copy info list mime mkdir monitor mount move open rename remove save set trash tree" -- "${COMP_WORDS[1]}")) + COMPREPLY=($(compgen -W "help version cat copy info launch list mime mkdir monitor mount move open rename remove save set trash tree" -- "${COMP_WORDS[1]}")) compopt +o nospace return 0 fi diff --git a/gio/gio-tool-launch.c b/gio/gio-tool-launch.c new file mode 100644 index 000000000..08c91c68a --- /dev/null +++ b/gio/gio-tool-launch.c @@ -0,0 +1,131 @@ +/* + * Copyright 2020 Frederic Martinsons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * Author: Frederic Martinsons + */ + +#include "config.h" + +#include + +#if defined(G_OS_UNIX) && !defined(HAVE_COCOA) +#include +#endif + +#include + +#include "gio-tool.h" + +static const GOptionEntry entries[] = { + { NULL } +}; + +int +handle_launch (int argc, char *argv[], gboolean do_help) +{ + GOptionContext *context; + GError *error = NULL; +#if defined(G_OS_UNIX) && !defined(HAVE_COCOA) + int i; + GAppInfo *app = NULL; + GAppLaunchContext *app_context = NULL; + GKeyFile *keyfile = NULL; + GList *args = NULL; + char *desktop_file = NULL; +#endif + int retval; + + g_set_prgname ("gio launch"); + + /* Translators: commandline placeholder */ + context = g_option_context_new (_("DESKTOP-FILE [FILE-ARG …]")); + g_option_context_set_help_enabled (context, FALSE); + g_option_context_set_summary (context, + _("Launch an application from a desktop file, passing optional filename arguments to it.")); + g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); + + if (do_help) + { + show_help (context, NULL); + g_option_context_free (context); + return 0; + } + + if (!g_option_context_parse (context, &argc, &argv, &error)) + { + show_help (context, error->message); + g_error_free (error); + g_option_context_free (context); + return 1; + } + + if (argc < 2) + { + show_help (context, _("No desktop file given")); + g_option_context_free (context); + return 1; + } + + g_option_context_free (context); + +#if !defined(G_OS_UNIX) || defined(HAVE_COCOA) + print_error (_("The launch command is not currently supported on this platform")); + retval = 1; +#else + retval = 0; + desktop_file = argv[1]; + + /* Use keyfile api for loading desktop app in order to check for + * - not existing file. + * - invalid keyfile format. + */ + keyfile = g_key_file_new (); + if (!g_key_file_load_from_file (keyfile, desktop_file, G_KEY_FILE_NONE, &error)) + { + print_error (_("Unable to load ‘%s‘: %s"), desktop_file, error->message); + g_clear_error (&error); + retval = 1; + } + else + { + app = (GAppInfo*)g_desktop_app_info_new_from_keyfile (keyfile); + if (!app) + { + print_error (_("Unable to load application information for ‘%s‘"), desktop_file); + retval = 1; + } + else + { + for (i = 2; i < argc; i++) + { + args = g_list_append (args, g_file_new_for_commandline_arg (argv[i])); + } + app_context = g_app_launch_context_new (); + if (!g_app_info_launch (app, args, app_context, &error)) + { + print_error (_("Unable to launch application ‘%s’: %s"), desktop_file, error->message); + g_clear_error (&error); + retval = 1; + } + g_list_free_full (args, g_object_unref); + g_clear_object (&app_context); + } + g_clear_object (&app); + } + g_key_file_free (keyfile); +#endif + return retval; +} diff --git a/gio/gio-tool.c b/gio/gio-tool.c index c0aec7492..ff82c638e 100644 --- a/gio/gio-tool.c +++ b/gio/gio-tool.c @@ -229,6 +229,7 @@ usage (void) g_printerr (" cat %s\n", _("Concatenate files to standard output")); g_printerr (" copy %s\n", _("Copy one or more files")); g_printerr (" info %s\n", _("Show information about locations")); + g_printerr (" launch %s\n", _("Launch an application from a desktop file")); g_printerr (" list %s\n", _("List the contents of locations")); g_printerr (" mime %s\n", _("Get or set the handler for a mimetype")); g_printerr (" mkdir %s\n", _("Create directories")); @@ -312,6 +313,8 @@ main (int argc, char **argv) return handle_copy (argc, argv, do_help); else if (g_str_equal (command, "info")) return handle_info (argc, argv, do_help); + else if (g_str_equal (command, "launch")) + return handle_launch (argc, argv, do_help); else if (g_str_equal (command, "list")) return handle_list (argc, argv, do_help); else if (g_str_equal (command, "mime")) diff --git a/gio/gio-tool.h b/gio/gio-tool.h index 5064165a6..6cd1d946a 100644 --- a/gio/gio-tool.h +++ b/gio/gio-tool.h @@ -37,6 +37,7 @@ gboolean file_is_dir (GFile *file); int handle_cat (int argc, char *argv[], gboolean do_help); int handle_copy (int argc, char *argv[], gboolean do_help); int handle_info (int argc, char *argv[], gboolean do_help); +int handle_launch (int argc, char *argv[], gboolean do_help); int handle_list (int argc, char *argv[], gboolean do_help); int handle_mime (int argc, char *argv[], gboolean do_help); int handle_mkdir (int argc, char *argv[], gboolean do_help); diff --git a/gio/meson.build b/gio/meson.build index f79d22053..465a7d2d6 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -908,6 +908,7 @@ gio_tool_sources = [ 'gio-tool-cat.c', 'gio-tool-copy.c', 'gio-tool-info.c', + 'gio-tool-launch.c', 'gio-tool-list.c', 'gio-tool-mime.c', 'gio-tool-mkdir.c', diff --git a/po/POTFILES.in b/po/POTFILES.in index bb9d8e370..c31517dcf 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -75,6 +75,7 @@ gio/gio-tool.c gio/gio-tool-cat.c gio/gio-tool-copy.c gio/gio-tool-info.c +gio/gio-tool-launch.c gio/gio-tool-list.c gio/gio-tool-mime.c gio/gio-tool-mkdir.c