[glib] gdbus-tool: Add tab completion support to `gdbus emit`



commit faf94409083f40ed096565b4f948852323bad697
Author: Philip Withnall <withnall endlessm com>
Date:   Mon Oct 9 10:46:55 2017 +0100

    gdbus-tool: Add tab completion support to `gdbus emit`
    
    Signed-off-by: Philip Withnall <withnall endlessm com>
    
    https://bugzilla.gnome.org/show_bug.cgi?id=788594

 gio/gdbus-tool.c |  128 +++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 107 insertions(+), 21 deletions(-)
---
diff --git a/gio/gdbus-tool.c b/gio/gdbus-tool.c
index bb7d598..286c507 100644
--- a/gio/gdbus-tool.c
+++ b/gio/gdbus-tool.c
@@ -137,9 +137,11 @@ modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
-print_methods (GDBusConnection *c,
-               const gchar *name,
-               const gchar *path)
+print_methods_and_signals (GDBusConnection *c,
+                           const gchar     *name,
+                           const gchar     *path,
+                           gboolean         print_methods,
+                           gboolean         print_signals)
 {
   GVariant *result;
   GError *error;
@@ -181,11 +183,16 @@ print_methods (GDBusConnection *c,
   for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
     {
       const GDBusInterfaceInfo *iface = node->interfaces[n];
-      for (m = 0; iface->methods != NULL && iface->methods[m] != NULL; m++)
+      for (m = 0; print_methods && iface->methods != NULL && iface->methods[m] != NULL; m++)
         {
           const GDBusMethodInfo *method = iface->methods[m];
           g_print ("%s.%s \n", iface->name, method->name);
         }
+      for (m = 0; print_signals && iface->signals != NULL && iface->signals[m] != NULL; m++)
+        {
+          const GDBusSignalInfo *signal = iface->signals[m];
+          g_print ("%s.%s \n", iface->name, signal->name);
+        }
     }
   g_dbus_node_info_unref (node);
 
@@ -565,6 +572,7 @@ handle_emit (gint        *argc,
   gboolean skip_dashes;
   guint parm;
   guint n;
+  gboolean complete_names, complete_paths, complete_signals;
 
   ret = FALSE;
   c = NULL;
@@ -580,6 +588,27 @@ handle_emit (gint        *argc,
   g_option_context_add_main_entries (o, emit_entries, GETTEXT_PACKAGE);
   g_option_context_add_group (o, connection_get_group ());
 
+  complete_names = FALSE;
+  if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
+    {
+      complete_names = TRUE;
+      remove_arg ((*argc) - 1, argc, argv);
+    }
+
+  complete_paths = FALSE;
+  if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
+    {
+      complete_paths = TRUE;
+      remove_arg ((*argc) - 1, argc, argv);
+    }
+
+  complete_signals = FALSE;
+  if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--signal") == 0)
+    {
+      complete_signals = TRUE;
+      remove_arg ((*argc) - 1, argc, argv);
+    }
+
   if (!g_option_context_parse (o, argc, argv, NULL))
     {
       if (!request_completion)
@@ -616,36 +645,99 @@ handle_emit (gint        *argc,
       goto out;
     }
 
-  /* All done with completion now */
-  if (request_completion)
-    goto out;
+  /* validate and complete destination (bus name) */
+  if (complete_names)
+    {
+      print_names (c, FALSE);
+      goto out;
+    }
+  if (opt_emit_dest == NULL)
+    {
+      if (request_completion)
+        g_print ("--dest \n");
+      else
+        g_printerr (_("Error: Destination is not specified\n"));
+      goto out;
+    }
+  if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
+    {
+      print_names (c, g_str_has_prefix (opt_emit_dest, ":"));
+      goto out;
+    }
+
+  if (!request_completion && !g_dbus_is_unique_name (opt_emit_dest))
+    {
+      g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
+      goto out;
+    }
 
+  /* validate and complete object path */
+  if (complete_paths)
+    {
+      print_paths (c, opt_emit_dest, "/");
+      goto out;
+    }
   if (opt_emit_object_path == NULL)
     {
-      g_printerr (_("Error: object path not specified.\n"));
+      if (request_completion)
+        g_print ("--object-path \n");
+      else
+        g_printerr (_("Error: Object path is not specified\n"));
       goto out;
     }
-  if (!g_variant_is_object_path (opt_emit_object_path))
+  if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
+    {
+      gchar *p;
+      s = g_strdup (opt_emit_object_path);
+      p = strrchr (s, '/');
+      if (p != NULL)
+        {
+          if (p == s)
+            p++;
+          *p = '\0';
+        }
+      print_paths (c, opt_emit_dest, s);
+      g_free (s);
+      goto out;
+    }
+  if (!request_completion && !g_variant_is_object_path (opt_emit_object_path))
     {
       g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
       goto out;
     }
 
+  /* validate and complete signal (interface + signal name) */
+  if (complete_signals)
+    {
+      print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE);
+      goto out;
+    }
   if (opt_emit_signal == NULL)
     {
-      g_printerr (_("Error: signal not specified.\n"));
+      if (request_completion)
+        g_print ("--signal \n");
+      else
+        g_printerr (_("Error: Signal name is not specified\n"));
+      goto out;
+    }
+  if (request_completion && g_strcmp0 ("--signal", completion_prev) == 0)
+    {
+      print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE);
       goto out;
     }
-
   s = strrchr (opt_emit_signal, '.');
-  if (s == NULL)
+  if (!request_completion && s == NULL)
     {
-      g_printerr (_("Error: signal must be the fully-qualified name.\n"));
+      g_printerr (_("Error: Signal name ā€œ%sā€ is invalid\n"), opt_emit_signal);
       goto out;
     }
   signal_name = g_strdup (s + 1);
   interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
 
+  /* All done with completion now */
+  if (request_completion)
+    goto out;
+
   if (!g_dbus_is_interface_name (interface_name))
     {
       g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
@@ -658,12 +750,6 @@ handle_emit (gint        *argc,
       goto out;
     }
 
-  if (opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
-    {
-      g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
-      goto out;
-    }
-
   /* Read parameters */
   g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
   skip_dashes = TRUE;
@@ -925,7 +1011,7 @@ handle_call (gint        *argc,
   /* validate and complete method (interface + method name) */
   if (complete_methods)
     {
-      print_methods (c, opt_call_dest, opt_call_object_path);
+      print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE);
       goto out;
     }
   if (opt_call_method == NULL)
@@ -938,7 +1024,7 @@ handle_call (gint        *argc,
     }
   if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
     {
-      print_methods (c, opt_call_dest, opt_call_object_path);
+      print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE);
       goto out;
     }
   s = strrchr (opt_call_method, '.');


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]