From 6287f64e1d74e100f88cecf65a6e8311778c1730 Mon Sep 17 00:00:00 2001 From: Niels De Graef Date: Mon, 1 Apr 2019 18:11:22 +0200 Subject: [PATCH] gdbus-tool: Colorize the output of "introspect" When available on stdout, the `gdbus introspect` command will now add colors to make it easier for humans to visually parse the output. https://gitlab.gnome.org/GNOME/glib/merge_requests/761 --- gio/gdbus-tool.c | 136 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 97 insertions(+), 39 deletions(-) diff --git a/gio/gdbus-tool.c b/gio/gdbus-tool.c index 3bef14c31..57978f1c2 100644 --- a/gio/gdbus-tool.c +++ b/gio/gdbus-tool.c @@ -36,6 +36,17 @@ /* ---------------------------------------------------------------------------------------------------- */ +/* Escape values for console colors */ +#define UNDERLINE "\033[4m" +#define BLUE "\033[34m" +#define CYAN "\033[36m" +#define GREEN "\033[32m" +#define MAGENTA "\033[35m" +#define RED "\033[31m" +#define YELLOW "\033[33m" + +/* ---------------------------------------------------------------------------------------------------- */ + G_GNUC_UNUSED static void completion_debug (const gchar *format, ...); /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice @@ -1226,18 +1237,30 @@ static gboolean opt_introspect_xml = FALSE; static gboolean opt_introspect_recurse = FALSE; static gboolean opt_introspect_only_properties = FALSE; +/* Introspect colors */ +#define RESET_COLOR (use_colors? "\033[0m": "") +#define INTROSPECT_TITLE_COLOR (use_colors? UNDERLINE: "") +#define INTROSPECT_NODE_COLOR (use_colors? RESET_COLOR: "") +#define INTROSPECT_INTERFACE_COLOR (use_colors? YELLOW: "") +#define INTROSPECT_METHOD_COLOR (use_colors? BLUE: "") +#define INTROSPECT_SIGNAL_COLOR (use_colors? BLUE: "") +#define INTROSPECT_PROPERTY_COLOR (use_colors? MAGENTA: "") +#define INTROSPECT_INOUT_COLOR (use_colors? RESET_COLOR: "") +#define INTROSPECT_TYPE_COLOR (use_colors? GREEN: "") +#define INTROSPECT_ANNOTATION_COLOR (use_colors? RESET_COLOR: "") + static void dump_annotation (const GDBusAnnotationInfo *o, guint indent, - gboolean ignore_indent) + gboolean ignore_indent, + gboolean use_colors) { guint n; - g_print ("%*s@%s(\"%s\")\n", + g_print ("%*s%s@%s(\"%s\")%s\n", ignore_indent ? 0 : indent, "", - o->key, - o->value); + INTROSPECT_ANNOTATION_COLOR, o->key, o->value, RESET_COLOR); for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) - dump_annotation (o->annotations[n], indent + 2, FALSE); + dump_annotation (o->annotations[n], indent + 2, FALSE, use_colors); } static void @@ -1245,20 +1268,21 @@ dump_arg (const GDBusArgInfo *o, guint indent, const gchar *direction, gboolean ignore_indent, - gboolean include_newline) + gboolean include_newline, + gboolean use_colors) { guint n; for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) { - dump_annotation (o->annotations[n], indent, ignore_indent); + dump_annotation (o->annotations[n], indent, ignore_indent, use_colors); ignore_indent = FALSE; } - g_print ("%*s%s%s %s%s", + g_print ("%*s%s%s%s%s%s%s %s%s", ignore_indent ? 0 : indent, "", - direction, - o->signature, + INTROSPECT_INOUT_COLOR, direction, RESET_COLOR, + INTROSPECT_TYPE_COLOR, o->signature, RESET_COLOR, o->name, include_newline ? ",\n" : ""); } @@ -1278,7 +1302,8 @@ count_args (GDBusArgInfo **args) static void dump_method (const GDBusMethodInfo *o, - guint indent) + guint indent, + gboolean use_colors) { guint n; guint m; @@ -1286,9 +1311,11 @@ dump_method (const GDBusMethodInfo *o, guint total_num_args; for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) - dump_annotation (o->annotations[n], indent, FALSE); + dump_annotation (o->annotations[n], indent, FALSE, use_colors); - g_print ("%*s%s(", indent, "", o->name); + g_print ("%*s%s%s%s(", + indent, "", + INTROSPECT_METHOD_COLOR, o->name, RESET_COLOR); name_len = strlen (o->name); total_num_args = count_args (o->in_args) + count_args (o->out_args); for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++) @@ -1300,7 +1327,8 @@ dump_method (const GDBusMethodInfo *o, indent + name_len + 1, "in ", ignore_indent, - include_newline); + include_newline, + use_colors); } for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++) { @@ -1310,23 +1338,27 @@ dump_method (const GDBusMethodInfo *o, indent + name_len + 1, "out ", ignore_indent, - include_newline); + include_newline, + use_colors); } g_print (");\n"); } static void dump_signal (const GDBusSignalInfo *o, - guint indent) + guint indent, + gboolean use_colors) { guint n; guint name_len; guint total_num_args; for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) - dump_annotation (o->annotations[n], indent, FALSE); + dump_annotation (o->annotations[n], indent, FALSE, use_colors); - g_print ("%*s%s(", indent, "", o->name); + g_print ("%*s%s%s%s(", + indent, "", + INTROSPECT_SIGNAL_COLOR, o->name, RESET_COLOR); name_len = strlen (o->name); total_num_args = count_args (o->args); for (n = 0; o->args != NULL && o->args[n] != NULL; n++) @@ -1337,7 +1369,8 @@ dump_signal (const GDBusSignalInfo *o, indent + name_len + 1, "", ignore_indent, - include_newline); + include_newline, + use_colors); } g_print (");\n"); } @@ -1345,6 +1378,7 @@ dump_signal (const GDBusSignalInfo *o, static void dump_property (const GDBusPropertyInfo *o, guint indent, + gboolean use_colors, GVariant *value) { const gchar *access; @@ -1360,12 +1394,15 @@ dump_property (const GDBusPropertyInfo *o, g_assert_not_reached (); for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) - dump_annotation (o->annotations[n], indent, FALSE); + dump_annotation (o->annotations[n], indent, FALSE, use_colors); if (value != NULL) { gchar *s = g_variant_print (value, FALSE); - g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s); + g_print ("%*s%s %s%s%s %s%s%s = %s;\n", indent, "", access, + INTROSPECT_TYPE_COLOR, o->signature, RESET_COLOR, + INTROSPECT_PROPERTY_COLOR, o->name, RESET_COLOR, + s); g_free (s); } else @@ -1379,6 +1416,7 @@ dump_interface (GDBusConnection *c, const gchar *name, const GDBusInterfaceInfo *o, guint indent, + gboolean use_colors, const gchar *object_path) { guint n; @@ -1459,28 +1497,37 @@ dump_interface (GDBusConnection *c, } for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) - dump_annotation (o->annotations[n], indent, FALSE); + dump_annotation (o->annotations[n], indent, FALSE, use_colors); - g_print ("%*sinterface %s {\n", indent, "", o->name); + g_print ("%*s%sinterface %s%s {\n", + indent, "", + INTROSPECT_INTERFACE_COLOR, o->name, RESET_COLOR); if (o->methods != NULL && !opt_introspect_only_properties) { - g_print ("%*s methods:\n", indent, ""); + g_print ("%*s %smethods%s:\n", + indent, "", + INTROSPECT_TITLE_COLOR, RESET_COLOR); for (n = 0; o->methods[n] != NULL; n++) - dump_method (o->methods[n], indent + 4); + dump_method (o->methods[n], indent + 4, use_colors); } if (o->signals != NULL && !opt_introspect_only_properties) { - g_print ("%*s signals:\n", indent, ""); + g_print ("%*s %ssignals%s:\n", + indent, "", + INTROSPECT_TITLE_COLOR, RESET_COLOR); for (n = 0; o->signals[n] != NULL; n++) - dump_signal (o->signals[n], indent + 4); + dump_signal (o->signals[n], indent + 4, use_colors); } if (o->properties != NULL) { - g_print ("%*s properties:\n", indent, ""); + g_print ("%*s %sproperties%s:\n", + indent, "", + INTROSPECT_TITLE_COLOR, RESET_COLOR); for (n = 0; o->properties[n] != NULL; n++) { dump_property (o->properties[n], indent + 4, + use_colors, g_hash_table_lookup (properties, (o->properties[n])->name)); } } @@ -1493,13 +1540,15 @@ dump_interface (GDBusConnection *c, static gboolean introspect_do (GDBusConnection *c, const gchar *object_path, - guint indent); + guint indent, + gboolean use_colors); static void dump_node (GDBusConnection *c, const gchar *name, const GDBusNodeInfo *o, guint indent, + gboolean use_colors, const gchar *object_path, gboolean recurse) { @@ -1511,9 +1560,13 @@ dump_node (GDBusConnection *c, object_path_to_print = o->path; for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) - dump_annotation (o->annotations[n], indent, FALSE); + dump_annotation (o->annotations[n], indent, FALSE, use_colors); - g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)"); + g_print ("%*s%snode %s%s", + indent, "", + INTROSPECT_NODE_COLOR, + object_path_to_print != NULL ? object_path_to_print : "(not set)", + RESET_COLOR); if (o->interfaces != NULL || o->nodes != NULL) { g_print (" {\n"); @@ -1522,11 +1575,11 @@ dump_node (GDBusConnection *c, if (opt_introspect_only_properties) { if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL) - dump_interface (c, name, o->interfaces[n], indent + 2, object_path); + dump_interface (c, name, o->interfaces[n], indent + 2, use_colors, object_path); } else { - dump_interface (c, name, o->interfaces[n], indent + 2, object_path); + dump_interface (c, name, o->interfaces[n], indent + 2, use_colors, object_path); } } for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++) @@ -1540,7 +1593,7 @@ dump_node (GDBusConnection *c, /* avoid infinite loops */ if (g_str_has_prefix (child_path, object_path)) { - introspect_do (c, child_path, indent + 2); + introspect_do (c, child_path, indent + 2, use_colors); } else { @@ -1554,13 +1607,13 @@ dump_node (GDBusConnection *c, child_path = g_strdup_printf ("/%s", o->nodes[n]->path); else child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path); - introspect_do (c, child_path, indent + 2); + introspect_do (c, child_path, indent + 2, use_colors); } g_free (child_path); } else { - dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL, recurse); + dump_node (NULL, NULL, o->nodes[n], indent + 2, use_colors, NULL, recurse); } } g_print ("%*s};\n", @@ -1585,7 +1638,8 @@ static const GOptionEntry introspect_entries[] = static gboolean introspect_do (GDBusConnection *c, const gchar *object_path, - guint indent) + guint indent, + gboolean use_colors) { GError *error; GVariant *result; @@ -1632,7 +1686,7 @@ introspect_do (GDBusConnection *c, goto out; } - dump_node (c, opt_introspect_dest, node, indent, object_path, opt_introspect_recurse); + dump_node (c, opt_introspect_dest, node, indent, use_colors, object_path, opt_introspect_recurse); } ret = TRUE; @@ -1659,6 +1713,7 @@ handle_introspect (gint *argc, GDBusConnection *c; gboolean complete_names; gboolean complete_paths; + gboolean color_support; ret = FALSE; c = NULL; @@ -1794,7 +1849,10 @@ handle_introspect (gint *argc, if (request_completion) goto out; - if (!introspect_do (c, opt_introspect_object_path, 0)) + /* Before we start printing the actual info, check if we can do colors*/ + color_support = g_log_writer_supports_color (fileno (stdout)); + + if (!introspect_do (c, opt_introspect_object_path, 0, color_support)) goto out; ret = TRUE;