[tracker/wip/carlosg/cli-improvements: 3/8] libtracker-common: Add tracker-term-utils




commit 513a08c31343981f105abaa21aa688ed79d93faf
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Aug 19 01:22:57 2020 +0200

    libtracker-common: Add tracker-term-utils
    
    Copied straight from tracker-miners repo.

 src/libtracker-common/meson.build          |   1 +
 src/libtracker-common/tracker-common.h     |   1 +
 src/libtracker-common/tracker-term-utils.c | 187 +++++++++++++++++++++++++++++
 src/libtracker-common/tracker-term-utils.h |  45 +++++++
 4 files changed, 234 insertions(+)
---
diff --git a/src/libtracker-common/meson.build b/src/libtracker-common/meson.build
index e2909e429..5a1ab7637 100644
--- a/src/libtracker-common/meson.build
+++ b/src/libtracker-common/meson.build
@@ -14,6 +14,7 @@ tracker_common_sources = [
   'tracker-date-time.c',
   'tracker-debug.c',
   'tracker-file-utils.c',
+  'tracker-term-utils.c',
   'tracker-type-utils.c',
   'tracker-utils.c',
   'tracker-locale.c',
diff --git a/src/libtracker-common/tracker-common.h b/src/libtracker-common/tracker-common.h
index f30aeeb52..afcecfdaa 100644
--- a/src/libtracker-common/tracker-common.h
+++ b/src/libtracker-common/tracker-common.h
@@ -33,6 +33,7 @@
 #include "tracker-file-utils.h"
 #include "tracker-language.h"
 #include "tracker-parser.h"
+#include "tracker-term-utils.h"
 #include "tracker-type-utils.h"
 #include "tracker-utils.h"
 #include "tracker-locale.h"
diff --git a/src/libtracker-common/tracker-term-utils.c b/src/libtracker-common/tracker-term-utils.c
new file mode 100644
index 000000000..96e90da5f
--- /dev/null
+++ b/src/libtracker-common/tracker-term-utils.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2020, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "tracker-term-utils.h"
+
+#include <gio/gio.h>
+#include <glib-unix.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+static guint n_columns = 0;
+static guint n_rows = 0;
+static GSubprocess *pager = NULL;
+static gint stdout_fd = 0;
+static guint signal_handler_id = 0;
+
+gchar *
+tracker_term_ellipsize (const gchar          *str,
+                        gint                  max_len,
+                        TrackerEllipsizeMode  mode)
+{
+       gint len = strlen (str);
+       gchar *substr, *retval;
+
+       if (len < max_len)
+               return g_strdup (str);
+
+       if (mode == TRACKER_ELLIPSIZE_START) {
+               substr = g_memdup (str + len - max_len + 1, max_len - 1);
+               retval = g_strdup_printf ("…%s", substr);
+               g_free (substr);
+       } else {
+               substr = g_memdup (str, max_len - 1);
+               retval = g_strdup_printf ("%s…", substr);
+               g_free (substr);
+       }
+
+       return retval;
+}
+
+static gboolean
+fd_term_dimensions (gint  fd,
+                    gint *cols,
+                    gint *rows)
+{
+        struct winsize ws = {};
+
+        if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
+                return FALSE;
+
+        if (ws.ws_col <= 0 || ws.ws_row <= 0)
+                return FALSE;
+
+        *cols = ws.ws_col;
+        *rows = ws.ws_row;
+
+        return TRUE;
+}
+
+void
+tracker_term_dimensions (guint *columns,
+                         guint *rows)
+{
+       if (n_columns == 0 || n_rows == 0)
+               fd_term_dimensions (STDOUT_FILENO, &n_columns, &n_rows);
+
+       if (n_columns <= 0)
+               n_columns = 80;
+       if (n_rows <= 0)
+               n_rows = 24;
+
+       if (columns)
+               *columns = n_columns;
+       if (rows)
+               *rows = n_rows;
+}
+
+gboolean
+tracker_term_is_tty (void)
+{
+       return isatty (STDOUT_FILENO) > 0;
+}
+
+static gboolean
+ignore_signal_cb (gpointer user_data)
+{
+       return G_SOURCE_CONTINUE;
+}
+
+static gchar *
+best_pager (void)
+{
+       guint i;
+       gchar *command;
+       const gchar *pagers[] = {
+               "pager",
+               "less",
+               "most",
+               "more",
+       };
+
+       for (i = 0; i < G_N_ELEMENTS (pagers); i++) {
+               command = g_find_program_in_path (pagers[i]);
+               if (command)
+                       return command;
+       }
+
+       return NULL;
+}
+
+gboolean
+tracker_term_pipe_to_pager (void)
+{
+       GSubprocessLauncher *launcher;
+       gchar *pager_command;
+       gint fds[2];
+
+       if (!tracker_term_is_tty ())
+               return FALSE;
+
+       if (pipe2 (fds, O_CLOEXEC) < 0)
+               return FALSE;
+
+       pager_command = best_pager ();
+       if (!pager_command)
+               return FALSE;
+
+       /* Ensure this is cached before we redirect to the pager */
+       tracker_term_dimensions (NULL, NULL);
+
+       launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
+       g_subprocess_launcher_take_stdin_fd (launcher, fds[0]);
+       g_subprocess_launcher_setenv (launcher, "LESS", "FRSXMK", TRUE);
+
+       pager = g_subprocess_launcher_spawn (launcher, NULL, pager_command, NULL);
+       g_free (pager_command);
+
+       stdout_fd = dup (STDOUT_FILENO);
+       close (fds[0]);
+
+       if (dup2(fds[1], STDOUT_FILENO) < 0)
+               return FALSE;
+
+       close (fds[1]);
+       signal_handler_id = g_unix_signal_add (SIGINT, ignore_signal_cb, NULL);
+
+       return TRUE;
+}
+
+gboolean
+tracker_term_pager_close (void)
+{
+       if (!pager)
+               return FALSE;
+
+       fflush (stdout);
+
+       /* Restore stdout */
+       dup2 (stdout_fd, STDOUT_FILENO);
+       close (stdout_fd);
+
+       g_subprocess_send_signal (pager, SIGCONT);
+       g_subprocess_wait (pager, NULL, NULL);
+       g_source_remove (signal_handler_id);
+
+       return TRUE;
+}
diff --git a/src/libtracker-common/tracker-term-utils.h b/src/libtracker-common/tracker-term-utils.h
new file mode 100644
index 000000000..1a4547d0b
--- /dev/null
+++ b/src/libtracker-common/tracker-term-utils.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef __TRACKER_TERM_UTILS_H__
+#define __TRACKER_TERM_UTILS_H__
+
+#include <glib.h>
+#include <gio/gio.h>
+
+typedef enum {
+       TRACKER_ELLIPSIZE_START,
+       TRACKER_ELLIPSIZE_END,
+} TrackerEllipsizeMode;
+
+gchar * tracker_term_ellipsize (const gchar          *str,
+                                gint                  max_len,
+                                TrackerEllipsizeMode  mode);
+
+void tracker_term_dimensions (guint *columns,
+                              guint *lines);
+
+gboolean tracker_term_is_tty (void);
+
+gboolean tracker_term_pipe_to_pager (void);
+gboolean tracker_term_pager_close (void);
+
+#endif /* __TRACKER_TERM_UTILS_H__ */


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