From 4eb2fdf219b3998a63f779929cd790e7bcbdb698 Mon Sep 17 00:00:00 2001
From: Yevgen Muntyan <17531749+muntyan@users.noreply.github.com>
Date: Sun, 11 Sep 2005 17:51:34 +0000
Subject: [PATCH] Added MooCmdView - widget for running commands and printing
output
---
moo.kdevelop | 26 +-
moo/mooapp/mooapp.c | 2 +-
moo/mooedit/Makefile.am | 2 +
moo/mooedit/moocmdview.c | 579 ++++++++++++++++++
moo/mooedit/moocmdview.h | 71 +++
moo/mooedit/moopaneview.c | 175 +++++-
moo/mooedit/moopaneview.h | 6 +-
moo/mooedit/mootextview.c | 17 +
moo/mooedit/mootextview.h | 3 +
moo/mooedit/plugins/Makefile.am | 14 +-
moo/mooedit/plugins/mooeditplugins.h | 2 +-
moo/mooedit/plugins/{moogrep.c => moofind.c} | 501 ++++-----------
.../plugins/{moogrep.glade => moofind.glade} | 287 ---------
moo/mooutils/moomarshals.list | 2 +
moo/mooutils/moostock.c | 3 +-
moo/mooutils/moostock.h | 3 +-
tests/medit.c.in | 2 +-
17 files changed, 993 insertions(+), 702 deletions(-)
create mode 100644 moo/mooedit/moocmdview.c
create mode 100644 moo/mooedit/moocmdview.h
rename moo/mooedit/plugins/{moogrep.c => moofind.c} (54%)
rename moo/mooedit/plugins/{moogrep.glade => moofind.glade} (54%)
diff --git a/moo.kdevelop b/moo.kdevelop
index a0853573..7af21ef0 100644
--- a/moo.kdevelop
+++ b/moo.kdevelop
@@ -36,7 +36,7 @@
debug
- tests/editor
+ tests/medit
executable
/
@@ -46,7 +46,7 @@
- --enable-debug=full --enable-all-gcc-warnings=fatal --enable-developer-mode --disable-moo-module --without-python --without-mooterm --without-mooui
+ --enable-debug=full --enable-all-gcc-warnings=fatal --enable-developer-mode --disable-moo-module --without-python --without-mooterm --without-mooui --without-mooapp
build/debug
kdevgccoptions
kdevgppoptions
@@ -54,13 +54,13 @@
-O0 -g3 -pg
-O0 -g3 -pg
-
-
-
-
-
-
-
+
+
+
+
+
+
+
--enable-all-gcc-warnings=fatal --enable-developer-mode --without-mooapp --without-mooterm --without-python
@@ -251,16 +251,16 @@
-
+
A new empty GAP source file
-
+
A new empty C++ file.
-
+
A new empty header file for C/C++.
-
+
A new empty C file.
diff --git a/moo/mooapp/mooapp.c b/moo/mooapp/mooapp.c
index 7c7e1dda..638b253b 100644
--- a/moo/mooapp/mooapp.c
+++ b/moo/mooapp/mooapp.c
@@ -717,7 +717,7 @@ static gboolean moo_app_init_real (MooApp *app)
G_CALLBACK (all_editors_closed),
app);
- moo_grep_init ();
+ moo_find_init ();
moo_file_selector_init ();
moo_plugin_read_dir (plugin_dir);
diff --git a/moo/mooedit/Makefile.am b/moo/mooedit/Makefile.am
index 235cae1e..7c446dbc 100644
--- a/moo/mooedit/Makefile.am
+++ b/moo/mooedit/Makefile.am
@@ -35,6 +35,8 @@ libmooedit_la_LIBADD = \
libmooedit_la_SOURCES = \
moobigpaned.c \
moobigpaned.h \
+ moocmdview.c \
+ moocmdview.h \
mooedit.c \
mooedit.h \
mooedit-private.h \
diff --git a/moo/mooedit/moocmdview.c b/moo/mooedit/moocmdview.c
new file mode 100644
index 00000000..eb9917bc
--- /dev/null
+++ b/moo/mooedit/moocmdview.c
@@ -0,0 +1,579 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*-
+ *
+ * moopaneview.c
+ *
+ * Copyright (C) 2004-2005 by Yevgen Muntyan
+ *
+ * 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.
+ *
+ * See COPYING file that comes with this distribution.
+ */
+
+#include "mooedit/moocmdview.h"
+#include "mooutils/moomarshals.h"
+#include
+
+
+struct _MooCmdViewPrivate {
+ gboolean running;
+ char *cmd;
+ int exit_status;
+ GPid pid;
+ int stdout;
+ int stderr;
+ GIOChannel *stdout_io;
+ GIOChannel *stderr_io;
+ guint child_watch;
+ guint stdout_watch;
+ guint stderr_watch;
+
+ GtkTextTag *error_tag;
+ GtkTextTag *message_tag;
+ GtkTextTag *stdout_tag;
+ GtkTextTag *stderr_tag;
+};
+
+static void moo_cmd_view_finalize (GObject *object);
+static void moo_cmd_view_destroy (GtkObject *object);
+static GObject *moo_cmd_view_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_param);
+
+static void moo_cmd_view_check_stop (MooCmdView *view);
+static void moo_cmd_view_cleanup (MooCmdView *view);
+
+static gboolean moo_cmd_view_abort_real (MooCmdView *view);
+static gboolean moo_cmd_view_cmd_exit (MooCmdView *view,
+ int status);
+static gboolean moo_cmd_view_stdout_line (MooCmdView *view,
+ const char *line);
+static gboolean moo_cmd_view_stderr_line (MooCmdView *view,
+ const char *line);
+
+
+
+enum {
+ ABORT,
+ CMD_EXIT,
+ OUTPUT_LINE,
+ STDOUT_LINE,
+ STDERR_LINE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+
+enum {
+ PROP_0,
+};
+
+
+/* MOO_TYPE_CMD_VIEW */
+G_DEFINE_TYPE (MooCmdView, moo_cmd_view, MOO_TYPE_PANE_VIEW)
+
+
+static void
+moo_cmd_view_class_init (MooCmdViewClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = moo_cmd_view_finalize;
+ gobject_class->constructor = moo_cmd_view_constructor;
+
+ gtkobject_class->destroy = moo_cmd_view_destroy;
+
+ klass->abort = moo_cmd_view_abort_real;
+ klass->cmd_exit = moo_cmd_view_cmd_exit;
+ klass->output_line = NULL;
+ klass->stdout_line = moo_cmd_view_stdout_line;
+ klass->stderr_line = moo_cmd_view_stderr_line;
+
+ signals[ABORT] =
+ g_signal_new ("abort",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (MooCmdViewClass, abort),
+ g_signal_accumulator_true_handled, NULL,
+ _moo_marshal_BOOL__VOID,
+ G_TYPE_BOOLEAN, 0);
+
+ signals[CMD_EXIT] =
+ g_signal_new ("cmd-exit",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MooCmdViewClass, cmd_exit),
+ g_signal_accumulator_true_handled, NULL,
+ _moo_marshal_BOOL__INT,
+ G_TYPE_BOOLEAN, 1,
+ G_TYPE_INT);
+
+ signals[OUTPUT_LINE] =
+ g_signal_new ("output-line",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MooCmdViewClass, output_line),
+ g_signal_accumulator_true_handled, NULL,
+ _moo_marshal_BOOL__STRING_BOOL,
+ G_TYPE_BOOLEAN, 2,
+ G_TYPE_STRING, G_TYPE_BOOLEAN);
+
+ signals[STDOUT_LINE] =
+ g_signal_new ("stdout-line",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MooCmdViewClass, stdout_line),
+ g_signal_accumulator_true_handled, NULL,
+ _moo_marshal_BOOL__STRING,
+ G_TYPE_BOOLEAN, 1,
+ G_TYPE_STRING);
+
+ signals[STDERR_LINE] =
+ g_signal_new ("stderr-line",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MooCmdViewClass, stderr_line),
+ g_signal_accumulator_true_handled, NULL,
+ _moo_marshal_BOOL__STRING,
+ G_TYPE_BOOLEAN, 1,
+ G_TYPE_STRING);
+}
+
+
+static void
+moo_cmd_view_init (MooCmdView *view)
+{
+ view->priv = g_new0 (MooCmdViewPrivate, 1);
+}
+
+
+static void
+moo_cmd_view_finalize (GObject *object)
+{
+ MooCmdView *view = MOO_CMD_VIEW (object);
+
+ g_free (view->priv);
+
+ G_OBJECT_CLASS (moo_cmd_view_parent_class)->finalize (object);
+}
+
+
+static GObject*
+moo_cmd_view_constructor (GType type,
+ guint n_props,
+ GObjectConstructParam *props)
+{
+ GObject *object;
+ MooCmdView *view;
+ GtkTextBuffer *buffer;
+
+ object = G_OBJECT_CLASS(moo_cmd_view_parent_class)->constructor (type, n_props, props);
+ view = MOO_CMD_VIEW (object);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ view->priv->message_tag = gtk_text_buffer_create_tag (buffer, "message", NULL);
+ view->priv->error_tag = gtk_text_buffer_create_tag (buffer, "error", NULL);
+ view->priv->stdout_tag = gtk_text_buffer_create_tag (buffer, "stdout", NULL);
+ view->priv->stderr_tag = gtk_text_buffer_create_tag (buffer, "stderr", NULL);
+
+ g_object_set (view->priv->error_tag, "foreground", "red", NULL);
+ g_object_set (view->priv->stderr_tag, "foreground", "red", NULL);
+
+ return object;
+}
+
+
+static void
+moo_cmd_view_destroy (GtkObject *object)
+{
+ MooCmdView *view = MOO_CMD_VIEW (object);
+
+ moo_cmd_view_abort (view);
+
+ if (GTK_OBJECT_CLASS (moo_cmd_view_parent_class)->destroy)
+ GTK_OBJECT_CLASS (moo_cmd_view_parent_class)->destroy (object);
+}
+
+
+GtkWidget*
+moo_cmd_view_new (void)
+{
+ return g_object_new (MOO_TYPE_CMD_VIEW, NULL);
+}
+
+
+static void
+command_exit (GPid pid,
+ gint status,
+ MooCmdView *view)
+{
+ g_return_if_fail (pid == view->priv->pid);
+
+ view->priv->child_watch = 0;
+ view->priv->exit_status = status;
+
+ g_spawn_close_pid (view->priv->pid);
+ view->priv->pid = 0;
+
+ moo_cmd_view_check_stop (view);
+}
+
+
+static void
+process_line (MooCmdView *view,
+ const char *line,
+ gboolean stderr)
+{
+ gboolean handled = FALSE;
+
+ g_signal_emit (view, signals[OUTPUT_LINE], 0, line, stderr, &handled);
+
+ if (!handled)
+ {
+ if (stderr)
+ g_signal_emit (view, signals[STDERR_LINE], 0, line, &handled);
+ else
+ g_signal_emit (view, signals[STDOUT_LINE], 0, line, &handled);
+ }
+}
+
+
+static gboolean
+command_out_or_err (MooCmdView *view,
+ GIOChannel *channel,
+ GIOCondition condition,
+ gboolean stdout)
+{
+ char *line;
+ GError *error = NULL;
+ GIOStatus status;
+
+ status = g_io_channel_read_line (channel, &line, NULL, NULL, &error);
+
+ if (line)
+ {
+ process_line (view, line, !stdout);
+ g_free (line);
+ }
+
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ if (condition & (G_IO_ERR | G_IO_HUP))
+ return FALSE;
+
+ if (status == G_IO_STATUS_EOF)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static gboolean
+command_out (GIOChannel *channel,
+ GIOCondition condition,
+ MooCmdView *view)
+{
+ return command_out_or_err (view, channel, condition, TRUE);
+}
+
+
+static gboolean
+command_err (GIOChannel *channel,
+ GIOCondition condition,
+ MooCmdView *view)
+{
+ return command_out_or_err (view, channel, condition, FALSE);
+}
+
+
+static void
+try_channel_leftover (MooCmdView *view,
+ GIOChannel *channel,
+ gboolean stdout)
+{
+ char *text;
+
+ g_io_channel_read_to_end (channel, &text, NULL, NULL);
+
+ if (text)
+ {
+ char **lines, **p;
+ g_strdelimit (text, "\r", '\n');
+ lines = g_strsplit (text, "\n", 0);
+
+ if (lines)
+ {
+ for (p = lines; *p != NULL; p++)
+ if (**p)
+ process_line (view, *p, !stdout);
+ }
+
+ g_strfreev (lines);
+ g_free (text);
+ }
+}
+
+
+static void
+stdout_watch_removed (MooCmdView *view)
+{
+ if (view->priv->stdout_io)
+ {
+ try_channel_leftover (view, view->priv->stdout_io, TRUE);
+ g_io_channel_unref (view->priv->stdout_io);
+ }
+
+ view->priv->stdout_io = NULL;
+ view->priv->stdout_watch = 0;
+ moo_cmd_view_check_stop (view);
+}
+
+
+static void
+stderr_watch_removed (MooCmdView *view)
+{
+ if (view->priv->stderr_io)
+ {
+ try_channel_leftover (view, view->priv->stderr_io, TRUE);
+ g_io_channel_unref (view->priv->stderr_io);
+ }
+
+ view->priv->stderr_io = NULL;
+ view->priv->stderr_watch = 0;
+ moo_cmd_view_check_stop (view);
+}
+
+
+gboolean
+moo_cmd_view_run_command (MooCmdView *view,
+ const char *cmd)
+{
+ GError *error = NULL;
+ char **argv = NULL;
+ gboolean result = TRUE;
+
+ g_return_val_if_fail (MOO_IS_CMD_VIEW (view), FALSE);
+ g_return_val_if_fail (cmd && cmd[0], FALSE);
+
+ g_return_val_if_fail (!view->priv->running, FALSE);
+
+ moo_pane_view_write_line (MOO_PANE_VIEW (view), cmd, -1,
+ view->priv->message_tag);
+
+ argv = g_new (char*, 4);
+ argv[0] = g_strdup ("/bin/sh");
+ argv[1] = g_strdup ("-c");
+ argv[2] = g_strdup (cmd);
+ argv[3] = NULL;
+
+ g_spawn_async_with_pipes (NULL,
+ argv, NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL,
+ &view->priv->pid,
+ NULL,
+ &view->priv->stdout,
+ &view->priv->stderr,
+ &error);
+
+ if (error)
+ {
+ moo_pane_view_write_line (MOO_PANE_VIEW (view),
+ error->message, -1,
+ view->priv->error_tag);
+ g_error_free (error);
+ goto out;
+ }
+
+ view->priv->running = TRUE;
+ view->priv->cmd = g_strdup (cmd);
+
+ view->priv->child_watch =
+ g_child_watch_add (view->priv->pid,
+ (GChildWatchFunc) command_exit,
+ view);
+
+ view->priv->stdout_io = g_io_channel_unix_new (view->priv->stdout);
+ g_io_channel_set_encoding (view->priv->stdout_io, NULL, NULL);
+ g_io_channel_set_buffered (view->priv->stdout_io, TRUE);
+ g_io_channel_set_flags (view->priv->stdout_io, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_close_on_unref (view->priv->stdout_io, TRUE);
+ view->priv->stdout_watch =
+ g_io_add_watch_full (view->priv->stdout_io,
+ G_PRIORITY_DEFAULT_IDLE,
+ G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
+ (GIOFunc) command_out, view,
+ (GDestroyNotify) stdout_watch_removed);
+
+ view->priv->stderr_io = g_io_channel_unix_new (view->priv->stderr);
+ g_io_channel_set_encoding (view->priv->stderr_io, NULL, NULL);
+ g_io_channel_set_buffered (view->priv->stderr_io, TRUE);
+ g_io_channel_set_flags (view->priv->stderr_io, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_close_on_unref (view->priv->stderr_io, TRUE);
+ view->priv->stderr_watch =
+ g_io_add_watch_full (view->priv->stderr_io,
+ G_PRIORITY_DEFAULT_IDLE,
+ G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
+ (GIOFunc) command_err, view,
+ (GDestroyNotify) stderr_watch_removed);
+
+out:
+ g_strfreev (argv);
+ return result;
+}
+
+
+static void
+moo_cmd_view_check_stop (MooCmdView *view)
+{
+ gboolean result;
+
+ if (!view->priv->running)
+ return;
+
+ if (!view->priv->child_watch && !view->priv->stdout_watch && !view->priv->stderr_watch)
+ {
+ g_signal_emit (view, signals[CMD_EXIT], 0, view->priv->exit_status, &result);
+ moo_cmd_view_cleanup (view);
+ }
+}
+
+
+static gboolean
+moo_cmd_view_cmd_exit (MooCmdView *view,
+ int status)
+{
+ if (WIFEXITED (status))
+ {
+ guint8 exit_code = WEXITSTATUS (status);
+
+ if (!exit_code)
+ {
+ moo_pane_view_write_line (MOO_PANE_VIEW (view),
+ "*** Done ***", -1,
+ view->priv->message_tag);
+ }
+ else
+ {
+ char *msg = g_strdup_printf ("*** Failed with code %d ***",
+ exit_code);
+ moo_pane_view_write_line (MOO_PANE_VIEW (view),
+ msg, -1,
+ view->priv->error_tag);
+ g_free (msg);
+ }
+ }
+#ifdef WCOREDUMP
+ else if (WCOREDUMP (status))
+ {
+ moo_pane_view_write_line (MOO_PANE_VIEW (view),
+ "*** Dumped core ***", -1,
+ view->priv->error_tag);
+ }
+#endif
+ else if (WIFSIGNALED (status))
+ {
+ moo_pane_view_write_line (MOO_PANE_VIEW (view),
+ "*** Killed ***", -1,
+ view->priv->error_tag);
+ }
+ else
+ {
+ moo_pane_view_write_line (MOO_PANE_VIEW (view),
+ "*** ??? ***", -1,
+ view->priv->error_tag);
+ }
+
+ return FALSE;
+}
+
+
+static void
+moo_cmd_view_cleanup (MooCmdView *view)
+{
+ if (!view->priv->running)
+ return;
+
+ view->priv->running = FALSE;
+
+ if (view->priv->child_watch)
+ g_source_remove (view->priv->child_watch);
+ if (view->priv->stdout_watch)
+ g_source_remove (view->priv->stdout_watch);
+ if (view->priv->stderr_watch)
+ g_source_remove (view->priv->stderr_watch);
+
+ if (view->priv->stdout_io)
+ g_io_channel_unref (view->priv->stdout_io);
+ if (view->priv->stderr_io)
+ g_io_channel_unref (view->priv->stderr_io);
+
+ if (view->priv->pid)
+ {
+ kill (view->priv->pid, SIGTERM);
+ g_spawn_close_pid (view->priv->pid);
+ }
+
+ g_free (view->priv->cmd);
+ view->priv->cmd = NULL;
+ view->priv->pid = 0;
+ view->priv->stdout = -1;
+ view->priv->stderr = -1;
+ view->priv->child_watch = 0;
+ view->priv->stdout_watch = 0;
+ view->priv->stderr_watch = 0;
+ view->priv->stdout_io = NULL;
+ view->priv->stderr_io = NULL;
+}
+
+
+static gboolean
+moo_cmd_view_abort_real (MooCmdView *view)
+{
+ if (!view->priv->running)
+ return TRUE;
+
+ g_return_val_if_fail (view->priv->pid != 0, TRUE);
+
+ kill (view->priv->pid, SIGTERM);
+ return TRUE;
+}
+
+
+void
+moo_cmd_view_abort (MooCmdView *view)
+{
+ gboolean handled;
+ g_return_if_fail (MOO_IS_CMD_VIEW (view));
+ g_signal_emit (view, signals[ABORT], 0, &handled);
+}
+
+
+static gboolean
+moo_cmd_view_stdout_line (MooCmdView *view,
+ const char *line)
+{
+ moo_pane_view_write_line (MOO_PANE_VIEW (view), line, -1,
+ view->priv->stdout_tag);
+ return FALSE;
+}
+
+
+static gboolean
+moo_cmd_view_stderr_line (MooCmdView *view,
+ const char *line)
+{
+ moo_pane_view_write_line (MOO_PANE_VIEW (view), line, -1,
+ view->priv->stderr_tag);
+ return FALSE;
+}
diff --git a/moo/mooedit/moocmdview.h b/moo/mooedit/moocmdview.h
new file mode 100644
index 00000000..6a5d807c
--- /dev/null
+++ b/moo/mooedit/moocmdview.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*-
+ *
+ * moocmdview.h
+ *
+ * Copyright (C) 2004-2005 by Yevgen Muntyan
+ *
+ * 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.
+ *
+ * See COPYING file that comes with this distribution.
+ */
+
+#ifndef __MOO_CMD_VIEW__
+#define __MOO_CMD_VIEW__
+
+#include "mooedit/moopaneview.h"
+
+G_BEGIN_DECLS
+
+
+#define MOO_TYPE_CMD_VIEW (moo_cmd_view_get_type ())
+#define MOO_CMD_VIEW(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_CMD_VIEW, MooCmdView))
+#define MOO_CMD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_CMD_VIEW, MooCmdViewClass))
+#define MOO_IS_CMD_VIEW(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_CMD_VIEW))
+#define MOO_IS_CMD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_CMD_VIEW))
+#define MOO_CMD_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_CMD_VIEW, MooCmdViewClass))
+
+
+typedef struct _MooCmdView MooCmdView;
+typedef struct _MooCmdViewPrivate MooCmdViewPrivate;
+typedef struct _MooCmdViewClass MooCmdViewClass;
+
+struct _MooCmdView
+{
+ MooPaneView parent;
+ MooCmdViewPrivate *priv;
+};
+
+struct _MooCmdViewClass
+{
+ MooPaneViewClass parent_class;
+
+ /* action signal */
+ gboolean (*abort) (MooCmdView *view);
+
+ gboolean (*cmd_exit) (MooCmdView *view,
+ int status);
+ gboolean (*output_line) (MooCmdView *view,
+ const char *line,
+ gboolean std_err);
+ gboolean (*stdout_line) (MooCmdView *view,
+ const char *line);
+ gboolean (*stderr_line) (MooCmdView *view,
+ const char *line);
+};
+
+
+GType moo_cmd_view_get_type (void) G_GNUC_CONST;
+
+GtkWidget *moo_cmd_view_new (void);
+
+gboolean moo_cmd_view_run_command (MooCmdView *view,
+ const char *cmd);
+void moo_cmd_view_abort (MooCmdView *view);
+
+
+G_END_DECLS
+
+#endif /* __MOO_CMD_VIEW__ */
diff --git a/moo/mooedit/moopaneview.c b/moo/mooedit/moopaneview.c
index 87e0f22c..0ceb44ae 100644
--- a/moo/mooedit/moopaneview.c
+++ b/moo/mooedit/moopaneview.c
@@ -14,6 +14,8 @@
#include "mooedit/moopaneview.h"
#include "mooutils/moomarshals.h"
+#include "mooutils/moosignal.h"
+#include
struct _MooPaneViewPrivate {
@@ -47,12 +49,23 @@ static void moo_pane_view_realize (GtkWidget *widget);
static gboolean moo_pane_view_button_press (GtkWidget *widget,
GdkEventButton *event);
+static void moo_pane_view_move_cursor (GtkTextView *text_view,
+ GtkMovementStep step,
+ gint count,
+ gboolean extend_selection);
+
+static gboolean activate (MooPaneView *view,
+ int line);
+static void activate_current_line (MooPaneView *view);
+
+
static GtkTextBuffer *get_buffer (MooPaneView *view);
static GHashTable *get_hash_table (MooPaneView *view);
enum {
- CLICK,
+ ACTIVATE,
+ ACTIVATE_CURRENT_LINE,
LAST_SIGNAL
};
@@ -72,6 +85,8 @@ static void moo_pane_view_class_init (MooPaneViewClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkTextViewClass *textview_class = GTK_TEXT_VIEW_CLASS (klass);
+ GtkBindingSet *binding_set;
// gobject_class->set_property = moo_pane_view_set_property;
// gobject_class->get_property = moo_pane_view_get_property;
@@ -80,15 +95,31 @@ static void moo_pane_view_class_init (MooPaneViewClass *klass)
widget_class->realize = moo_pane_view_realize;
widget_class->button_press_event = moo_pane_view_button_press;
- signals[CLICK] =
- g_signal_new ("click",
+ textview_class->move_cursor = moo_pane_view_move_cursor;
+
+ signals[ACTIVATE] =
+ g_signal_new ("activate",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MooPaneViewClass, click),
+ G_STRUCT_OFFSET (MooPaneViewClass, activate),
g_signal_accumulator_true_handled, NULL,
_moo_marshal_BOOL__POINTER_INT,
G_TYPE_BOOLEAN, 2,
G_TYPE_POINTER, G_TYPE_INT);
+
+ signals[ACTIVATE_CURRENT_LINE] =
+ moo_signal_new_cb ("activate-current-line",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (activate_current_line),
+ NULL, NULL,
+ _moo_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ binding_set = gtk_binding_set_by_class (klass);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
+ "activate-current-line", 0);
}
@@ -197,9 +228,8 @@ moo_pane_view_button_press (GtkWidget *widget,
{
GtkTextView *textview = GTK_TEXT_VIEW (widget);
MooPaneView *view = MOO_PANE_VIEW (widget);
- int buffer_x, buffer_y, line;
+ int buffer_x, buffer_y;
GtkTextIter iter;
- gpointer data;
gboolean handled = FALSE;
if (gtk_text_view_get_window_type (textview, event->window) == GTK_TEXT_WINDOW_TEXT)
@@ -211,10 +241,7 @@ moo_pane_view_button_press (GtkWidget *widget,
/* XXX */
gtk_text_view_get_line_at_y (textview, &iter, buffer_y, NULL);
- line = gtk_text_iter_get_line (&iter);
- data = moo_pane_view_get_line_data (view, line);
-
- g_signal_emit (view, signals[CLICK], 0, data, line, &handled);
+ handled = activate (view, gtk_text_iter_get_line (&iter));
if (handled)
gtk_text_buffer_place_cursor (get_buffer (view), &iter);
@@ -227,6 +254,134 @@ moo_pane_view_button_press (GtkWidget *widget,
}
+static gboolean
+activate (MooPaneView *view,
+ int line)
+{
+ gboolean handled = FALSE;
+ gpointer data = moo_pane_view_get_line_data (view, line);
+
+ g_signal_emit (view, signals[ACTIVATE], 0, data, line, &handled);
+
+ return handled;
+}
+
+
+static int
+get_current_line (MooPaneView *view)
+{
+ GtkTextIter iter;
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
+ return gtk_text_iter_get_line (&iter);
+}
+
+
+static void
+activate_current_line (MooPaneView *view)
+{
+ activate (view, get_current_line (view));
+}
+
+
+static int
+get_visible_height (GtkTextView *text_view)
+{
+ GdkRectangle rect;
+ GtkTextIter iter;
+ int start, end;
+
+ gtk_text_view_get_visible_rect (text_view, &rect);
+ gtk_text_view_get_line_at_y (text_view, &iter, rect.y, NULL);
+ start = gtk_text_iter_get_line (&iter);
+ gtk_text_view_get_line_at_y (text_view, &iter, rect.y + rect.height - 1, NULL);
+ end = gtk_text_iter_get_line (&iter);
+
+ return end - start + 1;
+}
+
+
+static void
+moo_pane_view_move_cursor (GtkTextView *text_view,
+ GtkMovementStep step,
+ gint count,
+ gboolean extend_selection)
+{
+ gboolean handle;
+ MooPaneView *view;
+ GtkTextBuffer *buffer;
+ int current_line, new_line, height, total;
+ GtkTextIter iter;
+
+ switch (step)
+ {
+ case GTK_MOVEMENT_LOGICAL_POSITIONS:
+ case GTK_MOVEMENT_VISUAL_POSITIONS:
+ case GTK_MOVEMENT_WORDS:
+ case GTK_MOVEMENT_PARAGRAPH_ENDS:
+ case GTK_MOVEMENT_HORIZONTAL_PAGES:
+ handle = FALSE;
+ break;
+
+ default:
+ handle = TRUE;
+ }
+
+ if (extend_selection)
+ handle = FALSE;
+
+ if (!handle)
+ return GTK_TEXT_VIEW_CLASS(moo_pane_view_parent_class)->move_cursor (text_view, step, count, extend_selection);
+
+ view = MOO_PANE_VIEW (text_view);
+ buffer = gtk_text_view_get_buffer (text_view);
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
+ current_line = get_current_line (view);
+
+ height = get_visible_height (text_view);
+ total = gtk_text_buffer_get_line_count (buffer);
+
+ switch (step)
+ {
+ case GTK_MOVEMENT_DISPLAY_LINES:
+ case GTK_MOVEMENT_PARAGRAPHS:
+ new_line = current_line + count;
+ break;
+
+ case GTK_MOVEMENT_PAGES:
+ new_line = current_line + count * (height - 1);
+ break;
+
+ case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
+ case GTK_MOVEMENT_BUFFER_ENDS:
+ if (count < 0)
+ new_line = 0;
+ else
+ new_line = total - 1;
+ break;
+
+ case GTK_MOVEMENT_LOGICAL_POSITIONS:
+ case GTK_MOVEMENT_VISUAL_POSITIONS:
+ case GTK_MOVEMENT_WORDS:
+ case GTK_MOVEMENT_PARAGRAPH_ENDS:
+ case GTK_MOVEMENT_HORIZONTAL_PAGES:
+ g_return_if_reached ();
+ }
+
+ new_line = CLAMP (new_line, 0, total - 1);
+ gtk_text_buffer_get_iter_at_line (buffer, &iter, new_line);
+ gtk_text_buffer_place_cursor (buffer, &iter);
+ gtk_text_view_scroll_to_mark (text_view,
+ gtk_text_buffer_get_insert (buffer),
+ 0, FALSE, 0, 0);
+}
+
+
+static gboolean activate (MooPaneView *view,
+ int line);
+
+
static void
moo_pane_view_realize (GtkWidget *widget)
{
diff --git a/moo/mooedit/moopaneview.h b/moo/mooedit/moopaneview.h
index 16ec6442..eecfcf44 100644
--- a/moo/mooedit/moopaneview.h
+++ b/moo/mooedit/moopaneview.h
@@ -42,9 +42,9 @@ struct _MooPaneViewClass
{
MooTextViewClass parent_class;
- gboolean (*click) (MooPaneView *view,
- gpointer line_data,
- int line);
+ gboolean (*activate) (MooPaneView *view,
+ gpointer line_data,
+ int line);
};
diff --git a/moo/mooedit/mootextview.c b/moo/mooedit/mootextview.c
index 38d8eafa..60af7000 100644
--- a/moo/mooedit/mootextview.c
+++ b/moo/mooedit/mootextview.c
@@ -1042,3 +1042,20 @@ moo_text_view_set_show_tabs (MooTextView *view,
if (GTK_WIDGET_DRAWABLE (view))
gtk_widget_queue_draw (GTK_WIDGET (view));
}
+
+
+GtkTextTag*
+moo_text_view_lookup_tag (MooTextView *view,
+ const char *name)
+{
+ GtkTextBuffer *buffer;
+ GtkTextTagTable *table;
+
+ g_return_val_if_fail (MOO_IS_TEXT_VIEW (view), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ buffer = get_buffer (view);
+ table = gtk_text_buffer_get_tag_table (buffer);
+
+ return gtk_text_tag_table_lookup (table, name);
+}
diff --git a/moo/mooedit/mootextview.h b/moo/mooedit/mootextview.h
index 7a13da10..d8ea5ade 100644
--- a/moo/mooedit/mootextview.h
+++ b/moo/mooedit/mootextview.h
@@ -130,6 +130,9 @@ void moo_text_view_set_current_line_color (MooTextView *view,
void moo_text_view_set_show_tabs (MooTextView *view,
gboolean show);
+GtkTextTag *moo_text_view_lookup_tag (MooTextView *view,
+ const char *name);
+
G_END_DECLS
diff --git a/moo/mooedit/plugins/Makefile.am b/moo/mooedit/plugins/Makefile.am
index 3fd50f60..ce1e19bc 100644
--- a/moo/mooedit/plugins/Makefile.am
+++ b/moo/mooedit/plugins/Makefile.am
@@ -31,12 +31,12 @@ noinst_LTLIBRARIES = libplugins.la
libplugins_la_SOURCES = \
mooeditplugins.h \
fileselector.c \
- moogrep.c \
- moogrep-glade.h
+ moofind.c \
+ moofind-glade.h
-BUILT_SOURCES = moogrep-glade.h
-EXTRA_DIST = moogrep.glade
+BUILT_SOURCES = moofind-glade.h
+EXTRA_DIST = moofind.glade
-moogrep-glade.h: moogrep.glade
- sh $(srcdir)/../../mooutils/xml2h.sh MOO_GREP_GLADE_XML $(srcdir)/moogrep.glade > \
- moogrep-glade.h
+moofind-glade.h: moofind.glade
+ sh $(srcdir)/../../mooutils/xml2h.sh MOO_FIND_GLADE_XML $(srcdir)/moofind.glade > \
+ moofind-glade.h
diff --git a/moo/mooedit/plugins/mooeditplugins.h b/moo/mooedit/plugins/mooeditplugins.h
index f649e46d..f33b133a 100644
--- a/moo/mooedit/plugins/mooeditplugins.h
+++ b/moo/mooedit/plugins/mooeditplugins.h
@@ -17,7 +17,7 @@
G_BEGIN_DECLS
-gboolean moo_grep_init (void);
+gboolean moo_find_init (void);
gboolean moo_file_selector_init (void);
diff --git a/moo/mooedit/plugins/moogrep.c b/moo/mooedit/plugins/moofind.c
similarity index 54%
rename from moo/mooedit/plugins/moogrep.c
rename to moo/mooedit/plugins/moofind.c
index 36e218b5..59554be1 100644
--- a/moo/mooedit/plugins/moogrep.c
+++ b/moo/mooedit/plugins/moofind.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*-
*
- * moogrep.c
+ * moofind.c
*
* Copyright (C) 2004-2005 by Yevgen Muntyan
*
@@ -20,10 +20,10 @@
#endif
#include "mooedit/mooplugin.h"
-#include "mooedit/plugins/moogrep-glade.h"
+#include "mooedit/plugins/moofind-glade.h"
#include "mooedit/plugins/mooeditplugins.h"
#include "mooedit/moofileview/moofileentry.h"
-#include "mooedit/moopaneview.h"
+#include "mooedit/moocmdview.h"
#include "mooui/moouiobject.h"
#include "mooutils/moostock.h"
#include "mooutils/mooglade.h"
@@ -32,7 +32,7 @@
#include
#include
-#define GREP_PLUGIN_ID "grep"
+#define FIND_PLUGIN_ID "find"
typedef struct {
@@ -40,22 +40,14 @@ typedef struct {
MooGladeXML *xml;
MooFileEntryCompletion *completion;
MooEditWindow *window;
- MooPaneView *output;
+ MooCmdView *output;
GtkTextTag *line_number_tag;
GtkTextTag *match_tag;
GtkTextTag *file_tag;
GtkTextTag *error_tag;
+ GtkTextTag *message_tag;
char *current_file;
- gboolean running;
- int exit_status;
- GPid pid;
- int stdout;
- int stderr;
- GIOChannel *stdout_io;
- GIOChannel *stderr_io;
- guint child_watch;
- guint stdout_watch;
- guint stderr_watch;
+ guint match_count;
} WindowStuff;
typedef struct {
@@ -66,8 +58,8 @@ typedef struct {
static WindowStuff *window_stuff_new (MooEditWindow *window);
static void window_stuff_free (WindowStuff *stuff);
-static void grep_plugin_attach (MooEditWindow *window);
-static void grep_plugin_detach (MooEditWindow *window);
+static void find_plugin_attach (MooEditWindow *window);
+static void find_plugin_detach (MooEditWindow *window);
static void do_find (MooEditWindow *window,
WindowStuff *stuff);
@@ -81,10 +73,15 @@ static void execute_find (const char *pattern,
const char *skip_files,
gboolean case_sensitive,
WindowStuff *stuff);
-static void stop_find (WindowStuff *stuff);
-static gboolean output_click (WindowStuff *stuff,
+static gboolean output_activate (WindowStuff *stuff,
FileLinePair *line_data);
-static void check_find_stop (WindowStuff *stuff);
+
+static gboolean command_exit (MooPaneView *view,
+ int status,
+ WindowStuff *stuff);
+static gboolean process_line (MooPaneView *view,
+ const char *line,
+ WindowStuff *stuff);
static void
@@ -93,7 +90,7 @@ find_in_files_cb (MooEditWindow *window)
WindowStuff *stuff;
int response;
- stuff = moo_plugin_get_window_data (GREP_PLUGIN_ID, window);
+ stuff = moo_plugin_get_window_data (FIND_PLUGIN_ID, window);
g_return_if_fail (stuff != NULL);
if (!stuff->dialog)
@@ -113,32 +110,38 @@ find_in_files_cb (MooEditWindow *window)
static void
-grep_plugin_attach (MooEditWindow *window)
+find_plugin_attach (MooEditWindow *window)
{
GtkWidget *swin;
MooPaneLabel *label;
WindowStuff *stuff = window_stuff_new (window);
- label = moo_pane_label_new (MOO_STOCK_GREP, NULL, NULL, "Find in Files");
- stuff->output = g_object_new (MOO_TYPE_PANE_VIEW,
+ label = moo_pane_label_new (MOO_STOCK_FIND_IN_FILES, NULL, NULL, "Find");
+ stuff->output = g_object_new (MOO_TYPE_CMD_VIEW,
"highlight-current-line", TRUE,
NULL);
- g_signal_connect_swapped (stuff->output, "click",
- G_CALLBACK (output_click), stuff);
+ g_signal_connect_swapped (stuff->output, "activate",
+ G_CALLBACK (output_activate), stuff);
- stuff->line_number_tag = moo_pane_view_create_tag (stuff->output, NULL,
- "weight", PANGO_WEIGHT_BOLD,
- NULL);
- stuff->match_tag = moo_pane_view_create_tag (stuff->output, NULL,
- "foreground", "blue",
- NULL);
- stuff->file_tag = moo_pane_view_create_tag (stuff->output, NULL,
- "foreground", "green",
- NULL);
- stuff->error_tag = moo_pane_view_create_tag (stuff->output, NULL,
- "foreground", "red",
- NULL);
+ stuff->line_number_tag =
+ moo_pane_view_create_tag (MOO_PANE_VIEW (stuff->output),
+ NULL, "weight", PANGO_WEIGHT_BOLD, NULL);
+ stuff->match_tag =
+ moo_pane_view_create_tag (MOO_PANE_VIEW (stuff->output), NULL,
+ "foreground", "blue", NULL);
+ stuff->file_tag =
+ moo_pane_view_create_tag (MOO_PANE_VIEW (stuff->output), NULL,
+ "foreground", "green", NULL);
+ stuff->error_tag =
+ moo_text_view_lookup_tag (MOO_TEXT_VIEW (stuff->output), "error");
+ stuff->message_tag =
+ moo_text_view_lookup_tag (MOO_TEXT_VIEW (stuff->output), "message");
+
+ g_signal_connect (stuff->output, "cmd-exit",
+ G_CALLBACK (command_exit), stuff);
+ g_signal_connect (stuff->output, "stdout-line",
+ G_CALLBACK (process_line), stuff);
swin = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
@@ -149,10 +152,10 @@ grep_plugin_attach (MooEditWindow *window)
gtk_container_add (GTK_CONTAINER (swin), GTK_WIDGET (stuff->output));
gtk_widget_show_all (swin);
- moo_edit_window_add_pane (window, GREP_PLUGIN_ID,
+ moo_edit_window_add_pane (window, FIND_PLUGIN_ID,
swin, label, MOO_PANE_POS_BOTTOM);
- moo_plugin_set_window_data (GREP_PLUGIN_ID, window, stuff,
+ moo_plugin_set_window_data (FIND_PLUGIN_ID, window, stuff,
(GDestroyNotify) window_stuff_free);
}
@@ -184,7 +187,7 @@ window_stuff_free (WindowStuff *stuff)
static gboolean
-grep_plugin_init (void)
+find_plugin_init (void)
{
GObjectClass *klass = g_type_class_ref (MOO_TYPE_EDIT_WINDOW);
g_return_val_if_fail (klass != NULL, FALSE);
@@ -194,7 +197,7 @@ grep_plugin_init (void)
"name", "Find In Files",
"label", "Find In Files",
"tooltip", "Find In Files",
- "icon-stock-id", MOO_STOCK_GREP,
+ "icon-stock-id", MOO_STOCK_FIND_IN_FILES,
"closure::callback", find_in_files_cb,
NULL);
@@ -204,14 +207,14 @@ grep_plugin_init (void)
static void
-grep_plugin_deinit (void)
+find_plugin_deinit (void)
{
/* XXX remove action */
}
gboolean
-moo_grep_init (void)
+moo_find_init (void)
{
MooPluginParams params = { TRUE };
MooPluginPrefsParams prefs_params;
@@ -219,16 +222,16 @@ moo_grep_init (void)
MooPluginInfo info = {
MOO_PLUGIN_CURRENT_VERSION,
- GREP_PLUGIN_ID,
- GREP_PLUGIN_ID,
- GREP_PLUGIN_ID,
+ FIND_PLUGIN_ID,
+ FIND_PLUGIN_ID,
+ FIND_PLUGIN_ID,
"Yevgen Muntyan ",
MOO_VERSION,
- (MooPluginInitFunc) grep_plugin_init,
- (MooPluginDeinitFunc) grep_plugin_deinit,
- (MooPluginWindowAttachFunc) grep_plugin_attach,
- (MooPluginWindowDetachFunc) grep_plugin_detach,
+ (MooPluginInitFunc) find_plugin_init,
+ (MooPluginDeinitFunc) find_plugin_deinit,
+ (MooPluginWindowAttachFunc) find_plugin_attach,
+ (MooPluginWindowDetachFunc) find_plugin_detach,
¶ms,
&prefs_params
@@ -252,9 +255,9 @@ static void
create_dialog (MooEditWindow *window,
WindowStuff *stuff)
{
- GtkWidget *dir_entry, *pattern_entry;
+ GtkWidget *dir_entry, *pattern_entry, *glob_entry, *skip_entry;
- stuff->xml = moo_glade_xml_new_from_buf (MOO_GREP_GLADE_XML, -1, NULL, NULL);
+ stuff->xml = moo_glade_xml_new_from_buf (MOO_FIND_GLADE_XML, -1, "dialog", NULL);
g_return_if_fail (stuff->xml != NULL);
stuff->dialog = moo_glade_xml_get_widget (stuff->xml, "dialog");
@@ -283,6 +286,17 @@ create_dialog (MooEditWindow *window,
"show-hidden", FALSE,
NULL);
moo_file_entry_completion_set_entry (stuff->completion, GTK_ENTRY (dir_entry));
+
+ glob_entry = moo_glade_xml_get_widget (stuff->xml, "glob_combo");
+ glob_entry = GTK_BIN(glob_entry)->child;
+
+ skip_entry = moo_glade_xml_get_widget (stuff->xml, "skip_combo");
+ skip_entry = GTK_BIN(skip_entry)->child;
+
+ gtk_entry_set_activates_default (GTK_ENTRY (pattern_entry), TRUE);
+ gtk_entry_set_activates_default (GTK_ENTRY (dir_entry), TRUE);
+ gtk_entry_set_activates_default (GTK_ENTRY (glob_entry), TRUE);
+ gtk_entry_set_activates_default (GTK_ENTRY (skip_entry), TRUE);
}
@@ -339,7 +353,7 @@ do_find (MooEditWindow *window,
gboolean case_sensitive;
char *dir;
- pane = moo_edit_window_get_pane (window, GREP_PLUGIN_ID);
+ pane = moo_edit_window_get_pane (window, FIND_PLUGIN_ID);
g_return_if_fail (pane != NULL);
dir_entry = GTK_BIN (moo_glade_xml_get_widget (stuff->xml, "dir_combo"))->child;
@@ -357,7 +371,7 @@ do_find (MooEditWindow *window,
skip = gtk_entry_get_text (GTK_ENTRY (skip_entry));
case_sensitive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (case_sensitive_button));
- moo_pane_view_clear (stuff->output);
+ moo_pane_view_clear (MOO_PANE_VIEW (stuff->output));
moo_big_paned_present_pane (window->paned, pane);
execute_find (pattern, glob, dir, skip,
@@ -365,23 +379,6 @@ do_find (MooEditWindow *window,
}
-static void
-command_exit (GPid pid,
- gint status,
- WindowStuff *stuff)
-{
- g_return_if_fail (pid == stuff->pid);
-
- stuff->child_watch = 0;
- stuff->exit_status = status;
-
- g_spawn_close_pid (stuff->pid);
- stuff->pid = 0;
-
- check_find_stop (stuff);
-}
-
-
static FileLinePair*
file_line_pair_new (const char *filename,
int line)
@@ -404,10 +401,10 @@ file_line_pair_free (FileLinePair *pair)
}
-static void
-process_line (WindowStuff *stuff,
+static gboolean
+process_line (MooPaneView *view,
const char *line,
- gboolean stderr)
+ WindowStuff *stuff)
{
char *filename = NULL;
char *number = NULL;
@@ -416,19 +413,9 @@ process_line (WindowStuff *stuff,
int line_no;
guint64 line_no_64;
- if (stderr)
- {
- moo_pane_view_write_line (stuff->output, line, -1,
- stuff->error_tag);
- return;
- }
-
- /* Binary file blah matches */
+ /* 'Binary file blah matches' */
if (g_str_has_prefix (line, "Binary file "))
- {
- moo_pane_view_write_line (stuff->output, line, -1, NULL);
- return;
- }
+ return FALSE;
p = line;
if (!(colon = strchr (p, ':')) || !colon[1])
@@ -447,10 +434,9 @@ process_line (WindowStuff *stuff,
{
g_free (stuff->current_file);
stuff->current_file = filename;
- view_line = moo_pane_view_write_line (stuff->output,
- filename, -1,
+ view_line = moo_pane_view_write_line (view, filename, -1,
stuff->file_tag);
- moo_pane_view_set_line_data (stuff->output, view_line,
+ moo_pane_view_set_line_data (view, view_line,
file_line_pair_new (filename, -1),
(GDestroyNotify) file_line_pair_free);
}
@@ -485,136 +471,29 @@ process_line (WindowStuff *stuff,
line_no = line_no_64 - 1;
}
- view_line = moo_pane_view_start_line (stuff->output);
- moo_pane_view_write (stuff->output, number, -1,
- stuff->line_number_tag);
- moo_pane_view_write (stuff->output, ": ", -1, NULL);
- moo_pane_view_write (stuff->output, p, -1, stuff->match_tag);
- moo_pane_view_end_line (stuff->output);
+ view_line = moo_pane_view_start_line (view);
+ moo_pane_view_write (view, number, -1, stuff->line_number_tag);
+ moo_pane_view_write (view, ": ", -1, NULL);
+ moo_pane_view_write (view, p, -1, stuff->match_tag);
+ moo_pane_view_end_line (view);
- moo_pane_view_set_line_data (stuff->output, view_line,
+ moo_pane_view_set_line_data (view, view_line,
file_line_pair_new (stuff->current_file, line_no),
(GDestroyNotify) file_line_pair_free);
+ stuff->match_count++;
g_free (number);
- return;
+ return TRUE;
parse_error:
g_warning ("%s: could not parse line '%s'",
G_STRLOC, line);
- moo_pane_view_write_line (stuff->output, line, -1, NULL);
g_free (filename);
g_free (number);
+ return FALSE;
}
-static gboolean
-command_out_or_err (GIOChannel *channel,
- GIOCondition condition,
- gboolean stdout,
- WindowStuff *stuff)
-{
- char *line;
- GError *error = NULL;
- GIOStatus status;
-
- status = g_io_channel_read_line (channel, &line, NULL, NULL, &error);
-
- if (line)
- {
- process_line (stuff, line, !stdout);
- g_free (line);
- }
-
- if (error)
- {
- g_warning ("%s: %s", G_STRLOC, error->message);
- g_error_free (error);
- return FALSE;
- }
-
- if (condition & (G_IO_ERR | G_IO_HUP))
- return FALSE;
-
- if (status == G_IO_STATUS_EOF)
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-command_out (GIOChannel *channel,
- GIOCondition condition,
- WindowStuff *stuff)
-{
- return command_out_or_err (channel, condition, TRUE, stuff);
-}
-
-
-static gboolean
-command_err (GIOChannel *channel,
- GIOCondition condition,
- WindowStuff *stuff)
-{
- return command_out_or_err (channel, condition, FALSE, stuff);
-}
-
-static void
-try_channel_leftover (WindowStuff *stuff,
- GIOChannel *channel,
- gboolean stdout)
-{
- char *text;
-
- g_io_channel_read_to_end (channel, &text, NULL, NULL);
-
- if (text)
- {
- char **lines, **p;
- g_strdelimit (text, "\r", '\n');
- lines = g_strsplit (text, "\n", 0);
-
- if (lines)
- {
- for (p = lines; *p != NULL; p++)
- if (**p)
- process_line (stuff, *p, !stdout);
- }
-
- g_strfreev (lines);
- g_free (text);
- }
-}
-
-
-static void
-stdout_watch_removed (WindowStuff *stuff)
-{
- if (stuff->stdout_io)
- {
- try_channel_leftover (stuff, stuff->stdout_io, TRUE);
- g_io_channel_unref (stuff->stdout_io);
- }
-
- stuff->stdout_io = NULL;
- stuff->stdout_watch = 0;
- check_find_stop (stuff);
-}
-
-static void
-stderr_watch_removed (WindowStuff *stuff)
-{
- if (stuff->stderr_io)
- {
- try_channel_leftover (stuff, stuff->stderr_io, FALSE);
- g_io_channel_unref (stuff->stderr_io);
- }
-
- stuff->stderr_io = NULL;
- stuff->stderr_watch = 0;
- check_find_stop (stuff);
-}
-
static void
execute_find (const char *pattern,
const char *glob,
@@ -623,19 +502,15 @@ execute_find (const char *pattern,
gboolean case_sensitive,
WindowStuff *stuff)
{
- GError *error = NULL;
- char **argv = NULL;
GString *command = NULL;
char **globs = NULL;
g_return_if_fail (stuff->output != NULL);
g_return_if_fail (pattern && pattern[0]);
- if (stuff->running)
- return;
-
g_free (stuff->current_file);
stuff->current_file = NULL;
+ stuff->match_count = 0;
command = g_string_new ("");
g_string_printf (command, "find '%s'", dir);
@@ -687,183 +562,55 @@ execute_find (const char *pattern,
g_string_append_printf (command, " | xargs egrep -H -n %s-e '%s'",
!case_sensitive ? "-i " : "", pattern);
- moo_pane_view_write_line (stuff->output, command->str, -1, NULL);
-
- argv = g_new (char*, 4);
- argv[0] = g_strdup ("/bin/sh");
- argv[1] = g_strdup ("-c");
- argv[2] = g_string_free (command, FALSE);
- argv[3] = NULL;
-
- g_spawn_async_with_pipes (NULL,
- argv, NULL,
- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
- NULL, NULL,
- &stuff->pid,
- NULL,
- &stuff->stdout,
- &stuff->stderr,
- &error);
-
- if (error)
- {
- moo_pane_view_write_line (stuff->output, error->message, -1,
- stuff->error_tag);
- g_error_free (error);
- goto out;
- }
-
- stuff->running = TRUE;
-
- stuff->child_watch =
- g_child_watch_add (stuff->pid,
- (GChildWatchFunc) command_exit,
- stuff);
-
- stuff->stdout_io = g_io_channel_unix_new (stuff->stdout);
- g_io_channel_set_encoding (stuff->stdout_io, NULL, NULL);
- g_io_channel_set_buffered (stuff->stdout_io, TRUE);
- g_io_channel_set_flags (stuff->stdout_io, G_IO_FLAG_NONBLOCK, NULL);
- g_io_channel_set_close_on_unref (stuff->stdout_io, TRUE);
- stuff->stdout_watch =
- g_io_add_watch_full (stuff->stdout_io,
- G_PRIORITY_DEFAULT_IDLE,
- G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
- (GIOFunc) command_out, stuff,
- (GDestroyNotify) stdout_watch_removed);
-
- stuff->stderr_io = g_io_channel_unix_new (stuff->stderr);
- g_io_channel_set_encoding (stuff->stderr_io, NULL, NULL);
- g_io_channel_set_buffered (stuff->stderr_io, TRUE);
- g_io_channel_set_flags (stuff->stderr_io, G_IO_FLAG_NONBLOCK, NULL);
- g_io_channel_set_close_on_unref (stuff->stderr_io, TRUE);
- stuff->stderr_watch =
- g_io_add_watch_full (stuff->stderr_io,
- G_PRIORITY_DEFAULT_IDLE,
- G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
- (GIOFunc) command_err, stuff,
- (GDestroyNotify) stderr_watch_removed);
-
-out:
- g_strfreev (argv);
+ moo_cmd_view_run_command (stuff->output, command->str);
+ g_string_free (command, TRUE);
}
static void
-grep_plugin_detach (MooEditWindow *window)
+find_plugin_detach (MooEditWindow *window)
{
- WindowStuff *stuff = moo_plugin_get_window_data (GREP_PLUGIN_ID, window);
+ WindowStuff *stuff = moo_plugin_get_window_data (FIND_PLUGIN_ID, window);
g_return_if_fail (stuff != NULL);
- stop_find (stuff);
-}
-
-static void
-stop_find (WindowStuff *stuff)
-{
- if (!stuff->running)
- return;
-
- stuff->running = FALSE;
-
- if (stuff->child_watch)
- g_source_remove (stuff->child_watch);
- if (stuff->stdout_watch)
- g_source_remove (stuff->stdout_watch);
- if (stuff->stderr_watch)
- g_source_remove (stuff->stderr_watch);
-
- if (stuff->stdout_io)
- g_io_channel_unref (stuff->stdout_io);
- if (stuff->stderr_io)
- g_io_channel_unref (stuff->stderr_io);
-
- if (stuff->pid)
- {
- kill (stuff->pid, SIGTERM);
- g_spawn_close_pid (stuff->pid);
- }
-
- g_free (stuff->current_file);
- stuff->current_file = NULL;
- stuff->pid = 0;
- stuff->stdout = -1;
- stuff->stderr = -1;
- stuff->child_watch = 0;
- stuff->stdout_watch = 0;
- stuff->stderr_watch = 0;
- stuff->stdout_io = NULL;
- stuff->stderr_io = NULL;
-}
-
-
-static void
-check_find_stop (WindowStuff *stuff)
-{
- if (!stuff->running)
- return;
-
- if (!stuff->child_watch && !stuff->stdout_watch && !stuff->stderr_watch)
- {
- if (WIFEXITED (stuff->exit_status))
- {
- guint8 exit_code = WEXITSTATUS (stuff->exit_status);
-
- /*
- xargs exits with the following status:
- 0 if it succeeds
- 123 if any invocation of the command exited with status 1-125
- 124 if the command exited with status 255
- 125 if the command is killed by a signal
- 126 if the command cannot be run
- 127 if the command is not found
- 1 if some other error occurred.
- */
-
- if (!exit_code || exit_code == 123)
- {
- moo_pane_view_write_line (stuff->output,
- "*** Done ***", -1,
- NULL);
- }
- else
- {
- char *msg = g_strdup_printf ("Command failed with status %d",
- exit_code);
- moo_pane_view_write_line (stuff->output,
- msg, -1, stuff->error_tag);
- g_free (msg);
- }
- }
-#ifdef WCOREDUMP
- else if (WCOREDUMP (stuff->exit_status))
- {
- moo_pane_view_write_line (stuff->output,
- "*** Dumped core ***", -1,
- NULL);
- }
-#endif
- else if (WIFSIGNALED (stuff->exit_status))
- {
- moo_pane_view_write_line (stuff->output,
- "*** Killed ***", -1,
- NULL);
- }
- else
- {
- moo_pane_view_write_line (stuff->output,
- "*** ??? ***", -1,
- NULL);
- }
-
- stop_find (stuff);
- }
+ g_signal_handlers_disconnect_by_func (stuff->output,
+ (gpointer) command_exit,
+ stuff);
+ g_signal_handlers_disconnect_by_func (stuff->output,
+ (gpointer) process_line,
+ stuff);
+ moo_cmd_view_abort (stuff->output);
}
static gboolean
-output_click (WindowStuff *stuff,
- FileLinePair *line_data)
+command_exit (MooPaneView *view,
+ int status,
+ WindowStuff *stuff)
+{
+ if (WIFEXITED (status))
+ {
+ guint8 exit_code = WEXITSTATUS (status);
+
+ /* xargs exits with code 123 if it's command exited with status 1-125*/
+ if (!exit_code || exit_code == 123)
+ {
+ char *msg = g_strdup_printf ("*** %d matches found ***",
+ stuff->match_count);
+ moo_pane_view_write_line (view, msg, -1,
+ stuff->message_tag);
+ g_free (msg);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+static gboolean
+output_activate (WindowStuff *stuff,
+ FileLinePair *line_data)
{
MooEditor *editor;
MooEdit *doc;
diff --git a/moo/mooedit/plugins/moogrep.glade b/moo/mooedit/plugins/moofind.glade
similarity index 54%
rename from moo/mooedit/plugins/moogrep.glade
rename to moo/mooedit/plugins/moofind.glade
index 232571d2..adeeb1c4 100644
--- a/moo/mooedit/plugins/moogrep.glade
+++ b/moo/mooedit/plugins/moofind.glade
@@ -332,291 +332,4 @@
-
- True
- window1
- GTK_WINDOW_TOPLEVEL
- GTK_WIN_POS_NONE
- False
- True
- False
- True
- False
- False
- GDK_WINDOW_TYPE_HINT_NORMAL
- GDK_GRAVITY_NORTH_WEST
-
-
-
- True
- 0.5
- 0.5
- 1
- 1
- 6
- 6
- 6
- 6
-
-
-
- True
- False
- 0
-
-
-
- True
- 4
- 2
- False
- 0
- 0
-
-
-
- True
-
-
- 1
- 2
- 2
- 3
-
-
-
-
-
-
- True
-
-
- 1
- 2
- 1
- 2
-
-
-
-
-
-
- True
-
-
- 1
- 2
- 0
- 1
-
-
-
-
-
-
- True
-
-
- 1
- 2
- 3
- 4
- fill
- fill
-
-
-
-
-
- True
- This entry content will be passed to grep
- True
- False
-
-
-
- True
- _Pattern:
- True
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 1
- 0.5
- 0
- 0
-
-
-
-
- 0
- 1
- 0
- 1
- fill
-
-
-
-
-
-
- True
- Enter semicolon-separated list of globs
- True
- False
-
-
-
- True
- Fi_les:
- True
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 1
- 0.5
- 0
- 0
-
-
-
-
- 0
- 1
- 1
- 2
- fill
-
-
-
-
-
-
- True
- You can use Tab completion in this entry. Try also Ctrl-L
- True
- False
-
-
-
- True
- _Directory:
- True
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 1
- 0.5
- 0
- 0
-
-
-
-
- 0
- 1
- 2
- 3
- fill
-
-
-
-
-
-
- True
- Enter semicolon-separated list of globs
- True
- False
-
-
-
- True
- _Skip files:
- True
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 1
- 0.5
- 0
- 0
-
-
-
-
- 0
- 1
- 3
- 4
- fill
-
-
-
-
-
- 0
- False
- False
-
-
-
-
-
- True
- False
- 0
-
-
-
- True
- True
- _Case sensitive
- True
- GTK_RELIEF_NORMAL
- True
- True
- False
- True
-
-
- 0
- False
- False
-
-
-
-
-
- True
- True
- gtk-find
- True
- GTK_RELIEF_NORMAL
- False
-
-
- 0
- False
- False
- GTK_PACK_END
-
-
-
-
- 6
- False
- False
-
-
-
-
-
-
-
-
diff --git a/moo/mooutils/moomarshals.list b/moo/mooutils/moomarshals.list
index 82899940..4f98f03d 100644
--- a/moo/mooutils/moomarshals.list
+++ b/moo/mooutils/moomarshals.list
@@ -1,9 +1,11 @@
BOOL:ENUM,INT
BOOL:ENUM,INT,BOOL
+BOOL:INT
BOOL:OBJECT,OBJECT
BOOL:POINTER
BOOL:POINTER,INT
BOOL:STRING
+BOOL:STRING,BOOL
BOOL:STRING,POINTER
BOOL:STRING,STRING
BOOL:STRING,STRING,POINTER
diff --git a/moo/mooutils/moostock.c b/moo/mooutils/moostock.c
index 8ad5eada..c2bf3de0 100644
--- a/moo/mooutils/moostock.c
+++ b/moo/mooutils/moostock.c
@@ -202,7 +202,8 @@ void moo_create_stock_items (void)
register_stock_icon_alias (factory, GTK_STOCK_GO_DOWN, MOO_STOCK_COMPILE);
register_stock_icon_alias (factory, GTK_STOCK_EXECUTE, MOO_STOCK_EXECUTE);
- register_stock_icon_alias (factory, GTK_STOCK_FIND, MOO_STOCK_GREP);
+ register_stock_icon_alias (factory, GTK_STOCK_FIND, MOO_STOCK_FIND_IN_FILES);
+ register_stock_icon_alias (factory, GTK_STOCK_FIND, MOO_STOCK_FIND_FILE);
g_object_unref (G_OBJECT (factory));
}
diff --git a/moo/mooutils/moostock.h b/moo/mooutils/moostock.h
index a927de17..7769f6fe 100644
--- a/moo/mooutils/moostock.h
+++ b/moo/mooutils/moostock.h
@@ -49,7 +49,8 @@ G_BEGIN_DECLS
#define MOO_STOCK_COMPILE "moo-compile"
#define MOO_STOCK_EXECUTE "moo-execute"
-#define MOO_STOCK_GREP "moo-grep"
+#define MOO_STOCK_FIND_IN_FILES "moo-find-in-files"
+#define MOO_STOCK_FIND_FILE "moo-find-file"
void moo_create_stock_items (void);
diff --git a/tests/medit.c.in b/tests/medit.c.in
index 16b88d06..bf9d4d74 100644
--- a/tests/medit.c.in
+++ b/tests/medit.c.in
@@ -44,7 +44,7 @@ int main (int argc, char **argv)
moo_plugin_read_dir (plugin_dir);
g_free (plugin_dir);
- moo_grep_init ();
+ moo_find_init ();
moo_file_selector_init ();
editor = moo_editor_new ();