[gnome-text-editor] app: allow opening local and remote stdin streams
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-text-editor] app: allow opening local and remote stdin streams
- Date: Thu, 12 May 2022 20:38:08 +0000 (UTC)
commit 9e99ceff8b7c0c16a9bea02ebe89830b89cf55f0
Author: Christian Hergert <chergert redhat com>
Date: Thu May 12 13:37:55 2022 -0700
app: allow opening local and remote stdin streams
This allows you to open a file using stdin with the standard - as the
filename. If an existing gnome-text-editor process is running, that
instance will be used to open the stdin stream.
Fixes #368
src/editor-application.c | 64 +++++++++++++++++++++++++++++++++++++++++--
src/editor-session.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
src/editor-session.h | 3 ++
3 files changed, 136 insertions(+), 2 deletions(-)
---
diff --git a/src/editor-application.c b/src/editor-application.c
index ae5e196..5d0131a 100644
--- a/src/editor-application.c
+++ b/src/editor-application.c
@@ -405,6 +405,25 @@ editor_application_startup (GApplication *application)
gtk_window_set_default_icon_name (PACKAGE_ICON_NAME);
}
+static gboolean
+load_stdin_stream_cb (gpointer user_data)
+{
+ EditorApplication *self = EDITOR_APPLICATION_DEFAULT;
+ EditorSession *session;
+ EditorWindow *window;
+ GInputStream *stream = user_data;
+
+ g_assert (EDITOR_IS_APPLICATION (self));
+ g_assert (G_IS_INPUT_STREAM (stream));
+
+ window = editor_application_get_current_window (self);
+ session = editor_application_get_session (self);
+ editor_session_open_stream (session, window, stream);
+ g_application_release (G_APPLICATION (self));
+
+ return G_SOURCE_REMOVE;
+}
+
static int
editor_application_command_line (GApplication *app,
GApplicationCommandLine *command_line)
@@ -412,6 +431,7 @@ editor_application_command_line (GApplication *app,
EditorApplication *self = (EditorApplication *)app;
g_auto(GStrv) argv = NULL;
g_autoptr(GPtrArray) files = NULL;
+ g_autoptr(GInputStream) stdin_stream = NULL;
GVariantDict *options;
gboolean new_window = FALSE;
const char *hint = NULL;
@@ -430,8 +450,28 @@ editor_application_command_line (GApplication *app,
files = g_ptr_array_new_with_free_func (g_object_unref);
for (int i = 1; i < argc; i++)
- g_ptr_array_add (files,
- g_application_command_line_create_file_for_arg (command_line, argv[i]));
+ {
+ /* We want to read stdin into temporary file if we get '-' */
+ if (g_strcmp0 (argv[i], "-") == 0)
+ {
+ if (stdin_stream != NULL)
+ g_application_command_line_printerr (command_line,
+ "%s\n",
+ _("Standard input was requested multiple times. Ignoring
request."));
+ else if (!(stdin_stream = g_application_command_line_get_stdin (command_line)))
+ g_application_command_line_printerr (command_line,
+ "%s\n",
+ _("Standard input is not supported on this platform.
Ignoring request."));
+ continue;
+ }
+
+ /* Otherwise add the file to the list of files we need to open, taking
+ * into account the other directory a remote instance could be running
+ * from.
+ */
+ g_ptr_array_add (files,
+ g_application_command_line_create_file_for_arg (command_line, argv[i]));
+ }
/* Only accept --new-window if this is a remote instance, we already
* create a window if we're in the same process.
@@ -449,6 +489,26 @@ editor_application_command_line (GApplication *app,
else
g_application_activate (app);
+ /* We've activated but there is a strong chance that our state has not yet
+ * been restored because that requires reading from disk. Give a bit of a
+ * delay before we process the intput stream for our initial windows to be
+ * created and state restored.
+ *
+ * This is basically a hack, but to do anything else would require more state
+ * tracking in the session manager which is particularly difficult as the
+ * stdin could be coming from another process which has been passed to us
+ * over D-Bus.
+ */
+ if (stdin_stream != NULL)
+ {
+ g_application_hold (G_APPLICATION (self));
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ 500 /* msec */,
+ load_stdin_stream_cb,
+ g_steal_pointer (&stdin_stream),
+ g_object_unref);
+ }
+
return EXIT_SUCCESS;
}
diff --git a/src/editor-session.c b/src/editor-session.c
index 44d3bf2..e0cc706 100644
--- a/src/editor-session.c
+++ b/src/editor-session.c
@@ -2444,3 +2444,74 @@ _editor_session_clear_history (EditorSession *self)
_editor_sidebar_model_remove_draft (self->recents, draft_id);
}
}
+
+static void
+editor_session_load_stream_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtkSourceFileLoader *loader = (GtkSourceFileLoader *)object;
+ g_autoptr(EditorDocument) document = user_data;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (GTK_SOURCE_IS_FILE_LOADER (loader));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (EDITOR_IS_DOCUMENT (document));
+
+ if (!gtk_source_file_loader_load_finish (loader, result, &error))
+ g_warning ("Failed to read input stream: %s", error->message);
+
+ gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (document), TRUE);
+}
+
+static void
+load_stream_into_document (GInputStream *stream,
+ EditorDocument *document)
+{
+ g_autoptr(GtkSourceFileLoader) loader = NULL;
+ g_autoptr(GtkSourceFile) file = NULL;
+
+ g_assert (G_IS_INPUT_STREAM (stream));
+ g_assert (EDITOR_IS_DOCUMENT (document));
+
+ file = gtk_source_file_new ();
+ loader = gtk_source_file_loader_new_from_stream (GTK_SOURCE_BUFFER (document), file, stream);
+ gtk_source_file_loader_load_async (loader,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ NULL, NULL, NULL,
+ editor_session_load_stream_cb,
+ g_object_ref (document));
+}
+
+void
+editor_session_open_stream (EditorSession *session,
+ EditorWindow *window,
+ GInputStream *stream)
+{
+ g_autoptr(EditorDocument) new_document = NULL;
+ EditorPage *old_page;
+ EditorPage *new_page;
+
+ g_return_if_fail (EDITOR_IS_SESSION (session));
+ g_return_if_fail (!window || EDITOR_IS_WINDOW (window));
+ g_return_if_fail (G_IS_INPUT_STREAM (stream));
+
+ if (window == NULL)
+ window = find_or_create_window (session);
+
+ /* If the window has a single empty page within it, just close that
+ * page and let our new page replace it.
+ */
+ if (editor_window_get_n_pages (window) == 1 &&
+ (old_page = editor_window_get_nth_page (window, 0)) &&
+ editor_page_get_can_discard (old_page))
+ _editor_window_remove_page (window, old_page);
+
+ new_document = editor_document_new_draft ();
+ new_page = editor_session_add_document (session, window, new_document);
+
+ load_stream_into_document (stream, new_document);
+ _editor_page_raise (new_page);
+ _editor_session_mark_dirty (session);
+}
diff --git a/src/editor-session.h b/src/editor-session.h
index 719f51f..e1a14b9 100644
--- a/src/editor-session.h
+++ b/src/editor-session.h
@@ -38,6 +38,9 @@ EditorPage *editor_session_open (EditorSession *self
EditorWindow *window,
GFile *file,
const GtkSourceEncoding *encoding);
+void editor_session_open_stream (EditorSession *session,
+ EditorWindow *window,
+ GInputStream *stream);
void editor_session_open_files (EditorSession *self,
GFile **files,
gint n_files,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]