Added MooCmdView - widget for running commands and printing output

master
Yevgen Muntyan 2005-09-11 17:51:34 +00:00
parent 365dc2cf6a
commit 4eb2fdf219
17 changed files with 993 additions and 702 deletions

View File

@ -36,7 +36,7 @@
<useconfiguration>debug</useconfiguration> <useconfiguration>debug</useconfiguration>
</general> </general>
<run> <run>
<mainprogram>tests/editor</mainprogram> <mainprogram>tests/medit</mainprogram>
<directoryradio>executable</directoryradio> <directoryradio>executable</directoryradio>
<customdirectory>/</customdirectory> <customdirectory>/</customdirectory>
<programargs></programargs> <programargs></programargs>
@ -46,7 +46,7 @@
</run> </run>
<configurations> <configurations>
<debug> <debug>
<configargs>--enable-debug=full --enable-all-gcc-warnings=fatal --enable-developer-mode --disable-moo-module --without-python --without-mooterm --without-mooui</configargs> <configargs>--enable-debug=full --enable-all-gcc-warnings=fatal --enable-developer-mode --disable-moo-module --without-python --without-mooterm --without-mooui --without-mooapp</configargs>
<builddir>build/debug</builddir> <builddir>build/debug</builddir>
<ccompiler>kdevgccoptions</ccompiler> <ccompiler>kdevgccoptions</ccompiler>
<cxxcompiler>kdevgppoptions</cxxcompiler> <cxxcompiler>kdevgppoptions</cxxcompiler>
@ -54,13 +54,13 @@
<cflags>-O0 -g3 -pg</cflags> <cflags>-O0 -g3 -pg</cflags>
<cxxflags>-O0 -g3 -pg</cxxflags> <cxxflags>-O0 -g3 -pg</cxxflags>
<envvars/> <envvars/>
<topsourcedir></topsourcedir> <topsourcedir/>
<cppflags></cppflags> <cppflags/>
<ldflags></ldflags> <ldflags/>
<ccompilerbinary></ccompilerbinary> <ccompilerbinary/>
<cxxcompilerbinary></cxxcompilerbinary> <cxxcompilerbinary/>
<f77compilerbinary></f77compilerbinary> <f77compilerbinary/>
<f77flags></f77flags> <f77flags/>
</debug> </debug>
<optimized> <optimized>
<configargs>--enable-all-gcc-warnings=fatal --enable-developer-mode --without-mooapp --without-mooterm --without-python</configargs> <configargs>--enable-all-gcc-warnings=fatal --enable-developer-mode --without-mooapp --without-mooterm --without-python</configargs>
@ -251,16 +251,16 @@
</kdevdoctreeview> </kdevdoctreeview>
<kdevfilecreate> <kdevfilecreate>
<filetypes> <filetypes>
<type icon="source" ext="g" create="template" name="GAP source" > <type icon="source" ext="g" name="GAP source" create="template" >
<descr>A new empty GAP source file</descr> <descr>A new empty GAP source file</descr>
</type> </type>
<type icon="source_cpp" ext="cpp" create="template" name="C++ Source" > <type icon="source_cpp" ext="cpp" name="C++ Source" create="template" >
<descr>A new empty C++ file.</descr> <descr>A new empty C++ file.</descr>
</type> </type>
<type icon="source_h" ext="h" create="template" name="C/C++ Header" > <type icon="source_h" ext="h" name="C/C++ Header" create="template" >
<descr>A new empty header file for C/C++.</descr> <descr>A new empty header file for C/C++.</descr>
</type> </type>
<type icon="source_c" ext="c" create="template" name="C Source" > <type icon="source_c" ext="c" name="C Source" create="template" >
<descr>A new empty C file.</descr> <descr>A new empty C file.</descr>
</type> </type>
</filetypes> </filetypes>

View File

@ -717,7 +717,7 @@ static gboolean moo_app_init_real (MooApp *app)
G_CALLBACK (all_editors_closed), G_CALLBACK (all_editors_closed),
app); app);
moo_grep_init (); moo_find_init ();
moo_file_selector_init (); moo_file_selector_init ();
moo_plugin_read_dir (plugin_dir); moo_plugin_read_dir (plugin_dir);

View File

@ -35,6 +35,8 @@ libmooedit_la_LIBADD = \
libmooedit_la_SOURCES = \ libmooedit_la_SOURCES = \
moobigpaned.c \ moobigpaned.c \
moobigpaned.h \ moobigpaned.h \
moocmdview.c \
moocmdview.h \
mooedit.c \ mooedit.c \
mooedit.h \ mooedit.h \
mooedit-private.h \ mooedit-private.h \

579
moo/mooedit/moocmdview.c Normal file
View File

@ -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 <muntyan@math.tamu.edu>
*
* 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 <sys/wait.h>
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;
}

71
moo/mooedit/moocmdview.h Normal file
View File

@ -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 <muntyan@math.tamu.edu>
*
* 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__ */

View File

@ -14,6 +14,8 @@
#include "mooedit/moopaneview.h" #include "mooedit/moopaneview.h"
#include "mooutils/moomarshals.h" #include "mooutils/moomarshals.h"
#include "mooutils/moosignal.h"
#include <gdk/gdkkeysyms.h>
struct _MooPaneViewPrivate { struct _MooPaneViewPrivate {
@ -47,12 +49,23 @@ static void moo_pane_view_realize (GtkWidget *widget);
static gboolean moo_pane_view_button_press (GtkWidget *widget, static gboolean moo_pane_view_button_press (GtkWidget *widget,
GdkEventButton *event); 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 GtkTextBuffer *get_buffer (MooPaneView *view);
static GHashTable *get_hash_table (MooPaneView *view); static GHashTable *get_hash_table (MooPaneView *view);
enum { enum {
CLICK, ACTIVATE,
ACTIVATE_CURRENT_LINE,
LAST_SIGNAL LAST_SIGNAL
}; };
@ -72,6 +85,8 @@ static void moo_pane_view_class_init (MooPaneViewClass *klass)
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_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->set_property = moo_pane_view_set_property;
// gobject_class->get_property = moo_pane_view_get_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->realize = moo_pane_view_realize;
widget_class->button_press_event = moo_pane_view_button_press; widget_class->button_press_event = moo_pane_view_button_press;
signals[CLICK] = textview_class->move_cursor = moo_pane_view_move_cursor;
g_signal_new ("click",
signals[ACTIVATE] =
g_signal_new ("activate",
G_OBJECT_CLASS_TYPE (klass), G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (MooPaneViewClass, click), G_STRUCT_OFFSET (MooPaneViewClass, activate),
g_signal_accumulator_true_handled, NULL, g_signal_accumulator_true_handled, NULL,
_moo_marshal_BOOL__POINTER_INT, _moo_marshal_BOOL__POINTER_INT,
G_TYPE_BOOLEAN, 2, G_TYPE_BOOLEAN, 2,
G_TYPE_POINTER, G_TYPE_INT); 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); GtkTextView *textview = GTK_TEXT_VIEW (widget);
MooPaneView *view = MOO_PANE_VIEW (widget); MooPaneView *view = MOO_PANE_VIEW (widget);
int buffer_x, buffer_y, line; int buffer_x, buffer_y;
GtkTextIter iter; GtkTextIter iter;
gpointer data;
gboolean handled = FALSE; gboolean handled = FALSE;
if (gtk_text_view_get_window_type (textview, event->window) == GTK_TEXT_WINDOW_TEXT) 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 */ /* XXX */
gtk_text_view_get_line_at_y (textview, &iter, buffer_y, NULL); gtk_text_view_get_line_at_y (textview, &iter, buffer_y, NULL);
line = gtk_text_iter_get_line (&iter); handled = activate (view, 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);
if (handled) if (handled)
gtk_text_buffer_place_cursor (get_buffer (view), &iter); 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 static void
moo_pane_view_realize (GtkWidget *widget) moo_pane_view_realize (GtkWidget *widget)
{ {

View File

@ -42,7 +42,7 @@ struct _MooPaneViewClass
{ {
MooTextViewClass parent_class; MooTextViewClass parent_class;
gboolean (*click) (MooPaneView *view, gboolean (*activate) (MooPaneView *view,
gpointer line_data, gpointer line_data,
int line); int line);
}; };

View File

@ -1042,3 +1042,20 @@ moo_text_view_set_show_tabs (MooTextView *view,
if (GTK_WIDGET_DRAWABLE (view)) if (GTK_WIDGET_DRAWABLE (view))
gtk_widget_queue_draw (GTK_WIDGET (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);
}

View File

@ -130,6 +130,9 @@ void moo_text_view_set_current_line_color (MooTextView *view,
void moo_text_view_set_show_tabs (MooTextView *view, void moo_text_view_set_show_tabs (MooTextView *view,
gboolean show); gboolean show);
GtkTextTag *moo_text_view_lookup_tag (MooTextView *view,
const char *name);
G_END_DECLS G_END_DECLS

View File

@ -31,12 +31,12 @@ noinst_LTLIBRARIES = libplugins.la
libplugins_la_SOURCES = \ libplugins_la_SOURCES = \
mooeditplugins.h \ mooeditplugins.h \
fileselector.c \ fileselector.c \
moogrep.c \ moofind.c \
moogrep-glade.h moofind-glade.h
BUILT_SOURCES = moogrep-glade.h BUILT_SOURCES = moofind-glade.h
EXTRA_DIST = moogrep.glade EXTRA_DIST = moofind.glade
moogrep-glade.h: moogrep.glade moofind-glade.h: moofind.glade
sh $(srcdir)/../../mooutils/xml2h.sh MOO_GREP_GLADE_XML $(srcdir)/moogrep.glade > \ sh $(srcdir)/../../mooutils/xml2h.sh MOO_FIND_GLADE_XML $(srcdir)/moofind.glade > \
moogrep-glade.h moofind-glade.h

View File

@ -17,7 +17,7 @@
G_BEGIN_DECLS G_BEGIN_DECLS
gboolean moo_grep_init (void); gboolean moo_find_init (void);
gboolean moo_file_selector_init (void); gboolean moo_file_selector_init (void);

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*- /* -*- 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 <muntyan@math.tamu.edu> * Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
* *
@ -20,10 +20,10 @@
#endif #endif
#include "mooedit/mooplugin.h" #include "mooedit/mooplugin.h"
#include "mooedit/plugins/moogrep-glade.h" #include "mooedit/plugins/moofind-glade.h"
#include "mooedit/plugins/mooeditplugins.h" #include "mooedit/plugins/mooeditplugins.h"
#include "mooedit/moofileview/moofileentry.h" #include "mooedit/moofileview/moofileentry.h"
#include "mooedit/moopaneview.h" #include "mooedit/moocmdview.h"
#include "mooui/moouiobject.h" #include "mooui/moouiobject.h"
#include "mooutils/moostock.h" #include "mooutils/moostock.h"
#include "mooutils/mooglade.h" #include "mooutils/mooglade.h"
@ -32,7 +32,7 @@
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#define GREP_PLUGIN_ID "grep" #define FIND_PLUGIN_ID "find"
typedef struct { typedef struct {
@ -40,22 +40,14 @@ typedef struct {
MooGladeXML *xml; MooGladeXML *xml;
MooFileEntryCompletion *completion; MooFileEntryCompletion *completion;
MooEditWindow *window; MooEditWindow *window;
MooPaneView *output; MooCmdView *output;
GtkTextTag *line_number_tag; GtkTextTag *line_number_tag;
GtkTextTag *match_tag; GtkTextTag *match_tag;
GtkTextTag *file_tag; GtkTextTag *file_tag;
GtkTextTag *error_tag; GtkTextTag *error_tag;
GtkTextTag *message_tag;
char *current_file; char *current_file;
gboolean running; guint match_count;
int exit_status;
GPid pid;
int stdout;
int stderr;
GIOChannel *stdout_io;
GIOChannel *stderr_io;
guint child_watch;
guint stdout_watch;
guint stderr_watch;
} WindowStuff; } WindowStuff;
typedef struct { typedef struct {
@ -66,8 +58,8 @@ typedef struct {
static WindowStuff *window_stuff_new (MooEditWindow *window); static WindowStuff *window_stuff_new (MooEditWindow *window);
static void window_stuff_free (WindowStuff *stuff); static void window_stuff_free (WindowStuff *stuff);
static void grep_plugin_attach (MooEditWindow *window); static void find_plugin_attach (MooEditWindow *window);
static void grep_plugin_detach (MooEditWindow *window); static void find_plugin_detach (MooEditWindow *window);
static void do_find (MooEditWindow *window, static void do_find (MooEditWindow *window,
WindowStuff *stuff); WindowStuff *stuff);
@ -81,10 +73,15 @@ static void execute_find (const char *pattern,
const char *skip_files, const char *skip_files,
gboolean case_sensitive, gboolean case_sensitive,
WindowStuff *stuff); WindowStuff *stuff);
static void stop_find (WindowStuff *stuff); static gboolean output_activate (WindowStuff *stuff,
static gboolean output_click (WindowStuff *stuff,
FileLinePair *line_data); 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 static void
@ -93,7 +90,7 @@ find_in_files_cb (MooEditWindow *window)
WindowStuff *stuff; WindowStuff *stuff;
int response; 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); g_return_if_fail (stuff != NULL);
if (!stuff->dialog) if (!stuff->dialog)
@ -113,32 +110,38 @@ find_in_files_cb (MooEditWindow *window)
static void static void
grep_plugin_attach (MooEditWindow *window) find_plugin_attach (MooEditWindow *window)
{ {
GtkWidget *swin; GtkWidget *swin;
MooPaneLabel *label; MooPaneLabel *label;
WindowStuff *stuff = window_stuff_new (window); WindowStuff *stuff = window_stuff_new (window);
label = moo_pane_label_new (MOO_STOCK_GREP, NULL, NULL, "Find in Files"); label = moo_pane_label_new (MOO_STOCK_FIND_IN_FILES, NULL, NULL, "Find");
stuff->output = g_object_new (MOO_TYPE_PANE_VIEW, stuff->output = g_object_new (MOO_TYPE_CMD_VIEW,
"highlight-current-line", TRUE, "highlight-current-line", TRUE,
NULL); NULL);
g_signal_connect_swapped (stuff->output, "click", g_signal_connect_swapped (stuff->output, "activate",
G_CALLBACK (output_click), stuff); G_CALLBACK (output_activate), stuff);
stuff->line_number_tag = moo_pane_view_create_tag (stuff->output, NULL, stuff->line_number_tag =
"weight", PANGO_WEIGHT_BOLD, moo_pane_view_create_tag (MOO_PANE_VIEW (stuff->output),
NULL); NULL, "weight", PANGO_WEIGHT_BOLD, NULL);
stuff->match_tag = moo_pane_view_create_tag (stuff->output, NULL, stuff->match_tag =
"foreground", "blue", moo_pane_view_create_tag (MOO_PANE_VIEW (stuff->output), NULL,
NULL); "foreground", "blue", NULL);
stuff->file_tag = moo_pane_view_create_tag (stuff->output, NULL, stuff->file_tag =
"foreground", "green", moo_pane_view_create_tag (MOO_PANE_VIEW (stuff->output), NULL,
NULL); "foreground", "green", NULL);
stuff->error_tag = moo_pane_view_create_tag (stuff->output, NULL, stuff->error_tag =
"foreground", "red", moo_text_view_lookup_tag (MOO_TEXT_VIEW (stuff->output), "error");
NULL); 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); swin = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin), 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_container_add (GTK_CONTAINER (swin), GTK_WIDGET (stuff->output));
gtk_widget_show_all (swin); 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); 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); (GDestroyNotify) window_stuff_free);
} }
@ -184,7 +187,7 @@ window_stuff_free (WindowStuff *stuff)
static gboolean static gboolean
grep_plugin_init (void) find_plugin_init (void)
{ {
GObjectClass *klass = g_type_class_ref (MOO_TYPE_EDIT_WINDOW); GObjectClass *klass = g_type_class_ref (MOO_TYPE_EDIT_WINDOW);
g_return_val_if_fail (klass != NULL, FALSE); g_return_val_if_fail (klass != NULL, FALSE);
@ -194,7 +197,7 @@ grep_plugin_init (void)
"name", "Find In Files", "name", "Find In Files",
"label", "Find In Files", "label", "Find In Files",
"tooltip", "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, "closure::callback", find_in_files_cb,
NULL); NULL);
@ -204,14 +207,14 @@ grep_plugin_init (void)
static void static void
grep_plugin_deinit (void) find_plugin_deinit (void)
{ {
/* XXX remove action */ /* XXX remove action */
} }
gboolean gboolean
moo_grep_init (void) moo_find_init (void)
{ {
MooPluginParams params = { TRUE }; MooPluginParams params = { TRUE };
MooPluginPrefsParams prefs_params; MooPluginPrefsParams prefs_params;
@ -219,16 +222,16 @@ moo_grep_init (void)
MooPluginInfo info = { MooPluginInfo info = {
MOO_PLUGIN_CURRENT_VERSION, MOO_PLUGIN_CURRENT_VERSION,
GREP_PLUGIN_ID, FIND_PLUGIN_ID,
GREP_PLUGIN_ID, FIND_PLUGIN_ID,
GREP_PLUGIN_ID, FIND_PLUGIN_ID,
"Yevgen Muntyan <muntyan@tamu.edu>", "Yevgen Muntyan <muntyan@tamu.edu>",
MOO_VERSION, MOO_VERSION,
(MooPluginInitFunc) grep_plugin_init, (MooPluginInitFunc) find_plugin_init,
(MooPluginDeinitFunc) grep_plugin_deinit, (MooPluginDeinitFunc) find_plugin_deinit,
(MooPluginWindowAttachFunc) grep_plugin_attach, (MooPluginWindowAttachFunc) find_plugin_attach,
(MooPluginWindowDetachFunc) grep_plugin_detach, (MooPluginWindowDetachFunc) find_plugin_detach,
&params, &params,
&prefs_params &prefs_params
@ -252,9 +255,9 @@ static void
create_dialog (MooEditWindow *window, create_dialog (MooEditWindow *window,
WindowStuff *stuff) 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); g_return_if_fail (stuff->xml != NULL);
stuff->dialog = moo_glade_xml_get_widget (stuff->xml, "dialog"); stuff->dialog = moo_glade_xml_get_widget (stuff->xml, "dialog");
@ -283,6 +286,17 @@ create_dialog (MooEditWindow *window,
"show-hidden", FALSE, "show-hidden", FALSE,
NULL); NULL);
moo_file_entry_completion_set_entry (stuff->completion, GTK_ENTRY (dir_entry)); 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; gboolean case_sensitive;
char *dir; 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); g_return_if_fail (pane != NULL);
dir_entry = GTK_BIN (moo_glade_xml_get_widget (stuff->xml, "dir_combo"))->child; 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)); skip = gtk_entry_get_text (GTK_ENTRY (skip_entry));
case_sensitive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (case_sensitive_button)); 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); moo_big_paned_present_pane (window->paned, pane);
execute_find (pattern, glob, dir, skip, 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* static FileLinePair*
file_line_pair_new (const char *filename, file_line_pair_new (const char *filename,
int line) int line)
@ -404,10 +401,10 @@ file_line_pair_free (FileLinePair *pair)
} }
static void static gboolean
process_line (WindowStuff *stuff, process_line (MooPaneView *view,
const char *line, const char *line,
gboolean stderr) WindowStuff *stuff)
{ {
char *filename = NULL; char *filename = NULL;
char *number = NULL; char *number = NULL;
@ -416,19 +413,9 @@ process_line (WindowStuff *stuff,
int line_no; int line_no;
guint64 line_no_64; guint64 line_no_64;
if (stderr) /* 'Binary file blah matches' */
{
moo_pane_view_write_line (stuff->output, line, -1,
stuff->error_tag);
return;
}
/* Binary file blah matches */
if (g_str_has_prefix (line, "Binary file ")) if (g_str_has_prefix (line, "Binary file "))
{ return FALSE;
moo_pane_view_write_line (stuff->output, line, -1, NULL);
return;
}
p = line; p = line;
if (!(colon = strchr (p, ':')) || !colon[1]) if (!(colon = strchr (p, ':')) || !colon[1])
@ -447,10 +434,9 @@ process_line (WindowStuff *stuff,
{ {
g_free (stuff->current_file); g_free (stuff->current_file);
stuff->current_file = filename; stuff->current_file = filename;
view_line = moo_pane_view_write_line (stuff->output, view_line = moo_pane_view_write_line (view, filename, -1,
filename, -1,
stuff->file_tag); 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), file_line_pair_new (filename, -1),
(GDestroyNotify) file_line_pair_free); (GDestroyNotify) file_line_pair_free);
} }
@ -485,135 +471,28 @@ process_line (WindowStuff *stuff,
line_no = line_no_64 - 1; line_no = line_no_64 - 1;
} }
view_line = moo_pane_view_start_line (stuff->output); view_line = moo_pane_view_start_line (view);
moo_pane_view_write (stuff->output, number, -1, moo_pane_view_write (view, number, -1, stuff->line_number_tag);
stuff->line_number_tag); moo_pane_view_write (view, ": ", -1, NULL);
moo_pane_view_write (stuff->output, ": ", -1, NULL); moo_pane_view_write (view, p, -1, stuff->match_tag);
moo_pane_view_write (stuff->output, p, -1, stuff->match_tag); moo_pane_view_end_line (view);
moo_pane_view_end_line (stuff->output);
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), file_line_pair_new (stuff->current_file, line_no),
(GDestroyNotify) file_line_pair_free); (GDestroyNotify) file_line_pair_free);
stuff->match_count++;
g_free (number); g_free (number);
return; return TRUE;
parse_error: parse_error:
g_warning ("%s: could not parse line '%s'", g_warning ("%s: could not parse line '%s'",
G_STRLOC, line); G_STRLOC, line);
moo_pane_view_write_line (stuff->output, line, -1, NULL);
g_free (filename); g_free (filename);
g_free (number); g_free (number);
}
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; 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 static void
execute_find (const char *pattern, execute_find (const char *pattern,
@ -623,19 +502,15 @@ execute_find (const char *pattern,
gboolean case_sensitive, gboolean case_sensitive,
WindowStuff *stuff) WindowStuff *stuff)
{ {
GError *error = NULL;
char **argv = NULL;
GString *command = NULL; GString *command = NULL;
char **globs = NULL; char **globs = NULL;
g_return_if_fail (stuff->output != NULL); g_return_if_fail (stuff->output != NULL);
g_return_if_fail (pattern && pattern[0]); g_return_if_fail (pattern && pattern[0]);
if (stuff->running)
return;
g_free (stuff->current_file); g_free (stuff->current_file);
stuff->current_file = NULL; stuff->current_file = NULL;
stuff->match_count = 0;
command = g_string_new (""); command = g_string_new ("");
g_string_printf (command, "find '%s'", dir); g_string_printf (command, "find '%s'", dir);
@ -687,182 +562,54 @@ execute_find (const char *pattern,
g_string_append_printf (command, " | xargs egrep -H -n %s-e '%s'", g_string_append_printf (command, " | xargs egrep -H -n %s-e '%s'",
!case_sensitive ? "-i " : "", pattern); !case_sensitive ? "-i " : "", pattern);
moo_pane_view_write_line (stuff->output, command->str, -1, NULL); moo_cmd_view_run_command (stuff->output, command->str);
g_string_free (command, TRUE);
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);
} }
static void 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); g_return_if_fail (stuff != NULL);
stop_find (stuff);
}
g_signal_handlers_disconnect_by_func (stuff->output,
static void (gpointer) command_exit,
stop_find (WindowStuff *stuff) stuff);
{ g_signal_handlers_disconnect_by_func (stuff->output,
if (!stuff->running) (gpointer) process_line,
return; stuff);
moo_cmd_view_abort (stuff->output);
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);
}
} }
static gboolean static gboolean
output_click (WindowStuff *stuff, 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) FileLinePair *line_data)
{ {
MooEditor *editor; MooEditor *editor;

View File

@ -332,291 +332,4 @@
</child> </child>
</widget> </widget>
<widget class="GtkWindow" id="window1">
<property name="visible">True</property>
<property name="title" translatable="yes">window1</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<child>
<widget class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">6</property>
<property name="bottom_padding">6</property>
<property name="left_padding">6</property>
<property name="right_padding">6</property>
<child>
<widget class="GtkVBox" id="search_vbox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="n_rows">4</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">0</property>
<property name="column_spacing">0</property>
<child>
<widget class="GtkComboBoxEntry" id="comboboxentry1">
<property name="visible">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkComboBoxEntry" id="comboboxentry2">
<property name="visible">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkComboBoxEntry" id="comboboxentry3">
<property name="visible">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkComboBoxEntry" id="comboboxentry4">
<property name="visible">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
</child>
<child>
<widget class="GtkEventBox" id="eventbox5">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">This entry content will be passed to grep</property>
<property name="visible_window">True</property>
<property name="above_child">False</property>
<child>
<widget class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="label" translatable="yes">_Pattern:</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEventBox" id="eventbox6">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Enter semicolon-separated list of globs</property>
<property name="visible_window">True</property>
<property name="above_child">False</property>
<child>
<widget class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="label" translatable="yes">Fi_les:</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEventBox" id="eventbox7">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">You can use Tab completion in this entry. Try also Ctrl-L</property>
<property name="visible_window">True</property>
<property name="above_child">False</property>
<child>
<widget class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="label" translatable="yes">_Directory:</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEventBox" id="eventbox8">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Enter semicolon-separated list of globs</property>
<property name="visible_window">True</property>
<property name="above_child">False</property>
<child>
<widget class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="label" translatable="yes">_Skip files:</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkCheckButton" id="checkbutton1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">_Case sensitive</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">True</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-find</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">False</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">6</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</glade-interface> </glade-interface>

View File

@ -1,9 +1,11 @@
BOOL:ENUM,INT BOOL:ENUM,INT
BOOL:ENUM,INT,BOOL BOOL:ENUM,INT,BOOL
BOOL:INT
BOOL:OBJECT,OBJECT BOOL:OBJECT,OBJECT
BOOL:POINTER BOOL:POINTER
BOOL:POINTER,INT BOOL:POINTER,INT
BOOL:STRING BOOL:STRING
BOOL:STRING,BOOL
BOOL:STRING,POINTER BOOL:STRING,POINTER
BOOL:STRING,STRING BOOL:STRING,STRING
BOOL:STRING,STRING,POINTER BOOL:STRING,STRING,POINTER

View File

@ -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_GO_DOWN, MOO_STOCK_COMPILE);
register_stock_icon_alias (factory, GTK_STOCK_EXECUTE, MOO_STOCK_EXECUTE); 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)); g_object_unref (G_OBJECT (factory));
} }

View File

@ -49,7 +49,8 @@ G_BEGIN_DECLS
#define MOO_STOCK_COMPILE "moo-compile" #define MOO_STOCK_COMPILE "moo-compile"
#define MOO_STOCK_EXECUTE "moo-execute" #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); void moo_create_stock_items (void);

View File

@ -44,7 +44,7 @@ int main (int argc, char **argv)
moo_plugin_read_dir (plugin_dir); moo_plugin_read_dir (plugin_dir);
g_free (plugin_dir); g_free (plugin_dir);
moo_grep_init (); moo_find_init ();
moo_file_selector_init (); moo_file_selector_init ();
editor = moo_editor_new (); editor = moo_editor_new ();