This commit is contained in:
Perberos
2011-11-07 16:46:58 -03:00
commit 528c1e5ff5
532 changed files with 709826 additions and 0 deletions

42
plugins/Makefile.am Executable file
View File

@@ -0,0 +1,42 @@
DIST_SUBDIRS = \
changecase \
checkupdate \
docinfo \
externaltools \
filebrowser \
modelines \
pythonconsole \
quickopen \
snippets \
sort \
spell \
taglist \
time
SUBDIRS = \
changecase \
docinfo \
filebrowser \
modelines \
sort \
taglist \
time
if ENABLE_PYTHON
SUBDIRS += pythonconsole snippets quickopen
if !OS_WIN32
SUBDIRS += externaltools
endif
endif
if ENABLE_ENCHANT
SUBDIRS += spell
endif
if ENABLE_UPDATER
SUBDIRS += checkupdate
endif
-include $(top_srcdir)/git.mk

34
plugins/changecase/Makefile.am Executable file
View File

@@ -0,0 +1,34 @@
# changecase plugin
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)
INCLUDES = \
-I$(top_srcdir) \
$(GEDIT_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS)
plugin_LTLIBRARIES = libchangecase.la
libchangecase_la_SOURCES = \
gedit-changecase-plugin.h \
gedit-changecase-plugin.c
libchangecase_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libchangecase_la_LIBADD = $(GEDIT_LIBS)
uidir = $(GEDIT_PLUGINS_DATA_DIR)/changecase
ui_DATA =
plugin_in_files = changecase.gedit-plugin.desktop.in
%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin)
EXTRA_DIST = $(ui_DATA) $(plugin_in_files)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = $(plugin_DATA)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,8 @@
[Gedit Plugin]
Module=changecase
IAge=2
_Name=Change Case
_Description=Changes the case of selected text.
Authors=Paolo Borelli <pborelli@katamail.com>
Copyright=Copyright © 2004-2005 Paolo Borelli
Website=http://www.gedit.org

View File

@@ -0,0 +1,395 @@
/*
* gedit-changecase-plugin.c
*
* Copyright (C) 2004-2005 - Paolo Borelli
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "gedit-changecase-plugin.h"
#include <glib/gi18n-lib.h>
#include <gmodule.h>
#include <gedit/gedit-debug.h>
#define WINDOW_DATA_KEY "GeditChangecasePluginWindowData"
GEDIT_PLUGIN_REGISTER_TYPE(GeditChangecasePlugin, gedit_changecase_plugin)
typedef enum {
TO_UPPER_CASE,
TO_LOWER_CASE,
INVERT_CASE,
TO_TITLE_CASE,
} ChangeCaseChoice;
static void
do_upper_case (GtkTextBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end)
{
GString *s = g_string_new (NULL);
while (!gtk_text_iter_is_end (start) &&
!gtk_text_iter_equal (start, end))
{
gunichar c, nc;
c = gtk_text_iter_get_char (start);
nc = g_unichar_toupper (c);
g_string_append_unichar (s, nc);
gtk_text_iter_forward_char (start);
}
gtk_text_buffer_delete_selection (buffer, TRUE, TRUE);
gtk_text_buffer_insert_at_cursor (buffer, s->str, s->len);
g_string_free (s, TRUE);
}
static void
do_lower_case (GtkTextBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end)
{
GString *s = g_string_new (NULL);
while (!gtk_text_iter_is_end (start) &&
!gtk_text_iter_equal (start, end))
{
gunichar c, nc;
c = gtk_text_iter_get_char (start);
nc = g_unichar_tolower (c);
g_string_append_unichar (s, nc);
gtk_text_iter_forward_char (start);
}
gtk_text_buffer_delete_selection (buffer, TRUE, TRUE);
gtk_text_buffer_insert_at_cursor (buffer, s->str, s->len);
g_string_free (s, TRUE);
}
static void
do_invert_case (GtkTextBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end)
{
GString *s = g_string_new (NULL);
while (!gtk_text_iter_is_end (start) &&
!gtk_text_iter_equal (start, end))
{
gunichar c, nc;
c = gtk_text_iter_get_char (start);
if (g_unichar_islower (c))
nc = g_unichar_toupper (c);
else
nc = g_unichar_tolower (c);
g_string_append_unichar (s, nc);
gtk_text_iter_forward_char (start);
}
gtk_text_buffer_delete_selection (buffer, TRUE, TRUE);
gtk_text_buffer_insert_at_cursor (buffer, s->str, s->len);
g_string_free (s, TRUE);
}
static void
do_title_case (GtkTextBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end)
{
GString *s = g_string_new (NULL);
while (!gtk_text_iter_is_end (start) &&
!gtk_text_iter_equal (start, end))
{
gunichar c, nc;
c = gtk_text_iter_get_char (start);
if (gtk_text_iter_starts_word (start))
nc = g_unichar_totitle (c);
else
nc = g_unichar_tolower (c);
g_string_append_unichar (s, nc);
gtk_text_iter_forward_char (start);
}
gtk_text_buffer_delete_selection (buffer, TRUE, TRUE);
gtk_text_buffer_insert_at_cursor (buffer, s->str, s->len);
g_string_free (s, TRUE);
}
static void
change_case (GeditWindow *window,
ChangeCaseChoice choice)
{
GeditDocument *doc;
GtkTextIter start, end;
gedit_debug (DEBUG_PLUGINS);
doc = gedit_window_get_active_document (window);
g_return_if_fail (doc != NULL);
if (!gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc),
&start, &end))
{
return;
}
gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (doc));
switch (choice)
{
case TO_UPPER_CASE:
do_upper_case (GTK_TEXT_BUFFER (doc), &start, &end);
break;
case TO_LOWER_CASE:
do_lower_case (GTK_TEXT_BUFFER (doc), &start, &end);
break;
case INVERT_CASE:
do_invert_case (GTK_TEXT_BUFFER (doc), &start, &end);
break;
case TO_TITLE_CASE:
do_title_case (GTK_TEXT_BUFFER (doc), &start, &end);
break;
default:
g_return_if_reached ();
}
gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (doc));
}
static void
upper_case_cb (GtkAction *action,
GeditWindow *window)
{
change_case (window, TO_UPPER_CASE);
}
static void
lower_case_cb (GtkAction *action,
GeditWindow *window)
{
change_case (window, TO_LOWER_CASE);
}
static void
invert_case_cb (GtkAction *action,
GeditWindow *window)
{
change_case (window, INVERT_CASE);
}
static void
title_case_cb (GtkAction *action,
GeditWindow *window)
{
change_case (window, TO_TITLE_CASE);
}
static const GtkActionEntry action_entries[] =
{
{ "ChangeCase", NULL, N_("C_hange Case") },
{ "UpperCase", NULL, N_("All _Upper Case"), NULL,
N_("Change selected text to upper case"),
G_CALLBACK (upper_case_cb) },
{ "LowerCase", NULL, N_("All _Lower Case"), NULL,
N_("Change selected text to lower case"),
G_CALLBACK (lower_case_cb) },
{ "InvertCase", NULL, N_("_Invert Case"), NULL,
N_("Invert the case of selected text"),
G_CALLBACK (invert_case_cb) },
{ "TitleCase", NULL, N_("_Title Case"), NULL,
N_("Capitalize the first letter of each selected word"),
G_CALLBACK (title_case_cb) }
};
const gchar submenu[] =
"<ui>"
" <menubar name='MenuBar'>"
" <menu name='EditMenu' action='Edit'>"
" <placeholder name='EditOps_6'>"
" <menu action='ChangeCase'>"
" <menuitem action='UpperCase'/>"
" <menuitem action='LowerCase'/>"
" <menuitem action='InvertCase'/>"
" <menuitem action='TitleCase'/>"
" </menu>"
" </placeholder>"
" </menu>"
" </menubar>"
"</ui>";
static void
gedit_changecase_plugin_init (GeditChangecasePlugin *plugin)
{
gedit_debug_message (DEBUG_PLUGINS, "GeditChangecasePlugin initializing");
}
static void
gedit_changecase_plugin_finalize (GObject *object)
{
G_OBJECT_CLASS (gedit_changecase_plugin_parent_class)->finalize (object);
gedit_debug_message (DEBUG_PLUGINS, "GeditChangecasePlugin finalizing");
}
typedef struct
{
GtkActionGroup *action_group;
guint ui_id;
} WindowData;
static void
free_window_data (WindowData *data)
{
g_return_if_fail (data != NULL);
g_slice_free (WindowData, data);
}
static void
update_ui_real (GeditWindow *window,
WindowData *data)
{
GtkTextView *view;
GtkAction *action;
gboolean sensitive = FALSE;
gedit_debug (DEBUG_PLUGINS);
view = GTK_TEXT_VIEW (gedit_window_get_active_view (window));
if (view != NULL)
{
GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer (view);
sensitive = (gtk_text_view_get_editable (view) &&
gtk_text_buffer_get_has_selection (buffer));
}
action = gtk_action_group_get_action (data->action_group,
"ChangeCase");
gtk_action_set_sensitive (action, sensitive);
}
static void
impl_activate (GeditPlugin *plugin,
GeditWindow *window)
{
GtkUIManager *manager;
WindowData *data;
GError *error = NULL;
gedit_debug (DEBUG_PLUGINS);
data = g_slice_new (WindowData);
manager = gedit_window_get_ui_manager (window);
data->action_group = gtk_action_group_new ("GeditChangecasePluginActions");
gtk_action_group_set_translation_domain (data->action_group,
GETTEXT_PACKAGE);
gtk_action_group_add_actions (data->action_group,
action_entries,
G_N_ELEMENTS (action_entries),
window);
gtk_ui_manager_insert_action_group (manager, data->action_group, -1);
data->ui_id = gtk_ui_manager_add_ui_from_string (manager,
submenu,
-1,
&error);
if (data->ui_id == 0)
{
g_warning ("%s", error->message);
free_window_data (data);
return;
}
g_object_set_data_full (G_OBJECT (window),
WINDOW_DATA_KEY,
data,
(GDestroyNotify) free_window_data);
update_ui_real (window, data);
}
static void
impl_deactivate (GeditPlugin *plugin,
GeditWindow *window)
{
GtkUIManager *manager;
WindowData *data;
gedit_debug (DEBUG_PLUGINS);
manager = gedit_window_get_ui_manager (window);
data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY);
g_return_if_fail (data != NULL);
gtk_ui_manager_remove_ui (manager, data->ui_id);
gtk_ui_manager_remove_action_group (manager, data->action_group);
g_object_set_data (G_OBJECT (window), WINDOW_DATA_KEY, NULL);
}
static void
impl_update_ui (GeditPlugin *plugin,
GeditWindow *window)
{
WindowData *data;
gedit_debug (DEBUG_PLUGINS);
data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY);
g_return_if_fail (data != NULL);
update_ui_real (window, data);
}
static void
gedit_changecase_plugin_class_init (GeditChangecasePluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass);
object_class->finalize = gedit_changecase_plugin_finalize;
plugin_class->activate = impl_activate;
plugin_class->deactivate = impl_deactivate;
plugin_class->update_ui = impl_update_ui;
}

View File

@@ -0,0 +1,72 @@
/*
* gedit-changecase-plugin.h
*
* Copyright (C) 2004-2005 - Paolo Borelli
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id$
*/
#ifndef __GEDIT_CHANGECASE_PLUGIN_H__
#define __GEDIT_CHANGECASE_PLUGIN_H__
#include <glib.h>
#include <glib-object.h>
#include <gedit/gedit-plugin.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define GEDIT_TYPE_CHANGECASE_PLUGIN (gedit_changecase_plugin_get_type ())
#define GEDIT_CHANGECASE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_CHANGECASE_PLUGIN, GeditChangecasePlugin))
#define GEDIT_CHANGECASE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_CHANGECASE_PLUGIN, GeditChangecasePluginClass))
#define GEDIT_IS_CHANGECASE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_CHANGECASE_PLUGIN))
#define GEDIT_IS_CHANGECASE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_CHANGECASE_PLUGIN))
#define GEDIT_CHANGECASE_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_CHANGECASE_PLUGIN, GeditChangecasePluginClass))
/*
* Main object structure
*/
typedef struct _GeditChangecasePlugin GeditChangecasePlugin;
struct _GeditChangecasePlugin
{
GeditPlugin parent_instance;
};
/*
* Class definition
*/
typedef struct _GeditChangecasePluginClass GeditChangecasePluginClass;
struct _GeditChangecasePluginClass
{
GeditPluginClass parent_class;
};
/*
* Public methods
*/
GType gedit_changecase_plugin_get_type (void) G_GNUC_CONST;
/* All the plugins must implement this function */
G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module);
G_END_DECLS
#endif /* __GEDIT_CHANGECASE_PLUGIN_H__ */

49
plugins/checkupdate/Makefile.am Executable file
View File

@@ -0,0 +1,49 @@
# gedit win32 updater
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)
INCLUDES = \
-I$(top_srcdir) \
$(GEDIT_CFLAGS) \
$(LIBSOUP_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS)
plugin_LTLIBRARIES = libcheckupdate.la
libcheckupdate_la_SOURCES = \
gedit-check-update-plugin.h \
gedit-check-update-plugin.c
libcheckupdate_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libcheckupdate_la_LIBADD = $(GEDIT_LIBS) $(LIBSOUP_LIBS)
plugin_in_files = checkupdate.gedit-plugin.desktop.in
%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin)
schemasdir = $(MATECONF_SCHEMA_FILE_DIR)
schemas_in_files = gedit-check-update.schemas.in
schemas_DATA = $(schemas_in_files:.schemas.in=.schemas)
@INTLTOOL_SCHEMAS_RULE@
if MATECONF_SCHEMAS_INSTALL
install-data-local:
if test -z "$(DESTDIR)" ; then \
for p in $(schemas_DATA) ; do \
MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(MATECONFTOOL) --makefile-install-rule $(top_builddir)/plugins/checkupdate/$$p ; \
done \
fi
else
install-data-local:
endif
EXTRA_DIST = $(plugin_in_files) $(schemas_in_files)
CLEANFILES = $(plugin_DATA) $(schemas_DATA)
DISTCLEANFILES = $(plugin_DATA) $(schemas_DATA)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,9 @@
[Gedit Plugin]
Module=checkupdate
IAge=2
_Name=Check update
_Description=Check for latest version of gedit
Icon=gedit-plugin
Authors=Ignacio Casal Quinteiro <icq@gnome.org>
Copyright=Copyright © 2009 Ignacio Casal Quinteiro
Website=http://www.gedit.org

View File

@@ -0,0 +1,697 @@
/*
* Copyright (C) 2009 - Ignacio Casal Quinteiro <icq@gnome.org>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "gedit-check-update-plugin.h"
#include <glib/gi18n-lib.h>
#include <gedit/gedit-debug.h>
#include <gedit/gedit-utils.h>
#include <libsoup/soup.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include <mateconf/mateconf-client.h>
#if !GTK_CHECK_VERSION(2, 17, 1)
#include <gedit/gedit-message-area.h>
#endif
#define MATECONF_KEY_BASE "/apps/gedit-2/plugins/checkupdate"
#define MATECONF_KEY_IGNORE_VERSION MATECONF_KEY_BASE "/ignore_version"
#define WINDOW_DATA_KEY "GeditCheckUpdatePluginWindowData"
#define VERSION_PLACE "<a href=\"[0-9]\\.[0-9]+/\">"
#ifdef G_OS_WIN32
#define GEDIT_URL "http://ftp.acc.umu.se/pub/mate/binaries/win32/gedit/"
#define FILE_REGEX "gedit\\-setup\\-[0-9]+\\.[0-9]+\\.[0-9]+(\\-[0-9]+)?\\.exe"
#else
#define GEDIT_URL "http://ftp.acc.umu.se/pub/mate/binaries/mac/gedit/"
#define FILE_REGEX "gedit\\-[0-9]+\\.[0-9]+\\.[0-9]+(\\-[0-9]+)?\\.dmg"
#endif
#ifdef OS_OSX
#include "gedit/osx/gedit-osx.h"
#endif
#define GEDIT_CHECK_UPDATE_PLUGIN_GET_PRIVATE(object) \
(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
GEDIT_TYPE_CHECK_UPDATE_PLUGIN, \
GeditCheckUpdatePluginPrivate))
GEDIT_PLUGIN_REGISTER_TYPE (GeditCheckUpdatePlugin, gedit_check_update_plugin)
struct _GeditCheckUpdatePluginPrivate
{
SoupSession *session;
MateConfClient *mateconf_client;
};
typedef struct
{
GeditCheckUpdatePlugin *plugin;
gchar *url;
gchar *version;
} WindowData;
static void
free_window_data (gpointer data)
{
WindowData *window_data;
if (data == NULL)
return;
window_data = (WindowData *)data;
g_free (window_data->url);
g_free (window_data->version);
g_slice_free (WindowData, data);
}
static void
gedit_check_update_plugin_init (GeditCheckUpdatePlugin *plugin)
{
plugin->priv = GEDIT_CHECK_UPDATE_PLUGIN_GET_PRIVATE (plugin);
gedit_debug_message (DEBUG_PLUGINS,
"GeditCheckUpdatePlugin initializing");
plugin->priv->session = soup_session_async_new ();
plugin->priv->mateconf_client = mateconf_client_get_default ();
mateconf_client_add_dir (plugin->priv->mateconf_client,
MATECONF_KEY_BASE,
MATECONF_CLIENT_PRELOAD_ONELEVEL,
NULL);
}
static void
gedit_check_update_plugin_dispose (GObject *object)
{
GeditCheckUpdatePlugin *plugin = GEDIT_CHECK_UPDATE_PLUGIN (object);
if (plugin->priv->session != NULL)
{
g_object_unref (plugin->priv->session);
plugin->priv->session = NULL;
}
if (plugin->priv->mateconf_client != NULL)
{
mateconf_client_suggest_sync (plugin->priv->mateconf_client, NULL);
g_object_unref (G_OBJECT (plugin->priv->mateconf_client));
plugin->priv->mateconf_client = NULL;
}
gedit_debug_message (DEBUG_PLUGINS,
"GeditCheckUpdatePlugin disposing");
G_OBJECT_CLASS (gedit_check_update_plugin_parent_class)->dispose (object);
}
static void
gedit_check_update_plugin_finalize (GObject *object)
{
gedit_debug_message (DEBUG_PLUGINS,
"GeditCheckUpdatePlugin finalizing");
G_OBJECT_CLASS (gedit_check_update_plugin_parent_class)->finalize (object);
}
static void
set_contents (GtkWidget *infobar,
GtkWidget *contents)
{
#if !GTK_CHECK_VERSION (2, 17, 1)
gedit_message_area_set_contents (GEDIT_MESSAGE_AREA (infobar),
contents);
#else
GtkWidget *content_area;
content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar));
gtk_container_add (GTK_CONTAINER (content_area), contents);
#endif
}
static void
set_message_area_text_and_icon (GtkWidget *message_area,
const gchar *icon_stock_id,
const gchar *primary_text,
const gchar *secondary_text)
{
GtkWidget *hbox_content;
GtkWidget *image;
GtkWidget *vbox;
gchar *primary_markup;
gchar *secondary_markup;
GtkWidget *primary_label;
GtkWidget *secondary_label;
hbox_content = gtk_hbox_new (FALSE, 8);
gtk_widget_show (hbox_content);
image = gtk_image_new_from_stock (icon_stock_id, GTK_ICON_SIZE_DIALOG);
gtk_widget_show (image);
gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0);
vbox = gtk_vbox_new (FALSE, 6);
gtk_widget_show (vbox);
gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
primary_label = gtk_label_new (primary_markup);
g_free (primary_markup);
gtk_widget_show (primary_label);
gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
gtk_misc_set_alignment (GTK_MISC (primary_label), 0, 0.5);
GTK_WIDGET_SET_FLAGS (primary_label, GTK_CAN_FOCUS);
gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
if (secondary_text != NULL)
{
secondary_markup = g_strdup_printf ("<small>%s</small>",
secondary_text);
secondary_label = gtk_label_new (secondary_markup);
g_free (secondary_markup);
gtk_widget_show (secondary_label);
gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
GTK_WIDGET_SET_FLAGS (secondary_label, GTK_CAN_FOCUS);
gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
gtk_misc_set_alignment (GTK_MISC (secondary_label), 0, 0.5);
}
set_contents (message_area, hbox_content);
}
static void
on_response_cb (GtkWidget *infobar,
gint response_id,
GeditWindow *window)
{
if (response_id == GTK_RESPONSE_YES)
{
GError *error = NULL;
WindowData *data;
data = g_object_get_data (G_OBJECT (window),
WINDOW_DATA_KEY);
#ifdef OS_OSX
gedit_osx_show_url (data->url);
#else
gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (window)),
data->url,
GDK_CURRENT_TIME,
&error);
#endif
if (error != NULL)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
_("There was an error displaying the URI."));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", error->message);
g_signal_connect (G_OBJECT (dialog),
"response",
G_CALLBACK (gtk_widget_destroy),
NULL);
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
gtk_widget_show (dialog);
g_error_free (error);
}
}
else if (response_id == GTK_RESPONSE_NO)
{
WindowData *data;
data = g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY);
mateconf_client_set_string (data->plugin->priv->mateconf_client,
MATECONF_KEY_IGNORE_VERSION,
data->version,
NULL);
}
g_object_set_data (G_OBJECT (window),
WINDOW_DATA_KEY,
NULL);
gtk_widget_destroy (infobar);
}
static GtkWidget *
create_infobar (GeditWindow *window,
const gchar *version)
{
GtkWidget *infobar;
gchar *message;
#if !GTK_CHECK_VERSION (2, 17, 1)
infobar = gedit_message_area_new ();
gedit_message_area_add_stock_button_with_text (GEDIT_MESSAGE_AREA (infobar),
_("_Download"),
GTK_STOCK_SAVE,
GTK_RESPONSE_YES);
gedit_message_area_add_stock_button_with_text (GEDIT_MESSAGE_AREA (infobar),
_("_Ignore Version"),
GTK_STOCK_DISCARD,
GTK_RESPONSE_NO);
gedit_message_area_add_button (GEDIT_MESSAGE_AREA (infobar),
GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL);
#else
GtkWidget *button;
infobar = gtk_info_bar_new ();
button = gedit_gtk_button_new_with_stock_icon (_("_Download"),
GTK_STOCK_SAVE);
gtk_widget_show (button);
gtk_info_bar_add_action_widget (GTK_INFO_BAR (infobar),
button,
GTK_RESPONSE_YES);
button = gedit_gtk_button_new_with_stock_icon (_("_Ignore Version"),
GTK_STOCK_DISCARD);
gtk_widget_show (button);
gtk_info_bar_add_action_widget (GTK_INFO_BAR (infobar),
button,
GTK_RESPONSE_NO);
gtk_info_bar_add_button (GTK_INFO_BAR (infobar),
GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL);
gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar),
GTK_MESSAGE_INFO);
#endif
message = g_strdup_printf ("%s (%s)", _("There is a new version of gedit"), version);
set_message_area_text_and_icon (infobar,
"gtk-dialog-info",
message,
_("You can download the new version of gedit"
" by clicking on the download button or"
" ignore that version and wait for a new one"));
g_free (message);
g_signal_connect (infobar, "response",
G_CALLBACK (on_response_cb),
window);
return infobar;
}
static void
pack_infobar (GtkWidget *window,
GtkWidget *infobar)
{
GtkWidget *vbox;
vbox = gtk_bin_get_child (GTK_BIN (window));
gtk_box_pack_start (GTK_BOX (vbox), infobar, FALSE, FALSE, 0);
gtk_box_reorder_child (GTK_BOX (vbox), infobar, 2);
}
static gchar *
get_file (const gchar *text,
const gchar *regex_place)
{
GRegex *regex;
GMatchInfo *match_info;
gchar *word = NULL;
regex = g_regex_new (regex_place, 0, 0, NULL);
g_regex_match (regex, text, 0, &match_info);
while (g_match_info_matches (match_info))
{
g_free (word);
word = g_match_info_fetch (match_info, 0);
g_match_info_next (match_info, NULL);
}
g_match_info_free (match_info);
g_regex_unref (regex);
return word;
}
static void
get_numbers (const gchar *version,
gint *major,
gint *minor,
gint *micro)
{
gchar **split;
gint num = 2;
if (micro != NULL)
num = 3;
split = g_strsplit (version, ".", num);
*major = atoi (split[0]);
*minor = atoi (split[1]);
if (micro != NULL)
*micro = atoi (split[2]);
g_strfreev (split);
}
static gboolean
newer_version (const gchar *v1,
const gchar *v2,
gboolean with_micro)
{
gboolean newer = FALSE;
gint major1, minor1, micro1;
gint major2, minor2, micro2;
if (v1 == NULL || v2 == NULL)
return FALSE;
if (with_micro)
{
get_numbers (v1, &major1, &minor1, &micro1);
get_numbers (v2, &major2, &minor2, &micro2);
}
else
{
get_numbers (v1, &major1, &minor1, NULL);
get_numbers (v2, &major2, &minor2, NULL);
}
if (major1 > major2)
{
newer = TRUE;
}
else if (minor1 > minor2 && major1 == major2)
{
newer = TRUE;
}
else if (with_micro && micro1 > micro2 && minor1 == minor2)
{
newer = TRUE;
}
return newer;
}
static gchar *
parse_file_version (const gchar *file)
{
gchar *p, *aux;
p = (gchar *)file;
while (*p != '\0' && !g_ascii_isdigit (*p))
{
p++;
}
if (*p == '\0')
return NULL;
aux = g_strrstr (p, "-");
if (aux == NULL)
aux = g_strrstr (p, ".");
return g_strndup (p, aux - p);
}
static gchar *
get_ignore_version (GeditCheckUpdatePlugin *plugin)
{
return mateconf_client_get_string (plugin->priv->mateconf_client,
MATECONF_KEY_IGNORE_VERSION,
NULL);
}
static void
parse_page_file (SoupSession *session,
SoupMessage *msg,
GeditWindow *window)
{
if (msg->status_code == SOUP_STATUS_OK)
{
gchar *file;
gchar *file_version;
gchar *ignore_version;
WindowData *data;
data = g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY);
file = get_file (msg->response_body->data, FILE_REGEX);
file_version = parse_file_version (file);
ignore_version = get_ignore_version (data->plugin);
if (newer_version (file_version, VERSION, TRUE) &&
(ignore_version == NULL || *ignore_version == '\0' ||
newer_version (file_version, ignore_version, TRUE)))
{
GtkWidget *infobar;
WindowData *data;
gchar *file_url;
data = g_object_get_data (G_OBJECT (window),
WINDOW_DATA_KEY);
file_url = g_strconcat (data->url, file, NULL);
g_free (data->url);
data->url = file_url;
data->version = g_strdup (file_version);
infobar = create_infobar (window, file_version);
pack_infobar (GTK_WIDGET (window), infobar);
gtk_widget_show (infobar);
}
g_free (ignore_version);
g_free (file_version);
g_free (file);
}
else
{
g_object_set_data (G_OBJECT (window),
WINDOW_DATA_KEY,
NULL);
}
}
static gboolean
is_unstable (const gchar *version)
{
gchar **split;
gint minor;
gboolean unstable = TRUE;;
split = g_strsplit (version, ".", 2);
minor = atoi (split[1]);
g_strfreev (split);
if ((minor % 2) == 0)
unstable = FALSE;
return unstable;
}
static gchar *
get_file_page_version (const gchar *text,
const gchar *regex_place)
{
GRegex *regex;
GMatchInfo *match_info;
GString *string = NULL;
gchar *unstable = NULL;
gchar *stable = NULL;
regex = g_regex_new (regex_place, 0, 0, NULL);
g_regex_match (regex, text, 0, &match_info);
while (g_match_info_matches (match_info))
{
gint end;
gint i;
g_match_info_fetch_pos (match_info, 0, NULL, &end);
string = g_string_new ("");
i = end;
while (text[i] != '/')
{
string = g_string_append_c (string, text[i]);
i++;
}
if (is_unstable (string->str))
{
g_free (unstable);
unstable = g_string_free (string, FALSE);
}
else
{
g_free (stable);
stable = g_string_free (string, FALSE);
}
g_match_info_next (match_info, NULL);
}
g_match_info_free (match_info);
g_regex_unref (regex);
if ((GEDIT_MINOR_VERSION % 2) == 0)
{
g_free (unstable);
return stable;
}
else
{
/* We need to check that stable isn't newer than unstable */
if (newer_version (stable, unstable, FALSE))
{
g_free (unstable);
return stable;
}
else
{
g_free (stable);
return unstable;
}
}
}
static void
parse_page_version (SoupSession *session,
SoupMessage *msg,
GeditWindow *window)
{
if (msg->status_code == SOUP_STATUS_OK)
{
gchar *version;
SoupMessage *msg2;
WindowData *data;
data = g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY);
version = get_file_page_version (msg->response_body->data,
VERSION_PLACE);
data->url = g_strconcat (GEDIT_URL, version, "/", NULL);
g_free (version);
msg2 = soup_message_new ("GET", data->url);
soup_session_queue_message (session, msg2,
(SoupSessionCallback)parse_page_file,
window);
}
else
{
g_object_set_data (G_OBJECT (window),
WINDOW_DATA_KEY,
NULL);
}
}
static void
impl_activate (GeditPlugin *plugin,
GeditWindow *window)
{
SoupMessage *msg;
WindowData *data;
gedit_debug (DEBUG_PLUGINS);
data = g_slice_new (WindowData);
data->plugin = GEDIT_CHECK_UPDATE_PLUGIN (plugin);
data->url = NULL;
data->version = NULL;
g_object_set_data_full (G_OBJECT (window),
WINDOW_DATA_KEY,
data,
free_window_data);
msg = soup_message_new ("GET", GEDIT_URL);
soup_session_queue_message (GEDIT_CHECK_UPDATE_PLUGIN (plugin)->priv->session, msg,
(SoupSessionCallback)parse_page_version,
window);
}
static void
impl_deactivate (GeditPlugin *plugin,
GeditWindow *window)
{
gedit_debug (DEBUG_PLUGINS);
soup_session_abort (GEDIT_CHECK_UPDATE_PLUGIN (plugin)->priv->session);
g_object_set_data (G_OBJECT (window),
WINDOW_DATA_KEY,
NULL);
}
static void
gedit_check_update_plugin_class_init (GeditCheckUpdatePluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass);
g_type_class_add_private (object_class, sizeof (GeditCheckUpdatePluginPrivate));
object_class->finalize = gedit_check_update_plugin_finalize;
object_class->dispose = gedit_check_update_plugin_dispose;
plugin_class->activate = impl_activate;
plugin_class->deactivate = impl_deactivate;
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2009 - Ignacio Casal Quinteiro <icq@gnome.org>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GEDIT_CHECK_UPDATE_PLUGIN_H__
#define __GEDIT_CHECK_UPDATE_PLUGIN_H__
#include <glib.h>
#include <glib-object.h>
#include <gedit/gedit-plugin.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define GEDIT_TYPE_CHECK_UPDATE_PLUGIN (gedit_check_update_plugin_get_type ())
#define GEDIT_CHECK_UPDATE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_CHECK_UPDATE_PLUGIN, GeditCheckUpdatePlugin))
#define GEDIT_CHECK_UPDATE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_CHECK_UPDATE_PLUGIN, GeditCheckUpdatePluginClass))
#define IS_GEDIT_CHECK_UPDATE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_CHECK_UPDATE_PLUGIN))
#define IS_GEDIT_CHECK_UPDATE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_CHECK_UPDATE_PLUGIN))
#define GEDIT_CHECK_UPDATE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_CHECK_UPDATE_PLUGIN, GeditCheckUpdatePluginClass))
/* Private structure type */
typedef struct _GeditCheckUpdatePluginPrivate GeditCheckUpdatePluginPrivate;
/*
* Main object structure
*/
typedef struct _GeditCheckUpdatePlugin GeditCheckUpdatePlugin;
struct _GeditCheckUpdatePlugin
{
GeditPlugin parent_instance;
/*< private >*/
GeditCheckUpdatePluginPrivate *priv;
};
/*
* Class definition
*/
typedef struct _GeditCheckUpdatePluginClass GeditCheckUpdatePluginClass;
struct _GeditCheckUpdatePluginClass
{
GeditPluginClass parent_class;
};
/*
* Public methods
*/
GType gedit_check_update_plugin_get_type (void) G_GNUC_CONST;
/* All the plugins must implement this function */
G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module);
G_END_DECLS
#endif /* __GEDIT_CHECK_UPDATE_PLUGIN_H__ */

View File

@@ -0,0 +1,13 @@
<mateconfschemafile>
<schemalist>
<schema>
<key>/schemas/apps/gedit-2/plugins/checkupdate/ignore_version</key>
<applyto>/apps/gedit-2/plugins/checkupdate/ignore_version</applyto>
<owner>gedit</owner>
<type>string</type>
<locale name="C">
<short>Version to ignore until the next version is released</short>
</locale>
</schema>
</schemalist>
</mateconfschemafile>

34
plugins/docinfo/Makefile.am Executable file
View File

@@ -0,0 +1,34 @@
# docinfo plugin
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)
INCLUDES = \
-I$(top_srcdir) \
$(GEDIT_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS)
plugin_LTLIBRARIES = libdocinfo.la
libdocinfo_la_SOURCES = \
gedit-docinfo-plugin.h \
gedit-docinfo-plugin.c
libdocinfo_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libdocinfo_la_LIBADD = $(GEDIT_LIBS)
uidir = $(GEDIT_PLUGINS_DATA_DIR)/docinfo
ui_DATA = docinfo.ui
plugin_in_files = docinfo.gedit-plugin.desktop.in
%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin)
EXTRA_DIST = $(ui_DATA) $(plugin_in_files)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = $(plugin_DATA)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,7 @@
[Gedit Plugin]
Module=docinfo
IAge=2
_Name=Document Statistics
_Description=Analyzes the current document and reports the number of words, lines, characters and non-space characters in it.
Authors=Paolo Maggi <paolo.maggi@polito.it>;Jorge Alberto Torres <jorge@deadoak.com>
Copyright=Copyright © 2002-2005 Paolo Maggi

621
plugins/docinfo/docinfo.ui Executable file
View File

@@ -0,0 +1,621 @@
<?xml version="1.0"?>
<!--*- mode: xml -*-->
<interface>
<object class="GtkDialog" id="dialog">
<property name="border_width">5</property>
<property name="title" translatable="yes">Document Statistics</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">False</property>
<property name="destroy_with_parent">True</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_DIALOG</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">8</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<object class="GtkButton" id="close_button">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</object>
</child>
<child>
<object class="GtkButton" id="update_button">
<property name="label" translatable="yes">_Update</property>
<property name="use_underline">True</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="image">update_image</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="docinfo_dialog_content">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="file_name_label">
<property name="visible">True</property>
<property name="label" translatable="yes">File Name</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
<attributes>
<attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
</attributes>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<object class="GtkLabel" id="label28">
<property name="visible">True</property>
<property name="label" translatable="yes"> </property>
<property name="use_underline">False</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">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkTable" id="table1">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="n_rows">6</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">6</property>
<property name="column_spacing">18</property>
<child>
<object class="GtkLabel" id="label26">
<property name="visible">True</property>
<property name="label" translatable="yes">Bytes</property>
<property name="use_underline">False</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">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">fill</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="bytes_label">
<property name="visible">True</property>
<property name="label">0</property>
<property name="use_underline">False</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>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">fill</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="label" translatable="yes">Characters (no spaces)</property>
<property name="use_underline">False</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">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">fill</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="chars_ns_label">
<property name="visible">True</property>
<property name="label">0</property>
<property name="use_underline">False</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>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">fill</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="label" translatable="yes">Characters (with spaces)</property>
<property name="use_underline">False</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">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<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"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="chars_label">
<property name="visible">True</property>
<property name="label">0</property>
<property name="use_underline">False</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>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<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"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="words_label">
<property name="visible">True</property>
<property name="label">0</property>
<property name="use_underline">False</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>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<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="x_options">fill</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">Words</property>
<property name="use_underline">False</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">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<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"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="label" translatable="yes">Lines</property>
<property name="use_underline">False</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">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<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"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="lines_label">
<property name="visible">True</property>
<property name="label">0</property>
<property name="use_underline">False</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>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<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="x_options">fill</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label30">
<property name="visible">True</property>
<property name="label" translatable="yes">Document</property>
<property name="use_underline">True</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_CENTER</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<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="x_options">fill</property>
<property name="y_options"/>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="selection_vbox">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="selection_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Selection</property>
<property name="use_underline">False</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">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="selected_lines_label">
<property name="visible">True</property>
<property name="label">0</property>
<property name="use_underline">False</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>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="selected_words_label">
<property name="visible">True</property>
<property name="label">0</property>
<property name="use_underline">False</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>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="selected_chars_label">
<property name="visible">True</property>
<property name="label">0</property>
<property name="use_underline">False</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>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="selected_chars_ns_label">
<property name="visible">True</property>
<property name="label">0</property>
<property name="use_underline">False</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>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="selected_bytes_label">
<property name="visible">True</property>
<property name="label">0</property>
<property name="use_underline">False</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>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-7">close_button</action-widget>
<action-widget response="-5">update_button</action-widget>
</action-widgets>
</object>
<object class="GtkImage" id="update_image">
<property name="visible">True</property>
<property name="stock">gtk-refresh</property>
</object>
</interface>

View File

@@ -0,0 +1,580 @@
/*
* gedit-docinfo-plugin.c
*
* Copyright (C) 2002-2005 Paolo Maggi
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "gedit-docinfo-plugin.h"
#include <string.h> /* For strlen (...) */
#include <glib/gi18n-lib.h>
#include <pango/pango-break.h>
#include <gmodule.h>
#include <gedit/gedit-debug.h>
#include <gedit/gedit-utils.h>
#define WINDOW_DATA_KEY "GeditDocInfoWindowData"
#define MENU_PATH "/MenuBar/ToolsMenu/ToolsOps_2"
GEDIT_PLUGIN_REGISTER_TYPE(GeditDocInfoPlugin, gedit_docinfo_plugin)
typedef struct
{
GtkWidget *dialog;
GtkWidget *file_name_label;
GtkWidget *lines_label;
GtkWidget *words_label;
GtkWidget *chars_label;
GtkWidget *chars_ns_label;
GtkWidget *bytes_label;
GtkWidget *selection_vbox;
GtkWidget *selected_lines_label;
GtkWidget *selected_words_label;
GtkWidget *selected_chars_label;
GtkWidget *selected_chars_ns_label;
GtkWidget *selected_bytes_label;
} DocInfoDialog;
typedef struct
{
GeditPlugin *plugin;
GtkActionGroup *ui_action_group;
guint ui_id;
DocInfoDialog *dialog;
} WindowData;
static void docinfo_dialog_response_cb (GtkDialog *widget,
gint res_id,
GeditWindow *window);
static void
docinfo_dialog_destroy_cb (GtkObject *obj,
WindowData *data)
{
gedit_debug (DEBUG_PLUGINS);
if (data != NULL)
{
g_free (data->dialog);
data->dialog = NULL;
}
}
static DocInfoDialog *
get_docinfo_dialog (GeditWindow *window,
WindowData *data)
{
DocInfoDialog *dialog;
gchar *data_dir;
gchar *ui_file;
GtkWidget *content;
GtkWidget *error_widget;
gboolean ret;
gedit_debug (DEBUG_PLUGINS);
dialog = g_new (DocInfoDialog, 1);
data_dir = gedit_plugin_get_data_dir (data->plugin);
ui_file = g_build_filename (data_dir, "docinfo.ui", NULL);
ret = gedit_utils_get_ui_objects (ui_file,
NULL,
&error_widget,
"dialog", &dialog->dialog,
"docinfo_dialog_content", &content,
"file_name_label", &dialog->file_name_label,
"words_label", &dialog->words_label,
"bytes_label", &dialog->bytes_label,
"lines_label", &dialog->lines_label,
"chars_label", &dialog->chars_label,
"chars_ns_label", &dialog->chars_ns_label,
"selection_vbox", &dialog->selection_vbox,
"selected_words_label", &dialog->selected_words_label,
"selected_bytes_label", &dialog->selected_bytes_label,
"selected_lines_label", &dialog->selected_lines_label,
"selected_chars_label", &dialog->selected_chars_label,
"selected_chars_ns_label", &dialog->selected_chars_ns_label,
NULL);
g_free (data_dir);
g_free (ui_file);
if (!ret)
{
const gchar *err_message;
err_message = gtk_label_get_label (GTK_LABEL (error_widget));
gedit_warning (GTK_WINDOW (window), "%s", err_message);
g_free (dialog);
gtk_widget_destroy (error_widget);
return NULL;
}
gtk_dialog_set_default_response (GTK_DIALOG (dialog->dialog),
GTK_RESPONSE_OK);
gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog),
GTK_WINDOW (window));
g_signal_connect (dialog->dialog,
"destroy",
G_CALLBACK (docinfo_dialog_destroy_cb),
data);
g_signal_connect (dialog->dialog,
"response",
G_CALLBACK (docinfo_dialog_response_cb),
window);
return dialog;
}
static void
calculate_info (GeditDocument *doc,
GtkTextIter *start,
GtkTextIter *end,
gint *chars,
gint *words,
gint *white_chars,
gint *bytes)
{
gchar *text;
gedit_debug (DEBUG_PLUGINS);
text = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc),
start,
end,
TRUE);
*chars = g_utf8_strlen (text, -1);
*bytes = strlen (text);
if (*chars > 0)
{
PangoLogAttr *attrs;
gint i;
attrs = g_new0 (PangoLogAttr, *chars + 1);
pango_get_log_attrs (text,
-1,
0,
pango_language_from_string ("C"),
attrs,
*chars + 1);
for (i = 0; i < (*chars); i++)
{
if (attrs[i].is_white)
++(*white_chars);
if (attrs[i].is_word_start)
++(*words);
}
g_free (attrs);
}
else
{
*white_chars = 0;
*words = 0;
}
g_free (text);
}
static void
docinfo_real (GeditDocument *doc,
DocInfoDialog *dialog)
{
GtkTextIter start, end;
gint words = 0;
gint chars = 0;
gint white_chars = 0;
gint lines = 0;
gint bytes = 0;
gchar *tmp_str;
gchar *doc_name;
gedit_debug (DEBUG_PLUGINS);
gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc),
&start,
&end);
lines = gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (doc));
calculate_info (doc,
&start, &end,
&chars, &words, &white_chars, &bytes);
if (chars == 0)
lines = 0;
gedit_debug_message (DEBUG_PLUGINS, "Chars: %d", chars);
gedit_debug_message (DEBUG_PLUGINS, "Lines: %d", lines);
gedit_debug_message (DEBUG_PLUGINS, "Words: %d", words);
gedit_debug_message (DEBUG_PLUGINS, "Chars non-space: %d", chars - white_chars);
gedit_debug_message (DEBUG_PLUGINS, "Bytes: %d", bytes);
doc_name = gedit_document_get_short_name_for_display (doc);
tmp_str = g_strdup_printf ("<span weight=\"bold\">%s</span>", doc_name);
gtk_label_set_markup (GTK_LABEL (dialog->file_name_label), tmp_str);
g_free (doc_name);
g_free (tmp_str);
tmp_str = g_strdup_printf("%d", lines);
gtk_label_set_text (GTK_LABEL (dialog->lines_label), tmp_str);
g_free (tmp_str);
tmp_str = g_strdup_printf("%d", words);
gtk_label_set_text (GTK_LABEL (dialog->words_label), tmp_str);
g_free (tmp_str);
tmp_str = g_strdup_printf("%d", chars);
gtk_label_set_text (GTK_LABEL (dialog->chars_label), tmp_str);
g_free (tmp_str);
tmp_str = g_strdup_printf("%d", chars - white_chars);
gtk_label_set_text (GTK_LABEL (dialog->chars_ns_label), tmp_str);
g_free (tmp_str);
tmp_str = g_strdup_printf("%d", bytes);
gtk_label_set_text (GTK_LABEL (dialog->bytes_label), tmp_str);
g_free (tmp_str);
}
static void
selectioninfo_real (GeditDocument *doc,
DocInfoDialog *dialog)
{
gboolean sel;
GtkTextIter start, end;
gint words = 0;
gint chars = 0;
gint white_chars = 0;
gint lines = 0;
gint bytes = 0;
gchar *tmp_str;
gedit_debug (DEBUG_PLUGINS);
sel = gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc),
&start,
&end);
if (sel)
{
lines = gtk_text_iter_get_line (&end) - gtk_text_iter_get_line (&start) + 1;
calculate_info (doc,
&start, &end,
&chars, &words, &white_chars, &bytes);
gedit_debug_message (DEBUG_PLUGINS, "Selected chars: %d", chars);
gedit_debug_message (DEBUG_PLUGINS, "Selected lines: %d", lines);
gedit_debug_message (DEBUG_PLUGINS, "Selected words: %d", words);
gedit_debug_message (DEBUG_PLUGINS, "Selected chars non-space: %d", chars - white_chars);
gedit_debug_message (DEBUG_PLUGINS, "Selected bytes: %d", bytes);
gtk_widget_set_sensitive (dialog->selection_vbox, TRUE);
}
else
{
gtk_widget_set_sensitive (dialog->selection_vbox, FALSE);
gedit_debug_message (DEBUG_PLUGINS, "Selection empty");
}
if (chars == 0)
lines = 0;
tmp_str = g_strdup_printf("%d", lines);
gtk_label_set_text (GTK_LABEL (dialog->selected_lines_label), tmp_str);
g_free (tmp_str);
tmp_str = g_strdup_printf("%d", words);
gtk_label_set_text (GTK_LABEL (dialog->selected_words_label), tmp_str);
g_free (tmp_str);
tmp_str = g_strdup_printf("%d", chars);
gtk_label_set_text (GTK_LABEL (dialog->selected_chars_label), tmp_str);
g_free (tmp_str);
tmp_str = g_strdup_printf("%d", chars - white_chars);
gtk_label_set_text (GTK_LABEL (dialog->selected_chars_ns_label), tmp_str);
g_free (tmp_str);
tmp_str = g_strdup_printf("%d", bytes);
gtk_label_set_text (GTK_LABEL (dialog->selected_bytes_label), tmp_str);
g_free (tmp_str);
}
static void
docinfo_cb (GtkAction *action,
GeditWindow *window)
{
GeditDocument *doc;
WindowData *data;
gedit_debug (DEBUG_PLUGINS);
data = (WindowData *) g_object_get_data (G_OBJECT (window),
WINDOW_DATA_KEY);
doc = gedit_window_get_active_document (window);
g_return_if_fail (doc != NULL);
if (data->dialog != NULL)
{
gtk_window_present (GTK_WINDOW (data->dialog->dialog));
gtk_widget_grab_focus (GTK_WIDGET (data->dialog->dialog));
}
else
{
DocInfoDialog *dialog;
dialog = get_docinfo_dialog (window, data);
g_return_if_fail (dialog != NULL);
data->dialog = dialog;
gtk_widget_show (GTK_WIDGET (dialog->dialog));
}
docinfo_real (doc,
data->dialog);
selectioninfo_real (doc,
data->dialog);
}
static void
docinfo_dialog_response_cb (GtkDialog *widget,
gint res_id,
GeditWindow *window)
{
WindowData *data;
gedit_debug (DEBUG_PLUGINS);
data = (WindowData *) g_object_get_data (G_OBJECT (window),
WINDOW_DATA_KEY);
switch (res_id)
{
case GTK_RESPONSE_CLOSE:
{
gedit_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_CLOSE");
gtk_widget_destroy (data->dialog->dialog);
break;
}
case GTK_RESPONSE_OK:
{
GeditDocument *doc;
gedit_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_OK");
doc = gedit_window_get_active_document (window);
g_return_if_fail (doc != NULL);
docinfo_real (doc,
data->dialog);
selectioninfo_real (doc,
data->dialog);
break;
}
}
}
static const GtkActionEntry action_entries[] =
{
{ "DocumentStatistics",
NULL,
N_("_Document Statistics"),
NULL,
N_("Get statistical information on the current document"),
G_CALLBACK (docinfo_cb) }
};
static void
free_window_data (WindowData *data)
{
g_return_if_fail (data != NULL);
gedit_debug (DEBUG_PLUGINS);
g_object_unref (data->plugin);
g_object_unref (data->ui_action_group);
if (data->dialog != NULL)
{
gtk_widget_destroy (data->dialog->dialog);
}
g_free (data);
}
static void
update_ui_real (GeditWindow *window,
WindowData *data)
{
GeditView *view;
gedit_debug (DEBUG_PLUGINS);
view = gedit_window_get_active_view (window);
gtk_action_group_set_sensitive (data->ui_action_group,
(view != NULL));
if (data->dialog != NULL)
{
gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog->dialog),
GTK_RESPONSE_OK,
(view != NULL));
}
}
static void
gedit_docinfo_plugin_init (GeditDocInfoPlugin *plugin)
{
gedit_debug_message (DEBUG_PLUGINS, "GeditDocInfoPlugin initializing");
}
static void
gedit_docinfo_plugin_finalize (GObject *object)
{
gedit_debug_message (DEBUG_PLUGINS, "GeditDocInfoPlugin finalizing");
G_OBJECT_CLASS (gedit_docinfo_plugin_parent_class)->finalize (object);
}
static void
impl_activate (GeditPlugin *plugin,
GeditWindow *window)
{
GtkUIManager *manager;
WindowData *data;
gedit_debug (DEBUG_PLUGINS);
data = g_new (WindowData, 1);
data->plugin = g_object_ref (plugin);
data->dialog = NULL;
data->ui_action_group = gtk_action_group_new ("GeditDocInfoPluginActions");
gtk_action_group_set_translation_domain (data->ui_action_group,
GETTEXT_PACKAGE);
gtk_action_group_add_actions (data->ui_action_group,
action_entries,
G_N_ELEMENTS (action_entries),
window);
manager = gedit_window_get_ui_manager (window);
gtk_ui_manager_insert_action_group (manager,
data->ui_action_group,
-1);
data->ui_id = gtk_ui_manager_new_merge_id (manager);
g_object_set_data_full (G_OBJECT (window),
WINDOW_DATA_KEY,
data,
(GDestroyNotify) free_window_data);
gtk_ui_manager_add_ui (manager,
data->ui_id,
MENU_PATH,
"DocumentStatistics",
"DocumentStatistics",
GTK_UI_MANAGER_MENUITEM,
FALSE);
update_ui_real (window,
data);
}
static void
impl_deactivate (GeditPlugin *plugin,
GeditWindow *window)
{
GtkUIManager *manager;
WindowData *data;
gedit_debug (DEBUG_PLUGINS);
manager = gedit_window_get_ui_manager (window);
data = (WindowData *) g_object_get_data (G_OBJECT (window),
WINDOW_DATA_KEY);
g_return_if_fail (data != NULL);
gtk_ui_manager_remove_ui (manager,
data->ui_id);
gtk_ui_manager_remove_action_group (manager,
data->ui_action_group);
g_object_set_data (G_OBJECT (window),
WINDOW_DATA_KEY,
NULL);
}
static void
impl_update_ui (GeditPlugin *plugin,
GeditWindow *window)
{
WindowData *data;
gedit_debug (DEBUG_PLUGINS);
data = (WindowData *) g_object_get_data (G_OBJECT (window),
WINDOW_DATA_KEY);
g_return_if_fail (data != NULL);
update_ui_real (window,
data);
}
static void
gedit_docinfo_plugin_class_init (GeditDocInfoPluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass);
object_class->finalize = gedit_docinfo_plugin_finalize;
plugin_class->activate = impl_activate;
plugin_class->deactivate = impl_deactivate;
plugin_class->update_ui = impl_update_ui;
}

View File

@@ -0,0 +1,75 @@
/*
* gedit-docinfo-plugin.h
*
* Copyright (C) 2002-2005 Paolo Maggi
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id$
*/
#ifndef __GEDIT_DOCINFO_PLUGIN_H__
#define __GEDIT_DOCINFO_PLUGIN_H__
#include <glib.h>
#include <glib-object.h>
#include <gedit/gedit-plugin.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define GEDIT_TYPE_DOCINFO_PLUGIN (gedit_docinfo_plugin_get_type ())
#define GEDIT_DOCINFO_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_DOCINFO_PLUGIN, GeditDocInfoPlugin))
#define GEDIT_DOCINFO_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_DOCINFO_PLUGIN, GeditDocInfoPluginClass))
#define GEDIT_IS_DOCINFO_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_DOCINFO_PLUGIN))
#define GEDIT_IS_DOCINFO_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_DOCINFO_PLUGIN))
#define GEDIT_DOCINFO_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_DOCINFO_PLUGIN, GeditDocInfoPluginClass))
/* Private structure type */
typedef struct _GeditDocInfoPluginPrivate GeditDocInfoPluginPrivate;
/*
* Main object structure
*/
typedef struct _GeditDocInfoPlugin GeditDocInfoPlugin;
struct _GeditDocInfoPlugin
{
GeditPlugin parent_instance;
};
/*
* Class definition
*/
typedef struct _GeditDocInfoPluginClass GeditDocInfoPluginClass;
struct _GeditDocInfoPluginClass
{
GeditPluginClass parent_class;
};
/*
* Public methods
*/
GType gedit_docinfo_plugin_get_type (void) G_GNUC_CONST;
/* All the plugins must implement this function */
G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module);
G_END_DECLS
#endif /* __GEDIT_DOCINFO_PLUGIN_H__ */

View File

@@ -0,0 +1,15 @@
# External Tools plugin
SUBDIRS = tools data scripts
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)
plugin_in_files = externaltools.gedit-plugin.desktop.in
%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin)
EXTRA_DIST = $(plugin_in_files)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = $(plugin_DATA)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,65 @@
TOOL_MERGE=$(top_srcdir)/plugins/externaltools/scripts/gedit-tool-merge.pl
tools_in_files = \
build.tool.in \
remove-trailing-spaces.tool.in
tools_in_linux = \
open-terminal-here.tool.in \
run-command.tool.in
tools_in_osx = \
open-terminal-here-osx.tool.in
tools_in_win32 =
install_tools_in_files = $(tools_in_files)
if PLATFORM_OSX
install_tools_in_files += $(tools_in_osx)
else
if PLATFORM_WIN32
install_tools_in_files += $(tools_in_win32)
else
install_tools_in_files += $(tools_in_linux)
endif
endif
desktop_in_files = $(install_tools_in_files:.tool.in=.desktop.in)
desktop_files = $(install_tools_in_files:.tool.in=.desktop)
tools_SCRIPTS = $(install_tools_in_files:.tool.in=)
toolsdir = $(GEDIT_PLUGINS_DATA_DIR)/externaltools/tools
all_tools_in_files = \
$(tools_in_files) \
$(tools_in_linux) \
$(tools_in_osx) \
$(tools_in_win32)
all_desktop_in_files = $(all_tools_in_files:.tool.in=.desktop.in)
all_desktop_files = $(all_tools_in_files:.tool.in=.desktop)
all_tools_files = $(all_tools_in_files:.tool.in=)
@INTLTOOL_DESKTOP_RULE@
# Tools are generated by merging a script file (.tool.in) with a data file
# (.desktop), which happens to be translated using intltool.
$(tools_SCRIPTS): %: %.tool.in %.desktop $(TOOL_MERGE)
perl $(TOOL_MERGE) -o $@ $< $(word 2,$^)
chmod 755 $@
EXTRA_DIST = \
$(all_desktop_in_files) \
$(all_tools_in_files)
CLEANFILES = \
$(all_desktop_files) \
$(all_tools_files)
DISTCLEANFILES = \
$(all_desktop_files) \
$(all_tools_files)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,9 @@
[Gedit Tool]
_Name=Build
_Comment=Run "make" in the document directory
Input=nothing
Output=output-panel
Shortcut=<Control>F8
Applicability=local
Save-files=nothing
Languages=

View File

@@ -0,0 +1,15 @@
#!/bin/sh
EHOME=`echo $HOME | sed "s/#/\#/"`
DIR=$GEDIT_CURRENT_DOCUMENT_DIR
while test "$DIR" != "/"; do
for m in GNUmakefile makefile Makefile; do
if [ -f "${DIR}/${m}" ]; then
echo "Using ${m} from ${DIR}" | sed "s#$EHOME#~#" > /dev/stderr
make -C "${DIR}"
exit
fi
done
DIR=`dirname "${DIR}"`
done
echo "No Makefile found!" > /dev/stderr

View File

@@ -0,0 +1,8 @@
[Gedit Tool]
_Name=Open terminal here
_Comment=Open a terminal in the document location
Input=nothing
Output=output-panel
Applicability=local
Save-files=nothing
Languages=

View File

@@ -0,0 +1,16 @@
#!/usr/bin/osascript
set the_path to system attribute "GEDIT_CURRENT_DOCUMENT_DIR"
set cmd to "cd " & quoted form of the_path
tell application "System Events" to set terminalIsRunning to exists application process "Terminal"
tell application "Terminal"
activate
if terminalIsRunning is true then
do script with command cmd
else
do script with command cmd in window 1
end if
end tell

View File

@@ -0,0 +1,8 @@
[Gedit Tool]
_Name=Open terminal here
_Comment=Open a terminal in the document location
Input=nothing
Output=output-panel
Applicability=local
Save-files=nothing
Languages=

View File

@@ -0,0 +1,4 @@
#!/bin/sh
#TODO: use "mateconftool-2 -g /desktop/mate/applications/terminal/exec"
mate-terminal --working-directory=$GEDIT_CURRENT_DOCUMENT_DIR &

View File

@@ -0,0 +1,9 @@
[Gedit Tool]
_Name=Remove trailing spaces
_Comment=Remove useless trailing spaces in your file
Input=document
Output=replace-document
Shortcut=<Alt>F12
Applicability=all
Save-files=nothing
Languages=

View File

@@ -0,0 +1,3 @@
#!/bin/sh
sed 's/[[:blank:]]*$//'

View File

@@ -0,0 +1,8 @@
[Gedit Tool]
_Name=Run command
_Comment=Execute a custom command and put its output in a new document
Input=nothing
Output=new-document
Applicability=all
Save-files=nothing
Languages=

View File

@@ -0,0 +1,4 @@
#!/bin/sh
#TODO: use "mateconftool-2 -g /desktop/mate/applications/terminal/exec"
exec `matedialog --entry --title="Run command - gedit" --text="Command to run"`

View File

@@ -0,0 +1,9 @@
[Gedit Plugin]
Loader=python
Module=externaltools
IAge=2
_Name=External Tools
_Description=Execute external commands and shell scripts.
Authors=Steve Frécinaux <steve@istique.net>
Copyright=Copyright © 2005 Steve Frécinaux
Website=http://www.gedit.org

View File

@@ -0,0 +1,4 @@
EXTRA_DIST = gedit-tool-merge.pl
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,78 @@
#!/usr/bin/perl
# gedit-tool-merge.pl
# This file is part of gedit
#
# Copyright (C) 2006 - Steve Frécinaux <code@istique.net>
#
# gedit 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.
#
# gedit is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gedit; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA
# This script merges a script file with a desktop file containing
# metadata about the external tool. This is required in order to
# have translatable tools (bug #342042) since intltool can't extract
# string directly from tool files (a tool file being the combination
# of a script file and a metadata section).
#
# The desktop file is embedded in a comment of the script file, under
# the assumption that any scripting language supports # as a comment
# mark (this is likely to be true since the shebang uses #!). The
# section is placed at the top of the tool file, after the shebang and
# modelines if present.
use strict;
use warnings;
use Getopt::Long;
sub usage {
print <<EOF;
Usage: ${0} [OPTION]... [SCRIPT] [DESKTOP]
Merges a script file with a desktop file, embedding it in a comment.
-o, --output=FILE Specify the output file name. [default: stdout]
EOF
exit;
}
my $output = "";
my $help;
GetOptions ("help|h" => \$help, "output|o=s" => \$output) or &usage;
usage if $help or @ARGV lt 2;
open INFILE, "<", $ARGV[0];
open DFILE, "<", $ARGV[1];
open STDOUT, ">", $output if $output;
# Put shebang and various modelines at the top of the generated file.
$_ = <INFILE>;
print and $_ = <INFILE> if /^#!/;
print and $_ = <INFILE> if /-\*-/;
print and $_ = <INFILE> if /(ex|vi|vim):/;
# Put a blank line before the info block if there is one in INFILE.
print and $_ = <INFILE> if /^\s*$/;
seek INFILE, -length, 1;
# Embed the desktop file...
print "# $_" while <DFILE>;
print "\n";
# ...and write the remaining part of the script.
print while <INFILE>;
close INFILE;
close DFILE;
close STDOUT;

View File

@@ -0,0 +1,23 @@
# Python snippets plugin
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)/externaltools
plugin_PYTHON = \
__init__.py \
capture.py \
library.py \
functions.py \
manager.py \
outputpanel.py \
filelookup.py \
linkparsing.py
uidir = $(GEDIT_PLUGINS_DATA_DIR)/externaltools/ui
ui_DATA = tools.ui \
outputpanel.ui
EXTRA_DIST = $(ui_DATA)
CLEANFILES = *.bak *.gladep
DISTCLEANFILES = *.bak *.gladep
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,281 @@
# -*- coding: UTF-8 -*-
# Gedit External Tools plugin
# Copyright (C) 2005-2006 Steve Frécinaux <steve@istique.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
__all__ = ('ExternalToolsPlugin', 'ExternalToolsWindowHelper',
'Manager', 'OutputPanel', 'Capture', 'UniqueById')
import gedit
import gtk
from manager import Manager
from library import ToolLibrary
from outputpanel import OutputPanel
from capture import Capture
from functions import *
class ToolMenu(object):
ACTION_HANDLER_DATA_KEY = "ExternalToolActionHandlerData"
ACTION_ITEM_DATA_KEY = "ExternalToolActionItemData"
def __init__(self, library, window, menupath):
super(ToolMenu, self).__init__()
self._library = library
self._window = window
self._menupath = menupath
self._merge_id = 0
self._action_group = gtk.ActionGroup("ExternalToolsPluginToolActions")
self._signals = []
self.update()
def deactivate(self):
self.remove()
def remove(self):
if self._merge_id != 0:
self._window.get_ui_manager().remove_ui(self._merge_id)
self._window.get_ui_manager().remove_action_group(self._action_group)
self._merge_id = 0
for action in self._action_group.list_actions():
handler = action.get_data(self.ACTION_HANDLER_DATA_KEY)
if handler is not None:
action.disconnect(handler)
action.set_data(self.ACTION_ITEM_DATA_KEY, None)
action.set_data(self.ACTION_HANDLER_DATA_KEY, None)
self._action_group.remove_action(action)
accelmap = gtk.accel_map_get()
for s in self._signals:
accelmap.disconnect(s)
self._signals = []
def _insert_directory(self, directory, path):
manager = self._window.get_ui_manager()
for item in directory.subdirs:
action_name = 'ExternalToolDirectory%X' % id(item)
action = gtk.Action(action_name, item.name.replace('_', '__'), None, None)
self._action_group.add_action(action)
manager.add_ui(self._merge_id, path,
action_name, action_name,
gtk.UI_MANAGER_MENU, False)
self._insert_directory(item, path + '/' + action_name)
for item in directory.tools:
action_name = 'ExternalToolTool%X' % id(item)
action = gtk.Action(action_name, item.name.replace('_', '__'), item.comment, None)
handler = action.connect("activate", capture_menu_action, self._window, item)
action.set_data(self.ACTION_ITEM_DATA_KEY, item)
action.set_data(self.ACTION_HANDLER_DATA_KEY, handler)
# Make sure to replace accel
accelpath = '<Actions>/ExternalToolsPluginToolActions/%s' % (action_name, )
if item.shortcut:
key, mod = gtk.accelerator_parse(item.shortcut)
gtk.accel_map_change_entry(accelpath, key, mod, True)
self._signals.append(gtk.accel_map_get().connect('changed::%s' % (accelpath,), self.on_accelmap_changed, item))
self._action_group.add_action_with_accel(action, item.shortcut)
manager.add_ui(self._merge_id, path,
action_name, action_name,
gtk.UI_MANAGER_MENUITEM, False)
def on_accelmap_changed(self, accelmap, path, key, mod, tool):
tool.shortcut = gtk.accelerator_name(key, mod)
tool.save()
self._window.get_data("ExternalToolsPluginWindowData").update_manager(tool)
def update(self):
self.remove()
self._merge_id = self._window.get_ui_manager().new_merge_id()
self._insert_directory(self._library.tree, self._menupath)
self._window.get_ui_manager().insert_action_group(self._action_group, -1)
self.filter(self._window.get_active_document())
def filter_language(self, language, item):
if not item.languages:
return True
if not language and 'plain' in item.languages:
return True
if language and (language.get_id() in item.languages):
return True
else:
return False
def filter(self, document):
if document is None:
return
titled = document.get_uri() is not None
remote = not document.is_local()
states = {
'all' : True,
'local': titled and not remote,
'remote': titled and remote,
'titled': titled,
'untitled': not titled,
}
language = document.get_language()
for action in self._action_group.list_actions():
item = action.get_data(self.ACTION_ITEM_DATA_KEY)
if item is not None:
action.set_visible(states[item.applicability] and self.filter_language(language, item))
class ExternalToolsWindowHelper(object):
def __init__(self, plugin, window):
super(ExternalToolsWindowHelper, self).__init__()
self._window = window
self._plugin = plugin
self._library = ToolLibrary()
manager = window.get_ui_manager()
self._action_group = gtk.ActionGroup('ExternalToolsPluginActions')
self._action_group.set_translation_domain('gedit')
self._action_group.add_actions([('ExternalToolManager',
None,
_('Manage _External Tools...'),
None,
_("Opens the External Tools Manager"),
lambda action: plugin.open_dialog()),
('ExternalTools',
None,
_('External _Tools'),
None,
_("External tools"),
None)])
manager.insert_action_group(self._action_group, -1)
ui_string = """
<ui>
<menubar name="MenuBar">
<menu name="ToolsMenu" action="Tools">
<placeholder name="ToolsOps_4">
<separator/>
<menu name="ExternalToolsMenu" action="ExternalTools">
<placeholder name="ExternalToolPlaceholder"/>
</menu>
<separator/>
</placeholder>
<placeholder name="ToolsOps_5">
<menuitem name="ExternalToolManager" action="ExternalToolManager"/>
</placeholder>
</menu>
</menubar>
</ui>"""
self._merge_id = manager.add_ui_from_string(ui_string)
self.menu = ToolMenu(self._library, self._window,
"/MenuBar/ToolsMenu/ToolsOps_4/ExternalToolsMenu/ExternalToolPlaceholder")
manager.ensure_update()
# Create output console
self._output_buffer = OutputPanel(self._plugin.get_data_dir(), window)
bottom = window.get_bottom_panel()
bottom.add_item(self._output_buffer.panel,
_("Shell Output"),
gtk.STOCK_EXECUTE)
def update_ui(self):
self.menu.filter(self._window.get_active_document())
self._window.get_ui_manager().ensure_update()
def deactivate(self):
manager = self._window.get_ui_manager()
self.menu.deactivate()
manager.remove_ui(self._merge_id)
manager.remove_action_group(self._action_group)
manager.ensure_update()
bottom = self._window.get_bottom_panel()
bottom.remove_item(self._output_buffer.panel)
def update_manager(self, tool):
self._plugin.update_manager(tool)
class ExternalToolsPlugin(gedit.Plugin):
WINDOW_DATA_KEY = "ExternalToolsPluginWindowData"
def __init__(self):
super(ExternalToolsPlugin, self).__init__()
self._manager = None
self._manager_default_size = None
ToolLibrary().set_locations(os.path.join(self.get_data_dir(), 'tools'))
def activate(self, window):
helper = ExternalToolsWindowHelper(self, window)
window.set_data(self.WINDOW_DATA_KEY, helper)
def deactivate(self, window):
window.get_data(self.WINDOW_DATA_KEY).deactivate()
window.set_data(self.WINDOW_DATA_KEY, None)
def update_ui(self, window):
window.get_data(self.WINDOW_DATA_KEY).update_ui()
def create_configure_dialog(self):
return self.open_dialog()
def open_dialog(self):
if not self._manager:
self._manager = Manager(self.get_data_dir())
if self._manager_default_size:
self._manager.dialog.set_default_size(*self._manager_default_size)
self._manager.dialog.connect('destroy', self.on_manager_destroy)
window = gedit.app_get_default().get_active_window()
self._manager.run(window)
return self._manager.dialog
def update_manager(self, tool):
if not self._manager:
return
self._manager.tool_changed(tool, True)
def on_manager_destroy(self, dialog):
self._manager_default_size = [dialog.allocation.width, dialog.allocation.height]
self._manager = None
# ex:ts=4:et:

View File

@@ -0,0 +1,214 @@
# -*- coding: utf-8 -*-
# Gedit External Tools plugin
# Copyright (C) 2005-2006 Steve Frécinaux <steve@istique.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
__all__ = ('Capture', )
import os, sys, signal
import locale
import subprocess
import gobject
import fcntl
import glib
class Capture(gobject.GObject):
CAPTURE_STDOUT = 0x01
CAPTURE_STDERR = 0x02
CAPTURE_BOTH = 0x03
CAPTURE_NEEDS_SHELL = 0x04
WRITE_BUFFER_SIZE = 0x4000
__gsignals__ = {
'stdout-line' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)),
'stderr-line' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)),
'begin-execute': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, tuple()),
'end-execute' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT,))
}
def __init__(self, command, cwd = None, env = {}):
gobject.GObject.__init__(self)
self.pipe = None
self.env = env
self.cwd = cwd
self.flags = self.CAPTURE_BOTH | self.CAPTURE_NEEDS_SHELL
self.command = command
self.input_text = None
def set_env(self, **values):
self.env.update(**values)
def set_command(self, command):
self.command = command
def set_flags(self, flags):
self.flags = flags
def set_input(self, text):
self.input_text = text
def set_cwd(self, cwd):
self.cwd = cwd
def execute(self):
if self.command is None:
return
# Initialize pipe
popen_args = {
'cwd' : self.cwd,
'shell': self.flags & self.CAPTURE_NEEDS_SHELL,
'env' : self.env
}
if self.input_text is not None:
popen_args['stdin'] = subprocess.PIPE
if self.flags & self.CAPTURE_STDOUT:
popen_args['stdout'] = subprocess.PIPE
if self.flags & self.CAPTURE_STDERR:
popen_args['stderr'] = subprocess.PIPE
self.tried_killing = False
self.idle_write_id = 0
self.read_buffer = ''
try:
self.pipe = subprocess.Popen(self.command, **popen_args)
except OSError, e:
self.pipe = None
self.emit('stderr-line', _('Could not execute command: %s') % (e, ))
return
# Signal
self.emit('begin-execute')
if self.flags & self.CAPTURE_STDOUT:
# Set non blocking
flags = fcntl.fcntl(self.pipe.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK
fcntl.fcntl(self.pipe.stdout.fileno(), fcntl.F_SETFL, flags)
gobject.io_add_watch(self.pipe.stdout,
gobject.IO_IN | gobject.IO_HUP,
self.on_output)
if self.flags & self.CAPTURE_STDERR:
# Set non blocking
flags = fcntl.fcntl(self.pipe.stderr.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK
fcntl.fcntl(self.pipe.stderr.fileno(), fcntl.F_SETFL, flags)
gobject.io_add_watch(self.pipe.stderr,
gobject.IO_IN | gobject.IO_HUP,
self.on_output)
# IO
if self.input_text is not None:
# Write async, in chunks of something
self.write_buffer = str(self.input_text)
if self.idle_write_chunk():
self.idle_write_id = gobject.idle_add(self.idle_write_chunk)
# Wait for the process to complete
gobject.child_watch_add(self.pipe.pid, self.on_child_end)
def idle_write_chunk(self):
if not self.pipe:
self.idle_write_id = 0
return False
try:
l = len(self.write_buffer)
m = min(l, self.WRITE_BUFFER_SIZE)
self.pipe.stdin.write(self.write_buffer[:m])
if m == l:
self.write_buffer = ''
self.pipe.stdin.close()
self.idle_write_id = 0
return False
else:
self.write_buffer = self.write_buffer[m:]
return True
except IOError:
self.pipe.stdin.close()
self.idle_write_id = 0
return False
def on_output(self, source, condition):
if condition & (glib.IO_IN | glib.IO_PRI):
line = source.read()
if len(line) > 0:
try:
line = unicode(line, 'utf-8')
except:
line = unicode(line,
locale.getdefaultlocale()[1],
'replace')
self.read_buffer += line
lines = self.read_buffer.splitlines(True)
if not lines[-1].endswith("\n"):
self.read_buffer = lines[-1]
lines = lines[0:-1]
else:
self.read_buffer = ''
for line in lines:
if not self.pipe or source == self.pipe.stdout:
self.emit('stdout-line', line)
else:
self.emit('stderr-line', line)
if condition & ~(glib.IO_IN | glib.IO_PRI):
if self.read_buffer:
if source == self.pipe.stdout:
self.emit('stdout-line', self.read_buffer)
else:
self.emit('stderr-line', self.read_buffer)
self.read_buffer = ''
self.pipe = None
return False
else:
return True
def stop(self, error_code = -1):
if self.pipe is not None:
if self.idle_write_id:
gobject.source_remove(self.idle_write_id)
self.idle_write_id = 0
if not self.tried_killing:
os.kill(self.pipe.pid, signal.SIGTERM)
self.tried_killing = True
else:
os.kill(self.pipe.pid, signal.SIGKILL)
def on_child_end(self, pid, error_code):
# In an idle, so it is emitted after all the std*-line signals
# have been intercepted
gobject.idle_add(self.emit, 'end-execute', error_code)
# ex:ts=4:et:

View File

@@ -0,0 +1,145 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2009-2010 Per Arneng <per.arneng@anyplanet.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import os
import gio
import gedit
class FileLookup:
"""
This class is responsible for looking up files given a part or the whole
path of a real file. The lookup is delegated to providers wich use different
methods of trying to find the real file.
"""
def __init__(self):
self.providers = []
self.providers.append(AbsoluteFileLookupProvider())
self.providers.append(CwdFileLookupProvider())
self.providers.append(OpenDocumentRelPathFileLookupProvider())
self.providers.append(OpenDocumentFileLookupProvider())
def lookup(self, path):
"""
Tries to find a file specified by the path parameter. It delegates to
different lookup providers and the first match is returned. If no file
was found then None is returned.
path -- the path to find
"""
found_file = None
for provider in self.providers:
found_file = provider.lookup(path)
if found_file is not None:
break
return found_file
class FileLookupProvider:
"""
The base class of all file lookup providers.
"""
def lookup(self, path):
"""
This method must be implemented by subclasses. Implementors will be
given a path and will try to find a matching file. If no file is found
then None is returned.
"""
raise NotImplementedError("need to implement a lookup method")
class AbsoluteFileLookupProvider(FileLookupProvider):
"""
This file tries to see if the path given is an absolute path and that the
path references a file.
"""
def lookup(self, path):
if os.path.isabs(path) and os.path.isfile(path):
return gio.File(path)
else:
return None
class CwdFileLookupProvider(FileLookupProvider):
"""
This lookup provider tries to find a file specified by the path relative to
the current working directory.
"""
def lookup(self, path):
try:
cwd = os.getcwd()
except OSError:
cwd = os.getenv('HOME')
real_path = os.path.join(cwd, path)
if os.path.isfile(real_path):
return gio.File(real_path)
else:
return None
class OpenDocumentRelPathFileLookupProvider(FileLookupProvider):
"""
Tries to see if the path is relative to any directories where the
currently open documents reside in. Example: If you have a document opened
'/tmp/Makefile' and a lookup is made for 'src/test2.c' then this class
will try to find '/tmp/src/test2.c'.
"""
def lookup(self, path):
if path.startswith('/'):
return None
for doc in gedit.app_get_default().get_documents():
if doc.is_local():
location = doc.get_location()
if location:
rel_path = location.get_parent().get_path()
joined_path = os.path.join(rel_path, path)
if os.path.isfile(joined_path):
return gio.File(joined_path)
return None
class OpenDocumentFileLookupProvider(FileLookupProvider):
"""
Makes a guess that the if the path that was looked for matches the end
of the path of a currently open document then that document is the one
that is looked for. Example: If a document is opened called '/tmp/t.c'
and a lookup is made for 't.c' or 'tmp/t.c' then both will match since
the open document ends with the path that is searched for.
"""
def lookup(self, path):
if path.startswith('/'):
return None
for doc in gedit.app_get_default().get_documents():
if doc.is_local():
location = doc.get_location()
if location and location.get_uri().endswith(path):
return location
return None
# ex:ts=4:et:

View File

@@ -0,0 +1,303 @@
# -*- coding: utf-8 -*-
# Gedit External Tools plugin
# Copyright (C) 2005-2006 Steve Frécinaux <steve@istique.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import os
import gtk
from gtk import gdk
import gio
import gedit
#import gtksourceview
from outputpanel import OutputPanel
from capture import *
def default(val, d):
if val is not None:
return val
else:
return d
def current_word(document):
piter = document.get_iter_at_mark(document.get_insert())
start = piter.copy()
if not piter.starts_word() and (piter.inside_word() or piter.ends_word()):
start.backward_word_start()
if not piter.ends_word() and piter.inside_word():
piter.forward_word_end()
return (start, piter)
# ==== Capture related functions ====
def run_external_tool(window, node):
# Configure capture environment
try:
cwd = os.getcwd()
except OSError:
cwd = os.getenv('HOME');
capture = Capture(node.command, cwd)
capture.env = os.environ.copy()
capture.set_env(GEDIT_CWD = cwd)
view = window.get_active_view()
if view is not None:
# Environment vars relative to current document
document = view.get_buffer()
uri = document.get_uri()
# Current line number
piter = document.get_iter_at_mark(document.get_insert())
capture.set_env(GEDIT_CURRENT_LINE_NUMBER=str(piter.get_line() + 1))
# Current line text
piter.set_line_offset(0)
end = piter.copy()
if not end.ends_line():
end.forward_to_line_end()
capture.set_env(GEDIT_CURRENT_LINE=piter.get_text(end))
# Selected text (only if input is not selection)
if node.input != 'selection' and node.input != 'selection-document':
bounds = document.get_selection_bounds()
if bounds:
capture.set_env(GEDIT_SELECTED_TEXT=bounds[0].get_text(bounds[1]))
bounds = current_word(document)
capture.set_env(GEDIT_CURRENT_WORD=bounds[0].get_text(bounds[1]))
capture.set_env(GEDIT_CURRENT_DOCUMENT_TYPE=document.get_mime_type())
if uri is not None:
gfile = gio.File(uri)
scheme = gfile.get_uri_scheme()
name = os.path.basename(uri)
capture.set_env(GEDIT_CURRENT_DOCUMENT_URI = uri,
GEDIT_CURRENT_DOCUMENT_NAME = name,
GEDIT_CURRENT_DOCUMENT_SCHEME = scheme)
if gedit.utils.uri_has_file_scheme(uri):
path = gfile.get_path()
cwd = os.path.dirname(path)
capture.set_cwd(cwd)
capture.set_env(GEDIT_CURRENT_DOCUMENT_PATH = path,
GEDIT_CURRENT_DOCUMENT_DIR = cwd)
documents_uri = [doc.get_uri()
for doc in window.get_documents()
if doc.get_uri() is not None]
documents_path = [gio.File(uri).get_path()
for uri in documents_uri
if gedit.utils.uri_has_file_scheme(uri)]
capture.set_env(GEDIT_DOCUMENTS_URI = ' '.join(documents_uri),
GEDIT_DOCUMENTS_PATH = ' '.join(documents_path))
flags = capture.CAPTURE_BOTH
if not node.has_hash_bang():
flags |= capture.CAPTURE_NEEDS_SHELL
capture.set_flags(flags)
# Get input text
input_type = node.input
output_type = node.output
# Get the panel
panel = window.get_data("ExternalToolsPluginWindowData")._output_buffer
panel.clear()
if output_type == 'output-panel':
panel.show()
# Assign the error output to the output panel
panel.set_process(capture)
if input_type != 'nothing' and view is not None:
if input_type == 'document':
start, end = document.get_bounds()
elif input_type == 'selection' or input_type == 'selection-document':
try:
start, end = document.get_selection_bounds()
print start, end
except ValueError:
if input_type == 'selection-document':
start, end = document.get_bounds()
if output_type == 'replace-selection':
document.select_range(start, end)
else:
start = document.get_iter_at_mark(document.get_insert())
end = start.copy()
elif input_type == 'line':
start = document.get_iter_at_mark(document.get_insert())
end = start.copy()
if not start.starts_line():
start.set_line_offset(0)
if not end.ends_line():
end.forward_to_line_end()
elif input_type == 'word':
start = document.get_iter_at_mark(document.get_insert())
end = start.copy()
if not start.inside_word():
panel.write(_('You must be inside a word to run this command'),
panel.command_tag)
return
if not start.starts_word():
start.backward_word_start()
if not end.ends_word():
end.forward_word_end()
input_text = document.get_text(start, end)
capture.set_input(input_text)
# Assign the standard output to the chosen "file"
if output_type == 'new-document':
tab = window.create_tab(True)
view = tab.get_view()
document = tab.get_document()
pos = document.get_start_iter()
capture.connect('stdout-line', capture_stdout_line_document, document, pos)
document.begin_user_action()
view.set_editable(False)
view.set_cursor_visible(False)
elif output_type != 'output-panel' and output_type != 'nothing' and view is not None:
document.begin_user_action()
view.set_editable(False)
view.set_cursor_visible(False)
if output_type == 'insert':
pos = document.get_iter_at_mark(document.get_mark('insert'))
elif output_type == 'replace-selection':
document.delete_selection(False, False)
pos = document.get_iter_at_mark(document.get_mark('insert'))
elif output_type == 'replace-document':
document.set_text('')
pos = document.get_end_iter()
else:
pos = document.get_end_iter()
capture.connect('stdout-line', capture_stdout_line_document, document, pos)
elif output_type != 'nothing':
capture.connect('stdout-line', capture_stdout_line_panel, panel)
document.begin_user_action()
capture.connect('stderr-line', capture_stderr_line_panel, panel)
capture.connect('begin-execute', capture_begin_execute_panel, panel, view, node.name)
capture.connect('end-execute', capture_end_execute_panel, panel, view, output_type)
# Run the command
capture.execute()
if output_type != 'nothing':
document.end_user_action()
class MultipleDocumentsSaver:
def __init__(self, window, docs, node):
self._window = window
self._node = node
self._error = False
self._counter = len(docs)
self._signal_ids = {}
self._counter = 0
signals = {}
for doc in docs:
signals[doc] = doc.connect('saving', self.on_document_saving)
gedit.commands.save_document(window, doc)
doc.disconnect(signals[doc])
def on_document_saving(self, doc, size, total_size):
self._counter += 1
self._signal_ids[doc] = doc.connect('saved', self.on_document_saved)
def on_document_saved(self, doc, error):
if error:
self._error = True
doc.disconnect(self._signal_ids[doc])
del self._signal_ids[doc]
self._counter -= 1
if self._counter == 0 and not self._error:
run_external_tool(self._window, self._node)
def capture_menu_action(action, window, node):
if node.save_files == 'document' and window.get_active_document():
MultipleDocumentsSaver(window, [window.get_active_document()], node)
return
elif node.save_files == 'all':
MultipleDocumentsSaver(window, window.get_documents(), node)
return
run_external_tool(window, node)
def capture_stderr_line_panel(capture, line, panel):
if not panel.visible():
panel.show()
panel.write(line, panel.error_tag)
def capture_begin_execute_panel(capture, panel, view, label):
view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(gdk.Cursor(gdk.WATCH))
panel['stop'].set_sensitive(True)
panel.clear()
panel.write(_("Running tool:"), panel.italic_tag);
panel.write(" %s\n\n" % label, panel.bold_tag);
def capture_end_execute_panel(capture, exit_code, panel, view, output_type):
panel['stop'].set_sensitive(False)
if output_type in ('new-document','replace-document'):
doc = view.get_buffer()
start = doc.get_start_iter()
end = start.copy()
end.forward_chars(300)
mtype = gio.content_type_guess(data=doc.get_text(start, end))
lmanager = gedit.get_language_manager()
language = lmanager.guess_language(doc.get_uri(), mtype)
if language is not None:
doc.set_language(language)
view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(gdk.Cursor(gdk.XTERM))
view.set_cursor_visible(True)
view.set_editable(True)
if exit_code == 0:
panel.write("\n" + _("Done.") + "\n", panel.italic_tag)
else:
panel.write("\n" + _("Exited") + ":", panel.italic_tag)
panel.write(" %d\n" % exit_code, panel.bold_tag)
def capture_stdout_line_panel(capture, line, panel):
panel.write(line)
def capture_stdout_line_document(capture, line, document, pos):
document.insert(pos, line)
# ex:ts=4:et:

View File

@@ -0,0 +1,493 @@
# -*- coding: utf-8 -*-
# Gedit External Tools plugin
# Copyright (C) 2006 Steve Frécinaux <code@istique.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import os
import re
import locale
import platform
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(
cls, *args, **kwargs)
cls._instance.__init_once__()
return cls._instance
class ToolLibrary(Singleton):
def __init_once__(self):
self.locations = []
def set_locations(self, datadir):
self.locations = []
if platform.platform() != 'Windows':
for d in self.get_xdg_data_dirs():
self.locations.append(os.path.join(d, 'gedit-2', 'plugins', 'externaltools', 'tools'))
self.locations.append(datadir)
# self.locations[0] is where we save the custom scripts
if platform.platform() == 'Windows':
toolsdir = os.path.expanduser('~/gedit/tools')
else:
userdir = os.getenv('MATE22_USER_DIR')
if userdir:
toolsdir = os.path.join(userdir, 'gedit/tools')
else:
toolsdir = os.path.expanduser('~/.mate2/gedit/tools')
self.locations.insert(0, toolsdir);
if not os.path.isdir(self.locations[0]):
os.makedirs(self.locations[0])
self.tree = ToolDirectory(self, '')
self.import_old_xml_store()
else:
self.tree = ToolDirectory(self, '')
# cf. http://standards.freedesktop.org/basedir-spec/latest/
def get_xdg_data_dirs(self):
dirs = os.getenv('XDG_DATA_DIRS')
if dirs:
dirs = dirs.split(os.pathsep)
else:
dirs = ('/usr/local/share', '/usr/share')
return dirs
# This function is meant to be ran only once, when the tools directory is
# created. It imports eventual tools that have been saved in the old XML
# storage file.
def import_old_xml_store(self):
import xml.etree.ElementTree as et
userdir = os.getenv('MATE22_USER_DIR')
if userdir:
filename = os.path.join(userdir, 'gedit/gedit-tools.xml')
else:
filename = os.path.expanduser('~/.mate2/gedit/gedit-tools.xml')
if not os.path.isfile(filename):
return
print "External tools: importing old tools into the new store..."
xtree = et.parse(filename)
xroot = xtree.getroot()
for xtool in xroot:
for i in self.tree.tools:
if i.name == xtool.get('label'):
tool = i
break
else:
tool = Tool(self.tree)
tool.name = xtool.get('label')
tool.autoset_filename()
self.tree.tools.append(tool)
tool.comment = xtool.get('description')
tool.shortcut = xtool.get('accelerator')
tool.applicability = xtool.get('applicability')
tool.output = xtool.get('output')
tool.input = xtool.get('input')
tool.save_with_script(xtool.text)
def get_full_path(self, path, mode='r', system = True, local = True):
assert (system or local)
if path is None:
return None
if mode == 'r':
if system and local:
locations = self.locations
elif local and not system:
locations = [self.locations[0]]
elif system and not local:
locations = self.locations[1:]
else:
raise ValueError("system and local can't be both set to False")
for i in locations:
p = os.path.join(i, path)
if os.path.lexists(p):
return p
return None
else:
path = os.path.join(self.locations[0], path)
dirname = os.path.dirname(path)
if not os.path.isdir(dirname):
os.mkdir(dirname)
return path
class ToolDirectory(object):
def __init__(self, parent, dirname):
super(ToolDirectory, self).__init__()
self.subdirs = list()
self.tools = list()
if isinstance(parent, ToolDirectory):
self.parent = parent
self.library = parent.library
else:
self.parent = None
self.library = parent
self.dirname = dirname
self._load()
def listdir(self):
elements = dict()
for l in self.library.locations:
d = os.path.join(l, self.dirname)
if not os.path.isdir(d):
continue
for i in os.listdir(d):
elements[i] = None
keys = elements.keys()
keys.sort()
return keys
def _load(self):
for p in self.listdir():
path = os.path.join(self.dirname, p)
full_path = self.library.get_full_path(path)
if os.path.isdir(full_path):
self.subdirs.append(ToolDirectory(self, p))
elif os.path.isfile(full_path) and os.access(full_path, os.X_OK):
self.tools.append(Tool(self, p))
def get_path(self):
if self.parent is None:
return self.dirname
else:
return os.path.join(self.parent.get_path(), self.dirname)
path = property(get_path)
def get_name(self):
return os.path.basename(self.dirname)
name = property(get_name)
def delete_tool(self, tool):
# Only remove it if it lays in $HOME
if tool in self.tools:
path = tool.get_path()
if path is not None:
filename = os.path.join(self.library.locations[0], path)
if os.path.isfile(filename):
os.unlink(filename)
self.tools.remove(tool)
return True
else:
return False
def revert_tool(self, tool):
# Only remove it if it lays in $HOME
filename = os.path.join(self.library.locations[0], tool.get_path())
if tool in self.tools and os.path.isfile(filename):
os.unlink(filename)
tool._load()
return True
else:
return False
class Tool(object):
RE_KEY = re.compile('^([a-zA-Z_][a-zA-Z0-9_.\-]*)(\[([a-zA-Z_@]+)\])?$')
def __init__(self, parent, filename = None):
super(Tool, self).__init__()
self.parent = parent
self.library = parent.library
self.filename = filename
self.changed = False
self._properties = dict()
self._transform = {
'Languages': [self._to_list, self._from_list]
}
self._load()
def _to_list(self, value):
if value.strip() == '':
return []
else:
return map(lambda x: x.strip(), value.split(','))
def _from_list(self, value):
return ','.join(value)
def _parse_value(self, key, value):
if key in self._transform:
return self._transform[key][0](value)
else:
return value
def _load(self):
if self.filename is None:
return
filename = self.library.get_full_path(self.get_path())
if filename is None:
return
fp = file(filename, 'r', 1)
in_block = False
lang = locale.getlocale(locale.LC_MESSAGES)[0]
for line in fp:
if not in_block:
in_block = line.startswith('# [Gedit Tool]')
continue
if line.startswith('##') or line.startswith('# #'): continue
if not line.startswith('# '): break
try:
(key, value) = [i.strip() for i in line[2:].split('=', 1)]
m = self.RE_KEY.match(key)
if m.group(3) is None:
self._properties[m.group(1)] = self._parse_value(m.group(1), value)
elif lang is not None and lang.startswith(m.group(3)):
self._properties[m.group(1)] = self._parse_value(m.group(1), value)
except ValueError:
break
fp.close()
self.changed = False
def _set_property_if_changed(self, key, value):
if value != self._properties.get(key):
self._properties[key] = value
self.changed = True
def is_global(self):
return self.library.get_full_path(self.get_path(), local=False) is not None
def is_local(self):
return self.library.get_full_path(self.get_path(), system=False) is not None
def is_global(self):
return self.library.get_full_path(self.get_path(), local=False) is not None
def get_path(self):
if self.filename is not None:
return os.path.join(self.parent.get_path(), self.filename)
else:
return None
path = property(get_path)
# This command is the one that is meant to be ran
# (later, could have an Exec key or something)
def get_command(self):
return self.library.get_full_path(self.get_path())
command = property(get_command)
def get_applicability(self):
applicability = self._properties.get('Applicability')
if applicability: return applicability
return 'all'
def set_applicability(self, value):
self._set_property_if_changed('Applicability', value)
applicability = property(get_applicability, set_applicability)
def get_name(self):
name = self._properties.get('Name')
if name: return name
return os.path.basename(self.filename)
def set_name(self, value):
self._set_property_if_changed('Name', value)
name = property(get_name, set_name)
def get_shortcut(self):
shortcut = self._properties.get('Shortcut')
if shortcut: return shortcut
return None
def set_shortcut(self, value):
self._set_property_if_changed('Shortcut', value)
shortcut = property(get_shortcut, set_shortcut)
def get_comment(self):
comment = self._properties.get('Comment')
if comment: return comment
return self.filename
def set_comment(self, value):
self._set_property_if_changed('Comment', value)
comment = property(get_comment, set_comment)
def get_input(self):
input = self._properties.get('Input')
if input: return input
return 'nothing'
def set_input(self, value):
self._set_property_if_changed('Input', value)
input = property(get_input, set_input)
def get_output(self):
output = self._properties.get('Output')
if output: return output
return 'output-panel'
def set_output(self, value):
self._set_property_if_changed('Output', value)
output = property(get_output, set_output)
def get_save_files(self):
save_files = self._properties.get('Save-files')
if save_files: return save_files
return 'nothing'
def set_save_files(self, value):
self._set_property_if_changed('Save-files', value)
save_files = property(get_save_files, set_save_files)
def get_languages(self):
languages = self._properties.get('Languages')
if languages: return languages
return []
def set_languages(self, value):
self._set_property_if_changed('Languages', value)
languages = property(get_languages, set_languages)
def has_hash_bang(self):
if self.filename is None:
return True
filename = self.library.get_full_path(self.get_path())
if filename is None:
return True
fp = open(filename, 'r', 1)
for line in fp:
if line.strip() == '':
continue
return line.startswith('#!')
# There is no property for this one because this function is quite
# expensive to perform
def get_script(self):
if self.filename is None:
return ["#!/bin/sh\n"]
filename = self.library.get_full_path(self.get_path())
if filename is None:
return ["#!/bin/sh\n"]
fp = open(filename, 'r', 1)
lines = list()
# before entering the data block
for line in fp:
if line.startswith('# [Gedit Tool]'):
break
lines.append(line)
# in the block:
for line in fp:
if line.startswith('##'): continue
if not (line.startswith('# ') and '=' in line):
# after the block: strip one emtpy line (if present)
if line.strip() != '':
lines.append(line)
break
# after the block
for line in fp:
lines.append(line)
fp.close()
return lines
def _dump_properties(self):
lines = ['# [Gedit Tool]']
for item in self._properties.iteritems():
if item[0] in self._transform:
lines.append('# %s=%s' % (item[0], self._transform[item[0]][1](item[1])))
elif item[1] is not None:
lines.append('# %s=%s' % item)
return '\n'.join(lines) + '\n'
def save_with_script(self, script):
filename = self.library.get_full_path(self.filename, 'w')
fp = open(filename, 'w', 1)
# Make sure to first print header (shebang, modeline), then
# properties, and then actual content
header = []
content = []
inheader = True
# Parse
for line in script:
line = line.rstrip("\n")
if not inheader:
content.append(line)
elif line.startswith('#!'):
# Shebang (should be always present)
header.append(line)
elif line.strip().startswith('#') and ('-*-' in line or 'ex:' in line or 'vi:' in line or 'vim:' in line):
header.append(line)
else:
content.append(line)
inheader = False
# Write out header
for line in header:
fp.write(line + "\n")
fp.write(self._dump_properties())
fp.write("\n")
for line in content:
fp.write(line + "\n")
fp.close()
os.chmod(filename, 0750)
self.changed = False
def save(self):
if self.changed:
self.save_with_script(self.get_script())
def autoset_filename(self):
if self.filename is not None:
return
dirname = self.parent.path
if dirname != '':
dirname += os.path.sep
basename = self.name.lower().replace(' ', '-').replace('/', '-')
if self.library.get_full_path(dirname + basename):
i = 2
while self.library.get_full_path(dirname + "%s-%d" % (basename, i)):
i += 1
basename = "%s-%d" % (basename, i)
self.filename = basename
if __name__ == '__main__':
library = ToolLibrary()
def print_tool(t, indent):
print indent * " " + "%s: %s" % (t.filename, t.name)
def print_dir(d, indent):
print indent * " " + d.dirname + '/'
for i in d.subdirs:
print_dir(i, indent+1)
for i in d.tools:
print_tool(i, indent+1)
print_dir(library.tree, 0)
# ex:ts=4:et:

View File

@@ -0,0 +1,231 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2009-2010 Per Arneng <per.arneng@anyplanet.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import re
class Link:
"""
This class represents a file link from within a string given by the
output of some software tool. A link contains a reference to a file, the
line number within the file and the boundaries within the given output
string that should be marked as a link.
"""
def __init__(self, path, line_nr, start, end):
"""
path -- the path of the file (that could be extracted)
line_nr -- the line nr of the specified file
start -- the index within the string that the link starts at
end -- the index within the string where the link ends at
"""
self.path = path
self.line_nr = int(line_nr)
self.start = start
self.end = end
def __repr__(self):
return "%s[%s](%s:%s)" % (self.path, self.line_nr,
self.start, self.end)
class LinkParser:
"""
Parses a text using different parsing providers with the goal of finding one
or more file links within the text. A typical example could be the output
from a compiler that specifies an error in a specific file. The path of the
file, the line nr and some more info is then returned so that it can be used
to be able to navigate from the error output in to the specific file.
The actual work of parsing the text is done by instances of classes that
inherits from AbstractLinkParser or by regular expressions. To add a new
parser just create a class that inherits from AbstractLinkParser and then
register in this class cunstructor using the method add_parser. If you want
to add a regular expression then just call add_regexp in this class
constructor and provide your regexp string as argument.
"""
def __init__(self):
self._providers = []
self.add_regexp(REGEXP_STANDARD)
self.add_regexp(REGEXP_PYTHON)
self.add_regexp(REGEXP_VALAC)
self.add_regexp(REGEXP_BASH)
self.add_regexp(REGEXP_RUBY)
self.add_regexp(REGEXP_PERL)
self.add_regexp(REGEXP_MCS)
def add_parser(self, parser):
self._providers.append(parser)
def add_regexp(self, regexp):
"""
Adds a regular expression string that should match a link using
re.MULTILINE and re.VERBOSE regexp. The area marked as a link should
be captured by a group named lnk. The path of the link should be
captured by a group named pth. The line number should be captured by
a group named ln. To read more about this look at the documentation
for the RegexpLinkParser constructor.
"""
self.add_parser(RegexpLinkParser(regexp))
def parse(self, text):
"""
Parses the given text and returns a list of links that are parsed from
the text. This method delegates to parser providers that can parse
output from different kinds of formats. If no links are found then an
empty list is returned.
text -- the text to scan for file links. 'text' can not be None.
"""
if text is None:
raise ValueError("text can not be None")
links = []
for provider in self._providers:
links.extend(provider.parse(text))
return links
class AbstractLinkParser(object):
"""The "abstract" base class for link parses"""
def parse(self, text):
"""
This method should be implemented by subclasses. It takes a text as
argument (never None) and then returns a list of Link objects. If no
links are found then an empty list is expected. The Link class is
defined in this module. If you do not override this method then a
NotImplementedError will be thrown.
text -- the text to parse. This argument is never None.
"""
raise NotImplementedError("need to implement a parse method")
class RegexpLinkParser(AbstractLinkParser):
"""
A class that represents parsers that only use one single regular expression.
It can be used by subclasses or by itself. See the constructor documentation
for details about the rules surrouning the regexp.
"""
def __init__(self, regex):
"""
Creates a new RegexpLinkParser based on the given regular expression.
The regular expression is multiline and verbose (se python docs on
compilation flags). The regular expression should contain three named
capturing groups 'lnk', 'pth' and 'ln'. 'lnk' represents the area wich
should be marked as a link in the text. 'pth' is the path that should
be looked for and 'ln' is the line number in that file.
"""
self.re = re.compile(regex, re.MULTILINE | re.VERBOSE)
def parse(self, text):
links = []
for m in re.finditer(self.re, text):
path = m.group("pth")
line_nr = m.group("ln")
start = m.start("lnk")
end = m.end("lnk")
link = Link(path, line_nr, start, end)
links.append(link)
return links
# gcc 'test.c:13: warning: ...'
# javac 'Test.java:13: ...'
# ruby 'test.rb:5: ...'
# scalac 'Test.scala:5: ...'
# 6g (go) 'test.go:9: ...'
REGEXP_STANDARD = r"""
^
(?P<lnk>
(?P<pth> .*[a-z0-9] )
\:
(?P<ln> \d+)
)
\:\s"""
# python ' File "test.py", line 13'
REGEXP_PYTHON = r"""
^\s\sFile\s
(?P<lnk>
\"
(?P<pth> [^\"]+ )
\",\sline\s
(?P<ln> \d+ )
),"""
# python 'test.sh: line 5:'
REGEXP_BASH = r"""
^(?P<lnk>
(?P<pth> .* )
\:\sline\s
(?P<ln> \d+ )
)\:"""
# valac 'Test.vala:13.1-13.3: ...'
REGEXP_VALAC = r"""
^(?P<lnk>
(?P<pth>
.*vala
)
\:
(?P<ln>
\d+
)
\.\d+-\d+\.\d+
)\: """
#ruby
#test.rb:5: ...
# from test.rb:3:in `each'
# fist line parsed by REGEXP_STANDARD
REGEXP_RUBY = r"""
^\s+from\s
(?P<lnk>
(?P<pth>
.*
)
\:
(?P<ln>
\d+
)
)"""
# perl 'syntax error at test.pl line 88, near "$fake_var'
REGEXP_PERL = r"""
\sat\s
(?P<lnk>
(?P<pth> .* )
\sline\s
(?P<ln> \d+ )
)"""
# mcs (C#) 'Test.cs(12,7): error CS0103: The name `fakeMethod'
REGEXP_MCS = r"""
^
(?P<lnk>
(?P<pth> .*\.[cC][sS] )
\(
(?P<ln> \d+ )
,\d+\)
)
\:\s
"""
# ex:ts=4:et:

View File

@@ -0,0 +1,948 @@
# -*- coding: utf-8 -*-
# Gedit External Tools plugin
# Copyright (C) 2005-2006 Steve Frécinaux <steve@istique.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
__all__ = ('Manager', )
import gedit
import gtk
import gtksourceview2 as gsv
import os.path
from library import *
from functions import *
import hashlib
from xml.sax import saxutils
import gobject
class LanguagesPopup(gtk.Window):
COLUMN_NAME = 0
COLUMN_ID = 1
COLUMN_ENABLED = 2
def __init__(self, languages):
gtk.Window.__init__(self, gtk.WINDOW_POPUP)
self.set_default_size(200, 200)
self.props.can_focus = True
self.build()
self.init_languages(languages)
self.show()
self.map()
self.grab_add()
gtk.gdk.keyboard_grab(self.window, False, 0L)
gtk.gdk.pointer_grab(self.window, False, gtk.gdk.BUTTON_PRESS_MASK |
gtk.gdk.BUTTON_RELEASE_MASK |
gtk.gdk.POINTER_MOTION_MASK |
gtk.gdk.ENTER_NOTIFY_MASK |
gtk.gdk.LEAVE_NOTIFY_MASK |
gtk.gdk.PROXIMITY_IN_MASK |
gtk.gdk.PROXIMITY_OUT_MASK, None, None, 0L)
self.view.get_selection().select_path((0,))
def build(self):
self.model = gtk.ListStore(str, str, bool)
self.sw = gtk.ScrolledWindow()
self.sw.show()
self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
self.view = gtk.TreeView(self.model)
self.view.show()
self.view.set_headers_visible(False)
column = gtk.TreeViewColumn()
renderer = gtk.CellRendererToggle()
column.pack_start(renderer, False)
column.set_attributes(renderer, active=self.COLUMN_ENABLED)
renderer.connect('toggled', self.on_language_toggled)
renderer = gtk.CellRendererText()
column.pack_start(renderer, True)
column.set_attributes(renderer, text=self.COLUMN_NAME)
self.view.append_column(column)
self.view.set_row_separator_func(self.on_separator)
self.sw.add(self.view)
self.add(self.sw)
def enabled_languages(self, model, path, piter, ret):
enabled = model.get_value(piter, self.COLUMN_ENABLED)
if path == (0,) and enabled:
return True
if enabled:
ret.append(model.get_value(piter, self.COLUMN_ID))
return False
def languages(self):
ret = []
self.model.foreach(self.enabled_languages, ret)
return ret
def on_separator(self, model, piter):
val = model.get_value(piter, self.COLUMN_NAME)
return val == '-'
def init_languages(self, languages):
manager = gsv.LanguageManager()
langs = gedit.language_manager_list_languages_sorted(manager, True)
self.model.append([_('All languages'), None, not languages])
self.model.append(['-', None, False])
self.model.append([_('Plain Text'), 'plain', 'plain' in languages])
self.model.append(['-', None, False])
for lang in langs:
self.model.append([lang.get_name(), lang.get_id(), lang.get_id() in languages])
def correct_all(self, model, path, piter, enabled):
if path == (0,):
return False
model.set_value(piter, self.COLUMN_ENABLED, enabled)
def on_language_toggled(self, renderer, path):
piter = self.model.get_iter(path)
enabled = self.model.get_value(piter, self.COLUMN_ENABLED)
self.model.set_value(piter, self.COLUMN_ENABLED, not enabled)
if path == '0':
self.model.foreach(self.correct_all, False)
else:
self.model.set_value(self.model.get_iter_first(), self.COLUMN_ENABLED, False)
def do_key_press_event(self, event):
if event.keyval == gtk.keysyms.Escape:
self.destroy()
return True
else:
event.window = self.view.get_bin_window()
return self.view.event(event)
def do_key_release_event(self, event):
event.window = self.view.get_bin_window()
return self.view.event(event)
def in_window(self, event, window=None):
if not window:
window = self.window
geometry = window.get_geometry()
origin = window.get_origin()
return event.x_root >= origin[0] and \
event.x_root <= origin[0] + geometry[2] and \
event.y_root >= origin[1] and \
event.y_root <= origin[1] + geometry[3]
def do_destroy(self):
gtk.gdk.keyboard_ungrab(0L)
gtk.gdk.pointer_ungrab(0L)
return gtk.Window.do_destroy(self)
def setup_event(self, event, window):
fr = event.window.get_origin()
to = window.get_origin()
event.window = window
event.x += fr[0] - to[0]
event.y += fr[1] - to[1]
def resolve_widgets(self, root):
res = [root]
if isinstance(root, gtk.Container):
root.forall(lambda x, y: res.extend(self.resolve_widgets(x)), None)
return res
def resolve_windows(self, window):
if not window:
return []
res = [window]
res.extend(window.get_children())
return res
def propagate_mouse_event(self, event):
allwidgets = self.resolve_widgets(self.get_child())
allwidgets.reverse()
orig = [event.x, event.y]
for widget in allwidgets:
windows = self.resolve_windows(widget.window)
windows.reverse()
for window in windows:
if not (window.get_events() & event.type):
continue
if self.in_window(event, window):
self.setup_event(event, window)
if widget.event(event):
return True
return False
def do_button_press_event(self, event):
if not self.in_window(event):
self.destroy()
else:
return self.propagate_mouse_event(event)
def do_button_release_event(self, event):
if not self.in_window(event):
self.destroy()
else:
return self.propagate_mouse_event(event)
def do_scroll_event(self, event):
return self.propagate_mouse_event(event)
def do_motion_notify_event(self, event):
return self.propagate_mouse_event(event)
def do_enter_notify_event(self, event):
return self.propagate_mouse_event(event)
def do_leave_notify_event(self, event):
return self.propagate_mouse_event(event)
def do_proximity_in_event(self, event):
return self.propagate_mouse_event(event)
def do_proximity_out_event(self, event):
return self.propagate_mouse_event(event)
gobject.type_register(LanguagesPopup)
class Manager:
TOOL_COLUMN = 0 # For Tree
NAME_COLUMN = 1 # For Combo
def __init__(self, datadir):
self.datadir = datadir
self.dialog = None
self._languages = {}
self._tool_rows = {}
self.build()
def build(self):
callbacks = {
'on_new_tool_button_clicked' : self.on_new_tool_button_clicked,
'on_remove_tool_button_clicked' : self.on_remove_tool_button_clicked,
'on_tool_manager_dialog_response' : self.on_tool_manager_dialog_response,
'on_tool_manager_dialog_focus_out': self.on_tool_manager_dialog_focus_out,
'on_accelerator_key_press' : self.on_accelerator_key_press,
'on_accelerator_focus_in' : self.on_accelerator_focus_in,
'on_accelerator_focus_out' : self.on_accelerator_focus_out,
'on_languages_button_clicked' : self.on_languages_button_clicked
}
# Load the "main-window" widget from the ui file.
self.ui = gtk.Builder()
self.ui.add_from_file(os.path.join(self.datadir, 'ui', 'tools.ui'))
self.ui.connect_signals(callbacks)
self.dialog = self.ui.get_object('tool-manager-dialog')
self.view = self.ui.get_object('view')
self.__init_tools_model()
self.__init_tools_view()
for name in ['input', 'output', 'applicability', 'save-files']:
self.__init_combobox(name)
self.do_update()
def expand_from_doc(self, doc):
row = None
if doc:
if doc.get_language():
lid = doc.get_language().get_id()
if lid in self._languages:
row = self._languages[lid]
elif 'plain' in self._languages:
row = self._languages['plain']
if not row and None in self._languages:
row = self._languages[None]
if not row:
return
self.view.expand_row(row.get_path(), False)
self.view.get_selection().select_path(row.get_path())
def run(self, window):
if self.dialog == None:
self.build()
# Open up language
self.expand_from_doc(window.get_active_document())
self.dialog.set_transient_for(window)
window.get_group().add_window(self.dialog)
self.dialog.present()
def add_accelerator(self, item):
if not item.shortcut:
return
if item.shortcut in self.accelerators:
if not item in self.accelerators[item.shortcut]:
self.accelerators[item.shortcut].append(item)
else:
self.accelerators[item.shortcut] = [item]
def remove_accelerator(self, item, shortcut=None):
if not shortcut:
shortcut = item.shortcut
if not shortcut in self.accelerators:
return
self.accelerators[shortcut].remove(item)
if not self.accelerators[shortcut]:
del self.accelerators[shortcut]
def add_tool_to_language(self, tool, language):
if isinstance(language, gsv.Language):
lid = language.get_id()
else:
lid = language
if not lid in self._languages:
piter = self.model.append(None, [language])
parent = gtk.TreeRowReference(self.model, self.model.get_path(piter))
self._languages[lid] = parent
else:
parent = self._languages[lid]
piter = self.model.get_iter(parent.get_path())
child = self.model.append(piter, [tool])
if not tool in self._tool_rows:
self._tool_rows[tool] = []
self._tool_rows[tool].append(gtk.TreeRowReference(self.model, self.model.get_path(child)))
return child
def add_tool(self, tool):
manager = gsv.LanguageManager()
ret = None
for lang in tool.languages:
l = manager.get_language(lang)
if l:
ret = self.add_tool_to_language(tool, l)
elif lang == 'plain':
ret = self.add_tool_to_language(tool, 'plain')
if not ret:
ret = self.add_tool_to_language(tool, None)
self.add_accelerator(tool)
return ret
def __init_tools_model(self):
self.tools = ToolLibrary()
self.current_node = None
self.script_hash = None
self.accelerators = dict()
self.model = gtk.TreeStore(object)
self.view.set_model(self.model)
for tool in self.tools.tree.tools:
self.add_tool(tool)
self.model.set_default_sort_func(self.sort_tools)
self.model.set_sort_column_id(-1, gtk.SORT_ASCENDING)
def sort_tools(self, model, iter1, iter2):
# For languages, sort All before everything else, otherwise alphabetical
t1 = model.get_value(iter1, self.TOOL_COLUMN)
t2 = model.get_value(iter2, self.TOOL_COLUMN)
if model.iter_parent(iter1) == None:
if t1 == None:
return -1
if t2 == None:
return 1
def lang_name(lang):
if isinstance(lang, gsv.Language):
return lang.get_name()
else:
return _('Plain Text')
n1 = lang_name(t1)
n2 = lang_name(t2)
else:
n1 = t1.name
n2 = t2.name
return cmp(n1.lower(), n2.lower())
def __init_tools_view(self):
# Tools column
column = gtk.TreeViewColumn('Tools')
renderer = gtk.CellRendererText()
column.pack_start(renderer, False)
renderer.set_property('editable', True)
self.view.append_column(column)
column.set_cell_data_func(renderer, self.get_cell_data_cb)
renderer.connect('edited', self.on_view_label_cell_edited)
renderer.connect('editing-started', self.on_view_label_cell_editing_started)
self.selection_changed_id = self.view.get_selection().connect('changed', self.on_view_selection_changed, None)
def __init_combobox(self, name):
combo = self[name]
combo.set_active(0)
# Convenience function to get an object from its name
def __getitem__(self, key):
return self.ui.get_object(key)
def set_active_by_name(self, combo_name, option_name):
combo = self[combo_name]
model = combo.get_model()
piter = model.get_iter_first()
while piter is not None:
if model.get_value(piter, self.NAME_COLUMN) == option_name:
combo.set_active_iter(piter)
return True
piter = model.iter_next(piter)
return False
def get_selected_tool(self):
model, piter = self.view.get_selection().get_selected()
if piter is not None:
tool = model.get_value(piter, self.TOOL_COLUMN)
if not isinstance(tool, Tool):
tool = None
return piter, tool
else:
return None, None
def compute_hash(self, string):
return hashlib.md5(string).hexdigest()
def save_current_tool(self):
if self.current_node is None:
return
if self.current_node.filename is None:
self.current_node.autoset_filename()
def combo_value(o, name):
combo = o[name]
return combo.get_model().get_value(combo.get_active_iter(), self.NAME_COLUMN)
self.current_node.input = combo_value(self, 'input')
self.current_node.output = combo_value(self, 'output')
self.current_node.applicability = combo_value(self, 'applicability')
self.current_node.save_files = combo_value(self, 'save-files')
buf = self['commands'].get_buffer()
script = buf.get_text(*buf.get_bounds())
h = self.compute_hash(script)
if h != self.script_hash:
# script has changed -> save it
self.current_node.save_with_script([line + "\n" for line in script.splitlines()])
self.script_hash = h
else:
self.current_node.save()
self.update_remove_revert()
def clear_fields(self):
self['accelerator'].set_text('')
buf = self['commands'].get_buffer()
buf.begin_not_undoable_action()
buf.set_text('')
buf.end_not_undoable_action()
for nm in ('input', 'output', 'applicability', 'save-files'):
self[nm].set_active(0)
self['languages_label'].set_text(_('All Languages'))
def fill_languages_button(self):
if not self.current_node or not self.current_node.languages:
self['languages_label'].set_text(_('All Languages'))
else:
manager = gsv.LanguageManager()
langs = []
for lang in self.current_node.languages:
if lang == 'plain':
langs.append(_('Plain Text'))
else:
l = manager.get_language(lang)
if l:
langs.append(l.get_name())
self['languages_label'].set_text(', '.join(langs))
def fill_fields(self):
node = self.current_node
self['accelerator'].set_text(default(node.shortcut, ''))
buf = self['commands'].get_buffer()
script = default(''.join(node.get_script()), '')
buf.begin_not_undoable_action()
buf.set_text(script)
buf.end_not_undoable_action()
self.script_hash = self.compute_hash(script)
contenttype = gio.content_type_guess(data=script)
lmanager = gedit.get_language_manager()
language = lmanager.guess_language(content_type=contenttype)
if language is not None:
buf.set_language(language)
buf.set_highlight_syntax(True)
else:
buf.set_highlight_syntax(False)
for nm in ('input', 'output', 'applicability', 'save-files'):
model = self[nm].get_model()
piter = model.get_iter_first()
self.set_active_by_name(nm,
default(node.__getattribute__(nm.replace('-', '_')),
model.get_value(piter, self.NAME_COLUMN)))
self.fill_languages_button()
def update_remove_revert(self):
piter, node = self.get_selected_tool()
removable = node is not None and node.is_local()
self['remove-tool-button'].set_sensitive(removable)
self['revert-tool-button'].set_sensitive(removable)
if node is not None and node.is_global():
self['remove-tool-button'].hide()
self['revert-tool-button'].show()
else:
self['remove-tool-button'].show()
self['revert-tool-button'].hide()
def do_update(self):
self.update_remove_revert()
piter, node = self.get_selected_tool()
self.current_node = node
if node is not None:
self.fill_fields()
self['tool-table'].set_sensitive(True)
else:
self.clear_fields()
self['tool-table'].set_sensitive(False)
def language_id_from_iter(self, piter):
if not piter:
return None
tool = self.model.get_value(piter, self.TOOL_COLUMN)
if isinstance(tool, Tool):
piter = self.model.iter_parent(piter)
tool = self.model.get_value(piter, self.TOOL_COLUMN)
if isinstance(tool, gsv.Language):
return tool.get_id()
elif tool:
return 'plain'
return None
def selected_language_id(self):
# Find current language if there is any
model, piter = self.view.get_selection().get_selected()
return self.language_id_from_iter(piter)
def on_new_tool_button_clicked(self, button):
self.save_current_tool()
# block handlers while inserting a new item
self.view.get_selection().handler_block(self.selection_changed_id)
self.current_node = Tool(self.tools.tree);
self.current_node.name = _('New tool')
self.tools.tree.tools.append(self.current_node)
lang = self.selected_language_id()
if lang:
self.current_node.languages = [lang]
piter = self.add_tool(self.current_node)
self.view.set_cursor(self.model.get_path(piter), self.view.get_column(self.TOOL_COLUMN), True)
self.fill_fields()
self['tool-table'].set_sensitive(True)
self.view.get_selection().handler_unblock(self.selection_changed_id)
def tool_changed(self, tool, refresh=False):
for row in self._tool_rows[tool]:
self.model.row_changed(row.get_path(), self.model.get_iter(row.get_path()))
if refresh and tool == self.current_node:
self.fill_fields()
self.update_remove_revert()
def on_remove_tool_button_clicked(self, button):
piter, node = self.get_selected_tool()
if not node:
return
if node.is_global():
shortcut = node.shortcut
if node.parent.revert_tool(node):
self.remove_accelerator(node, shortcut)
self.add_accelerator(node)
self['revert-tool-button'].set_sensitive(False)
self.fill_fields()
self.tool_changed(node)
else:
parent = self.model.iter_parent(piter)
language = self.language_id_from_iter(parent)
self.model.remove(piter)
if language in node.languages:
node.languages.remove(language)
self._tool_rows[node] = filter(lambda x: x.valid(), self._tool_rows[node])
if not self._tool_rows[node]:
del self._tool_rows[node]
if node.parent.delete_tool(node):
self.remove_accelerator(node)
self.current_node = None
self.script_hash = None
if self.model.iter_is_valid(piter):
self.view.set_cursor(self.model.get_path(piter), self.view.get_column(self.TOOL_COLUMN), False)
self.view.grab_focus()
path = self._languages[language].get_path()
parent = self.model.get_iter(path)
if not self.model.iter_has_child(parent):
self.model.remove(parent)
del self._languages[language]
def on_view_label_cell_edited(self, cell, path, new_text):
if new_text != '':
piter = self.model.get_iter(path)
tool = self.model.get_value(piter, self.TOOL_COLUMN)
tool.name = new_text
self.save_current_tool()
self.tool_changed(tool)
def on_view_label_cell_editing_started(self, renderer, editable, path):
piter = self.model.get_iter(path)
tool = self.model.get_value(piter, self.TOOL_COLUMN)
if isinstance(editable, gtk.Entry):
editable.set_text(tool.name)
editable.grab_focus()
def on_view_selection_changed(self, selection, userdata):
self.save_current_tool()
self.do_update()
def accelerator_collision(self, name, node):
if not name in self.accelerators:
return []
ret = []
for other in self.accelerators[name]:
if not other.languages or not node.languages:
ret.append(other)
continue
for lang in other.languages:
if lang in node.languages:
ret.append(other)
continue
return ret
def set_accelerator(self, keyval, mod):
# Check whether accelerator already exists
self.remove_accelerator(self.current_node)
name = gtk.accelerator_name(keyval, mod)
if name == '':
self.current_node.shorcut = None
self.save_current_tool()
return True
col = self.accelerator_collision(name, self.current_node)
if col:
dialog = gtk.MessageDialog(self.dialog,
gtk.DIALOG_MODAL,
gtk.MESSAGE_ERROR,
gtk.BUTTONS_OK,
_('This accelerator is already bound to %s') % (', '.join(map(lambda x: x.name, col)),))
dialog.run()
dialog.destroy()
self.add_accelerator(self.current_node)
return False
self.current_node.shortcut = name
self.add_accelerator(self.current_node)
self.save_current_tool()
return True
def on_accelerator_key_press(self, entry, event):
mask = event.state & gtk.accelerator_get_default_mod_mask()
if event.keyval == gtk.keysyms.Escape:
entry.set_text(default(self.current_node.shortcut, ''))
self['commands'].grab_focus()
return True
elif event.keyval == gtk.keysyms.Delete \
or event.keyval == gtk.keysyms.BackSpace:
entry.set_text('')
self.remove_accelerator(self.current_node)
self.current_node.shortcut = None
self['commands'].grab_focus()
return True
elif event.keyval in range(gtk.keysyms.F1, gtk.keysyms.F12 + 1):
# New accelerator
if self.set_accelerator(event.keyval, mask):
entry.set_text(default(self.current_node.shortcut, ''))
self['commands'].grab_focus()
# Capture all `normal characters`
return True
elif gtk.gdk.keyval_to_unicode(event.keyval):
if mask:
# New accelerator
if self.set_accelerator(event.keyval, mask):
entry.set_text(default(self.current_node.shortcut, ''))
self['commands'].grab_focus()
# Capture all `normal characters`
return True
else:
return False
def on_accelerator_focus_in(self, entry, event):
if self.current_node is None:
return
if self.current_node.shortcut:
entry.set_text(_('Type a new accelerator, or press Backspace to clear'))
else:
entry.set_text(_('Type a new accelerator'))
def on_accelerator_focus_out(self, entry, event):
if self.current_node is not None:
entry.set_text(default(self.current_node.shortcut, ''))
self.tool_changed(self.current_node)
def on_tool_manager_dialog_response(self, dialog, response):
if response == gtk.RESPONSE_HELP:
gedit.help_display(self.dialog, 'gedit', 'gedit-external-tools-plugin')
return
self.on_tool_manager_dialog_focus_out(dialog, None)
self.dialog.destroy()
self.dialog = None
self.tools = None
def on_tool_manager_dialog_focus_out(self, dialog, event):
self.save_current_tool()
for window in gedit.app_get_default().get_windows():
helper = window.get_data("ExternalToolsPluginWindowData")
helper.menu.update()
def get_cell_data_cb(self, column, cell, model, piter):
tool = model.get_value(piter, self.TOOL_COLUMN)
if tool == None or not isinstance(tool, Tool):
if tool == None:
label = _('All Languages')
elif not isinstance(tool, gsv.Language):
label = _('Plain Text')
else:
label = tool.get_name()
markup = saxutils.escape(label)
editable = False
else:
escaped = saxutils.escape(tool.name)
if tool.shortcut:
markup = '%s (<b>%s</b>)' % (escaped, saxutils.escape(tool.shortcut))
else:
markup = escaped
editable = True
cell.set_properties(markup=markup, editable=editable)
def tool_in_language(self, tool, lang):
if not lang in self._languages:
return False
ref = self._languages[lang]
parent = ref.get_path()
for row in self._tool_rows[tool]:
path = row.get_path()
if path[0] == parent[0]:
return True
return False
def update_languages(self, popup):
self.current_node.languages = popup.languages()
self.fill_languages_button()
piter, node = self.get_selected_tool()
ret = None
if node:
ref = gtk.TreeRowReference(self.model, self.model.get_path(piter))
# Update languages, make sure to inhibit selection change stuff
self.view.get_selection().handler_block(self.selection_changed_id)
# Remove all rows that are no longer
for row in list(self._tool_rows[self.current_node]):
piter = self.model.get_iter(row.get_path())
language = self.language_id_from_iter(piter)
if (not language and not self.current_node.languages) or \
(language in self.current_node.languages):
continue
# Remove from language
self.model.remove(piter)
self._tool_rows[self.current_node].remove(row)
# If language is empty, remove it
parent = self.model.get_iter(self._languages[language].get_path())
if not self.model.iter_has_child(parent):
self.model.remove(parent)
del self._languages[language]
# Now, add for any that are new
manager = gsv.LanguageManager()
for lang in self.current_node.languages:
if not self.tool_in_language(self.current_node, lang):
l = manager.get_language(lang)
if not l:
l = 'plain'
self.add_tool_to_language(self.current_node, l)
if not self.current_node.languages and not self.tool_in_language(self.current_node, None):
self.add_tool_to_language(self.current_node, None)
# Check if we can still keep the current
if not ref or not ref.valid():
# Change selection to first language
path = self._tool_rows[self.current_node][0].get_path()
piter = self.model.get_iter(path)
parent = self.model.iter_parent(piter)
# Expand parent, select child and scroll to it
self.view.expand_row(self.model.get_path(parent), False)
self.view.get_selection().select_path(path)
self.view.set_cursor(path, self.view.get_column(self.TOOL_COLUMN), False)
self.view.get_selection().handler_unblock(self.selection_changed_id)
def on_languages_button_clicked(self, button):
popup = LanguagesPopup(self.current_node.languages)
popup.set_transient_for(self.dialog)
origin = button.window.get_origin()
popup.move(origin[0], origin[1] - popup.allocation.height)
popup.connect('destroy', self.update_languages)
# ex:et:ts=4:

View File

@@ -0,0 +1,224 @@
# -*- coding: utf-8 -*-
# Gedit External Tools plugin
# Copyright (C) 2005-2006 Steve Frécinaux <steve@istique.net>
# Copyright (C) 2010 Per Arneng <per.arneng@anyplanet.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
__all__ = ('OutputPanel', 'UniqueById')
import gtk, gedit
import pango
import gobject
import os
from weakref import WeakKeyDictionary
from capture import *
from gtk import gdk
import re
import gio
import linkparsing
import filelookup
class UniqueById:
__shared_state = WeakKeyDictionary()
def __init__(self, i):
if i in self.__class__.__shared_state:
self.__dict__ = self.__class__.__shared_state[i]
return True
else:
self.__class__.__shared_state[i] = self.__dict__
return False
def states(self):
return self.__class__.__shared_state
class OutputPanel(UniqueById):
def __init__(self, datadir, window):
if UniqueById.__init__(self, window):
return
callbacks = {
'on_stop_clicked' : self.on_stop_clicked,
'on_view_visibility_notify_event': self.on_view_visibility_notify_event,
'on_view_motion_notify_event': self.on_view_motion_notify_event,
'on_view_button_press_event': self.on_view_button_press_event
}
self.window = window
self.ui = gtk.Builder()
self.ui.add_from_file(os.path.join(datadir, 'ui', 'outputpanel.ui'))
self.ui.connect_signals(callbacks)
self.panel = self["output-panel"]
self['view'].modify_font(pango.FontDescription('Monospace'))
buffer = self['view'].get_buffer()
self.normal_tag = buffer.create_tag('normal')
self.error_tag = buffer.create_tag('error')
self.error_tag.set_property('foreground', 'red')
self.italic_tag = buffer.create_tag('italic')
self.italic_tag.set_property('style', pango.STYLE_OBLIQUE)
self.bold_tag = buffer.create_tag('bold')
self.bold_tag.set_property('weight', pango.WEIGHT_BOLD)
self.invalid_link_tag = buffer.create_tag('invalid_link')
self.link_tag = buffer.create_tag('link')
self.link_tag.set_property('underline', pango.UNDERLINE_SINGLE)
self.link_cursor = gdk.Cursor(gdk.HAND2)
self.normal_cursor = gdk.Cursor(gdk.XTERM)
self.process = None
self.links = []
self.link_parser = linkparsing.LinkParser()
self.file_lookup = filelookup.FileLookup()
def set_process(self, process):
self.process = process
def __getitem__(self, key):
# Convenience function to get an object from its name
return self.ui.get_object(key)
def on_stop_clicked(self, widget, *args):
if self.process is not None:
self.write("\n" + _('Stopped.') + "\n",
self.italic_tag)
self.process.stop(-1)
def scroll_to_end(self):
iter = self['view'].get_buffer().get_end_iter()
self['view'].scroll_to_iter(iter, 0.0)
return False # don't requeue this handler
def clear(self):
self['view'].get_buffer().set_text("")
self.links = []
def visible(self):
panel = self.window.get_bottom_panel()
return panel.props.visible and panel.item_is_active(self.panel)
def write(self, text, tag = None):
buffer = self['view'].get_buffer()
end_iter = buffer.get_end_iter()
insert = buffer.create_mark(None, end_iter, True)
if tag is None:
buffer.insert(end_iter, text)
else:
buffer.insert_with_tags(end_iter, text, tag)
# find all links and apply the appropriate tag for them
links = self.link_parser.parse(text)
for lnk in links:
insert_iter = buffer.get_iter_at_mark(insert)
lnk.start = insert_iter.get_offset() + lnk.start
lnk.end = insert_iter.get_offset() + lnk.end
start_iter = buffer.get_iter_at_offset(lnk.start)
end_iter = buffer.get_iter_at_offset(lnk.end)
tag = None
# if the link points to an existing file then it is a valid link
if self.file_lookup.lookup(lnk.path) is not None:
self.links.append(lnk)
tag = self.link_tag
else:
tag = self.invalid_link_tag
buffer.apply_tag(tag, start_iter, end_iter)
buffer.delete_mark(insert)
gobject.idle_add(self.scroll_to_end)
def show(self):
panel = self.window.get_bottom_panel()
panel.show()
panel.activate_item(self.panel)
def update_cursor_style(self, view, x, y):
if self.get_link_at_location(view, x, y) is not None:
cursor = self.link_cursor
else:
cursor = self.normal_cursor
view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(cursor)
def on_view_motion_notify_event(self, view, event):
if event.window == view.get_window(gtk.TEXT_WINDOW_TEXT):
self.update_cursor_style(view, int(event.x), int(event.y))
return False
def on_view_visibility_notify_event(self, view, event):
if event.window == view.get_window(gtk.TEXT_WINDOW_TEXT):
x, y, m = event.window.get_pointer()
self.update_cursor_style(view, x, y)
return False
def idle_grab_focus(self):
self.window.get_active_view().grab_focus()
return False
def get_link_at_location(self, view, x, y):
"""
Get the link under a specified x,y coordinate. If no link exists then
None is returned.
"""
# get the offset within the buffer from the x,y coordinates
buff_x, buff_y = view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
x, y)
iter_at_xy = view.get_iter_at_location(buff_x, buff_y)
offset = iter_at_xy.get_offset()
# find the first link that contains the offset
for lnk in self.links:
if offset >= lnk.start and offset <= lnk.end:
return lnk
# no link was found at x,y
return None
def on_view_button_press_event(self, view, event):
if event.button != 1 or event.type != gdk.BUTTON_PRESS or \
event.window != view.get_window(gtk.TEXT_WINDOW_TEXT):
return False
link = self.get_link_at_location(view, int(event.x), int(event.y))
if link is None:
return False
gfile = self.file_lookup.lookup(link.path)
if gfile:
gedit.commands.load_uri(self.window, gfile.get_uri(), None,
link.line_nr)
gobject.idle_add(self.idle_grab_focus)
# ex:ts=4:et:

View File

@@ -0,0 +1,53 @@
<?xml version="1.0"?>
<!-- Generated with glade3
Version: 2.91.3
Date: Sat Nov 18 13:58:59 2006
User: sf
Host: antea
-->
<interface>
<object class="GtkHBox" id="output-panel">
<property name="visible">True</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<child>
<object class="GtkTextView" id="view">
<property name="visible">True</property>
<property name="editable">False</property>
<property name="wrap_mode">GTK_WRAP_WORD</property>
<property name="cursor_visible">False</property>
<property name="accepts_tab">False</property>
<signal name="button_press_event" handler="on_view_button_press_event"/>
<signal name="motion_notify_event" handler="on_view_motion_notify_event"/>
<signal name="visibility_notify_event" handler="on_view_visibility_notify_event"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkVButtonBox" id="vbuttonbox1">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="spacing">6</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<object class="GtkButton" id="stop">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="label">gtk-stop</property>
<property name="use_stock">True</property>
<signal handler="on_stop_clicked" name="clicked"/>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
</interface>

View File

@@ -0,0 +1,606 @@
<?xml version="1.0"?>
<interface>
<object class="GtkListStore" id="model_save_files">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Nothing</col>
<col id="1">nothing</col>
</row>
<row>
<col id="0" translatable="yes">Current document</col>
<col id="1">document</col>
</row>
<row>
<col id="0" translatable="yes">All documents</col>
<col id="1">all</col>
</row>
</data>
</object>
<object class="GtkListStore" id="model_input">
<columns>
<column type="gchararray"/>
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Nothing</col>
<col id="1">nothing</col>
</row>
<row>
<col id="0" translatable="yes">Current document</col>
<col id="1">document</col>
</row>
<row>
<col id="0" translatable="yes">Current selection</col>
<col id="1">selection</col>
</row>
<row>
<col id="0" translatable="yes">Current selection (default to document)</col>
<col id="1">selection-document</col>
</row>
<row>
<col id="0" translatable="yes">Current line</col>
<col id="1">line</col>
</row>
<row>
<col id="0" translatable="yes">Current word</col>
<col id="1">word</col>
</row>
</data>
</object>
<object class="GtkListStore" id="model_output">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Nothing</col>
<col id="1">nothing</col>
</row>
<row>
<col id="0" translatable="yes">Display in bottom pane</col>
<col id="1">output-panel</col>
</row>
<row>
<col id="0" translatable="yes">Create new document</col>
<col id="1">new-document</col>
</row>
<row>
<col id="0" translatable="yes">Append to current document</col>
<col id="1">append-document</col>
</row>
<row>
<col id="0" translatable="yes">Replace current document</col>
<col id="1">replace-document</col>
</row>
<row>
<col id="0" translatable="yes">Replace current selection</col>
<col id="1">replace-selection</col>
</row>
<row>
<col id="0" translatable="yes">Insert at cursor position</col>
<col id="1">insert</col>
</row>
</data>
</object>
<object class="GtkListStore" id="model_applicability">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">All documents</col>
<col id="1">all</col>
</row>
<row>
<col id="0" translatable="yes">All documents except untitled ones</col>
<col id="1">titled</col>
</row>
<row>
<col id="0" translatable="yes">Local files only</col>
<col id="1">local</col>
</row>
<row>
<col id="0" translatable="yes">Remote files only</col>
<col id="1">remote</col>
</row>
<row>
<col id="0" translatable="yes">Untitled documents only</col>
<col id="1">untitled</col>
</row>
</data>
</object>
<object class="GeditDocument" id="commands_buffer">
<property name="highlight-matching-brackets">True</property>
</object>
<object class="GtkDialog" id="tool-manager-dialog">
<property name="title" translatable="yes">External Tools Manager</property>
<property name="default_width">750</property>
<property name="default_height">500</property>
<property name="type_hint">dialog</property>
<property name="skip_taskbar_hint">True</property>
<property name="has_separator">False</property>
<signal name="focus_out_event" handler="on_tool_manager_dialog_focus_out"/>
<signal name="response" handler="on_tool_manager_dialog_response"/>
<child internal-child="vbox">
<object class="GtkVBox" id="tool-manager-dialog-vbox">
<property name="visible">True</property>
<child>
<object class="GtkHPaned" id="paned">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="border_width">6</property>
<property name="position">275</property>
<child>
<object class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label20">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Tools:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">view</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolled_window1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">False</property>
<property name="reorderable">True</property>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkButton" id="new-tool-button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<signal name="clicked" handler="on_new_tool_button_clicked"/>
<child>
<object class="GtkImage" id="new-tool-image">
<property name="visible">True</property>
<property name="stock">gtk-new</property>
<property name="icon-size">4</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="revert-tool-button">
<property name="can_focus">False</property>
<property name="receives_default">False</property>
<signal name="clicked" handler="on_remove_tool_button_clicked"/>
<child>
<object class="GtkImage" id="revert-tool-image">
<property name="visible">True</property>
<property name="stock">gtk-revert-to-saved</property>
<property name="icon-size">4</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="remove-tool-button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<signal name="clicked" handler="on_remove_tool_button_clicked"/>
<child>
<object class="GtkImage" id="remove-tool-image">
<property name="visible">True</property>
<property name="stock">gtk-delete</property>
<property name="icon-size">4</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="resize">False</property>
<property name="shrink">False</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox5">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="title">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="label" translatable="yes">_Edit:</property>
<property name="mnemonic_widget">commands</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox7">
<property name="visible">True</property>
<child>
<object class="GtkLabel" id="label22">
<property name="visible">True</property>
<property name="label" translatable="yes"> </property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkTable" id="tool-table">
<property name="visible">True</property>
<property name="n_rows">6</property>
<property name="n_columns">2</property>
<property name="column_spacing">6</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkEntry" id="accelerator">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="key_press_event" handler="on_accelerator_key_press"/>
<signal name="focus_out_event" handler="on_accelerator_focus_out"/>
<signal name="focus_in_event" handler="on_accelerator_focus_in"/>
</object>
<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="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<child>
<object class="GtkComboBox" id="applicability">
<property name="visible">True</property>
<property name="model">model_applicability</property>
<child>
<object class="GtkCellRendererText" id="applicability_renderer"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="position">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<object class="GtkEventBox" id="languages_event_box">
<property name="visible">True</property>
<property name="visible-window">True</property>
<child>
<object class="GtkButton" id="languages_button">
<property name="visible">True</property>
<signal name="clicked" handler="on_languages_button_clicked"/>
<child>
<object class="GtkLabel" id="languages_label">
<property name="visible">True</property>
<property name="label" translatable="yes">All Languages</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="output">
<property name="visible">True</property>
<property name="model">model_output</property>
<child>
<object class="GtkCellRendererText" id="output_renderer"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="input">
<property name="visible">True</property>
<property name="model">model_input</property>
<child>
<object class="GtkCellRendererText" id="input_renderer"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<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">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="save-files">
<property name="model">model_save_files</property>
<property name="visible">True</property>
<child>
<object class="GtkCellRendererText" id="renderer1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<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="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label23">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Applicability:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">applicability</property>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Output:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">output</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Input:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">input</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label6">
<property name="xalign">0</property>
<property name="label" translatable="yes">_Save:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">save-files</property>
<property name="visible">True</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Shortcut Key:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">accelerator</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<object class="GeditView" id="commands">
<property name="buffer">commands_buffer</property>
<property name="visible">True</property>
<property name="auto-indent">True</property>
<property name="insert-spaces-instead-of-tabs">False</property>
<property name="smart-home-end">GTK_SOURCE_SMART_HOME_END_AFTER</property>
<property name="tab-width">2</property>
<property name="highlight-current-line">True</property>
<property name="show-right-margin">False</property>
<property name="show-line-numbers">True</property>
</object>
</child>
</object>
<packing>
<property name="right_attach">2</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">False</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button1">
<property name="label">gtk-help</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-11">button1</action-widget>
<action-widget response="-7">button2</action-widget>
</action-widgets>
</object>
</interface>

104
plugins/filebrowser/Makefile.am Executable file
View File

@@ -0,0 +1,104 @@
# filebrowser
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)
INCLUDES = \
-I$(top_srcdir) \
$(GEDIT_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS)
BUILT_SOURCES = \
gedit-file-browser-enum-types.h \
gedit-file-browser-enum-types.c \
gedit-file-browser-marshal.h \
gedit-file-browser-marshal.c
plugin_LTLIBRARIES = libfilebrowser.la
NOINST_H_FILES = \
gedit-file-bookmarks-store.h \
gedit-file-browser-store.h \
gedit-file-browser-view.h \
gedit-file-browser-widget.h \
gedit-file-browser-error.h \
gedit-file-browser-utils.h \
gedit-file-browser-plugin.h \
gedit-file-browser-messages.h
libfilebrowser_la_SOURCES = \
$(BUILT_SOURCES) \
gedit-file-bookmarks-store.c \
gedit-file-browser-store.c \
gedit-file-browser-view.c \
gedit-file-browser-widget.c \
gedit-file-browser-utils.c \
gedit-file-browser-plugin.c \
gedit-file-browser-messages.c \
$(NOINST_H_FILES)
libfilebrowser_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libfilebrowser_la_LIBADD = $(GEDIT_LIBS)
# UI files (if you use ui for your plugin, list those files here)
uidir = $(GEDIT_PLUGINS_DATA_DIR)/filebrowser
ui_DATA = gedit-file-browser-widget-ui.xml
plugin_in_files = filebrowser.gedit-plugin.desktop.in
%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
gedit-file-browser-enum-types.h: gedit-file-browser-enum-types.h.template $(NOINST_H_FILES) $(GLIB_MKENUMS)
(cd $(srcdir) && $(GLIB_MKENUMS) --template gedit-file-browser-enum-types.h.template $(NOINST_H_FILES)) > $@
gedit-file-browser-enum-types.c: gedit-file-browser-enum-types.c.template gedit-file-browser-enum-register.c.template $(NOINST_H_FILES) $(GLIB_MKENUMS)
$(AM_V_GEN) (cd $(srcdir) && \
$(GLIB_MKENUMS) --template gedit-file-browser-enum-types.c.template $(NOINST_H_FILES) && \
$(GLIB_MKENUMS) --template gedit-file-browser-enum-register.c.template $(NOINST_H_FILES)) > $@
gedit-file-browser-marshal.h: gedit-file-browser-marshal.list $(GLIB_GENMARSHAL)
$(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=gedit_file_browser_marshal > $@
gedit-file-browser-marshal.c: gedit-file-browser-marshal.list $(GLIB_GENMARSHAL)
$(AM_V_GEN) echo "#include \"gedit-file-browser-marshal.h\"" > $@ && \
$(GLIB_GENMARSHAL) $< --body --prefix=gedit_file_browser_marshal >> $@
plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin)
schemasdir = $(MATECONF_SCHEMA_FILE_DIR)
schemas_in_files = gedit-file-browser.schemas.in
schemas_DATA = $(schemas_in_files:.schemas.in=.schemas)
@INTLTOOL_SCHEMAS_RULE@
if MATECONF_SCHEMAS_INSTALL
install-data-local:
if test -z "$(DESTDIR)" ; then \
for p in $(schemas_DATA) ; do \
MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(MATECONFTOOL) --makefile-install-rule $(top_builddir)/plugins/filebrowser/$$p ; \
done \
fi
else
install-data-local:
endif
EXTRA_DIST = \
$(ui_DATA) \
$(plugin_in_files) \
$(schemas_in_files) \
gedit-file-browser-enum-types.h.template \
gedit-file-browser-enum-types.c.template \
gedit-file-browser-enum-register.c.template \
gedit-file-browser-marshal.list
CLEANFILES = \
$(plugin_DATA) \
$(schemas_DATA) \
$(BUILT_SOURCES)
DISTCLEANFILES = \
$(plugin_DATA) \
$(schemas_DATA) \
$(BUILT_SOURCES)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,10 @@
[Gedit Plugin]
Loader=C
Module=filebrowser
IAge=2
_Name=File Browser Pane
_Description=Easy file access from the side pane
Icon=system-file-manager
Authors=Jesse van den Kieboom <jesse@icecrew.nl>
Copyright=Copyright © 2006 Jesse van den Kieboom
Website=http://www.gedit.org

View File

@@ -0,0 +1,879 @@
/*
* gedit-file-bookmarks-store.c - Gedit plugin providing easy file access
* from the sidepanel
*
* Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include <gedit/gedit-utils.h>
#include <gedit/gedit-plugin.h>
#include "gedit-file-bookmarks-store.h"
#include "gedit-file-browser-utils.h"
#define GEDIT_FILE_BOOKMARKS_STORE_GET_PRIVATE(object)( \
G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_FILE_BOOKMARKS_STORE, \
GeditFileBookmarksStorePrivate))
struct _GeditFileBookmarksStorePrivate
{
GVolumeMonitor * volume_monitor;
GFileMonitor * bookmarks_monitor;
};
static void remove_node (GtkTreeModel * model,
GtkTreeIter * iter);
static void on_fs_changed (GVolumeMonitor *monitor,
GObject *object,
GeditFileBookmarksStore *model);
static void on_bookmarks_file_changed (GFileMonitor * monitor,
GFile * file,
GFile * other_file,
GFileMonitorEvent event_type,
GeditFileBookmarksStore * model);
static gboolean find_with_flags (GtkTreeModel * model,
GtkTreeIter * iter,
gpointer obj,
guint flags,
guint notflags);
GEDIT_PLUGIN_DEFINE_TYPE(GeditFileBookmarksStore, gedit_file_bookmarks_store, GTK_TYPE_TREE_STORE)
static void
gedit_file_bookmarks_store_dispose (GObject * object)
{
GeditFileBookmarksStore *obj = GEDIT_FILE_BOOKMARKS_STORE (object);
if (obj->priv->volume_monitor != NULL) {
g_signal_handlers_disconnect_by_func (obj->priv->volume_monitor,
on_fs_changed,
obj);
g_object_unref (obj->priv->volume_monitor);
obj->priv->volume_monitor = NULL;
}
if (obj->priv->bookmarks_monitor != NULL) {
g_object_unref (obj->priv->bookmarks_monitor);
obj->priv->bookmarks_monitor = NULL;
}
G_OBJECT_CLASS (gedit_file_bookmarks_store_parent_class)->dispose (object);
}
static void
gedit_file_bookmarks_store_finalize (GObject * object)
{
G_OBJECT_CLASS (gedit_file_bookmarks_store_parent_class)->finalize (object);
}
static void
gedit_file_bookmarks_store_class_init (GeditFileBookmarksStoreClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gedit_file_bookmarks_store_dispose;
object_class->finalize = gedit_file_bookmarks_store_finalize;
g_type_class_add_private (object_class, sizeof (GeditFileBookmarksStorePrivate));
}
static void
gedit_file_bookmarks_store_init (GeditFileBookmarksStore * obj)
{
obj->priv = GEDIT_FILE_BOOKMARKS_STORE_GET_PRIVATE (obj);
}
/* Private */
static void
add_node (GeditFileBookmarksStore *model,
GdkPixbuf *pixbuf,
const gchar *name,
GObject *obj,
guint flags,
GtkTreeIter *iter)
{
GtkTreeIter newiter;
gtk_tree_store_append (GTK_TREE_STORE (model), &newiter, NULL);
gtk_tree_store_set (GTK_TREE_STORE (model), &newiter,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_ICON, pixbuf,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_NAME, name,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_OBJECT, obj,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_FLAGS, flags,
-1);
if (iter != NULL)
*iter = newiter;
}
static gboolean
add_file (GeditFileBookmarksStore *model,
GFile *file,
const gchar *name,
guint flags,
GtkTreeIter *iter)
{
GdkPixbuf *pixbuf = NULL;
gboolean native;
gchar *newname;
native = g_file_is_native (file);
if (native && !g_file_query_exists (file, NULL)) {
return FALSE;
}
if (flags & GEDIT_FILE_BOOKMARKS_STORE_IS_HOME)
pixbuf = gedit_file_browser_utils_pixbuf_from_theme ("user-home", GTK_ICON_SIZE_MENU);
else if (flags & GEDIT_FILE_BOOKMARKS_STORE_IS_DESKTOP)
pixbuf = gedit_file_browser_utils_pixbuf_from_theme ("user-desktop", GTK_ICON_SIZE_MENU);
else if (flags & GEDIT_FILE_BOOKMARKS_STORE_IS_ROOT)
pixbuf = gedit_file_browser_utils_pixbuf_from_theme ("drive-harddisk", GTK_ICON_SIZE_MENU);
if (pixbuf == NULL) {
/* getting the icon is a sync get_info call, so we just do it for local files */
if (native) {
pixbuf = gedit_file_browser_utils_pixbuf_from_file (file, GTK_ICON_SIZE_MENU);
} else {
pixbuf = gedit_file_browser_utils_pixbuf_from_theme ("folder", GTK_ICON_SIZE_MENU);
}
}
if (name == NULL) {
newname = gedit_file_browser_utils_file_basename (file);
} else {
newname = g_strdup (name);
}
add_node (model, pixbuf, newname, G_OBJECT (file), flags, iter);
if (pixbuf)
g_object_unref (pixbuf);
g_free (newname);
return TRUE;
}
static void
check_mount_separator (GeditFileBookmarksStore * model, guint flags,
gboolean added)
{
GtkTreeIter iter;
gboolean found;
found =
find_with_flags (GTK_TREE_MODEL (model), &iter, NULL,
flags |
GEDIT_FILE_BOOKMARKS_STORE_IS_SEPARATOR, 0);
if (added && !found) {
/* Add the separator */
add_node (model, NULL, NULL, NULL,
flags | GEDIT_FILE_BOOKMARKS_STORE_IS_SEPARATOR,
NULL);
} else if (!added && found) {
remove_node (GTK_TREE_MODEL (model), &iter);
}
}
static void
init_special_directories (GeditFileBookmarksStore * model)
{
gchar const *path;
GFile * file;
path = g_get_home_dir ();
if (path != NULL)
{
file = g_file_new_for_path (path);
add_file (model, file, NULL, GEDIT_FILE_BOOKMARKS_STORE_IS_HOME |
GEDIT_FILE_BOOKMARKS_STORE_IS_SPECIAL_DIR, NULL);
g_object_unref (file);
}
path = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
if (path != NULL)
{
file = g_file_new_for_path (path);
add_file (model, file, NULL, GEDIT_FILE_BOOKMARKS_STORE_IS_DESKTOP |
GEDIT_FILE_BOOKMARKS_STORE_IS_SPECIAL_DIR, NULL);
g_object_unref (file);
}
path = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
if (path != NULL)
{
file = g_file_new_for_path (path);
add_file (model, file, NULL, GEDIT_FILE_BOOKMARKS_STORE_IS_DOCUMENTS |
GEDIT_FILE_BOOKMARKS_STORE_IS_SPECIAL_DIR, NULL);
g_object_unref (file);
}
file = g_file_new_for_uri ("file:///");
add_file (model, file, _("File System"), GEDIT_FILE_BOOKMARKS_STORE_IS_ROOT, NULL);
g_object_unref (file);
check_mount_separator (model, GEDIT_FILE_BOOKMARKS_STORE_IS_ROOT, TRUE);
}
static void
get_fs_properties (gpointer fs,
gchar **name,
GdkPixbuf **pixbuf,
guint *flags)
{
GIcon *icon = NULL;
*flags = GEDIT_FILE_BOOKMARKS_STORE_IS_FS;
*name = NULL;
*pixbuf = NULL;
if (G_IS_DRIVE (fs))
{
icon = g_drive_get_icon (G_DRIVE (fs));
*name = g_drive_get_name (G_DRIVE (fs));
*flags |= GEDIT_FILE_BOOKMARKS_STORE_IS_DRIVE;
}
else if (G_IS_VOLUME (fs))
{
icon = g_volume_get_icon (G_VOLUME (fs));
*name = g_volume_get_name (G_VOLUME (fs));
*flags |= GEDIT_FILE_BOOKMARKS_STORE_IS_VOLUME;
}
else if (G_IS_MOUNT (fs))
{
icon = g_mount_get_icon (G_MOUNT (fs));
*name = g_mount_get_name (G_MOUNT (fs));
*flags |= GEDIT_FILE_BOOKMARKS_STORE_IS_MOUNT;
}
if (icon)
{
*pixbuf = gedit_file_browser_utils_pixbuf_from_icon (icon, GTK_ICON_SIZE_MENU);
g_object_unref (icon);
}
}
static void
add_fs (GeditFileBookmarksStore *model,
gpointer fs,
guint flags,
GtkTreeIter *iter)
{
gchar *name;
GdkPixbuf *pixbuf;
guint fsflags;
get_fs_properties (fs, &name, &pixbuf, &fsflags);
add_node (model, pixbuf, name, fs, flags | fsflags, iter);
if (pixbuf)
g_object_unref (pixbuf);
g_free (name);
check_mount_separator (model, GEDIT_FILE_BOOKMARKS_STORE_IS_FS, TRUE);
}
static void
process_volume_cb (GVolume *volume,
GeditFileBookmarksStore *model)
{
GMount *mount;
guint flags = GEDIT_FILE_BOOKMARKS_STORE_NONE;
mount = g_volume_get_mount (volume);
/* CHECK: should we use the LOCAL/REMOTE thing still? */
if (mount)
{
/* Show mounted volume */
add_fs (model, mount, flags, NULL);
g_object_unref (mount);
}
else if (g_volume_can_mount (volume))
{
/* We also show the unmounted volume here so users can
mount it if they want to access it */
add_fs (model, volume, flags, NULL);
}
}
static void
process_drive_novolumes (GeditFileBookmarksStore *model,
GDrive *drive)
{
if (g_drive_is_media_removable (drive) &&
!g_drive_is_media_check_automatic (drive) &&
g_drive_can_poll_for_media (drive))
{
/* This can be the case for floppy drives or other
drives where media detection fails. We show the
drive and poll for media when the user activates
it */
add_fs (model, drive, GEDIT_FILE_BOOKMARKS_STORE_NONE, NULL);
}
}
static void
process_drive_cb (GDrive *drive,
GeditFileBookmarksStore *model)
{
GList *volumes;
volumes = g_drive_get_volumes (drive);
if (volumes)
{
/* Add all volumes for the drive */
g_list_foreach (volumes, (GFunc)process_volume_cb, model);
g_list_free (volumes);
}
else
{
process_drive_novolumes (model, drive);
}
}
static void
init_drives (GeditFileBookmarksStore *model)
{
GList *drives;
drives = g_volume_monitor_get_connected_drives (model->priv->volume_monitor);
g_list_foreach (drives, (GFunc)process_drive_cb, model);
g_list_foreach (drives, (GFunc)g_object_unref, NULL);
g_list_free (drives);
}
static void
process_volume_nodrive_cb (GVolume *volume,
GeditFileBookmarksStore *model)
{
GDrive *drive;
drive = g_volume_get_drive (volume);
if (drive)
{
g_object_unref (drive);
return;
}
process_volume_cb (volume, model);
}
static void
init_volumes (GeditFileBookmarksStore *model)
{
GList *volumes;
volumes = g_volume_monitor_get_volumes (model->priv->volume_monitor);
g_list_foreach (volumes, (GFunc)process_volume_nodrive_cb, model);
g_list_foreach (volumes, (GFunc)g_object_unref, NULL);
g_list_free (volumes);
}
static void
process_mount_novolume_cb (GMount *mount,
GeditFileBookmarksStore *model)
{
GVolume *volume;
volume = g_mount_get_volume (mount);
if (volume)
{
g_object_unref (volume);
}
else if (!g_mount_is_shadowed (mount))
{
/* Add the mount */
add_fs (model, mount, GEDIT_FILE_BOOKMARKS_STORE_NONE, NULL);
}
}
static void
init_mounts (GeditFileBookmarksStore *model)
{
GList *mounts;
mounts = g_volume_monitor_get_mounts (model->priv->volume_monitor);
g_list_foreach (mounts, (GFunc)process_mount_novolume_cb, model);
g_list_foreach (mounts, (GFunc)g_object_unref, NULL);
g_list_free (mounts);
}
static void
init_fs (GeditFileBookmarksStore * model)
{
if (model->priv->volume_monitor == NULL) {
const gchar **ptr;
const gchar *signals[] = {
"drive-connected", "drive-changed", "drive-disconnected",
"volume-added", "volume-removed", "volume-changed",
"mount-added", "mount-removed", "mount-changed",
NULL
};
model->priv->volume_monitor = g_volume_monitor_get ();
/* Connect signals */
for (ptr = signals; *ptr; ptr++)
{
g_signal_connect (model->priv->volume_monitor,
*ptr,
G_CALLBACK (on_fs_changed), model);
}
}
/* First go through all the connected drives */
init_drives (model);
/* Then add all volumes, not associated with a drive */
init_volumes (model);
/* Then finally add all mounts that have no volume */
init_mounts (model);
}
static gboolean
add_bookmark (GeditFileBookmarksStore * model,
gchar const * name,
gchar const * uri)
{
GFile * file;
gboolean ret;
guint flags = GEDIT_FILE_BOOKMARKS_STORE_IS_BOOKMARK;
GtkTreeIter iter;
file = g_file_new_for_uri (uri);
if (g_file_is_native (file)) {
flags |= GEDIT_FILE_BOOKMARKS_STORE_IS_LOCAL_BOOKMARK;
} else {
flags |= GEDIT_FILE_BOOKMARKS_STORE_IS_REMOTE_BOOKMARK;
}
ret = add_file (model, file, name, flags, &iter);
g_object_unref (file);
return ret;
}
static void
init_bookmarks (GeditFileBookmarksStore * model)
{
gchar *bookmarks;
GError *error = NULL;
gchar *contents;
gchar **lines;
gchar **line;
gboolean added = FALSE;
/* Read the bookmarks file */
bookmarks = g_build_filename (g_get_home_dir (),
".gtk-bookmarks",
NULL);
if (g_file_get_contents (bookmarks, &contents, NULL, &error)) {
lines = g_strsplit (contents, "\n", 0);
for (line = lines; *line; ++line) {
if (**line) {
gchar *pos;
gchar *name;
/* CHECK: is this really utf8? */
pos = g_utf8_strchr (*line, -1, ' ');
if (pos != NULL) {
*pos = '\0';
name = pos + 1;
} else {
name = NULL;
}
/* the bookmarks file should contain valid
* URIs, but paranoia is good */
if (gedit_utils_is_valid_uri (*line)) {
added |= add_bookmark (model, name, *line);
}
}
}
g_strfreev (lines);
g_free (contents);
/* Add a watch */
if (model->priv->bookmarks_monitor == NULL) {
GFile * file;
file = g_file_new_for_path (bookmarks);
model->priv->bookmarks_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
g_object_unref (file);
g_signal_connect (model->priv->bookmarks_monitor,
"changed",
(GCallback)on_bookmarks_file_changed,
model);
}
} else {
/* The bookmarks file doesn't exist (which is perfectly fine) */
g_error_free (error);
}
if (added) {
/* Bookmarks separator */
add_node (model, NULL, NULL, NULL,
GEDIT_FILE_BOOKMARKS_STORE_IS_BOOKMARK |
GEDIT_FILE_BOOKMARKS_STORE_IS_SEPARATOR, NULL);
}
g_free (bookmarks);
}
static gint flags_order[] = {
GEDIT_FILE_BOOKMARKS_STORE_IS_HOME,
GEDIT_FILE_BOOKMARKS_STORE_IS_DESKTOP,
GEDIT_FILE_BOOKMARKS_STORE_IS_SPECIAL_DIR,
GEDIT_FILE_BOOKMARKS_STORE_IS_ROOT,
GEDIT_FILE_BOOKMARKS_STORE_IS_FS,
GEDIT_FILE_BOOKMARKS_STORE_IS_BOOKMARK,
-1
};
static gint
utf8_casecmp (gchar const *s1, const gchar * s2)
{
gchar *n1;
gchar *n2;
gint result;
n1 = g_utf8_casefold (s1, -1);
n2 = g_utf8_casefold (s2, -1);
result = g_utf8_collate (n1, n2);
g_free (n1);
g_free (n2);
return result;
}
static gint
bookmarks_compare_names (GtkTreeModel * model, GtkTreeIter * a,
GtkTreeIter * b)
{
gchar *n1;
gchar *n2;
gint result;
guint f1;
guint f2;
gtk_tree_model_get (model, a,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_NAME, &n1,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_FLAGS, &f1,
-1);
gtk_tree_model_get (model, b,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_NAME, &n2,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_FLAGS, &f2,
-1);
/* do not sort actual bookmarks to keep same order as in caja */
if ((f1 & GEDIT_FILE_BOOKMARKS_STORE_IS_BOOKMARK) &&
(f2 & GEDIT_FILE_BOOKMARKS_STORE_IS_BOOKMARK))
result = 0;
else if (n1 == NULL && n2 == NULL)
result = 0;
else if (n1 == NULL)
result = -1;
else if (n2 == NULL)
result = 1;
else
result = utf8_casecmp (n1, n2);
g_free (n1);
g_free (n2);
return result;
}
static gint
bookmarks_compare_flags (GtkTreeModel * model, GtkTreeIter * a,
GtkTreeIter * b)
{
guint f1;
guint f2;
gint *flags;
guint sep;
sep = GEDIT_FILE_BOOKMARKS_STORE_IS_SEPARATOR;
gtk_tree_model_get (model, a,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_FLAGS, &f1,
-1);
gtk_tree_model_get (model, b,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_FLAGS, &f2,
-1);
for (flags = flags_order; *flags != -1; ++flags) {
if ((f1 & *flags) != (f2 & *flags)) {
if (f1 & *flags) {
return -1;
} else {
return 1;
}
} else if ((f1 & *flags) && (f1 & sep) != (f2 & sep)) {
if (f1 & sep)
return -1;
else
return 1;
}
}
return 0;
}
static gint
bookmarks_compare_func (GtkTreeModel * model, GtkTreeIter * a,
GtkTreeIter * b, gpointer user_data)
{
gint result;
result = bookmarks_compare_flags (model, a, b);
if (result == 0)
result = bookmarks_compare_names (model, a, b);
return result;
}
static gboolean
find_with_flags (GtkTreeModel * model, GtkTreeIter * iter, gpointer obj,
guint flags, guint notflags)
{
GtkTreeIter child;
guint childflags = 0;
GObject * childobj;
gboolean fequal;
if (!gtk_tree_model_get_iter_first (model, &child))
return FALSE;
do {
gtk_tree_model_get (model, &child,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_OBJECT,
&childobj,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_FLAGS,
&childflags, -1);
fequal = (obj == childobj);
if (childobj)
g_object_unref (childobj);
if ((obj == NULL || fequal) &&
(childflags & flags) == flags
&& !(childflags & notflags)) {
*iter = child;
return TRUE;
}
} while (gtk_tree_model_iter_next (model, &child));
return FALSE;
}
static void
remove_node (GtkTreeModel * model, GtkTreeIter * iter)
{
guint flags;
gtk_tree_model_get (model, iter,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_FLAGS, &flags,
-1);
if (!(flags & GEDIT_FILE_BOOKMARKS_STORE_IS_SEPARATOR)) {
if (flags & GEDIT_FILE_BOOKMARKS_STORE_IS_FS) {
check_mount_separator (GEDIT_FILE_BOOKMARKS_STORE (model),
flags & GEDIT_FILE_BOOKMARKS_STORE_IS_FS,
FALSE);
}
}
gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
}
static void
remove_bookmarks (GeditFileBookmarksStore * model)
{
GtkTreeIter iter;
while (find_with_flags (GTK_TREE_MODEL (model), &iter, NULL,
GEDIT_FILE_BOOKMARKS_STORE_IS_BOOKMARK,
0)) {
remove_node (GTK_TREE_MODEL (model), &iter);
}
}
static void
initialize_fill (GeditFileBookmarksStore * model)
{
init_special_directories (model);
init_fs (model);
init_bookmarks (model);
}
/* Public */
GeditFileBookmarksStore *
gedit_file_bookmarks_store_new (void)
{
GeditFileBookmarksStore *model;
GType column_types[] = {
GDK_TYPE_PIXBUF,
G_TYPE_STRING,
G_TYPE_OBJECT,
G_TYPE_UINT
};
model = g_object_new (GEDIT_TYPE_FILE_BOOKMARKS_STORE, NULL);
gtk_tree_store_set_column_types (GTK_TREE_STORE (model),
GEDIT_FILE_BOOKMARKS_STORE_N_COLUMNS,
column_types);
gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
bookmarks_compare_func,
NULL, NULL);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
GTK_SORT_ASCENDING);
initialize_fill (model);
return model;
}
gchar *
gedit_file_bookmarks_store_get_uri (GeditFileBookmarksStore * model,
GtkTreeIter * iter)
{
GObject * obj;
GFile * file = NULL;
guint flags;
gchar * ret = NULL;
gboolean isfs;
g_return_val_if_fail (GEDIT_IS_FILE_BOOKMARKS_STORE (model), NULL);
g_return_val_if_fail (iter != NULL, NULL);
gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_FLAGS,
&flags,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_OBJECT,
&obj,
-1);
if (obj == NULL)
return NULL;
isfs = (flags & GEDIT_FILE_BOOKMARKS_STORE_IS_FS);
if (isfs && (flags & GEDIT_FILE_BOOKMARKS_STORE_IS_MOUNT))
{
file = g_mount_get_root (G_MOUNT (obj));
}
else if (!isfs)
{
file = g_object_ref (obj);
}
g_object_unref (obj);
if (file)
{
ret = g_file_get_uri (file);
g_object_unref (file);
}
return ret;
}
void
gedit_file_bookmarks_store_refresh (GeditFileBookmarksStore * model)
{
gtk_tree_store_clear (GTK_TREE_STORE (model));
initialize_fill (model);
}
static void
on_fs_changed (GVolumeMonitor *monitor,
GObject *object,
GeditFileBookmarksStore *model)
{
GtkTreeModel *tree_model = GTK_TREE_MODEL (model);
guint flags = GEDIT_FILE_BOOKMARKS_STORE_IS_FS;
guint noflags = GEDIT_FILE_BOOKMARKS_STORE_IS_SEPARATOR;
GtkTreeIter iter;
/* clear all fs items */
while (find_with_flags (tree_model, &iter, NULL, flags, noflags))
remove_node (tree_model, &iter);
/* then reinitialize */
init_fs (model);
}
static void
on_bookmarks_file_changed (GFileMonitor * monitor,
GFile * file,
GFile * other_file,
GFileMonitorEvent event_type,
GeditFileBookmarksStore * model)
{
switch (event_type) {
case G_FILE_MONITOR_EVENT_CHANGED:
case G_FILE_MONITOR_EVENT_CREATED:
/* Re-initialize bookmarks */
remove_bookmarks (model);
init_bookmarks (model);
break;
case G_FILE_MONITOR_EVENT_DELETED: // FIXME: shouldn't we also monitor the directory?
/* Remove bookmarks */
remove_bookmarks (model);
g_object_unref (monitor);
model->priv->bookmarks_monitor = NULL;
break;
default:
break;
}
}
// ex:ts=8:noet:

View File

@@ -0,0 +1,90 @@
/*
* gedit-file-bookmarks-store.h - Gedit plugin providing easy file access
* from the sidepanel
*
* Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GEDIT_FILE_BOOKMARKS_STORE_H__
#define __GEDIT_FILE_BOOKMARKS_STORE_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define GEDIT_TYPE_FILE_BOOKMARKS_STORE (gedit_file_bookmarks_store_get_type ())
#define GEDIT_FILE_BOOKMARKS_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_BOOKMARKS_STORE, GeditFileBookmarksStore))
#define GEDIT_FILE_BOOKMARKS_STORE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_BOOKMARKS_STORE, GeditFileBookmarksStore const))
#define GEDIT_FILE_BOOKMARKS_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_FILE_BOOKMARKS_STORE, GeditFileBookmarksStoreClass))
#define GEDIT_IS_FILE_BOOKMARKS_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_FILE_BOOKMARKS_STORE))
#define GEDIT_IS_FILE_BOOKMARKS_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_FILE_BOOKMARKS_STORE))
#define GEDIT_FILE_BOOKMARKS_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_FILE_BOOKMARKS_STORE, GeditFileBookmarksStoreClass))
typedef struct _GeditFileBookmarksStore GeditFileBookmarksStore;
typedef struct _GeditFileBookmarksStoreClass GeditFileBookmarksStoreClass;
typedef struct _GeditFileBookmarksStorePrivate GeditFileBookmarksStorePrivate;
enum
{
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_ICON = 0,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_NAME,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_OBJECT,
GEDIT_FILE_BOOKMARKS_STORE_COLUMN_FLAGS,
GEDIT_FILE_BOOKMARKS_STORE_N_COLUMNS
};
enum
{
GEDIT_FILE_BOOKMARKS_STORE_NONE = 0,
GEDIT_FILE_BOOKMARKS_STORE_IS_SEPARATOR = 1 << 0, /* Separator item */
GEDIT_FILE_BOOKMARKS_STORE_IS_SPECIAL_DIR = 1 << 1, /* Special user dir */
GEDIT_FILE_BOOKMARKS_STORE_IS_HOME = 1 << 2, /* The special Home user directory */
GEDIT_FILE_BOOKMARKS_STORE_IS_DESKTOP = 1 << 3, /* The special Desktop user directory */
GEDIT_FILE_BOOKMARKS_STORE_IS_DOCUMENTS = 1 << 4, /* The special Documents user directory */
GEDIT_FILE_BOOKMARKS_STORE_IS_FS = 1 << 5, /* A mount object */
GEDIT_FILE_BOOKMARKS_STORE_IS_MOUNT = 1 << 6, /* A mount object */
GEDIT_FILE_BOOKMARKS_STORE_IS_VOLUME = 1 << 7, /* A volume object */
GEDIT_FILE_BOOKMARKS_STORE_IS_DRIVE = 1 << 8, /* A drive object */
GEDIT_FILE_BOOKMARKS_STORE_IS_ROOT = 1 << 9, /* The root file system (file:///) */
GEDIT_FILE_BOOKMARKS_STORE_IS_BOOKMARK = 1 << 10, /* A gtk bookmark */
GEDIT_FILE_BOOKMARKS_STORE_IS_REMOTE_BOOKMARK = 1 << 11, /* A remote gtk bookmark */
GEDIT_FILE_BOOKMARKS_STORE_IS_LOCAL_BOOKMARK = 1 << 12 /* A local gtk bookmark */
};
struct _GeditFileBookmarksStore
{
GtkTreeStore parent;
GeditFileBookmarksStorePrivate *priv;
};
struct _GeditFileBookmarksStoreClass
{
GtkTreeStoreClass parent_class;
};
GType gedit_file_bookmarks_store_get_type (void) G_GNUC_CONST;
GType gedit_file_bookmarks_store_register_type (GTypeModule * module);
GeditFileBookmarksStore *gedit_file_bookmarks_store_new (void);
gchar *gedit_file_bookmarks_store_get_uri (GeditFileBookmarksStore * model,
GtkTreeIter * iter);
void gedit_file_bookmarks_store_refresh (GeditFileBookmarksStore * model);
G_END_DECLS
#endif /* __GEDIT_FILE_BOOKMARKS_STORE_H__ */
// ex:ts=8:noet:

View File

@@ -0,0 +1,20 @@
/*** BEGIN file-header ***/
void
gedit_file_browser_enum_and_flag_register_type (GTypeModule * module)
{
/*** END file-header ***/
/*** BEGIN file-production ***/
/* Enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN enumeration-production ***/
register_@enum_name@ (module);
/*** END enumeration-production ***/
/*** BEGIN file-tail ***/
}
/*** END file-tail ***/

View File

@@ -0,0 +1,45 @@
/*** BEGIN file-header ***/
#include "gedit-file-browser-enum-types.h"
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
#include "@filename@"
/*** END file-production ***/
/*** BEGIN value-header ***/
static GType @enum_name@_type = 0;
static GType
register_@enum_name@ (GTypeModule *module)
{
static const G@Type@Value values[] = {
/*** END value-header ***/
/*** BEGIN value-production ***/
{ @VALUENAME@,
"@VALUENAME@",
"@valuenick@" },
/*** END value-production ***/
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
@enum_name@_type =
g_type_module_register_@type@ (module,
"@EnumName@",
values);
return @enum_name@_type;
}
GType
@enum_name@_get_type (void)
{
return @enum_name@_type;
}
/*** END value-tail ***/

View File

@@ -0,0 +1,29 @@
/*** BEGIN file-header ***/
#ifndef __GEDIT_FILE_BROWSER_ENUM_TYPES_H__
#define __GEDIT_FILE_BROWSER_ENUM_TYPES_H__
#include <glib-object.h>
G_BEGIN_DECLS
/*** END file-header ***/
/*** BEGIN file-production ***/
/* Enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN enumeration-production ***/
#define GEDIT_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
GType @enum_name@_get_type (void) G_GNUC_CONST;
/*** END enumeration-production ***/
/*** BEGIN file-tail ***/
void gedit_file_browser_enum_and_flag_register_type (GTypeModule * module);
G_END_DECLS
#endif /* __GEDIT_FILE_BROWSER_ENUM_TYPES_H__ */
/*** END file-tail ***/

View File

@@ -0,0 +1,41 @@
/*
* gedit-file-browser-error.h - Gedit plugin providing easy file access
* from the sidepanel
*
* Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GEDIT_FILE_BROWSER_ERROR_H__
#define __GEDIT_FILE_BROWSER_ERROR_H__
G_BEGIN_DECLS
typedef enum {
GEDIT_FILE_BROWSER_ERROR_NONE,
GEDIT_FILE_BROWSER_ERROR_RENAME,
GEDIT_FILE_BROWSER_ERROR_DELETE,
GEDIT_FILE_BROWSER_ERROR_NEW_FILE,
GEDIT_FILE_BROWSER_ERROR_NEW_DIRECTORY,
GEDIT_FILE_BROWSER_ERROR_OPEN_DIRECTORY,
GEDIT_FILE_BROWSER_ERROR_SET_ROOT,
GEDIT_FILE_BROWSER_ERROR_LOAD_DIRECTORY,
GEDIT_FILE_BROWSER_ERROR_NUM
} GeditFileBrowserError;
G_END_DECLS
#endif /* __GEDIT_FILE_BROWSER_ERROR_H__ */

View File

@@ -0,0 +1,5 @@
VOID:UINT,STRING
VOID:STRING,STRING
BOOL:OBJECT,POINTER
BOOL:POINTER
BOOL:VOID

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
/*
* gedit-file-browser-messages.h - Gedit plugin providing easy file access
* from the sidepanel
*
* Copyright (C) 2008 - Jesse van den Kieboom <jesse@icecrew.nl>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GEDIT_FILE_BROWSER_MESSAGES_H__
#define __GEDIT_FILE_BROWSER_MESSAGES_H__
#include <gedit/gedit-window.h>
#include <gedit/gedit-message-bus.h>
#include "gedit-file-browser-widget.h"
void gedit_file_browser_messages_register (GeditWindow *window,
GeditFileBrowserWidget *widget);
void gedit_file_browser_messages_unregister (GeditWindow *window);
#endif /* __GEDIT_FILE_BROWSER_MESSAGES_H__ */
// ex:ts=8:noet:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,71 @@
/*
* gedit-file-browser-plugin.h - Gedit plugin providing easy file access
* from the sidepanel
*
* Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GEDIT_FILE_BROWSER_PLUGIN_H__
#define __GEDIT_FILE_BROWSER_PLUGIN_H__
#include <glib.h>
#include <glib-object.h>
#include <gedit/gedit-plugin.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define GEDIT_TYPE_FILE_BROWSER_PLUGIN (filetree_plugin_get_type ())
#define GEDIT_FILE_BROWSER_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_FILE_BROWSER_PLUGIN, GeditFileBrowserPlugin))
#define GEDIT_FILE_BROWSER_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_FILE_BROWSER_PLUGIN, GeditFileBrowserPluginClass))
#define GEDIT_IS_FILE_BROWSER_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_FILE_BROWSER_PLUGIN))
#define GEDIT_IS_FILE_BROWSER_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_FILE_BROWSER_PLUGIN))
#define GEDIT_FILE_BROWSER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_FILE_BROWSER_PLUGIN, GeditFileBrowserPluginClass))
/* Private structure type */
typedef struct _GeditFileBrowserPluginPrivate GeditFileBrowserPluginPrivate;
typedef struct _GeditFileBrowserPlugin GeditFileBrowserPlugin;
typedef struct _GeditFileBrowserPluginClass GeditFileBrowserPluginClass;
struct _GeditFileBrowserPlugin
{
GeditPlugin parent_instance;
/*< private > */
GeditFileBrowserPluginPrivate *priv;
};
struct _GeditFileBrowserPluginClass
{
GeditPluginClass parent_class;
};
/*
* Public methods
*/
GType filetree_plugin_get_type (void) G_GNUC_CONST;
/* All the plugins must implement this function */
G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule * module);
G_END_DECLS
#endif /* __GEDIT_FILE_BROWSER_PLUGIN_H__ */
// ex:ts=8:noet:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,200 @@
/*
* gedit-file-browser-store.h - Gedit plugin providing easy file access
* from the sidepanel
*
* Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GEDIT_FILE_BROWSER_STORE_H__
#define __GEDIT_FILE_BROWSER_STORE_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define GEDIT_TYPE_FILE_BROWSER_STORE (gedit_file_browser_store_get_type ())
#define GEDIT_FILE_BROWSER_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_BROWSER_STORE, GeditFileBrowserStore))
#define GEDIT_FILE_BROWSER_STORE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_BROWSER_STORE, GeditFileBrowserStore const))
#define GEDIT_FILE_BROWSER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_FILE_BROWSER_STORE, GeditFileBrowserStoreClass))
#define GEDIT_IS_FILE_BROWSER_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_FILE_BROWSER_STORE))
#define GEDIT_IS_FILE_BROWSER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_FILE_BROWSER_STORE))
#define GEDIT_FILE_BROWSER_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_FILE_BROWSER_STORE, GeditFileBrowserStoreClass))
typedef enum
{
GEDIT_FILE_BROWSER_STORE_COLUMN_ICON = 0,
GEDIT_FILE_BROWSER_STORE_COLUMN_NAME,
GEDIT_FILE_BROWSER_STORE_COLUMN_URI,
GEDIT_FILE_BROWSER_STORE_COLUMN_FLAGS,
GEDIT_FILE_BROWSER_STORE_COLUMN_EMBLEM,
GEDIT_FILE_BROWSER_STORE_COLUMN_NUM
} GeditFileBrowserStoreColumn;
typedef enum
{
GEDIT_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY = 1 << 0,
GEDIT_FILE_BROWSER_STORE_FLAG_IS_HIDDEN = 1 << 1,
GEDIT_FILE_BROWSER_STORE_FLAG_IS_TEXT = 1 << 2,
GEDIT_FILE_BROWSER_STORE_FLAG_LOADED = 1 << 3,
GEDIT_FILE_BROWSER_STORE_FLAG_IS_FILTERED = 1 << 4,
GEDIT_FILE_BROWSER_STORE_FLAG_IS_DUMMY = 1 << 5
} GeditFileBrowserStoreFlag;
typedef enum
{
GEDIT_FILE_BROWSER_STORE_RESULT_OK,
GEDIT_FILE_BROWSER_STORE_RESULT_NO_CHANGE,
GEDIT_FILE_BROWSER_STORE_RESULT_ERROR,
GEDIT_FILE_BROWSER_STORE_RESULT_NO_TRASH,
GEDIT_FILE_BROWSER_STORE_RESULT_MOUNTING,
GEDIT_FILE_BROWSER_STORE_RESULT_NUM
} GeditFileBrowserStoreResult;
typedef enum
{
GEDIT_FILE_BROWSER_STORE_FILTER_MODE_NONE = 0,
GEDIT_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN = 1 << 0,
GEDIT_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY = 1 << 1
} GeditFileBrowserStoreFilterMode;
#define FILE_IS_DIR(flags) (flags & GEDIT_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY)
#define FILE_IS_HIDDEN(flags) (flags & GEDIT_FILE_BROWSER_STORE_FLAG_IS_HIDDEN)
#define FILE_IS_TEXT(flags) (flags & GEDIT_FILE_BROWSER_STORE_FLAG_IS_TEXT)
#define FILE_LOADED(flags) (flags & GEDIT_FILE_BROWSER_STORE_FLAG_LOADED)
#define FILE_IS_FILTERED(flags) (flags & GEDIT_FILE_BROWSER_STORE_FLAG_IS_FILTERED)
#define FILE_IS_DUMMY(flags) (flags & GEDIT_FILE_BROWSER_STORE_FLAG_IS_DUMMY)
typedef struct _GeditFileBrowserStore GeditFileBrowserStore;
typedef struct _GeditFileBrowserStoreClass GeditFileBrowserStoreClass;
typedef struct _GeditFileBrowserStorePrivate GeditFileBrowserStorePrivate;
typedef gboolean (*GeditFileBrowserStoreFilterFunc) (GeditFileBrowserStore
* model,
GtkTreeIter * iter,
gpointer user_data);
struct _GeditFileBrowserStore
{
GObject parent;
GeditFileBrowserStorePrivate *priv;
};
struct _GeditFileBrowserStoreClass {
GObjectClass parent_class;
/* Signals */
void (*begin_loading) (GeditFileBrowserStore * model,
GtkTreeIter * iter);
void (*end_loading) (GeditFileBrowserStore * model,
GtkTreeIter * iter);
void (*error) (GeditFileBrowserStore * model,
guint code,
gchar * message);
gboolean (*no_trash) (GeditFileBrowserStore * model,
GList * files);
void (*rename) (GeditFileBrowserStore * model,
const gchar * olduri,
const gchar * newuri);
void (*begin_refresh) (GeditFileBrowserStore * model);
void (*end_refresh) (GeditFileBrowserStore * model);
void (*unload) (GeditFileBrowserStore * model,
const gchar * uri);
};
GType gedit_file_browser_store_get_type (void) G_GNUC_CONST;
GType gedit_file_browser_store_register_type (GTypeModule * module);
GeditFileBrowserStore *gedit_file_browser_store_new (gchar const *root);
GeditFileBrowserStoreResult
gedit_file_browser_store_set_root_and_virtual_root (GeditFileBrowserStore * model,
gchar const *root,
gchar const *virtual_root);
GeditFileBrowserStoreResult
gedit_file_browser_store_set_root (GeditFileBrowserStore * model,
gchar const *root);
GeditFileBrowserStoreResult
gedit_file_browser_store_set_virtual_root (GeditFileBrowserStore * model,
GtkTreeIter * iter);
GeditFileBrowserStoreResult
gedit_file_browser_store_set_virtual_root_from_string (GeditFileBrowserStore * model,
gchar const *root);
GeditFileBrowserStoreResult
gedit_file_browser_store_set_virtual_root_up (GeditFileBrowserStore * model);
GeditFileBrowserStoreResult
gedit_file_browser_store_set_virtual_root_top (GeditFileBrowserStore * model);
gboolean
gedit_file_browser_store_get_iter_virtual_root (GeditFileBrowserStore * model,
GtkTreeIter * iter);
gboolean gedit_file_browser_store_get_iter_root (GeditFileBrowserStore * model,
GtkTreeIter * iter);
gchar * gedit_file_browser_store_get_root (GeditFileBrowserStore * model);
gchar * gedit_file_browser_store_get_virtual_root (GeditFileBrowserStore * model);
gboolean gedit_file_browser_store_iter_equal (GeditFileBrowserStore * model,
GtkTreeIter * iter1,
GtkTreeIter * iter2);
void gedit_file_browser_store_set_value (GeditFileBrowserStore * tree_model,
GtkTreeIter * iter,
gint column,
GValue * value);
void _gedit_file_browser_store_iter_expanded (GeditFileBrowserStore * model,
GtkTreeIter * iter);
void _gedit_file_browser_store_iter_collapsed (GeditFileBrowserStore * model,
GtkTreeIter * iter);
GeditFileBrowserStoreFilterMode
gedit_file_browser_store_get_filter_mode (GeditFileBrowserStore * model);
void gedit_file_browser_store_set_filter_mode (GeditFileBrowserStore * model,
GeditFileBrowserStoreFilterMode mode);
void gedit_file_browser_store_set_filter_func (GeditFileBrowserStore * model,
GeditFileBrowserStoreFilterFunc func,
gpointer user_data);
void gedit_file_browser_store_refilter (GeditFileBrowserStore * model);
GeditFileBrowserStoreFilterMode
gedit_file_browser_store_filter_mode_get_default (void);
void gedit_file_browser_store_refresh (GeditFileBrowserStore * model);
gboolean gedit_file_browser_store_rename (GeditFileBrowserStore * model,
GtkTreeIter * iter,
gchar const *new_name,
GError ** error);
GeditFileBrowserStoreResult
gedit_file_browser_store_delete (GeditFileBrowserStore * model,
GtkTreeIter * iter,
gboolean trash);
GeditFileBrowserStoreResult
gedit_file_browser_store_delete_all (GeditFileBrowserStore * model,
GList *rows,
gboolean trash);
gboolean gedit_file_browser_store_new_file (GeditFileBrowserStore * model,
GtkTreeIter * parent,
GtkTreeIter * iter);
gboolean gedit_file_browser_store_new_directory (GeditFileBrowserStore * model,
GtkTreeIter * parent,
GtkTreeIter * iter);
void gedit_file_browser_store_cancel_mount_operation (GeditFileBrowserStore *store);
G_END_DECLS
#endif /* __GEDIT_FILE_BROWSER_STORE_H__ */
// ex:ts=8:noet:

View File

@@ -0,0 +1,198 @@
/*
* gedit-file-bookmarks-store.c - Gedit plugin providing easy file access
* from the sidepanel
*
* Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "gedit-file-browser-utils.h"
#include <gedit/gedit-utils.h>
static GdkPixbuf *
process_icon_pixbuf (GdkPixbuf * pixbuf,
gchar const * name,
gint size,
GError * error)
{
GdkPixbuf * scale;
if (error != NULL) {
g_warning ("Could not load theme icon %s: %s",
name,
error->message);
g_error_free (error);
}
if (pixbuf && gdk_pixbuf_get_width (pixbuf) > size) {
scale = gdk_pixbuf_scale_simple (pixbuf,
size,
size,
GDK_INTERP_BILINEAR);
g_object_unref (pixbuf);
pixbuf = scale;
}
return pixbuf;
}
GdkPixbuf *
gedit_file_browser_utils_pixbuf_from_theme (gchar const * name,
GtkIconSize size)
{
gint width;
GError *error = NULL;
GdkPixbuf *pixbuf;
gtk_icon_size_lookup (size, &width, NULL);
pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
name,
width,
0,
&error);
pixbuf = process_icon_pixbuf (pixbuf, name, width, error);
return pixbuf;
}
GdkPixbuf *
gedit_file_browser_utils_pixbuf_from_icon (GIcon * icon,
GtkIconSize size)
{
GdkPixbuf * ret = NULL;
GtkIconTheme *theme;
GtkIconInfo *info;
gint width;
if (!icon)
return NULL;
theme = gtk_icon_theme_get_default ();
gtk_icon_size_lookup (size, &width, NULL);
info = gtk_icon_theme_lookup_by_gicon (theme,
icon,
width,
GTK_ICON_LOOKUP_USE_BUILTIN);
if (!info)
return NULL;
ret = gtk_icon_info_load_icon (info, NULL);
gtk_icon_info_free (info);
return ret;
}
GdkPixbuf *
gedit_file_browser_utils_pixbuf_from_file (GFile * file,
GtkIconSize size)
{
GIcon * icon;
GFileInfo * info;
GdkPixbuf * ret = NULL;
info = g_file_query_info (file,
G_FILE_ATTRIBUTE_STANDARD_ICON,
G_FILE_QUERY_INFO_NONE,
NULL,
NULL);
if (!info)
return NULL;
icon = g_file_info_get_icon (info);
if (icon != NULL)
ret = gedit_file_browser_utils_pixbuf_from_icon (icon, size);
g_object_unref (info);
return ret;
}
gchar *
gedit_file_browser_utils_file_basename (GFile * file)
{
gchar *uri;
gchar *ret;
uri = g_file_get_uri (file);
ret = gedit_file_browser_utils_uri_basename (uri);
g_free (uri);
return ret;
}
gchar *
gedit_file_browser_utils_uri_basename (gchar const * uri)
{
return gedit_utils_basename_for_display (uri);
}
gboolean
gedit_file_browser_utils_confirmation_dialog (GeditWindow * window,
GtkMessageType type,
gchar const *message,
gchar const *secondary,
gchar const * button_stock,
gchar const * button_label)
{
GtkWidget *dlg;
gint ret;
GtkWidget *button;
dlg = gtk_message_dialog_new (GTK_WINDOW (window),
GTK_DIALOG_MODAL |
GTK_DIALOG_DESTROY_WITH_PARENT,
type,
GTK_BUTTONS_NONE, "%s", message);
if (secondary)
gtk_message_dialog_format_secondary_text
(GTK_MESSAGE_DIALOG (dlg), "%s", secondary);
/* Add a cancel button */
button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
gtk_widget_show (button);
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_dialog_add_action_widget (GTK_DIALOG (dlg),
button,
GTK_RESPONSE_CANCEL);
/* Add custom button */
button = gtk_button_new_from_stock (button_stock);
if (button_label) {
gtk_button_set_use_stock (GTK_BUTTON (button), FALSE);
gtk_button_set_label (GTK_BUTTON (button), button_label);
}
gtk_widget_show (button);
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_dialog_add_action_widget (GTK_DIALOG (dlg),
button,
GTK_RESPONSE_OK);
ret = gtk_dialog_run (GTK_DIALOG (dlg));
gtk_widget_destroy (dlg);
return (ret == GTK_RESPONSE_OK);
}
// ex:ts=8:noet:

View File

@@ -0,0 +1,27 @@
#ifndef __GEDIT_FILE_BROWSER_UTILS_H__
#define __GEDIT_FILE_BROWSER_UTILS_H__
#include <gedit/gedit-window.h>
#include <gio/gio.h>
GdkPixbuf *gedit_file_browser_utils_pixbuf_from_theme (gchar const *name,
GtkIconSize size);
GdkPixbuf *gedit_file_browser_utils_pixbuf_from_icon (GIcon * icon,
GtkIconSize size);
GdkPixbuf *gedit_file_browser_utils_pixbuf_from_file (GFile * file,
GtkIconSize size);
gchar * gedit_file_browser_utils_file_basename (GFile * file);
gchar * gedit_file_browser_utils_uri_basename (gchar const * uri);
gboolean gedit_file_browser_utils_confirmation_dialog (GeditWindow * window,
GtkMessageType type,
gchar const *message,
gchar const *secondary,
gchar const * button_stock,
gchar const * button_label);
#endif /* __GEDIT_FILE_BROWSER_UTILS_H__ */
// ex:ts=8:noet:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
/*
* gedit-file-browser-view.h - Gedit plugin providing easy file access
* from the sidepanel
*
* Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GEDIT_FILE_BROWSER_VIEW_H__
#define __GEDIT_FILE_BROWSER_VIEW_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define GEDIT_TYPE_FILE_BROWSER_VIEW (gedit_file_browser_view_get_type ())
#define GEDIT_FILE_BROWSER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_BROWSER_VIEW, GeditFileBrowserView))
#define GEDIT_FILE_BROWSER_VIEW_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_BROWSER_VIEW, GeditFileBrowserView const))
#define GEDIT_FILE_BROWSER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_FILE_BROWSER_VIEW, GeditFileBrowserViewClass))
#define GEDIT_IS_FILE_BROWSER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_FILE_BROWSER_VIEW))
#define GEDIT_IS_FILE_BROWSER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_FILE_BROWSER_VIEW))
#define GEDIT_FILE_BROWSER_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_FILE_BROWSER_VIEW, GeditFileBrowserViewClass))
typedef struct _GeditFileBrowserView GeditFileBrowserView;
typedef struct _GeditFileBrowserViewClass GeditFileBrowserViewClass;
typedef struct _GeditFileBrowserViewPrivate GeditFileBrowserViewPrivate;
typedef enum {
GEDIT_FILE_BROWSER_VIEW_CLICK_POLICY_DOUBLE,
GEDIT_FILE_BROWSER_VIEW_CLICK_POLICY_SINGLE
} GeditFileBrowserViewClickPolicy;
struct _GeditFileBrowserView
{
GtkTreeView parent;
GeditFileBrowserViewPrivate *priv;
};
struct _GeditFileBrowserViewClass
{
GtkTreeViewClass parent_class;
/* Signals */
void (*error) (GeditFileBrowserView * filetree,
guint code,
gchar const *message);
void (*file_activated) (GeditFileBrowserView * filetree,
GtkTreeIter *iter);
void (*directory_activated) (GeditFileBrowserView * filetree,
GtkTreeIter *iter);
void (*bookmark_activated) (GeditFileBrowserView * filetree,
GtkTreeIter *iter);
};
GType gedit_file_browser_view_get_type (void) G_GNUC_CONST;
GType gedit_file_browser_view_register_type (GTypeModule * module);
GtkWidget *gedit_file_browser_view_new (void);
void gedit_file_browser_view_set_model (GeditFileBrowserView * tree_view,
GtkTreeModel * model);
void gedit_file_browser_view_start_rename (GeditFileBrowserView * tree_view,
GtkTreeIter * iter);
void gedit_file_browser_view_set_click_policy (GeditFileBrowserView * tree_view,
GeditFileBrowserViewClickPolicy policy);
void gedit_file_browser_view_set_restore_expand_state (GeditFileBrowserView * tree_view,
gboolean restore_expand_state);
G_END_DECLS
#endif /* __GEDIT_FILE_BROWSER_VIEW_H__ */
// ex:ts=8:noet:

View File

@@ -0,0 +1,54 @@
<ui>
<toolbar name="ToolBar">
<placeholder name="Tool_Opt1"/>
<toolitem action="DirectoryUp"/>
<separator/>
<toolitem action="DirectoryRefresh"/>
<separator/>
<placeholder name="Tool_Opt2"/>
<separator/>
<toolitem action="FilterHidden"/>
<separator/>
<placeholder name="Tool_Opt3"/>
</toolbar>
<popup name="FilePopup" action="FilePopupAction">
<menuitem action="FileOpen" />
<placeholder name="FilePopup_Opt1" />
<separator/>
<menuitem action="DirectoryNew" />
<menuitem action="FileNew" />
<separator/>
<placeholder name="FilePopup_Opt2" />
<separator/>
<menuitem action="FileRename"/>
<menuitem action="FileMoveToTrash"/>
<menuitem action="FileDelete"/>
<separator/>
<placeholder name="FilePopup_Opt3" />
<separator/>
<menuitem action="DirectoryRefresh"/>
<menuitem action="DirectoryOpen"/>
<placeholder name="FilePopup_Opt4" />
<separator/>
<placeholder name="FilePopup_Opt5" />
<separator/>
<menu name="FilterMenu" action="FilterMenuAction">
<menuitem action="FilterHidden"/>
<menuitem action="FilterBinary"/>
</menu>
<placeholder name="FilePopup_Opt6" />
<separator/>
</popup>
<popup name="BookmarkPopup" action="BookmarkPopupAction">
<placeholder name="BookmarkPopup_Opt1" />
<separator/>
<placeholder name="BookmarkPopup_Opt2" />
<separator/>
<menuitem action="BookmarkOpen"/>
<placeholder name="BookmarkPopup_Opt3" />
<separator/>
<placeholder name="BookmarkPopup_Opt4" />
</popup>
</ui>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,121 @@
/*
* gedit-file-browser-widget.h - Gedit plugin providing easy file access
* from the sidepanel
*
* Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GEDIT_FILE_BROWSER_WIDGET_H__
#define __GEDIT_FILE_BROWSER_WIDGET_H__
#include <gtk/gtk.h>
#include "gedit-file-browser-store.h"
#include "gedit-file-bookmarks-store.h"
#include "gedit-file-browser-view.h"
G_BEGIN_DECLS
#define GEDIT_TYPE_FILE_BROWSER_WIDGET (gedit_file_browser_widget_get_type ())
#define GEDIT_FILE_BROWSER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_BROWSER_WIDGET, GeditFileBrowserWidget))
#define GEDIT_FILE_BROWSER_WIDGET_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_BROWSER_WIDGET, GeditFileBrowserWidget const))
#define GEDIT_FILE_BROWSER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_FILE_BROWSER_WIDGET, GeditFileBrowserWidgetClass))
#define GEDIT_IS_FILE_BROWSER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_FILE_BROWSER_WIDGET))
#define GEDIT_IS_FILE_BROWSER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_FILE_BROWSER_WIDGET))
#define GEDIT_FILE_BROWSER_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_FILE_BROWSER_WIDGET, GeditFileBrowserWidgetClass))
typedef struct _GeditFileBrowserWidget GeditFileBrowserWidget;
typedef struct _GeditFileBrowserWidgetClass GeditFileBrowserWidgetClass;
typedef struct _GeditFileBrowserWidgetPrivate GeditFileBrowserWidgetPrivate;
typedef
gboolean (*GeditFileBrowserWidgetFilterFunc) (GeditFileBrowserWidget * obj,
GeditFileBrowserStore *
model, GtkTreeIter * iter,
gpointer user_data);
struct _GeditFileBrowserWidget
{
GtkVBox parent;
GeditFileBrowserWidgetPrivate *priv;
};
struct _GeditFileBrowserWidgetClass
{
GtkVBoxClass parent_class;
/* Signals */
void (*uri_activated) (GeditFileBrowserWidget * widget,
gchar const *uri);
void (*error) (GeditFileBrowserWidget * widget,
guint code,
gchar const *message);
gboolean (*confirm_delete) (GeditFileBrowserWidget * widget,
GeditFileBrowserStore * model,
GList *list);
gboolean (*confirm_no_trash) (GeditFileBrowserWidget * widget,
GList *list);
};
GType gedit_file_browser_widget_get_type (void) G_GNUC_CONST;
GType gedit_file_browser_widget_register_type (GTypeModule * module);
GtkWidget *gedit_file_browser_widget_new (const gchar *data_dir);
void gedit_file_browser_widget_show_bookmarks (GeditFileBrowserWidget * obj);
void gedit_file_browser_widget_show_files (GeditFileBrowserWidget * obj);
void gedit_file_browser_widget_set_root (GeditFileBrowserWidget * obj,
gchar const *root,
gboolean virtual_root);
void
gedit_file_browser_widget_set_root_and_virtual_root (GeditFileBrowserWidget * obj,
gchar const *root,
gchar const *virtual_root);
gboolean
gedit_file_browser_widget_get_selected_directory (GeditFileBrowserWidget * obj,
GtkTreeIter * iter);
GeditFileBrowserStore *
gedit_file_browser_widget_get_browser_store (GeditFileBrowserWidget * obj);
GeditFileBookmarksStore *
gedit_file_browser_widget_get_bookmarks_store (GeditFileBrowserWidget * obj);
GeditFileBrowserView *
gedit_file_browser_widget_get_browser_view (GeditFileBrowserWidget * obj);
GtkWidget *
gedit_file_browser_widget_get_filter_entry (GeditFileBrowserWidget * obj);
GtkUIManager *
gedit_file_browser_widget_get_ui_manager (GeditFileBrowserWidget * obj);
gulong gedit_file_browser_widget_add_filter (GeditFileBrowserWidget * obj,
GeditFileBrowserWidgetFilterFunc func,
gpointer user_data,
GDestroyNotify notify);
void gedit_file_browser_widget_remove_filter (GeditFileBrowserWidget * obj,
gulong id);
void gedit_file_browser_widget_set_filter_pattern (GeditFileBrowserWidget * obj,
gchar const *pattern);
void gedit_file_browser_widget_refresh (GeditFileBrowserWidget * obj);
void gedit_file_browser_widget_history_back (GeditFileBrowserWidget * obj);
void gedit_file_browser_widget_history_forward (GeditFileBrowserWidget * obj);
G_END_DECLS
#endif /* __GEDIT_FILE_BROWSER_WIDGET_H__ */
// ex:ts=8:noet:

View File

@@ -0,0 +1,97 @@
<mateconfschemafile>
<schemalist>
<schema>
<key>/schemas/apps/gedit-2/plugins/filebrowser/on_load/tree_view</key>
<applyto>/apps/gedit-2/plugins/filebrowser/on_load/tree_view</applyto>
<owner>gedit</owner>
<type>bool</type>
<default>TRUE</default>
<locale name="C">
<short>Open With Tree View</short>
<long>Open the tree view when the file browser plugin gets loaded instead of the bookmarks view</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gedit-2/plugins/filebrowser/on_load/root</key>
<applyto>/apps/gedit-2/plugins/filebrowser/on_load/root</applyto>
<owner>gedit</owner>
<type>string</type>
<default></default>
<locale name="C">
<short>File Browser Root Directory</short>
<long>The file browser root directory to use when loading the file
browser plugin and onload/tree_view is TRUE.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gedit-2/plugins/filebrowser/on_load/virtual_root</key>
<applyto>/apps/gedit-2/plugins/filebrowser/on_load/virtual_root</applyto>
<owner>gedit</owner>
<type>string</type>
<default></default>
<locale name="C">
<short>File Browser Virtual Root Directory</short>
<long>The file browser virtual root directory to use when loading the
file browser plugin when onload/tree_view is TRUE. The virtual root
must always be below the actual root.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gedit-2/plugins/filebrowser/on_load/enable_remote</key>
<applyto>/apps/gedit-2/plugins/filebrowser/on_load/enable_remote</applyto>
<owner>gedit</owner>
<type>bool</type>
<default>FALSE</default>
<locale name="C">
<short>Enable Restore of Remote Locations</short>
<long>Sets whether to enable restoring of remote locations.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gedit-2/plugins/filebrowser/open_at_first_doc</key>
<applyto>/apps/gedit-2/plugins/filebrowser/open_at_first_doc</applyto>
<owner>gedit</owner>
<type>bool</type>
<default>TRUE</default>
<locale name="C">
<short>Set Location to First Document</short>
<long>If TRUE the file browser plugin will view the directory of
the first opened document given that the file browser hasn't been
used yet. (Thus this generally applies to opening a document from
the command line or opening it with Caja, etc.)</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gedit-2/plugins/filebrowser/filter_mode</key>
<applyto>/apps/gedit-2/plugins/filebrowser/filter_mode</applyto>
<owner>gedit</owner>
<type>string</type>
<default>hidden_and_binary</default>
<locale name="C">
<short>File Browser Filter Mode</short>
<long>This value determines what files get filtered from the file
browser. Valid values are: none (filter nothing),
hidden (filter hidden files), binary (filter binary files) and
hidden_and_binary (filter both hidden and binary files).</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gedit-2/plugins/filebrowser/filter_pattern</key>
<applyto>/apps/gedit-2/plugins/filebrowser/filter_pattern</applyto>
<owner>gedit</owner>
<type>string</type>
<default></default>
<locale name="C">
<short>File Browser Filter Pattern</short>
<long>The filter pattern to filter the file browser with. This filter
works on top of the filter_mode.</long>
</locale>
</schema>
</schemalist>
</mateconfschemafile>

38
plugins/modelines/Makefile.am Executable file
View File

@@ -0,0 +1,38 @@
# Modelines Plugin
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)
INCLUDES = \
-I$(top_srcdir) \
$(GEDIT_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS)
modelinesdir = $(GEDIT_PLUGINS_DATA_DIR)/modelines
modelines_DATA = \
language-mappings
plugin_LTLIBRARIES = libmodelines.la
libmodelines_la_SOURCES = \
gedit-modeline-plugin.h \
gedit-modeline-plugin.c \
modeline-parser.h \
modeline-parser.c
libmodelines_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libmodelines_la_LIBADD = $(GEDIT_LIBS)
plugin_in_files = modelines.gedit-plugin.desktop.in
%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin)
EXTRA_DIST = \
$(plugin_in_files) \
$(modelines_DATA)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = $(plugin_DATA)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,248 @@
/*
* gedit-modeline-plugin.c
* Emacs, Kate and Vim-style modelines support for gedit.
*
* Copyright (C) 2005-2007 - Steve Frécinaux <code@istique.net>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <glib/gi18n-lib.h>
#include <gmodule.h>
#include "gedit-modeline-plugin.h"
#include "modeline-parser.h"
#include <gedit/gedit-debug.h>
#include <gedit/gedit-utils.h>
#define WINDOW_DATA_KEY "GeditModelinePluginWindowData"
#define DOCUMENT_DATA_KEY "GeditModelinePluginDocumentData"
typedef struct
{
gulong tab_added_handler_id;
gulong tab_removed_handler_id;
} WindowData;
typedef struct
{
gulong document_loaded_handler_id;
gulong document_saved_handler_id;
} DocumentData;
static void gedit_modeline_plugin_activate (GeditPlugin *plugin, GeditWindow *window);
static void gedit_modeline_plugin_deactivate (GeditPlugin *plugin, GeditWindow *window);
static GObject *gedit_modeline_plugin_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_param);
static void gedit_modeline_plugin_finalize (GObject *object);
GEDIT_PLUGIN_REGISTER_TYPE(GeditModelinePlugin, gedit_modeline_plugin)
static void
window_data_free (WindowData *wdata)
{
g_slice_free (WindowData, wdata);
}
static void
document_data_free (DocumentData *ddata)
{
g_slice_free (DocumentData, ddata);
}
static void
gedit_modeline_plugin_class_init (GeditModelinePluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass);
object_class->constructor = gedit_modeline_plugin_constructor;
object_class->finalize = gedit_modeline_plugin_finalize;
plugin_class->activate = gedit_modeline_plugin_activate;
plugin_class->deactivate = gedit_modeline_plugin_deactivate;
}
static GObject *
gedit_modeline_plugin_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_param)
{
GObject *object;
gchar *data_dir;
object = G_OBJECT_CLASS (gedit_modeline_plugin_parent_class)->constructor (type,
n_construct_properties,
construct_param);
data_dir = gedit_plugin_get_data_dir (GEDIT_PLUGIN (object));
modeline_parser_init (data_dir);
g_free (data_dir);
return object;
}
static void
gedit_modeline_plugin_init (GeditModelinePlugin *plugin)
{
gedit_debug_message (DEBUG_PLUGINS, "GeditModelinePlugin initializing");
}
static void
gedit_modeline_plugin_finalize (GObject *object)
{
gedit_debug_message (DEBUG_PLUGINS, "GeditModelinePlugin finalizing");
modeline_parser_shutdown ();
G_OBJECT_CLASS (gedit_modeline_plugin_parent_class)->finalize (object);
}
static void
on_document_loaded_or_saved (GeditDocument *document,
const GError *error,
GtkSourceView *view)
{
modeline_parser_apply_modeline (view);
}
static void
connect_handlers (GeditView *view)
{
DocumentData *data;
GtkTextBuffer *doc;
doc = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
data = g_slice_new (DocumentData);
data->document_loaded_handler_id =
g_signal_connect (doc, "loaded",
G_CALLBACK (on_document_loaded_or_saved),
view);
data->document_saved_handler_id =
g_signal_connect (doc, "saved",
G_CALLBACK (on_document_loaded_or_saved),
view);
g_object_set_data_full (G_OBJECT (doc), DOCUMENT_DATA_KEY,
data, (GDestroyNotify) document_data_free);
}
static void
disconnect_handlers (GeditView *view)
{
DocumentData *data;
GtkTextBuffer *doc;
doc = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
data = g_object_steal_data (G_OBJECT (doc), DOCUMENT_DATA_KEY);
if (data)
{
g_signal_handler_disconnect (doc, data->document_loaded_handler_id);
g_signal_handler_disconnect (doc, data->document_saved_handler_id);
document_data_free (data);
}
else
{
g_warning ("Modeline handlers not found");
}
}
static void
on_window_tab_added (GeditWindow *window,
GeditTab *tab,
gpointer user_data)
{
connect_handlers (gedit_tab_get_view (tab));
}
static void
on_window_tab_removed (GeditWindow *window,
GeditTab *tab,
gpointer user_data)
{
disconnect_handlers (gedit_tab_get_view (tab));
}
static void
gedit_modeline_plugin_activate (GeditPlugin *plugin,
GeditWindow *window)
{
WindowData *wdata;
GList *views;
GList *l;
gedit_debug (DEBUG_PLUGINS);
views = gedit_window_get_views (window);
for (l = views; l != NULL; l = l->next)
{
connect_handlers (GEDIT_VIEW (l->data));
modeline_parser_apply_modeline (GTK_SOURCE_VIEW (l->data));
}
g_list_free (views);
wdata = g_slice_new (WindowData);
wdata->tab_added_handler_id =
g_signal_connect (window, "tab-added",
G_CALLBACK (on_window_tab_added), NULL);
wdata->tab_removed_handler_id =
g_signal_connect (window, "tab-removed",
G_CALLBACK (on_window_tab_removed), NULL);
g_object_set_data_full (G_OBJECT (window), WINDOW_DATA_KEY,
wdata, (GDestroyNotify) window_data_free);
}
static void
gedit_modeline_plugin_deactivate (GeditPlugin *plugin,
GeditWindow *window)
{
WindowData *wdata;
GList *views;
GList *l;
gedit_debug (DEBUG_PLUGINS);
wdata = g_object_steal_data (G_OBJECT (window), WINDOW_DATA_KEY);
g_signal_handler_disconnect (window, wdata->tab_added_handler_id);
g_signal_handler_disconnect (window, wdata->tab_removed_handler_id);
window_data_free (wdata);
views = gedit_window_get_views (window);
for (l = views; l != NULL; l = l->next)
{
disconnect_handlers (GEDIT_VIEW (l->data));
modeline_parser_deactivate (GTK_SOURCE_VIEW (l->data));
}
g_list_free (views);
}

View File

@@ -0,0 +1,48 @@
/*
* gedit-modeline-plugin.h
* Emacs, Kate and Vim-style modelines support for gedit.
*
* Copyright (C) 2005-2007 - Steve Frécinaux <code@istique.net>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GEDIT_MODELINE_PLUGIN_H__
#define __GEDIT_MODELINE_PLUGIN_H__
#include <glib.h>
#include <glib-object.h>
#include <gedit/gedit-plugin.h>
G_BEGIN_DECLS
#define GEDIT_TYPE_MODELINE_PLUGIN (gedit_modeline_plugin_get_type ())
#define GEDIT_MODELINE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_MODELINE_PLUGIN, GeditModelinePlugin))
#define GEDIT_MODELINE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_MODELINE_PLUGIN, GeditModelinePluginClass))
#define GEDIT_IS_MODELINE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_MODELINE_PLUGIN))
#define GEDIT_IS_MODELINE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_MODELINE_PLUGIN))
#define GEDIT_MODELINE_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_MODELINE_PLUGIN, GeditModelinePluginClass))
/* Private structure type */
typedef GeditPluginClass GeditModelinePluginClass;
typedef GeditPlugin GeditModelinePlugin;
GType gedit_modeline_plugin_get_type (void) G_GNUC_CONST;
G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module);
G_END_DECLS
#endif /* __GEDIT_MODELINE_PLUGIN_H__ */

View File

@@ -0,0 +1,14 @@
[vim]
cs=c-sharp
docbk=docbook
javascript=js
lhaskell=haskell-literate
spec=rpmspec
tex=latex
xhtml=html
[emacs]
c++=cpp
[kate]

View File

@@ -0,0 +1,852 @@
/*
* modeline-parser.c
* Emacs, Kate and Vim-style modelines support for gedit.
*
* Copyright (C) 2005-2007 - Steve Frécinaux <code@istique.net>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <gedit/gedit-language-manager.h>
#include <gedit/gedit-prefs-manager.h>
#include <gedit/gedit-debug.h>
#include "modeline-parser.h"
#define MODELINES_LANGUAGE_MAPPINGS_FILE "language-mappings"
/* base dir to lookup configuration files */
static gchar *modelines_data_dir;
/* Mappings: language name -> Gedit language ID */
static GHashTable *vim_languages;
static GHashTable *emacs_languages;
static GHashTable *kate_languages;
typedef enum
{
MODELINE_SET_NONE = 0,
MODELINE_SET_TAB_WIDTH = 1 << 0,
MODELINE_SET_INDENT_WIDTH = 1 << 1,
MODELINE_SET_WRAP_MODE = 1 << 2,
MODELINE_SET_SHOW_RIGHT_MARGIN = 1 << 3,
MODELINE_SET_RIGHT_MARGIN_POSITION = 1 << 4,
MODELINE_SET_LANGUAGE = 1 << 5,
MODELINE_SET_INSERT_SPACES = 1 << 6
} ModelineSet;
typedef struct _ModelineOptions
{
gchar *language_id;
/* these options are similar to the GtkSourceView properties of the
* same names.
*/
gboolean insert_spaces;
guint tab_width;
guint indent_width;
GtkWrapMode wrap_mode;
gboolean display_right_margin;
guint right_margin_position;
ModelineSet set;
} ModelineOptions;
#define MODELINE_OPTIONS_DATA_KEY "ModelineOptionsDataKey"
static gboolean
has_option (ModelineOptions *options,
ModelineSet set)
{
return options->set & set;
}
void
modeline_parser_init (const gchar *data_dir)
{
modelines_data_dir = g_strdup (data_dir);
}
void
modeline_parser_shutdown ()
{
if (vim_languages != NULL)
g_hash_table_destroy (vim_languages);
if (emacs_languages != NULL)
g_hash_table_destroy (emacs_languages);
if (kate_languages != NULL)
g_hash_table_destroy (kate_languages);
vim_languages = NULL;
emacs_languages = NULL;
kate_languages = NULL;
g_free (modelines_data_dir);
}
static GHashTable *
load_language_mappings_group (GKeyFile *key_file, const gchar *group)
{
GHashTable *table;
gchar **keys;
gsize length = 0;
int i;
table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
keys = g_key_file_get_keys (key_file, group, &length, NULL);
gedit_debug_message (DEBUG_PLUGINS,
"%" G_GSIZE_FORMAT " mappings in group %s",
length, group);
for (i = 0; i < length; i++)
{
gchar *name = keys[i];
gchar *id = g_key_file_get_string (key_file, group, name, NULL);
g_hash_table_insert (table, name, id);
}
g_free (keys);
return table;
}
/* lazy loading of language mappings */
static void
load_language_mappings (void)
{
gchar *fname;
GKeyFile *mappings;
GError *error = NULL;
fname = g_build_filename (modelines_data_dir,
MODELINES_LANGUAGE_MAPPINGS_FILE,
NULL);
mappings = g_key_file_new ();
if (g_key_file_load_from_file (mappings, fname, 0, &error))
{
gedit_debug_message (DEBUG_PLUGINS,
"Loaded language mappings from %s",
fname);
vim_languages = load_language_mappings_group (mappings, "vim");
emacs_languages = load_language_mappings_group (mappings, "emacs");
kate_languages = load_language_mappings_group (mappings, "kate");
}
else
{
gedit_debug_message (DEBUG_PLUGINS,
"Failed to loaded language mappings from %s: %s",
fname, error->message);
g_error_free (error);
}
g_key_file_free (mappings);
g_free (fname);
}
static gchar *
get_language_id (const gchar *language_name, GHashTable *mapping)
{
gchar *name;
gchar *language_id;
name = g_ascii_strdown (language_name, -1);
language_id = g_hash_table_lookup (mapping, name);
if (language_id != NULL)
{
g_free (name);
return g_strdup (language_id);
}
else
{
/* by default assume that the gtksourcevuew id is the same */
return name;
}
}
static gchar *
get_language_id_vim (const gchar *language_name)
{
if (vim_languages == NULL)
load_language_mappings ();
return get_language_id (language_name, vim_languages);
}
static gchar *
get_language_id_emacs (const gchar *language_name)
{
if (emacs_languages == NULL)
load_language_mappings ();
return get_language_id (language_name, emacs_languages);
}
static gchar *
get_language_id_kate (const gchar *language_name)
{
if (kate_languages == NULL)
load_language_mappings ();
return get_language_id (language_name, kate_languages);
}
static gboolean
skip_whitespaces (gchar **s)
{
while (**s != '\0' && g_ascii_isspace (**s))
(*s)++;
return **s != '\0';
}
/* Parse vi(m) modelines.
* Vi(m) modelines looks like this:
* - first form: [text]{white}{vi:|vim:|ex:}[white]{options}
* - second form: [text]{white}{vi:|vim:|ex:}[white]se[t] {options}:[text]
* They can happen on the three first or last lines.
*/
static gchar *
parse_vim_modeline (gchar *s,
ModelineOptions *options)
{
gboolean in_set = FALSE;
gboolean neg;
guint intval;
GString *key, *value;
key = g_string_sized_new (8);
value = g_string_sized_new (8);
while (*s != '\0' && !(in_set && *s == ':'))
{
while (*s != '\0' && (*s == ':' || g_ascii_isspace (*s)))
s++;
if (*s == '\0')
break;
if (strncmp (s, "set ", 4) == 0 ||
strncmp (s, "se ", 3) == 0)
{
s = strchr(s, ' ') + 1;
in_set = TRUE;
}
neg = FALSE;
if (strncmp (s, "no", 2) == 0)
{
neg = TRUE;
s += 2;
}
g_string_assign (key, "");
g_string_assign (value, "");
while (*s != '\0' && *s != ':' && *s != '=' &&
!g_ascii_isspace (*s))
{
g_string_append_c (key, *s);
s++;
}
if (*s == '=')
{
s++;
while (*s != '\0' && *s != ':' &&
!g_ascii_isspace (*s))
{
g_string_append_c (value, *s);
s++;
}
}
if (strcmp (key->str, "ft") == 0 ||
strcmp (key->str, "filetype") == 0)
{
g_free (options->language_id);
options->language_id = get_language_id_vim (value->str);
options->set |= MODELINE_SET_LANGUAGE;
}
else if (strcmp (key->str, "et") == 0 ||
strcmp (key->str, "expandtab") == 0)
{
options->insert_spaces = !neg;
options->set |= MODELINE_SET_INSERT_SPACES;
}
else if (strcmp (key->str, "ts") == 0 ||
strcmp (key->str, "tabstop") == 0)
{
intval = atoi (value->str);
if (intval)
{
options->tab_width = intval;
options->set |= MODELINE_SET_TAB_WIDTH;
}
}
else if (strcmp (key->str, "sw") == 0 ||
strcmp (key->str, "shiftwidth") == 0)
{
intval = atoi (value->str);
if (intval)
{
options->indent_width = intval;
options->set |= MODELINE_SET_INDENT_WIDTH;
}
}
else if (strcmp (key->str, "wrap") == 0)
{
options->wrap_mode = neg ? GTK_WRAP_NONE : GTK_WRAP_WORD;
options->set |= MODELINE_SET_WRAP_MODE;
}
else if (strcmp (key->str, "textwidth") == 0)
{
intval = atoi (value->str);
if (intval)
{
options->right_margin_position = intval;
options->display_right_margin = TRUE;
options->set |= MODELINE_SET_SHOW_RIGHT_MARGIN |
MODELINE_SET_RIGHT_MARGIN_POSITION;
}
}
}
g_string_free (key, TRUE);
g_string_free (value, TRUE);
return s;
}
/* Parse emacs modelines.
* Emacs modelines looks like this: "-*- key1: value1; key2: value2 -*-"
* They can happen on the first line, or on the second one if the first line is
* a shebang (#!)
* See http://www.delorie.com/gnu/docs/emacs/emacs_486.html
*/
static gchar *
parse_emacs_modeline (gchar *s,
ModelineOptions *options)
{
guint intval;
GString *key, *value;
key = g_string_sized_new (8);
value = g_string_sized_new (8);
while (*s != '\0')
{
while (*s != '\0' && (*s == ';' || g_ascii_isspace (*s)))
s++;
if (*s == '\0' || strncmp (s, "-*-", 3) == 0)
break;
g_string_assign (key, "");
g_string_assign (value, "");
while (*s != '\0' && *s != ':' && *s != ';' &&
!g_ascii_isspace (*s))
{
g_string_append_c (key, *s);
s++;
}
if (!skip_whitespaces (&s))
break;
if (*s != ':')
continue;
s++;
if (!skip_whitespaces (&s))
break;
while (*s != '\0' && *s != ';' && !g_ascii_isspace (*s))
{
g_string_append_c (value, *s);
s++;
}
gedit_debug_message (DEBUG_PLUGINS,
"Emacs modeline bit: %s = %s",
key->str, value->str);
/* "Mode" key is case insenstive */
if (g_ascii_strcasecmp (key->str, "Mode") == 0)
{
g_free (options->language_id);
options->language_id = get_language_id_emacs (value->str);
options->set |= MODELINE_SET_LANGUAGE;
}
else if (strcmp (key->str, "tab-width") == 0)
{
intval = atoi (value->str);
if (intval)
{
options->tab_width = intval;
options->set |= MODELINE_SET_TAB_WIDTH;
}
}
else if (strcmp (key->str, "indent-offset") == 0)
{
intval = atoi (value->str);
if (intval)
{
options->indent_width = intval;
options->set |= MODELINE_SET_INDENT_WIDTH;
}
}
else if (strcmp (key->str, "indent-tabs-mode") == 0)
{
intval = strcmp (value->str, "nil") == 0;
options->insert_spaces = intval;
options->set |= MODELINE_SET_INSERT_SPACES;
}
else if (strcmp (key->str, "autowrap") == 0)
{
intval = strcmp (value->str, "nil") != 0;
options->wrap_mode = intval ? GTK_WRAP_WORD : GTK_WRAP_NONE;
options->set |= MODELINE_SET_WRAP_MODE;
}
}
g_string_free (key, TRUE);
g_string_free (value, TRUE);
return *s == '\0' ? s : s + 2;
}
/*
* Parse kate modelines.
* Kate modelines are of the form "kate: key1 value1; key2 value2;"
* These can happen on the 10 first or 10 last lines of the buffer.
* See http://wiki.kate-editor.org/index.php/Modelines
*/
static gchar *
parse_kate_modeline (gchar *s,
ModelineOptions *options)
{
guint intval;
GString *key, *value;
key = g_string_sized_new (8);
value = g_string_sized_new (8);
while (*s != '\0')
{
while (*s != '\0' && (*s == ';' || g_ascii_isspace (*s)))
s++;
if (*s == '\0')
break;
g_string_assign (key, "");
g_string_assign (value, "");
while (*s != '\0' && *s != ';' && !g_ascii_isspace (*s))
{
g_string_append_c (key, *s);
s++;
}
if (!skip_whitespaces (&s))
break;
if (*s == ';')
continue;
while (*s != '\0' && *s != ';' &&
!g_ascii_isspace (*s))
{
g_string_append_c (value, *s);
s++;
}
gedit_debug_message (DEBUG_PLUGINS,
"Kate modeline bit: %s = %s",
key->str, value->str);
if (strcmp (key->str, "hl") == 0 ||
strcmp (key->str, "syntax") == 0)
{
g_free (options->language_id);
options->language_id = get_language_id_kate (value->str);
options->set |= MODELINE_SET_LANGUAGE;
}
else if (strcmp (key->str, "tab-width") == 0)
{
intval = atoi (value->str);
if (intval)
{
options->tab_width = intval;
options->set |= MODELINE_SET_TAB_WIDTH;
}
}
else if (strcmp (key->str, "indent-width") == 0)
{
intval = atoi (value->str);
if (intval) options->indent_width = intval;
}
else if (strcmp (key->str, "space-indent") == 0)
{
intval = strcmp (value->str, "on") == 0 ||
strcmp (value->str, "true") == 0 ||
strcmp (value->str, "1") == 0;
options->insert_spaces = intval;
options->set |= MODELINE_SET_INSERT_SPACES;
}
else if (strcmp (key->str, "word-wrap") == 0)
{
intval = strcmp (value->str, "on") == 0 ||
strcmp (value->str, "true") == 0 ||
strcmp (value->str, "1") == 0;
options->wrap_mode = intval ? GTK_WRAP_WORD : GTK_WRAP_NONE;
options->set |= MODELINE_SET_WRAP_MODE;
}
else if (strcmp (key->str, "word-wrap-column") == 0)
{
intval = atoi (value->str);
if (intval)
{
options->right_margin_position = intval;
options->display_right_margin = TRUE;
options->set |= MODELINE_SET_RIGHT_MARGIN_POSITION |
MODELINE_SET_SHOW_RIGHT_MARGIN;
}
}
}
g_string_free (key, TRUE);
g_string_free (value, TRUE);
return s;
}
/* Scan a line for vi(m)/emacs/kate modelines.
* Line numbers are counted starting at one.
*/
static void
parse_modeline (gchar *s,
gint line_number,
gint line_count,
ModelineOptions *options)
{
gchar prev;
/* look for the beginning of a modeline */
for (prev = ' '; (s != NULL) && (*s != '\0'); prev = *(s++))
{
if (!g_ascii_isspace (prev))
continue;
if ((line_number <= 3 || line_number > line_count - 3) &&
(strncmp (s, "ex:", 3) == 0 ||
strncmp (s, "vi:", 3) == 0 ||
strncmp (s, "vim:", 4) == 0))
{
gedit_debug_message (DEBUG_PLUGINS, "Vim modeline on line %d", line_number);
while (*s != ':') s++;
s = parse_vim_modeline (s + 1, options);
}
else if (line_number <= 2 && strncmp (s, "-*-", 3) == 0)
{
gedit_debug_message (DEBUG_PLUGINS, "Emacs modeline on line %d", line_number);
s = parse_emacs_modeline (s + 3, options);
}
else if ((line_number <= 10 || line_number > line_count - 10) &&
strncmp (s, "kate:", 5) == 0)
{
gedit_debug_message (DEBUG_PLUGINS, "Kate modeline on line %d", line_number);
s = parse_kate_modeline (s + 5, options);
}
}
}
static gboolean
check_previous (GtkSourceView *view,
ModelineOptions *previous,
ModelineSet set)
{
GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
/* Do not restore default when this is the first time */
if (!previous)
return FALSE;
/* Do not restore default when previous was not set */
if (!(previous->set & set))
return FALSE;
/* Only restore default when setting has not changed */
switch (set)
{
case MODELINE_SET_INSERT_SPACES:
return gtk_source_view_get_insert_spaces_instead_of_tabs (view) ==
previous->insert_spaces;
break;
case MODELINE_SET_TAB_WIDTH:
return gtk_source_view_get_tab_width (view) == previous->tab_width;
break;
case MODELINE_SET_INDENT_WIDTH:
return gtk_source_view_get_indent_width (view) == previous->indent_width;
break;
case MODELINE_SET_WRAP_MODE:
return gtk_text_view_get_wrap_mode (GTK_TEXT_VIEW (view)) ==
previous->wrap_mode;
break;
case MODELINE_SET_RIGHT_MARGIN_POSITION:
return gtk_source_view_get_right_margin_position (view) ==
previous->right_margin_position;
break;
case MODELINE_SET_SHOW_RIGHT_MARGIN:
return gtk_source_view_get_show_right_margin (view) ==
previous->display_right_margin;
break;
case MODELINE_SET_LANGUAGE:
{
GtkSourceLanguage *language = gtk_source_buffer_get_language (buffer);
return (language == NULL && previous->language_id == NULL) ||
(language != NULL && g_strcmp0 (gtk_source_language_get_id (language),
previous->language_id) == 0);
}
break;
default:
return FALSE;
break;
}
}
static void
free_modeline_options (ModelineOptions *options)
{
g_free (options->language_id);
g_slice_free (ModelineOptions, options);
}
void
modeline_parser_apply_modeline (GtkSourceView *view)
{
ModelineOptions options;
GtkTextBuffer *buffer;
GtkTextIter iter, liter;
gint line_count;
options.language_id = NULL;
options.set = MODELINE_SET_NONE;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
gtk_text_buffer_get_start_iter (buffer, &iter);
line_count = gtk_text_buffer_get_line_count (buffer);
/* Parse the modelines on the 10 first lines... */
while ((gtk_text_iter_get_line (&iter) < 10) &&
!gtk_text_iter_is_end (&iter))
{
gchar *line;
liter = iter;
gtk_text_iter_forward_to_line_end (&iter);
line = gtk_text_buffer_get_text (buffer, &liter, &iter, TRUE);
parse_modeline (line,
1 + gtk_text_iter_get_line (&iter),
line_count,
&options);
gtk_text_iter_forward_line (&iter);
g_free (line);
}
/* ...and on the 10 last ones (modelines are not allowed in between) */
if (!gtk_text_iter_is_end (&iter))
{
gint cur_line;
guint remaining_lines;
/* we are on the 11th line (count from 0) */
cur_line = gtk_text_iter_get_line (&iter);
/* g_assert (10 == cur_line); */
remaining_lines = line_count - cur_line - 1;
if (remaining_lines > 10)
{
gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_iter_backward_lines (&iter, 9);
}
}
while (!gtk_text_iter_is_end (&iter))
{
gchar *line;
liter = iter;
gtk_text_iter_forward_to_line_end (&iter);
line = gtk_text_buffer_get_text (buffer, &liter, &iter, TRUE);
parse_modeline (line,
1 + gtk_text_iter_get_line (&iter),
line_count,
&options);
gtk_text_iter_forward_line (&iter);
g_free (line);
}
/* Try to set language */
if (has_option (&options, MODELINE_SET_LANGUAGE) && options.language_id)
{
GtkSourceLanguageManager *manager;
GtkSourceLanguage *language;
manager = gedit_get_language_manager ();
language = gtk_source_language_manager_get_language
(manager, options.language_id);
if (language != NULL)
{
gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (buffer),
language);
}
}
ModelineOptions *previous = g_object_get_data (G_OBJECT (buffer),
MODELINE_OPTIONS_DATA_KEY);
/* Apply the options we got from modelines and restore defaults if
we set them before */
if (has_option (&options, MODELINE_SET_INSERT_SPACES))
{
gtk_source_view_set_insert_spaces_instead_of_tabs
(view, options.insert_spaces);
}
else if (check_previous (view, previous, MODELINE_SET_INSERT_SPACES))
{
gtk_source_view_set_insert_spaces_instead_of_tabs
(view,
gedit_prefs_manager_get_insert_spaces ());
}
if (has_option (&options, MODELINE_SET_TAB_WIDTH))
{
gtk_source_view_set_tab_width (view, options.tab_width);
}
else if (check_previous (view, previous, MODELINE_SET_TAB_WIDTH))
{
gtk_source_view_set_tab_width (view,
gedit_prefs_manager_get_tabs_size ());
}
if (has_option (&options, MODELINE_SET_INDENT_WIDTH))
{
gtk_source_view_set_indent_width (view, options.indent_width);
}
else if (check_previous (view, previous, MODELINE_SET_INDENT_WIDTH))
{
gtk_source_view_set_indent_width (view, -1);
}
if (has_option (&options, MODELINE_SET_WRAP_MODE))
{
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), options.wrap_mode);
}
else if (check_previous (view, previous, MODELINE_SET_WRAP_MODE))
{
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view),
gedit_prefs_manager_get_wrap_mode ());
}
if (has_option (&options, MODELINE_SET_RIGHT_MARGIN_POSITION))
{
gtk_source_view_set_right_margin_position (view, options.right_margin_position);
}
else if (check_previous (view, previous, MODELINE_SET_RIGHT_MARGIN_POSITION))
{
gtk_source_view_set_right_margin_position (view,
gedit_prefs_manager_get_right_margin_position ());
}
if (has_option (&options, MODELINE_SET_SHOW_RIGHT_MARGIN))
{
gtk_source_view_set_show_right_margin (view, options.display_right_margin);
}
else if (check_previous (view, previous, MODELINE_SET_SHOW_RIGHT_MARGIN))
{
gtk_source_view_set_show_right_margin (view,
gedit_prefs_manager_get_display_right_margin ());
}
if (previous)
{
*previous = options;
previous->language_id = g_strdup (options.language_id);
}
else
{
previous = g_slice_new (ModelineOptions);
*previous = options;
previous->language_id = g_strdup (options.language_id);
g_object_set_data_full (G_OBJECT (buffer),
MODELINE_OPTIONS_DATA_KEY,
previous,
(GDestroyNotify)free_modeline_options);
}
g_free (options.language_id);
}
void
modeline_parser_deactivate (GtkSourceView *view)
{
g_object_set_data (G_OBJECT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))),
MODELINE_OPTIONS_DATA_KEY,
NULL);
}
/* vi:ts=8 */

View File

@@ -0,0 +1,37 @@
/*
* modelie-parser.h
* Emacs, Kate and Vim-style modelines support for gedit.
*
* Copyright (C) 2005-2007 - Steve Frécinaux <code@istique.net>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __MODELINE_PARSER_H__
#define __MODELINE_PARSER_H__
#include <glib.h>
#include <gtksourceview/gtksourceview.h>
G_BEGIN_DECLS
void modeline_parser_init (const gchar *data_dir);
void modeline_parser_shutdown (void);
void modeline_parser_apply_modeline (GtkSourceView *view);
void modeline_parser_deactivate (GtkSourceView *view);
G_END_DECLS
#endif /* __MODELINE_PARSER_H__ */

View File

@@ -0,0 +1,8 @@
[Gedit Plugin]
Module=modelines
IAge=2
_Name=Modelines
_Description=Emacs, Kate and Vim-style modelines support for gedit.
Authors=Steve Frécinaux <steve@istique.net>
Copyright=Copyright © 2005 Steve Frécinaux
Website=http://www.gedit.org

View File

@@ -0,0 +1,15 @@
# Python Console Plugin
SUBDIRS = pythonconsole
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)
plugin_in_files = pythonconsole.gedit-plugin.desktop.in
%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin)
EXTRA_DIST = $(plugin_in_files)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = $(plugin_DATA)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,10 @@
[Gedit Plugin]
Loader=python
Module=pythonconsole
IAge=2
_Name=Python Console
_Description=Interactive Python console standing in the bottom panel
Icon=mate-mime-text-x-python
Authors=Steve Frécinaux <steve@istique.net>
Copyright=Copyright © 2006 Steve Frécinaux
Website=http://www.gedit.org

View File

@@ -0,0 +1,17 @@
# Python console plugin
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)/pythonconsole
plugin_PYTHON = \
__init__.py \
console.py \
config.py
uidir = $(GEDIT_PLUGINS_DATA_DIR)/pythonconsole/ui
ui_DATA = config.ui
EXTRA_DIST = $(ui_DATA)
CLEANFILES =
DISTCLEANFILES =
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
# __init__.py -- plugin object
#
# Copyright (C) 2006 - Steve Frécinaux
#
# 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, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Parts from "Interactive Python-GTK Console" (stolen from epiphany's console.py)
# Copyright (C), 1998 James Henstridge <james@daa.com.au>
# Copyright (C), 2005 Adam Hooper <adamh@densi.com>
# Bits from gedit Python Console Plugin
# Copyrignt (C), 2005 Raphaël Slinckx
import gtk
import gedit
from console import PythonConsole
from config import PythonConsoleConfigDialog
from config import PythonConsoleConfig
PYTHON_ICON = 'mate-mime-text-x-python'
class PythonConsolePlugin(gedit.Plugin):
def __init__(self):
gedit.Plugin.__init__(self)
self.dlg = None
def activate(self, window):
console = PythonConsole(namespace = {'__builtins__' : __builtins__,
'gedit' : gedit,
'window' : window})
console.eval('print "You can access the main window through ' \
'\'window\' :\\n%s" % window', False)
bottom = window.get_bottom_panel()
image = gtk.Image()
image.set_from_icon_name(PYTHON_ICON, gtk.ICON_SIZE_MENU)
bottom.add_item(console, _('Python Console'), image)
window.set_data('PythonConsolePluginInfo', console)
def deactivate(self, window):
console = window.get_data("PythonConsolePluginInfo")
console.stop()
window.set_data("PythonConsolePluginInfo", None)
bottom = window.get_bottom_panel()
bottom.remove_item(console)
def create_configure_dialog(self):
if not self.dlg:
self.dlg = PythonConsoleConfigDialog(self.get_data_dir())
dialog = self.dlg.dialog()
window = gedit.app_get_default().get_active_window()
if window:
dialog.set_transient_for(window)
return dialog
# Here we dynamically insert create_configure_dialog based on if configuration
# is enabled. This has to be done like this because gedit checks if a plugin
# is configurable solely on the fact that it has this member defined or not
if PythonConsoleConfig.enabled():
PythonConsolePlugin.create_configure_dialog = create_configure_dialog
# ex:et:ts=4:

View File

@@ -0,0 +1,134 @@
# -*- coding: utf-8 -*-
# config.py -- Config dialog
#
# Copyright (C) 2008 - B. Clausius
#
# 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, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Parts from "Interactive Python-GTK Console" (stolen from epiphany's console.py)
# Copyright (C), 1998 James Henstridge <james@daa.com.au>
# Copyright (C), 2005 Adam Hooper <adamh@densi.com>
# Bits from gedit Python Console Plugin
# Copyrignt (C), 2005 Raphaël Slinckx
import os
import gtk
__all__ = ('PythonConsoleConfig', 'PythonConsoleConfigDialog')
MATECONF_KEY_BASE = '/apps/gedit-2/plugins/pythonconsole'
MATECONF_KEY_COMMAND_COLOR = MATECONF_KEY_BASE + '/command-color'
MATECONF_KEY_ERROR_COLOR = MATECONF_KEY_BASE + '/error-color'
DEFAULT_COMMAND_COLOR = '#314e6c' # Blue Shadow
DEFAULT_ERROR_COLOR = '#990000' # Accent Red Dark
class PythonConsoleConfig(object):
try:
import mateconf
except ImportError:
mateconf = None
def __init__(self):
pass
@staticmethod
def enabled():
return PythonConsoleConfig.mateconf != None
@staticmethod
def add_handler(handler):
if PythonConsoleConfig.mateconf:
PythonConsoleConfig.mateconf.client_get_default().notify_add(MATECONF_KEY_BASE, handler)
color_command = property(
lambda self: self.mateconf_get_str(MATECONF_KEY_COMMAND_COLOR, DEFAULT_COMMAND_COLOR),
lambda self, value: self.mateconf_set_str(MATECONF_KEY_COMMAND_COLOR, value))
color_error = property(
lambda self: self.mateconf_get_str(MATECONF_KEY_ERROR_COLOR, DEFAULT_ERROR_COLOR),
lambda self, value: self.mateconf_set_str(MATECONF_KEY_ERROR_COLOR, value))
@staticmethod
def mateconf_get_str(key, default=''):
if not PythonConsoleConfig.mateconf:
return default
val = PythonConsoleConfig.mateconf.client_get_default().get(key)
if val is not None and val.type == mateconf.VALUE_STRING:
return val.get_string()
else:
return default
@staticmethod
def mateconf_set_str(key, value):
if not PythonConsoleConfig.mateconf:
return
v = PythonConsoleConfig.mateconf.Value(mateconf.VALUE_STRING)
v.set_string(value)
PythonConsoleConfig.mateconf.client_get_default().set(key, v)
class PythonConsoleConfigDialog(object):
def __init__(self, datadir):
object.__init__(self)
self._dialog = None
self._ui_path = os.path.join(datadir, 'ui', 'config.ui')
self.config = PythonConsoleConfig()
def dialog(self):
if self._dialog is None:
self._ui = gtk.Builder()
self._ui.add_from_file(self._ui_path)
self.set_colorbutton_color(self._ui.get_object('colorbutton-command'),
self.config.color_command)
self.set_colorbutton_color(self._ui.get_object('colorbutton-error'),
self.config.color_error)
self._ui.connect_signals(self)
self._dialog = self._ui.get_object('dialog-config')
self._dialog.show_all()
else:
self._dialog.present()
return self._dialog
@staticmethod
def set_colorbutton_color(colorbutton, value):
try:
color = gtk.gdk.color_parse(value)
except ValueError:
pass # Default color in config.ui used
else:
colorbutton.set_color(color)
def on_dialog_config_response(self, dialog, response_id):
self._dialog.destroy()
def on_dialog_config_destroy(self, dialog):
self._dialog = None
self._ui = None
def on_colorbutton_command_color_set(self, colorbutton):
self.config.color_command = colorbutton.get_color().to_string()
def on_colorbutton_error_color_set(self, colorbutton):
self.config.color_error = colorbutton.get_color().to_string()
# ex:et:ts=4:

View File

@@ -0,0 +1,107 @@
<?xml version="1.0"?>
<interface>
<requires lib="gtk+" version="2.14"/>
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkDialog" id="dialog-config">
<property name="window_position">center-on-parent</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">dialog</property>
<property name="has_separator">False</property>
<signal name="destroy" handler="on_dialog_config_destroy"/>
<signal name="response" handler="on_dialog_config_response"/>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<child>
<object class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<property name="column_spacing">6</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkLabel" id="label-command">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">C_ommand color:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">colorbutton-command</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label-error">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Error color:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">colorbutton-error</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkColorButton" id="colorbutton-command">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="color">#31314e4e6c6c</property>
<signal name="color_set" handler="on_colorbutton_command_color_set"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkColorButton" id="colorbutton-error">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="color">#999900000000</property>
<signal name="color_set" handler="on_colorbutton_error_color_set"/>
</object>
<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>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button1">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-7">button1</action-widget>
</action-widgets>
</object>
</interface>

View File

@@ -0,0 +1,370 @@
# -*- coding: utf-8 -*-
# pythonconsole.py -- Console widget
#
# Copyright (C) 2006 - Steve Frécinaux
#
# 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, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Parts from "Interactive Python-GTK Console" (stolen from epiphany's console.py)
# Copyright (C), 1998 James Henstridge <james@daa.com.au>
# Copyright (C), 2005 Adam Hooper <adamh@densi.com>
# Bits from gedit Python Console Plugin
# Copyrignt (C), 2005 Raphaël Slinckx
import string
import sys
import re
import traceback
import gobject
import gtk
import pango
from config import PythonConsoleConfig
__all__ = ('PythonConsole', 'OutFile')
class PythonConsole(gtk.ScrolledWindow):
__gsignals__ = {
'grab-focus' : 'override',
}
def __init__(self, namespace = {}):
gtk.ScrolledWindow.__init__(self)
self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
self.set_shadow_type(gtk.SHADOW_IN)
self.view = gtk.TextView()
self.view.modify_font(pango.FontDescription('Monospace'))
self.view.set_editable(True)
self.view.set_wrap_mode(gtk.WRAP_WORD_CHAR)
self.add(self.view)
self.view.show()
buffer = self.view.get_buffer()
self.normal = buffer.create_tag("normal")
self.error = buffer.create_tag("error")
self.command = buffer.create_tag("command")
PythonConsoleConfig.add_handler(self.apply_preferences)
self.apply_preferences()
self.__spaces_pattern = re.compile(r'^\s+')
self.namespace = namespace
self.block_command = False
# Init first line
buffer.create_mark("input-line", buffer.get_end_iter(), True)
buffer.insert(buffer.get_end_iter(), ">>> ")
buffer.create_mark("input", buffer.get_end_iter(), True)
# Init history
self.history = ['']
self.history_pos = 0
self.current_command = ''
self.namespace['__history__'] = self.history
# Set up hooks for standard output.
self.stdout = OutFile(self, sys.stdout.fileno(), self.normal)
self.stderr = OutFile(self, sys.stderr.fileno(), self.error)
# Signals
self.view.connect("key-press-event", self.__key_press_event_cb)
buffer.connect("mark-set", self.__mark_set_cb)
def do_grab_focus(self):
self.view.grab_focus()
def apply_preferences(self, *args):
config = PythonConsoleConfig()
self.error.set_property("foreground", config.color_error)
self.command.set_property("foreground", config.color_command)
def stop(self):
self.namespace = None
def __key_press_event_cb(self, view, event):
modifier_mask = gtk.accelerator_get_default_mod_mask()
event_state = event.state & modifier_mask
if event.keyval == gtk.keysyms.d and event_state == gtk.gdk.CONTROL_MASK:
self.destroy()
elif event.keyval == gtk.keysyms.Return and event_state == gtk.gdk.CONTROL_MASK:
# Get the command
buffer = view.get_buffer()
inp_mark = buffer.get_mark("input")
inp = buffer.get_iter_at_mark(inp_mark)
cur = buffer.get_end_iter()
line = buffer.get_text(inp, cur)
self.current_command = self.current_command + line + "\n"
self.history_add(line)
# Prepare the new line
cur = buffer.get_end_iter()
buffer.insert(cur, "\n... ")
cur = buffer.get_end_iter()
buffer.move_mark(inp_mark, cur)
# Keep indentation of precendent line
spaces = re.match(self.__spaces_pattern, line)
if spaces is not None:
buffer.insert(cur, line[spaces.start() : spaces.end()])
cur = buffer.get_end_iter()
buffer.place_cursor(cur)
gobject.idle_add(self.scroll_to_end)
return True
elif event.keyval == gtk.keysyms.Return:
# Get the marks
buffer = view.get_buffer()
lin_mark = buffer.get_mark("input-line")
inp_mark = buffer.get_mark("input")
# Get the command line
inp = buffer.get_iter_at_mark(inp_mark)
cur = buffer.get_end_iter()
line = buffer.get_text(inp, cur)
self.current_command = self.current_command + line + "\n"
self.history_add(line)
# Make the line blue
lin = buffer.get_iter_at_mark(lin_mark)
buffer.apply_tag(self.command, lin, cur)
buffer.insert(cur, "\n")
cur_strip = self.current_command.rstrip()
if cur_strip.endswith(":") \
or (self.current_command[-2:] != "\n\n" and self.block_command):
# Unfinished block command
self.block_command = True
com_mark = "... "
elif cur_strip.endswith("\\"):
com_mark = "... "
else:
# Eval the command
self.__run(self.current_command)
self.current_command = ''
self.block_command = False
com_mark = ">>> "
# Prepare the new line
cur = buffer.get_end_iter()
buffer.move_mark(lin_mark, cur)
buffer.insert(cur, com_mark)
cur = buffer.get_end_iter()
buffer.move_mark(inp_mark, cur)
buffer.place_cursor(cur)
gobject.idle_add(self.scroll_to_end)
return True
elif event.keyval == gtk.keysyms.KP_Down or event.keyval == gtk.keysyms.Down:
# Next entry from history
view.emit_stop_by_name("key_press_event")
self.history_down()
gobject.idle_add(self.scroll_to_end)
return True
elif event.keyval == gtk.keysyms.KP_Up or event.keyval == gtk.keysyms.Up:
# Previous entry from history
view.emit_stop_by_name("key_press_event")
self.history_up()
gobject.idle_add(self.scroll_to_end)
return True
elif event.keyval == gtk.keysyms.KP_Left or event.keyval == gtk.keysyms.Left or \
event.keyval == gtk.keysyms.BackSpace:
buffer = view.get_buffer()
inp = buffer.get_iter_at_mark(buffer.get_mark("input"))
cur = buffer.get_iter_at_mark(buffer.get_insert())
if inp.compare(cur) == 0:
if not event_state:
buffer.place_cursor(inp)
return True
return False
# For the console we enable smart/home end behavior incoditionally
# since it is useful when editing python
elif (event.keyval == gtk.keysyms.KP_Home or event.keyval == gtk.keysyms.Home) and \
event_state == event_state & (gtk.gdk.SHIFT_MASK|gtk.gdk.CONTROL_MASK):
# Go to the begin of the command instead of the begin of the line
buffer = view.get_buffer()
iter = buffer.get_iter_at_mark(buffer.get_mark("input"))
ins = buffer.get_iter_at_mark(buffer.get_insert())
while iter.get_char().isspace():
iter.forward_char()
if iter.equal(ins):
iter = buffer.get_iter_at_mark(buffer.get_mark("input"))
if event_state & gtk.gdk.SHIFT_MASK:
buffer.move_mark_by_name("insert", iter)
else:
buffer.place_cursor(iter)
return True
elif (event.keyval == gtk.keysyms.KP_End or event.keyval == gtk.keysyms.End) and \
event_state == event_state & (gtk.gdk.SHIFT_MASK|gtk.gdk.CONTROL_MASK):
buffer = view.get_buffer()
iter = buffer.get_end_iter()
ins = buffer.get_iter_at_mark(buffer.get_insert())
iter.backward_char()
while iter.get_char().isspace():
iter.backward_char()
iter.forward_char()
if iter.equal(ins):
iter = buffer.get_end_iter()
if event_state & gtk.gdk.SHIFT_MASK:
buffer.move_mark_by_name("insert", iter)
else:
buffer.place_cursor(iter)
return True
def __mark_set_cb(self, buffer, iter, name):
input = buffer.get_iter_at_mark(buffer.get_mark("input"))
pos = buffer.get_iter_at_mark(buffer.get_insert())
self.view.set_editable(pos.compare(input) != -1)
def get_command_line(self):
buffer = self.view.get_buffer()
inp = buffer.get_iter_at_mark(buffer.get_mark("input"))
cur = buffer.get_end_iter()
return buffer.get_text(inp, cur)
def set_command_line(self, command):
buffer = self.view.get_buffer()
mark = buffer.get_mark("input")
inp = buffer.get_iter_at_mark(mark)
cur = buffer.get_end_iter()
buffer.delete(inp, cur)
buffer.insert(inp, command)
self.view.grab_focus()
def history_add(self, line):
if line.strip() != '':
self.history_pos = len(self.history)
self.history[self.history_pos - 1] = line
self.history.append('')
def history_up(self):
if self.history_pos > 0:
self.history[self.history_pos] = self.get_command_line()
self.history_pos = self.history_pos - 1
self.set_command_line(self.history[self.history_pos])
def history_down(self):
if self.history_pos < len(self.history) - 1:
self.history[self.history_pos] = self.get_command_line()
self.history_pos = self.history_pos + 1
self.set_command_line(self.history[self.history_pos])
def scroll_to_end(self):
iter = self.view.get_buffer().get_end_iter()
self.view.scroll_to_iter(iter, 0.0)
return False
def write(self, text, tag = None):
buffer = self.view.get_buffer()
if tag is None:
buffer.insert(buffer.get_end_iter(), text)
else:
buffer.insert_with_tags(buffer.get_end_iter(), text, tag)
gobject.idle_add(self.scroll_to_end)
def eval(self, command, display_command = False):
buffer = self.view.get_buffer()
lin = buffer.get_mark("input-line")
buffer.delete(buffer.get_iter_at_mark(lin),
buffer.get_end_iter())
if isinstance(command, list) or isinstance(command, tuple):
for c in command:
if display_command:
self.write(">>> " + c + "\n", self.command)
self.__run(c)
else:
if display_command:
self.write(">>> " + c + "\n", self.command)
self.__run(command)
cur = buffer.get_end_iter()
buffer.move_mark_by_name("input-line", cur)
buffer.insert(cur, ">>> ")
cur = buffer.get_end_iter()
buffer.move_mark_by_name("input", cur)
self.view.scroll_to_iter(buffer.get_end_iter(), 0.0)
def __run(self, command):
sys.stdout, self.stdout = self.stdout, sys.stdout
sys.stderr, self.stderr = self.stderr, sys.stderr
# eval and exec are broken in how they deal with utf8-encoded
# strings so we have to explicitly decode the command before
# passing it along
command = command.decode('utf8')
try:
try:
r = eval(command, self.namespace, self.namespace)
if r is not None:
print `r`
except SyntaxError:
exec command in self.namespace
except:
if hasattr(sys, 'last_type') and sys.last_type == SystemExit:
self.destroy()
else:
traceback.print_exc()
sys.stdout, self.stdout = self.stdout, sys.stdout
sys.stderr, self.stderr = self.stderr, sys.stderr
def destroy(self):
pass
#gtk.ScrolledWindow.destroy(self)
class OutFile:
"""A fake output file object. It sends output to a TK test widget,
and if asked for a file number, returns one set on instance creation"""
def __init__(self, console, fn, tag):
self.fn = fn
self.console = console
self.tag = tag
def close(self): pass
def flush(self): pass
def fileno(self): return self.fn
def isatty(self): return 0
def read(self, a): return ''
def readline(self): return ''
def readlines(self): return []
def write(self, s): self.console.write(s, self.tag)
def writelines(self, l): self.console.write(l, self.tag)
def seek(self, a): raise IOError, (29, 'Illegal seek')
def tell(self): raise IOError, (29, 'Illegal seek')
truncate = tell
# ex:et:ts=4:

15
plugins/quickopen/Makefile.am Executable file
View File

@@ -0,0 +1,15 @@
# Quick Open Plugin
SUBDIRS = quickopen
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)
plugin_in_files = quickopen.gedit-plugin.desktop.in
%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin)
EXTRA_DIST = $(plugin_in_files)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = $(plugin_DATA)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,10 @@
[Gedit Plugin]
Loader=python
Module=quickopen
IAge=2
_Name=Quick Open
_Description=Quickly open files
Icon=gtk-open
Authors=Jesse van den Kieboom <jessevdk@gnome.org>
Copyright=Copyright © 2009 Jesse van den Kieboom
Website=http://www.gedit.org

View File

@@ -0,0 +1,13 @@
# Quick Open Plugin
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)/quickopen
plugin_PYTHON = \
__init__.py \
popup.py \
virtualdirs.py \
windowhelper.py
CLEANFILES =
DISTCLEANFILES =
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2009 - Jesse van den Kieboom
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA 02111-1307, USA.
import gedit
from windowhelper import WindowHelper
class QuickOpenPlugin(gedit.Plugin):
def __init__(self):
gedit.Plugin.__init__(self)
self._popup_size = (450, 300)
self._helpers = {}
def activate(self, window):
self._helpers[window] = WindowHelper(window, self)
def deactivate(self, window):
self._helpers[window].deactivate()
del self._helpers[window]
def update_ui(self, window):
self._helpers[window].update_ui()
def get_popup_size(self):
return self._popup_size
def set_popup_size(self, size):
self._popup_size = size
# ex:ts=8:et:

View File

@@ -0,0 +1,534 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2009 - Jesse van den Kieboom
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA 02111-1307, USA.
import gtk
import gtk.gdk
import gobject
import os
import gio
import pango
import glib
import fnmatch
import gedit
import xml.sax.saxutils
from virtualdirs import VirtualDirectory
class Popup(gtk.Dialog):
def __init__(self, window, paths, handler):
gtk.Dialog.__init__(self,
title=_('Quick Open'),
parent=window,
flags=gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_NO_SEPARATOR | gtk.DIALOG_MODAL)
self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
self._open_button = self.add_button(gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT)
self._handler = handler
self._build_ui()
self._dirs = []
self._cache = {}
self._theme = None
self._cursor = None
self._shift_start = None
accel_group = gtk.AccelGroup()
accel_group.connect_group(gtk.keysyms.l, gtk.gdk.CONTROL_MASK, 0, self.on_focus_entry)
self.add_accel_group(accel_group)
unique = []
for path in paths:
if not path.get_uri() in unique:
self._dirs.append(path)
unique.append(path.get_uri())
def _build_ui(self):
vbox = self.get_content_area()
vbox.set_spacing(3)
self._entry = gtk.Entry()
self._entry.connect('changed', self.on_changed)
self._entry.connect('key-press-event', self.on_key_press_event)
sw = gtk.ScrolledWindow(None, None)
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
sw.set_shadow_type(gtk.SHADOW_OUT)
tv = gtk.TreeView()
tv.set_headers_visible(False)
self._store = gtk.ListStore(gio.Icon, str, object, int)
tv.set_model(self._store)
self._treeview = tv
tv.connect('row-activated', self.on_row_activated)
renderer = gtk.CellRendererPixbuf()
column = gtk.TreeViewColumn()
column.pack_start(renderer, False)
column.set_attributes(renderer, gicon=0)
renderer = gtk.CellRendererText()
column.pack_start(renderer, True)
column.set_attributes(renderer, markup=1)
column.set_cell_data_func(renderer, self.on_cell_data_cb)
tv.append_column(column)
sw.add(tv)
selection = tv.get_selection()
selection.connect('changed', self.on_selection_changed)
selection.set_mode(gtk.SELECTION_MULTIPLE)
vbox.pack_start(self._entry, False, False, 0)
vbox.pack_start(sw, True, True, 0)
lbl = gtk.Label()
lbl.set_alignment(0, 0.5)
lbl.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
self._info_label = lbl
vbox.pack_start(lbl, False, False, 0)
# Initial selection
self.on_selection_changed(tv.get_selection())
vbox.show_all()
def on_cell_data_cb(self, column, cell, model, piter):
path = model.get_path(piter)
if self._cursor and path == self._cursor.get_path():
style = self._treeview.get_style()
bg = style.bg[gtk.STATE_PRELIGHT]
cell.set_property('cell-background-gdk', bg)
cell.set_property('style', pango.STYLE_ITALIC)
else:
cell.set_property('cell-background-set', False)
cell.set_property('style-set', False)
def _icon_from_stock(self, stock):
theme = gtk.icon_theme_get_default()
size = gtk.icon_size_lookup(gtk.ICON_SIZE_MENU)
pixbuf = theme.load_icon(stock, size[0], gtk.ICON_LOOKUP_USE_BUILTIN)
return pixbuf
def _list_dir(self, gfile):
entries = []
try:
entries = gfile.enumerate_children("standard::*")
except glib.GError:
pass
children = []
for entry in entries:
if isinstance(gfile, VirtualDirectory):
child, entry = entry
else:
child = gfile.get_child(entry.get_name())
children.append((child, entry.get_name(), entry.get_file_type(), entry.get_icon()))
return children
def _compare_entries(self, a, b, lpart):
if lpart in a:
if lpart in b:
return cmp(a.index(lpart), b.index(lpart))
else:
return -1
elif lpart in b:
return 1
else:
return 0
def _match_glob(self, s, glob):
if glob:
glob += '*'
return fnmatch.fnmatch(s, glob)
def do_search_dir(self, parts, d):
if not parts or not d:
return []
if not d in self._cache:
entries = self._list_dir(d)
entries.sort(lambda x, y: cmp(x[1].lower(), y[1].lower()))
self._cache[d] = entries
else:
entries = self._cache[d]
found = []
newdirs = []
lpart = parts[0].lower()
for entry in entries:
if not entry:
continue
lentry = entry[1].lower()
if not lpart or lpart in lentry or self._match_glob(lentry, lpart):
if entry[2] == gio.FILE_TYPE_DIRECTORY:
if len(parts) > 1:
newdirs.append(entry[0])
else:
found.append(entry)
elif entry[2] == gio.FILE_TYPE_REGULAR and \
(not lpart or len(parts) == 1):
found.append(entry)
found.sort(lambda a, b: self._compare_entries(a[1].lower(), b[1].lower(), lpart))
if lpart == '..':
newdirs.append(d.get_parent())
for dd in newdirs:
found.extend(self.do_search_dir(parts[1:], dd))
return found
def _replace_insensitive(self, s, find, rep):
out = ''
l = s.lower()
find = find.lower()
last = 0
if len(find) == 0:
return xml.sax.saxutils.escape(s)
while True:
m = l.find(find, last)
if m == -1:
break
else:
out += xml.sax.saxutils.escape(s[last:m]) + rep % (xml.sax.saxutils.escape(s[m:m + len(find)]),)
last = m + len(find)
return out + xml.sax.saxutils.escape(s[last:])
def make_markup(self, parts, path):
out = []
for i in range(0, len(parts)):
out.append(self._replace_insensitive(path[i], parts[i], "<b>%s</b>"))
return os.sep.join(out)
def _get_icon(self, f):
query = f.query_info(gio.FILE_ATTRIBUTE_STANDARD_ICON)
if not query:
return None
else:
return query.get_icon()
def _make_parts(self, parent, child, pp):
parts = []
# We went from parent, to child, using pp
idx = len(pp) - 1
while idx >= 0:
if pp[idx] == '..':
parts.insert(0, '..')
else:
parts.insert(0, child.get_basename())
child = child.get_parent()
idx -= 1
return parts
def normalize_relative(self, parts):
if not parts:
return []
out = self.normalize_relative(parts[:-1])
if parts[-1] == '..':
if not out or (out[-1] == '..') or len(out) == 1:
out.append('..')
else:
del out[-1]
else:
out.append(parts[-1])
return out
def _append_to_store(self, item):
if not item in self._stored_items:
self._store.append(item)
self._stored_items[item] = True
def _clear_store(self):
self._store.clear()
self._stored_items = {}
def _show_virtuals(self):
for d in self._dirs:
if isinstance(d, VirtualDirectory):
for entry in d.enumerate_children("standard::*"):
self._append_to_store((entry[1].get_icon(), xml.sax.saxutils.escape(entry[1].get_name()), entry[0], entry[1].get_file_type()))
def _remove_cursor(self):
if self._cursor:
path = self._cursor.get_path()
self._cursor = None
self._store.row_changed(path, self._store.get_iter(path))
def do_search(self):
self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
self._remove_cursor()
text = self._entry.get_text().strip()
self._clear_store()
if text == '':
self._show_virtuals()
else:
parts = self.normalize_relative(text.split(os.sep))
files = []
for d in self._dirs:
for entry in self.do_search_dir(parts, d):
pathparts = self._make_parts(d, entry[0], parts)
self._append_to_store((entry[3], self.make_markup(parts, pathparts), entry[0], entry[2]))
piter = self._store.get_iter_first()
if piter:
self._treeview.get_selection().select_path(self._store.get_path(piter))
self.window.set_cursor(None)
def do_show(self):
gtk.Window.do_show(self)
self._entry.grab_focus()
self._entry.set_text("")
self.do_search()
def on_changed(self, editable):
self.do_search()
self.on_selection_changed(self._treeview.get_selection())
def _shift_extend(self, towhere):
selection = self._treeview.get_selection()
if not self._shift_start:
model, rows = selection.get_selected_rows()
start = rows[0]
self._shift_start = gtk.TreeRowReference(self._store, start)
else:
start = self._shift_start.get_path()
selection.unselect_all()
selection.select_range(start, towhere)
def _select_index(self, idx, hasctrl, hasshift):
path = (idx,)
if not (hasctrl or hasshift):
self._treeview.get_selection().unselect_all()
if hasshift:
self._shift_extend(path)
else:
self._shift_start = None
if not hasctrl:
self._treeview.get_selection().select_path(path)
self._treeview.scroll_to_cell(path, None, True, 0.5, 0)
self._remove_cursor()
if hasctrl or hasshift:
self._cursor = gtk.TreeRowReference(self._store, path)
piter = self._store.get_iter(path)
self._store.row_changed(path, piter)
def _move_selection(self, howmany, hasctrl, hasshift):
num = self._store.iter_n_children(None)
if num == 0:
return True
# Test for cursor
path = None
if self._cursor:
path = self._cursor.get_path()
else:
model, rows = self._treeview.get_selection().get_selected_rows()
if len(rows) == 1:
path = rows[0]
if not path:
if howmany > 0:
self._select_index(0, hasctrl, hasshift)
else:
self._select_index(num - 1, hasctrl, hasshift)
else:
idx = path[0]
if idx + howmany < 0:
self._select_index(0, hasctrl, hasshift)
elif idx + howmany >= num:
self._select_index(num - 1, hasctrl, hasshift)
else:
self._select_index(idx + howmany, hasctrl, hasshift)
return True
def _direct_file(self):
uri = self._entry.get_text()
gfile = None
if gedit.utils.uri_is_valid(uri):
gfile = gio.File(uri)
elif os.path.isabs(uri):
f = gio.File(uri)
if f.query_exists():
gfile = f
return gfile
def _activate(self):
model, rows = self._treeview.get_selection().get_selected_rows()
ret = True
for row in rows:
s = model.get_iter(row)
info = model.get(s, 2, 3)
if info[1] != gio.FILE_TYPE_DIRECTORY:
ret = ret and self._handler(info[0])
else:
text = self._entry.get_text()
for i in range(len(text) - 1, -1, -1):
if text[i] == os.sep:
break
self._entry.set_text(os.path.join(text[:i], os.path.basename(info[0].get_uri())) + os.sep)
self._entry.set_position(-1)
self._entry.grab_focus()
return True
if rows and ret:
self.destroy()
if not rows:
gfile = self._direct_file()
if gfile and self._handler(gfile):
self.destroy()
else:
ret = False
else:
ret = False
return ret
def toggle_cursor(self):
if not self._cursor:
return
path = self._cursor.get_path()
selection = self._treeview.get_selection()
if selection.path_is_selected(path):
selection.unselect_path(path)
else:
selection.select_path(path)
def on_key_press_event(self, widget, event):
move_mapping = {
gtk.keysyms.Down: 1,
gtk.keysyms.Up: -1,
gtk.keysyms.Page_Down: 5,
gtk.keysyms.Page_Up: -5
}
if event.keyval == gtk.keysyms.Escape:
self.destroy()
return True
elif event.keyval in move_mapping:
return self._move_selection(move_mapping[event.keyval], event.state & gtk.gdk.CONTROL_MASK, event.state & gtk.gdk.SHIFT_MASK)
elif event.keyval in [gtk.keysyms.Return, gtk.keysyms.KP_Enter, gtk.keysyms.Tab, gtk.keysyms.ISO_Left_Tab]:
return self._activate()
elif event.keyval == gtk.keysyms.space and event.state & gtk.gdk.CONTROL_MASK:
self.toggle_cursor()
return False
def on_row_activated(self, view, path, column):
self._activate()
def do_response(self, response):
if response != gtk.RESPONSE_ACCEPT or not self._activate():
self.destroy()
def on_selection_changed(self, selection):
model, rows = selection.get_selected_rows()
gfile = None
fname = None
if not rows:
gfile = self._direct_file()
elif len(rows) == 1:
gfile = model.get(model.get_iter(rows[0]), 2)[0]
else:
fname = ''
if gfile:
if gfile.is_native():
fname = xml.sax.saxutils.escape(gfile.get_path())
else:
fname = xml.sax.saxutils.escape(gfile.get_uri())
self._open_button.set_sensitive(fname != None)
self._info_label.set_markup(fname or '')
def on_focus_entry(self, group, accel, keyval, modifier):
self._entry.grab_focus()
gobject.type_register(Popup)
# ex:ts=8:et:

View File

@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2009 - Jesse van den Kieboom
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA 02111-1307, USA.
import gtk
import gio
class VirtualDirectory:
def __init__(self, name):
self._name = name
self._children = []
def get_uri(self):
return 'virtual://' + self._name
def get_parent(self):
return None
def enumerate_children(self, attr):
return self._children
def append(self, child):
if not child.is_native():
return
try:
info = child.query_info("standard::*")
if info:
self._children.append((child, info))
except:
pass
class RecentDocumentsDirectory(VirtualDirectory):
def __init__(self, maxitems=10, screen=None):
VirtualDirectory.__init__(self, 'recent')
self._maxitems = maxitems
self.fill(screen)
def fill(self, screen):
if screen:
manager = gtk.recent_manager_get_for_screen(screen)
else:
manager = gtk.recent_manager_get_default()
items = manager.get_items()
items.sort(lambda a, b: cmp(b.get_visited(), a.get_visited()))
added = 0
for item in items:
if item.has_group('gedit'):
self.append(gio.File(item.get_uri()))
added += 1
if added >= self._maxitems:
break
class CurrentDocumentsDirectory(VirtualDirectory):
def __init__(self, window):
VirtualDirectory.__init__(self, 'documents')
self.fill(window)
def fill(self, window):
for doc in window.get_documents():
location = doc.get_location()
if location:
self.append(location)
# ex:ts=8:et:

View File

@@ -0,0 +1,198 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2009 - Jesse van den Kieboom
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA 02111-1307, USA.
import gedit
import gtk
from popup import Popup
import os
import gedit.commands
import gio
import glib
from virtualdirs import RecentDocumentsDirectory
from virtualdirs import CurrentDocumentsDirectory
ui_str = """<ui>
<menubar name="MenuBar">
<menu name="FileMenu" action="File">
<placeholder name="FileOps_2">
<menuitem name="QuickOpen" action="QuickOpen"/>
</placeholder>
</menu>
</menubar>
</ui>
"""
class WindowHelper:
def __init__(self, window, plugin):
self._window = window
self._plugin = plugin
self._popup = None
self._install_menu()
def deactivate(self):
self._uninstall_menu()
self._window = None
self._plugin = None
def update_ui(self):
pass
def _uninstall_menu(self):
manager = self._window.get_ui_manager()
manager.remove_ui(self._ui_id)
manager.remove_action_group(self._action_group)
manager.ensure_update()
def _install_menu(self):
manager = self._window.get_ui_manager()
self._action_group = gtk.ActionGroup("GeditQuickOpenPluginActions")
self._action_group.add_actions([
("QuickOpen", gtk.STOCK_OPEN, _("Quick open"),
'<Ctrl><Alt>O', _("Quickly open documents"),
self.on_quick_open_activate)
])
manager.insert_action_group(self._action_group, -1)
self._ui_id = manager.add_ui_from_string(ui_str)
def _create_popup(self):
paths = []
# Open documents
paths.append(CurrentDocumentsDirectory(self._window))
doc = self._window.get_active_document()
# Current document directory
if doc and doc.is_local():
gfile = doc.get_location()
paths.append(gfile.get_parent())
# File browser root directory
if gedit.version[0] > 2 or (gedit.version[0] == 2 and (gedit.version[1] > 26 or (gedit.version[1] == 26 and gedit.version[2] >= 2))):
bus = self._window.get_message_bus()
try:
msg = bus.send_sync('/plugins/filebrowser', 'get_root')
if msg:
uri = msg.get_value('uri')
if uri:
gfile = gio.File(uri)
if gfile.is_native():
paths.append(gfile)
except StandardError:
pass
# Recent documents
paths.append(RecentDocumentsDirectory(screen=self._window.get_screen()))
# Local bookmarks
for path in self._local_bookmarks():
paths.append(path)
# Desktop directory
desktopdir = self._desktop_dir()
if desktopdir:
paths.append(gio.File(desktopdir))
# Home directory
paths.append(gio.File(os.path.expanduser('~')))
self._popup = Popup(self._window, paths, self.on_activated)
self._popup.set_default_size(*self._plugin.get_popup_size())
self._popup.set_transient_for(self._window)
self._popup.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self._window.get_group().add_window(self._popup)
self._popup.connect('destroy', self.on_popup_destroy)
def _local_bookmarks(self):
filename = os.path.expanduser('~/.gtk-bookmarks')
if not os.path.isfile(filename):
return []
paths = []
for line in file(filename, 'r').xreadlines():
uri = line.strip().split(" ")[0]
f = gio.File(uri)
if f.is_native():
try:
info = f.query_info("standard::type")
if info and info.get_file_type() == gio.FILE_TYPE_DIRECTORY:
paths.append(f)
except glib.GError:
pass
return paths
def _desktop_dir(self):
config = os.getenv('XDG_CONFIG_HOME')
if not config:
config = os.path.expanduser('~/.config')
config = os.path.join(config, 'user-dirs.dirs')
desktopdir = None
if os.path.isfile(config):
for line in file(config, 'r').xreadlines():
line = line.strip()
if line.startswith('XDG_DESKTOP_DIR'):
parts = line.split('=', 1)
desktopdir = os.path.expandvars(parts[1].strip('"').strip("'"))
break
if not desktopdir:
desktopdir = os.path.expanduser('~/Desktop')
return desktopdir
# Callbacks
def on_quick_open_activate(self, action):
if not self._popup:
self._create_popup()
self._popup.show()
def on_popup_destroy(self, popup):
alloc = popup.get_allocation()
self._plugin.set_popup_size((alloc.width, alloc.height))
self._popup = None
def on_activated(self, gfile):
gedit.commands.load_uri(self._window, gfile.get_uri(), None, -1)
return True
# ex:ts=8:et:

15
plugins/snippets/Makefile.am Executable file
View File

@@ -0,0 +1,15 @@
# Python snippets plugin
SUBDIRS = snippets data
plugindir = $(GEDIT_PLUGINS_LIBS_DIR)
plugin_in_files = snippets.gedit-plugin.desktop.in
%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin)
EXTRA_DIST = $(plugin_in_files)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = $(plugin_DATA)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,33 @@
# Python snippets plugin
SUBDIRS = lang
snippets_DATA = \
css.xml \
c.xml \
cpp.xml \
chdr.xml \
docbook.xml \
fortran.xml \
global.xml \
haskell.xml \
html.xml \
idl.xml \
javascript.xml \
java.xml \
latex.xml \
mallard.xml \
perl.xml \
php.xml \
python.xml \
ruby.xml \
sh.xml \
snippets.xml \
tcl.xml \
xml.xml \
xslt.xml
snippetsdir = $(GEDIT_PLUGINS_DATA_DIR)/snippets
EXTRA_DIST = $(snippets_DATA)
-include $(top_srcdir)/git.mk

283
plugins/snippets/data/c.xml Executable file
View File

@@ -0,0 +1,283 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets language="C">
<snippet id="gpl">
<text><![CDATA[/*
* ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]}
* This file is part of ${2:<program name>}
*
* Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4:
import pwd, os
try:
return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0]
except KeyError:
return '<author\>' >
*
* ${2} 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.
*
* ${2} is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ${2}; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
$0]]></text>
<tag>gpl</tag>
<description>GPL License</description>
</snippet>
<snippet id="lgpl">
<text><![CDATA[/*
* ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]}
* This file is part of ${2:<library name>}
*
* Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4:
import pwd, os
try:
return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0]
except KeyError:
return '<author\>' >
*
* ${2} is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ${2} is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
$0]]></text>
<tag>lgpl</tag>
<description>LGPL License</description>
</snippet>
<snippet id="do">
<text><![CDATA[do
{
$0
} while ($1);]]></text>
<tag>do</tag>
<description>do .. while</description>
</snippet>
<snippet id="for">
<text><![CDATA[for (${1:i} = ${2:0}; ${1:i} < ${3:count}; ${1:i} += ${4:1})
{
$0
}]]></text>
<tag>for</tag>
<description>for loop</description>
</snippet>
<snippet id="while">
<text><![CDATA[while (${1:condition})
{
$0
}]]></text>
<tag>while</tag>
<description>while loop</description>
</snippet>
<snippet id="if">
<text><![CDATA[if (${1:condition})
{
$0
}]]></text>
<tag>if</tag>
<description>if</description>
</snippet>
<snippet id="elif">
<text><![CDATA[else if (${1:condition})
{
$0
}]]></text>
<tag>elif</tag>
<description>else if</description>
</snippet>
<snippet id="else">
<text><![CDATA[else
{
$0
}]]></text>
<tag>else</tag>
<description>else</description>
</snippet>
<snippet id="Inc">
<text><![CDATA[#include <${1:file}.h>
$0]]></text>
<tag>Inc</tag>
<description>#include &lt;..&gt;</description>
</snippet>
<snippet id="inc">
<text><![CDATA[#include "${1:file}.h"
$0]]></text>
<tag>inc</tag>
<description>#include ".."</description>
</snippet>
<snippet id="main">
<text><![CDATA[int
main (int argc, char *argv[])
{
$0
return 0;
}]]></text>
<tag>main</tag>
<description>main</description>
</snippet>
<snippet id="struct">
<text><![CDATA[struct ${1:name}
{
${0:/* data */}
};]]></text>
<tag>struct</tag>
<description>struct</description>
</snippet>
<snippet id="endif">
<text><![CDATA[#endif
$0]]></text>
<description>#endif</description>
<accelerator><![CDATA[<Control><Alt>period]]></accelerator>
</snippet>
<snippet id="td">
<text><![CDATA[typedef ${1:newtype} ${2:type};
$0]]></text>
<tag>td</tag>
<description>typedef</description>
</snippet>
<snippet id="gobject">
<text><![CDATA[#include "$1.h"
$<
global camel_str,low_str, type_str, is_str, up_str
components = $1.split('-')
low_str = '_'.join(components).lower()
up_str = '_'.join(components).upper()
type_str = '_'.join([components[0], 'TYPE'] + components[1:]).upper()
is_str = '_'.join([components[0], 'IS'] + components[1:]).upper()
camel_str = ''
for t in components:
camel_str += t.capitalize()
>
#define $<[1]: return up_str >_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), $<[1]: return type_str >, $<[1]: return camel_str >Private))
struct _$<[1]: return camel_str >Private
{
};
G_DEFINE_TYPE ($<[1]: return camel_str >, $<[1]: return low_str >, ${2:G_TYPE_OBJECT})
static void
$<[1]: return low_str>_finalize (GObject *object)
{
G_OBJECT_CLASS ($<[1]: return low_str >_parent_class)->finalize (object);
}
static void
$<[1]: return low_str >_class_init ($<[1]: return camel_str >Class *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = $<[1]: return low_str >_finalize;
g_type_class_add_private (object_class, sizeof ($<[1]: return camel_str >Private));
}
static void
$<[1]: return low_str >_init ($<[1]: return camel_str> *self)
{
self->priv = $<[1]: return up_str >_GET_PRIVATE (self);
}
$<[1]: return camel_str > *
$<[1]: return low_str >_new ()
{
return g_object_new ($<[1]: return type_str >, NULL);
}]]></text>
<tag>gobject</tag>
<description>GObject template</description>
</snippet>
<snippet id="ginterface">
<text><![CDATA[#include "$1.h"
$<
global camel_str,low_str,up_str
components = $1.split('-')
low_str = '_'.join(components).lower()
up_str = '_'.join(components).upper()
camel_str = ''
for t in components:
camel_str += t.capitalize()
>
/* Default implementation */
static const gchar *
$<[1]: return low_str>_example_method_default ($<[1]: return camel_str > *self)
{
g_return_val_if_reached (NULL);
}
static void
$<[1]: return low_str>_init ($<[1]: return camel_str >Iface *iface)
{
static gboolean initialized = FALSE;
iface->example_method = $<[1]: return low_str>_example_method_default;
if (!initialized)
{
initialized = TRUE;
}
}
/*
* This is an method example for an interface
*/
const gchar *
$<[1]: return low_str>_example_method ($<[1]: return camel_str > *self)
{
g_return_val_if_fail ($<[1]: return up_str> (self), NULL);
return $<[1]: return up_str>_GET_INTERFACE (self)->example_method (self);
}
GType
$<[1]: return low_str>_get_type ()
{
static GType $<[1]: return low_str>_type_id = 0;
if (!$<[1]: return low_str>_type_id)
{
static const GTypeInfo g_define_type_info =
{
sizeof ($<[1]: return camel_str >Iface),
(GBaseInitFunc) $<[1]: return low_str>_init,
NULL,
NULL,
NULL,
NULL,
0,
0,
NULL
};
$<[1]: return low_str>_type_id =
g_type_register_static (G_TYPE_INTERFACE,
"$<[1]: return camel_str>",
&g_define_type_info,
0);
}
return $<[1]: return low_str>_type_id;
}]]></text>
<tag>ginterface</tag>
<description>GObject interface</description>
</snippet>
</snippets>

241
plugins/snippets/data/chdr.xml Executable file
View File

@@ -0,0 +1,241 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets language="chdr">
<snippet id="once">
<text><![CDATA[#ifndef __${1:NAME}_H__
#define __$1_H__
$0
#endif /* __$1_H__ */
]]></text>
<description>Header Include-Guard</description>
<tag>once</tag>
</snippet>
<snippet id="inc">
<text><![CDATA[#include "${1:file}"
$0]]></text>
<description>#include ".."</description>
<tag>inc</tag>
</snippet>
<snippet id="Inc">
<text><![CDATA[#include <${1:file}>
$0]]></text>
<description>#include &lt;..&gt;</description>
<tag>Inc</tag>
</snippet>
<snippet id="namespace">
<text><![CDATA[namespace ${1:ns}
{
$0
};
]]></text>
<description>namespace ..</description>
<tag>namespace</tag>
</snippet>
<snippet id="gpl">
<text><![CDATA[/*
* ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]}
* This file is part of ${2:<program name>}
*
* Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4:
import pwd, os
try:
return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0]
except KeyError:
return '<author\>' >
*
* ${2} 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.
*
* ${2} is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ${2}; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
$0]]></text>
<tag>gpl</tag>
<description>GPL License</description>
</snippet>
<snippet id="lgpl">
<text><![CDATA[/*
* ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]}
* This file is part of ${2:<library name>}
*
* Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4:
import pwd, os
try:
return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0]
except KeyError:
return '<author\>' >
*
* ${2} is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ${2} is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
$0]]></text>
<tag>lgpl</tag>
<description>LGPL License</description>
</snippet>
<snippet id="td">
<text><![CDATA[typedef ${1:newtype} ${2:type};
$0]]></text>
<tag>td</tag>
<description>typedef</description>
</snippet>
<snippet id="class">
<text><![CDATA[class ${1:name}
{
public:
${1:name} (${2:arguments});
virtual ~${1:name} ();
private:
${0:/* data */}
};]]></text>
<description>class ..</description>
<tag>class</tag>
</snippet>
<snippet id="struct">
<text><![CDATA[struct ${1:name}
{
${0:/* data */}
};]]></text>
<tag>struct</tag>
<description>struct</description>
</snippet>
<snippet id="template">
<text><![CDATA[template <typename ${1:_InputIter}>]]></text>
<description>template &lt;typename ..&gt;</description>
<tag>template</tag>
</snippet>
<snippet id="gobject">
<text><![CDATA[#ifndef __${1:NAME}_H__
#define __$1_H__
#include <${2:glib-object.h}>
G_BEGIN_DECLS
$<
global camel_str
components = $1.split('_')
type_str = '_'.join([components[0], 'TYPE'] + components[1:])
is_str = '_'.join([components[0], 'IS'] + components[1:])
camel_str = ''
for t in components:
camel_str += t.capitalize()
items = [ \
['#define ' + type_str, '(' + $1.lower() + '_get_type ())'], \
['#define ' + $1 + '(obj)', '(G_TYPE_CHECK_INSTANCE_CAST ((obj), ' + type_str + ', ' + camel_str + '))'], \
['#define ' + $1 + '_CONST(obj)', '(G_TYPE_CHECK_INSTANCE_CAST ((obj), ' + type_str + ', ' + camel_str + ' const))'], \
['#define ' + $1 + '_CLASS(klass)', '(G_TYPE_CHECK_CLASS_CAST ((klass), ' + type_str + ', ' + camel_str + 'Class))'], \
['#define ' + is_str + '(obj)', '(G_TYPE_CHECK_INSTANCE_TYPE ((obj), ' + type_str + '))'], \
['#define ' + is_str + '_CLASS(klass)', '(G_TYPE_CHECK_CLASS_TYPE ((klass), ' + type_str + '))'], \
['#define ' + $1 + '_GET_CLASS(obj)', '(G_TYPE_INSTANCE_GET_CLASS ((obj), ' + type_str + ', ' + camel_str + 'Class))']
]
return align(items) >
$<[1]:
items = [ \
['typedef struct _' + camel_str, camel_str + ';'], \
['typedef struct _' + camel_str + 'Class', camel_str + 'Class;'], \
['typedef struct _' + camel_str + 'Private', camel_str + 'Private;'] \
]
return align(items) >
struct _$<[1]: return camel_str > {
${7:GObject} parent;
$<[1]: return camel_str >Private *priv;
};
struct _$<[1]: return camel_str >Class {
$7Class parent_class;
};
GType $< return $1.lower() + '_get_type' > (void) G_GNUC_CONST;
$<[1]: return camel_str > *$< return $1.lower()>_new (void);
$0
G_END_DECLS
#endif /* __$1_H__ */]]></text>
<tag>gobject</tag>
<description>GObject template</description>
</snippet>
<snippet id="ginterface">
<text><![CDATA[#ifndef __${1:NAME}_H__
#define __$1_H__
#include <${2:glib-object.h}>
G_BEGIN_DECLS
$<
global camel_str
components = $1.split('_')
type_str = '_'.join([components[0], 'TYPE'] + components[1:])
is_str = '_'.join([components[0], 'IS'] + components[1:])
camel_str = ''
for t in components:
camel_str += t.capitalize()
items = [ \
['#define ' + type_str, '(' + $1.lower() + '_get_type ())'], \
['#define ' + $1 + '(obj)', '(G_TYPE_CHECK_INSTANCE_CAST ((obj), ' + type_str + ', ' + camel_str + '))'], \
['#define ' + is_str + '(obj)', '(G_TYPE_CHECK_INSTANCE_TYPE ((obj), ' + type_str + '))'], \
['#define ' + $1 + '_GET_INTERFACE(obj)', '(G_TYPE_INSTANCE_GET_INTERFACE ((obj), ' + type_str + ', ' + camel_str + 'Iface))']
]
return align(items) >
$<[1]:
items = [ \
['typedef struct _' + camel_str, camel_str + ';'], \
['typedef struct _' + camel_str + 'Iface', camel_str + 'Iface;'], \
]
return align(items) >
struct _$<[1]: return camel_str >Iface
{
${7:GTypeInterface} parent;
const gchar * (*example_method) ($<[1]: return camel_str > *self);
};
GType $< return $1.lower() + '_get_type' > (void) G_GNUC_CONST;
const gchar *$< return $1.lower()>_example_method ($<[1]: return camel_str > *self);
$0
G_END_DECLS
#endif /* __$1_H__ */]]></text>
<tag>ginterface</tag>
<description>GObject interface</description>
</snippet>
</snippets>

183
plugins/snippets/data/cpp.xml Executable file
View File

@@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets language="cpp">
<snippet id="main">
<text><![CDATA[int main (int argc, char const* argv[])
{
$0
return 0;
}]]></text>
<description>main</description>
<tag>main</tag>
</snippet>
<snippet id="for">
<text><![CDATA[for (${1:unsigned int} ${2:i} = ${3:0}; ${2:i} < ${4:count}; ${2:i} += ${5:1})
{
$0
}]]></text>
<description>for loop</description>
<tag>for</tag>
</snippet>
<snippet id="beginend">
<text><![CDATA[${1:v}.begin(), ${1:v}.end()]]></text>
<description>$1.begin</description>
<tag>beginend</tag>
</snippet>
<snippet id="do">
<text><![CDATA[do
{
$0
} while ($1 );]]></text>
<description>do .. while</description>
<tag>do</tag>
</snippet>
<snippet id="endif">
<text><![CDATA[#endif
$0]]></text>
<accelerator><![CDATA[<Control><Alt>period]]></accelerator>
<description>#endif</description>
</snippet>
<snippet id="if">
<text><![CDATA[if (${1:condition})
{
$0
}]]></text>
<description>if ..</description>
<tag>if</tag>
</snippet>
<snippet id="inc">
<text><![CDATA[#include "${1:file}"
$0]]></text>
<description>#include ".."</description>
<tag>inc</tag>
</snippet>
<snippet id="Inc">
<text><![CDATA[#include <${1:file}>
$0]]></text>
<description>#include &lt;..&gt;</description>
<tag>Inc</tag>
</snippet>
<snippet id="namespace">
<text><![CDATA[namespace ${1:ns}
{
$0
};
]]></text>
<description>namespace ..</description>
<tag>namespace</tag>
</snippet>
<snippet id="readfile">
<text><![CDATA[std::vector<uint8_t> v;
if (FILE* fp = fopen (${1:"filename"}, "r"))
{
uint8_t buf[1024];
while (size_t len = fread (buf, 1, sizeof (buf), fp))
v.insert (v.end(), buf, buf + len);
fclose(fp);
}
$0]]></text>
<description>Read File Into Vector</description>
<tag>readfile</tag>
</snippet>
<snippet id="map">
<text><![CDATA[std::map<${1:key}, ${2:value}> ${3:map};
$0]]></text>
<description>std::map</description>
<tag>map</tag>
</snippet>
<snippet id="vector">
<text><![CDATA[std::vector<${1:char}> ${2:v};
$0]]></text>
<description>std::vector</description>
<tag>vector</tag>
</snippet>
<snippet id="struct">
<text><![CDATA[struct ${1:name}
{
${0:/* data */}
};]]></text>
<description>struct ..</description>
<tag>struct</tag>
</snippet>
<snippet id="template">
<text><![CDATA[template <typename ${1:_InputIter}>]]></text>
<description>template &lt;typename ..&gt;</description>
<tag>template</tag>
</snippet>
<snippet id="gpl">
<text><![CDATA[/*
* ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]}
* This file is part of ${2:<program name>}
*
* Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4:
import pwd, os
try:
return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0]
except KeyError:
return '<author\>' >
*
* ${2} 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.
*
* ${2} is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ${2}; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
$0]]></text>
<tag>gpl</tag>
<description>GPL License</description>
</snippet>
<snippet id="lgpl">
<text><![CDATA[/*
* ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]}
* This file is part of ${2:<library name>}
*
* Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4:
import pwd, os
try:
return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0]
except KeyError:
return '<author\>' >
*
* ${2} is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ${2} is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
$0]]></text>
<tag>lgpl</tag>
<description>LGPL License</description>
</snippet>
<snippet id="td">
<text><![CDATA[typedef ${1:newtype} ${2:type};
$0]]></text>
<tag>td</tag>
<description>typedef</description>
</snippet>
<snippet id="while">
<text><![CDATA[while ($1)
{
$0
}]]></text>
<tag>while</tag>
<description>while</description>
</snippet>
</snippets>

557
plugins/snippets/data/css.xml Executable file
View File

@@ -0,0 +1,557 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets language="CSS">
<snippet id="background">
<text><![CDATA[background-attachment: ${1:scroll/fixed};
$0]]></text>
<description>background-attachment: scroll/fixed</description>
<tag>background</tag>
</snippet>
<snippet id="background-1">
<text><![CDATA[background-color: #${1:DDD};
$0]]></text>
<description>background-color: color-hex</description>
<tag>background</tag>
</snippet>
<snippet id="background-2">
<text><![CDATA[background-color: ${1:red};
$0]]></text>
<description>background-color: color-name</description>
<tag>background</tag>
</snippet>
<snippet id="background-3">
<text><![CDATA[background-color: rgb(${1:255},${2:255},${3:255});
$0]]></text>
<description>background-color: color-rgb</description>
<tag>background</tag>
</snippet>
<snippet id="background-4">
<text><![CDATA[background: #${1:DDD} url($2) ${3:repeat/repeat-x/repeat-y/no-repeat} ${4:scroll/fixed} ${5:top letft/top center/top right/center left/center center/center right/bottom left/bottom center/bottom right/x-% y-%/x-pos y-pos};
$0]]></text>
<description>background: color image repeat attachment position</description>
<tag>background</tag>
</snippet>
<snippet id="background-5">
<text><![CDATA[background-color: transparent;
$0]]></text>
<description>background-color: transparent</description>
<tag>background</tag>
</snippet>
<snippet id="background-6">
<text><![CDATA[background-image: none;
$0]]></text>
<description>background-image: none</description>
<tag>background</tag>
</snippet>
<snippet id="background-7">
<text><![CDATA[background-image: url($1);
$0]]></text>
<description>background-image: url</description>
<tag>background</tag>
</snippet>
<snippet id="background-8">
<text><![CDATA[background-position: ${1:top letft/top center/top right/center left/center center/center right/bottom left/bottom center/bottom right/x-% y-%/x-pos y-pos};
$0]]></text>
<description>background-position: position</description>
<tag>background</tag>
</snippet>
<snippet id="background-9">
<text><![CDATA[background-repeat: ${1:repeat/repeat-x/repeat-y/no-repeat};
$0]]></text>
<description>background-repeat: r/r-x/r-y/n-r</description>
<tag>background</tag>
</snippet>
<snippet id="border">
<text><![CDATA[border-bottom-color: #${1:999};
$0]]></text>
<description>border-bottom-color: size style color</description>
<tag>border</tag>
</snippet>
<snippet id="border-1">
<text><![CDATA[border-bottom: ${1:1}px ${2:solid} #${3:999};
$0]]></text>
<description>border-bottom: size style color</description>
<tag>border</tag>
</snippet>
<snippet id="border-2">
<text><![CDATA[border-bottom-style: ${1:none/hidden/dotted/dashed/solid/double/groove/ridge/inset/outset};
$0]]></text>
<description>border-bottom-style: size style color</description>
<tag>border</tag>
</snippet>
<snippet id="border-3">
<text><![CDATA[border-bottom-width: ${1:1}px ${2:solid} #${3:999};
$0]]></text>
<description>border-bottom-width: size style color</description>
<tag>border</tag>
</snippet>
<snippet id="border-4">
<text><![CDATA[border-color: ${1:999};
$0]]></text>
<description>border-color: color</description>
<tag>border</tag>
</snippet>
<snippet id="border-5">
<text><![CDATA[border-right-color: #${1:999};
$0]]></text>
<description>border-left-color: color</description>
<tag>border</tag>
</snippet>
<snippet id="border-6">
<text><![CDATA[border-left: ${1:1}px ${2:solid} #${3:999};
$0]]></text>
<description>border-left: size style color</description>
<tag>border</tag>
</snippet>
<snippet id="border-7">
<text><![CDATA[border-left-style: ${1:none/hidden/dotted/dashed/solid/double/groove/ridge/inset/outset};
$0]]></text>
<description>border-left-style: style</description>
<tag>border</tag>
</snippet>
<snippet id="border-8">
<text><![CDATA[border-left-width: ${1:1}px ${2:solid} #${3:999};
$0]]></text>
<description>border-left-width: size</description>
<tag>border</tag>
</snippet>
<snippet id="border-9">
<text><![CDATA[border-right-color: #${1:999};
$0]]></text>
<description>border-right-color: color</description>
<tag>border</tag>
</snippet>
<snippet id="border-10">
<text><![CDATA[border-right: ${1:1}px ${2:solid} #${3:999};
$0]]></text>
<description>border-right: size style color</description>
<tag>border</tag>
</snippet>
<snippet id="border-11">
<text><![CDATA[border-right-style: ${1:none/hidden/dotted/dashed/solid/double/groove/ridge/inset/outset};
$0]]></text>
<description>border-right-style: style</description>
<tag>border</tag>
</snippet>
<snippet id="border-12">
<text><![CDATA[border-right-width: ${1:1}px ${2:solid} #${3:999};
$0]]></text>
<description>border-right-width: size</description>
<tag>border</tag>
</snippet>
<snippet id="border-13">
<text><![CDATA[border: ${1:1px} ${2:solid} #${3:999};
$0]]></text>
<description>border: size style color</description>
<tag>border</tag>
</snippet>
<snippet id="border-14">
<text><![CDATA[border-style: ${1:none/hidden/dotted/dashed/solid/double/groove/ridge/inset/outset};
$0]]></text>
<description>border-style: style</description>
<tag>border</tag>
</snippet>
<snippet id="border-15">
<text><![CDATA[border-top-color: #${1:999};
$0]]></text>
<description>border-top-color: color</description>
<tag>border</tag>
</snippet>
<snippet id="border-16">
<text><![CDATA[border-top: ${1:1}px ${2:solid} #${3:999};
$0]]></text>
<description>border-top: size style color</description>
<tag>border</tag>
</snippet>
<snippet id="border-17">
<text><![CDATA[border-top-style: ${1:none/hidden/dotted/dashed/solid/double/groove/ridge/inset/outset};
$0]]></text>
<description>border-top-style: style</description>
<tag>border</tag>
</snippet>
<snippet id="border-18">
<text><![CDATA[border-top-width: ${1:1}px ${2:solid} #${3:999};
$0]]></text>
<description>border-top-width: size</description>
<tag>border</tag>
</snippet>
<snippet id="border-19">
<text><![CDATA[border-color: ${1:1px};
$0]]></text>
<description>border-width: width</description>
<tag>border</tag>
</snippet>
<snippet id="clear">
<text><![CDATA[clear: ${1:left/right/both/none};
$0]]></text>
<description>clear: value</description>
<tag>clear</tag>
</snippet>
<snippet id="color">
<text><![CDATA[color: #${1:DDD};
$0]]></text>
<description>color: color-hex</description>
<tag>color</tag>
</snippet>
<snippet id="color-1">
<text><![CDATA[color: ${1:red};
$0]]></text>
<description>color: color-name</description>
<tag>color</tag>
</snippet>
<snippet id="color-2">
<text><![CDATA[color: rgb(${1:255},${2:255},${3:255});
$0]]></text>
<description>color: color-rgb</description>
<tag>color</tag>
</snippet>
<snippet id="cursor">
<text><![CDATA[cursor: {$1:default/auto/crosshair/pointer/move/*-resize/text/wait/help};
$0]]></text>
<description>cursor: type</description>
<tag>cursor</tag>
</snippet>
<snippet id="clear-1">
<text><![CDATA[cursor: url($1);
$0]]></text>
<description>cursor: url</description>
<tag>clear</tag>
</snippet>
<snippet id="direction">
<text><![CDATA[direction: ${1:ltr|rtl};
$0]]></text>
<description>direction: ltr|rtl</description>
<tag>direction</tag>
</snippet>
<snippet id="display">
<text><![CDATA[display: block;
$0]]></text>
<description>display: block</description>
<tag>display</tag>
</snippet>
<snippet id="display-1">
<text><![CDATA[display: ${1:none/inline/block/list-item/run-in/compact/marker};
$0]]></text>
<description>display: common-types</description>
<tag>display</tag>
</snippet>
<snippet id="display-2">
<text><![CDATA[display: inline;
$0]]></text>
<description>display: inline</description>
<tag>display</tag>
</snippet>
<snippet id="display-3">
<text><![CDATA[display: ${1:table/inline-table/table-row-group/table-header-group/table-footer-group/table-row/table-column-group/table-column/table-cell/table-caption};
$0]]></text>
<description>display: table-types</description>
<tag>display</tag>
</snippet>
<snippet id="float">
<text><![CDATA[float: ${1:left/right/none};
$0]]></text>
<description>float: left/right/none</description>
<tag>float</tag>
</snippet>
<snippet id="font">
<text><![CDATA[font-family: ${1:Arial, "MS Trebuchet"}, ${2:sans-}serif;
$0]]></text>
<description>font-family: family</description>
<tag>font</tag>
</snippet>
<snippet id="font-1">
<text><![CDATA[font: ${1:75%} ${2:"Lucida Grande", "Trebuchet MS", Verdana,} ${3:sans-}serif;
$0]]></text>
<description>font: size font</description>
<tag>font</tag>
</snippet>
<snippet id="font-2">
<text><![CDATA[font-size: ${1:100%};
$0]]></text>
<description>font-size: size</description>
<tag>font</tag>
</snippet>
<snippet id="font-3">
<text><![CDATA[font-style: ${1:normal/italic/oblique};
$0]]></text>
<description>font-style: normal/italic/oblique</description>
<tag>font</tag>
</snippet>
<snippet id="font-4">
<text><![CDATA[font: ${1:normal/italic/oblique} ${2:normal/small-caps} ${3:normal/bold} ${4:1em/1.5em} ${5:Arial}, ${6:sans-}serif;
$0]]></text>
<description>font: style variant weight size/line-height font-family</description>
<tag>font</tag>
</snippet>
<snippet id="font-5">
<text><![CDATA[font-variant: ${1:normal/small-caps};
$0]]></text>
<description>font-variant: normal/small-caps</description>
<tag>font</tag>
</snippet>
<snippet id="font-6">
<text><![CDATA[font-weight: ${1:normal/bold};
$0]]></text>
<description>font-weight: weight</description>
<tag>font</tag>
</snippet>
<snippet id="letter">
<text><![CDATA[letter-spacing: $1em;
$0]]></text>
<description>letter-spacing: length-em</description>
<tag>letter</tag>
</snippet>
<snippet id="letter-1">
<text><![CDATA[letter-spacing: $1px;
$0]]></text>
<description>letter-spacing: length-px</description>
<tag>letter</tag>
</snippet>
<snippet id="list">
<text><![CDATA[list-style-image: url($1);
$0]]></text>
<description>list-style-image: url</description>
<tag>list</tag>
</snippet>
<snippet id="list-1">
<text><![CDATA[list-style-position: ${1:inside/outside};
$0]]></text>
<description>list-style-position: pos</description>
<tag>list</tag>
</snippet>
<snippet id="list-2">
<text><![CDATA[list-style-type: ${1:cjk-ideographic/hiragana/katakana/hiragana-iroha/katakana-iroha};
$0]]></text>
<description>list-style-type: asian</description>
<tag>list</tag>
</snippet>
<snippet id="list-3">
<text><![CDATA[list-style-type: ${1:none/disc/circle/square};
$0]]></text>
<description>list-style-type: marker</description>
<tag>list</tag>
</snippet>
<snippet id="list-4">
<text><![CDATA[list-style-type: ${1:decimal/decimal-leading-zero/zero};
$0]]></text>
<description>list-style-type: numeric</description>
<tag>list</tag>
</snippet>
<snippet id="list-5">
<text><![CDATA[list-style-type: ${1:hebrew/armenian/georgian};
$0]]></text>
<description>list-style-type: other</description>
<tag>list</tag>
</snippet>
<snippet id="list-6">
<text><![CDATA[list-style: ${1:none/disc/circle/square/decimal/zero} ${2:inside/outside} url($3);
$0]]></text>
<description>list-style: type position image</description>
<tag>list</tag>
</snippet>
<snippet id="list-7">
<text><![CDATA[list-style-type: ${1:lower-roman/uppert-roman/lower-alpha/upper-alpha/lower-greek/lower-latin/upper-latin};
$0]]></text>
<description>list-style-type: roman-alpha-greek</description>
<tag>list</tag>
</snippet>
<snippet id="margin">
<text><![CDATA[margin: ${1:20px};
$0]]></text>
<description>margin: all</description>
<tag>margin</tag>
</snippet>
<snippet id="margin-1">
<text><![CDATA[margin-bottom: ${1:20px};
$0]]></text>
<description>margin-bottom: length</description>
<tag>margin</tag>
</snippet>
<snippet id="margin-2">
<text><![CDATA[margin-left: ${1:20px};
$0]]></text>
<description>margin-left: length</description>
<tag>margin</tag>
</snippet>
<snippet id="margin-3">
<text><![CDATA[margin-right: ${1:20px};
$0]]></text>
<description>margin-right: length</description>
<tag>margin</tag>
</snippet>
<snippet id="margin-4">
<text><![CDATA[margin-top: ${1:20px};
$0]]></text>
<description>margin-top: length</description>
<tag>margin</tag>
</snippet>
<snippet id="margin-5">
<text><![CDATA[margin: ${1:20px} ${2:0px} ${3:40px} ${4:0px};
$0]]></text>
<description>margin: T R B L</description>
<tag>margin</tag>
</snippet>
<snippet id="margin-6">
<text><![CDATA[margin: ${1:20px} ${2:0px};
$0]]></text>
<description>margin: V H</description>
<tag>margin</tag>
</snippet>
<snippet id="marker">
<text><![CDATA[marker-offset: auto;
$0]]></text>
<description>marker-offset: auto</description>
<tag>marker</tag>
</snippet>
<snippet id="marker-1">
<text><![CDATA[marker-offset: ${1:10px};
$0]]></text>
<description>marker-offset: length</description>
<tag>marker</tag>
</snippet>
<snippet id="overflow">
<text><![CDATA[overflow: ${1:visible/hidden/scroll/auto};
$0]]></text>
<description>overflow: type</description>
<tag>overflow</tag>
</snippet>
<snippet id="padding">
<text><![CDATA[padding: ${1:20px};
$0]]></text>
<description>padding: all</description>
<tag>padding</tag>
</snippet>
<snippet id="margin-7">
<text><![CDATA[padding-bottom: ${1:20px};
$0]]></text>
<description>padding-bottom: length</description>
<tag>margin</tag>
</snippet>
<snippet id="margin-8">
<text><![CDATA[padding-left: ${1:20px};
$0]]></text>
<description>padding-left: length</description>
<tag>margin</tag>
</snippet>
<snippet id="margin-9">
<text><![CDATA[padding-right: ${1:20px};
$0]]></text>
<description>padding-right: length</description>
<tag>margin</tag>
</snippet>
<snippet id="margin-10">
<text><![CDATA[padding-top: ${1:20px};
$0]]></text>
<description>padding-top: length</description>
<tag>margin</tag>
</snippet>
<snippet id="padding-1">
<text><![CDATA[padding: ${1:20px} ${2:0px} ${3:40px} ${4:0px};
$0]]></text>
<description>padding: T R B L</description>
<tag>padding</tag>
</snippet>
<snippet id="padding-2">
<text><![CDATA[padding: ${1:20px} ${2:0px};
$0]]></text>
<description>padding: V H</description>
<tag>padding</tag>
</snippet>
<snippet id="position">
<text><![CDATA[position: ${1:static/relative/absolute/fixed};
$0]]></text>
<description>position: type</description>
<tag>position</tag>
</snippet>
<snippet id="{">
<text><![CDATA[{
/* $1 */
$0
]]></text>
<description>properties { }</description>
<tag>{</tag>
</snippet>
<snippet id="text">
<text><![CDATA[text-align: ${1:left/right/center/justify};
$0]]></text>
<description>text-align: left/center/right</description>
<tag>text</tag>
</snippet>
<snippet id="text-1">
<text><![CDATA[text-decoration: ${1:none/underline/overline/line-through/blink};
$0]]></text>
<description>text-decoration: none/underline/overline/line-through/blink</description>
<tag>text</tag>
</snippet>
<snippet id="text-2">
<text><![CDATA[text-indent: ${1:10p}x;
$0]]></text>
<description>text-indent: length</description>
<tag>text</tag>
</snippet>
<snippet id="text-3">
<text><![CDATA[text-shadow: #${1:DDD} ${2:10px} ${3:10px} ${4:2px};
$0]]></text>
<description>text-shadow: color-hex x y blur</description>
<tag>text</tag>
</snippet>
<snippet id="text-4">
<text><![CDATA[text-shadow: rgb(${1:255},${2:255},${3:255}) ${4:10px} ${5:10px} ${6:2px};
$0]]></text>
<description>text-shadow: color-rgb x y blur</description>
<tag>text</tag>
</snippet>
<snippet id="text-5">
<text><![CDATA[text-shadow: none;
$0]]></text>
<description>text-shadow: none</description>
<tag>text</tag>
</snippet>
<snippet id="text-6">
<text><![CDATA[text-transform: ${1:capitalize/uppercase/lowercase};
$0]]></text>
<description>text-transform: capitalize/upper/lower</description>
<tag>text</tag>
</snippet>
<snippet id="text-7">
<text><![CDATA[text-transform: none;
$0]]></text>
<description>text-transform: none</description>
<tag>text</tag>
</snippet>
<snippet id="vertical">
<text><![CDATA[vertical-align: ${1:baseline/sub/super/top/text-top/middle/bottom/text-bottom/length/%};
$0]]></text>
<description>vertical-align: type</description>
<tag>vertical</tag>
</snippet>
<snippet id="visibility">
<text><![CDATA[visibility: ${1:visible/hidden/collapse};
$0]]></text>
<description>visibility: type</description>
<tag>visibility</tag>
</snippet>
<snippet id="white">
<text><![CDATA[white-space: ${1:normal/pre/nowrap};
$0]]></text>
<description>white-space: normal/pre/nowrap</description>
<tag>white</tag>
</snippet>
<snippet id="word">
<text><![CDATA[word-spacing: ${1:10px};
$0]]></text>
<description>word-spacing: length</description>
<tag>word</tag>
</snippet>
<snippet id="word-1">
<text><![CDATA[word-spacing: normal;
$0]]></text>
<description>word-spacing: normal</description>
<tag>word</tag>
</snippet>
<snippet id="z">
<text><![CDATA[z-index: $1;
$0]]></text>
<description>z-index: index</description>
<tag>z</tag>
</snippet>
</snippets>

118
plugins/snippets/data/docbook.xml Executable file
View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets language="docbook">
<!-- useful snippets from xml set -->
<snippet id="&lt;">
<text><![CDATA[<${1}>$0</${1}>]]></text>
<description>XML tag</description>
<tag>&lt;</tag>
</snippet>
<snippet id="menuchoice">
<text><![CDATA[<menuchoice><guimenu>$1</guimenu><guimenuitem>$2</guimenuitem></menuchoice>
]]></text>
<tag>menu</tag>
<description>menuchoice</description>
<accelerator />
</snippet>
<snippet id="keycombo">
<text><![CDATA[<keycombo><keycap>${1:Ctrl}</keycap><keycap>${2}</keycap></keycombo>]]></text>
<tag>key</tag>
<description>keycombo</description>
<accelerator/>
</snippet>
<snippet id="sect">
<text><![CDATA[<sect${1} id="${2}">
<title>${3}</title>
</sect${1}>]]></text>
<tag>sect</tag>
<description>sect*</description>
<accelerator/>
</snippet>
<snippet id="app">
<text><![CDATA[<application>&app;</application>]]></text>
<tag>app</tag>
<description>app entity</description>
<accelerator/>
</snippet>
<snippet id="appwrap">
<text><![CDATA[<application>$GEDIT_SELECTED_TEXT</application>]]></text>
<tag>application</tag>
<description>application tag</description>
<accelerator/>
</snippet>
<snippet id="enclose">
<text><![CDATA[<${1}>$GEDIT_SELECTED_TEXT</${1}>]]></text>
<tag>enclose</tag>
<description>enclose selected text</description>
<accelerator/>
</snippet>
<snippet id="itemizedlist">
<text><![CDATA[<itemizedlist>
<listitem>
<para>${1}</para>
</listitem>
</itemizedlist>]]></text>
<tag>ul</tag>
<description>itemized list</description>
<accelerator/>
</snippet>
<snippet id="orderedlist">
<text><![CDATA[<orderedlist>
<listitem>
<para>${1}</para>
</listitem>
</orderedlist>]]></text>
<tag>ol</tag>
<description>ordered list</description>
<accelerator/>
</snippet>
<snippet id="listitem">
<text><![CDATA[<listitem>
<para>${1}</para>
</listitem>]]></text>
<tag>li</tag>
<description>list item</description>
<accelerator/>
</snippet>
<snippet id="variablelist">
<text><![CDATA[<variablelist>
$1
</variablelist>]]></text>
<tag>vl</tag>
<description>variablelist</description>
<accelerator/>
</snippet>
<snippet id="varlistentry">
<text><![CDATA[<varlistentry><term>${1}</term>
<listitem>
<para>${2}</para>
</listitem>
</varlistentry>]]></text>
<tag>vli</tag>
<description>variablelist entry</description>
<accelerator/>
</snippet>
<snippet id="closepara">
<text><![CDATA[</para>]]></text>
<tag>/</tag>
<description>para close</description>
<accelerator/>
</snippet>
<snippet id="openpara">
<text><![CDATA[<para>]]></text>
<tag>p</tag>
<description>para open</description>
<accelerator/>
</snippet>
<snippet id="http">
<text><![CDATA[<ulink type="http" url="$1">$2</ulink>]]></text>
<tag>http</tag>
<description>ulink http</description>
<accelerator/>
</snippet>
<snippet id="yelp">
<text><![CDATA[<ulink type="help" url="$1">$2</ulink>]]></text>
<tag>help</tag>
<description>ulink mate help</description>
<accelerator/>
</snippet>
</snippets>

164
plugins/snippets/data/fortran.xml Executable file
View File

@@ -0,0 +1,164 @@
<?xml version='1.0' encoding='utf-8'?>
<snippets language="fortran">
<snippet id="c">
<text><![CDATA[character(len=${1:10}) :: $0]]></text>
<tag>c</tag>
<description>character</description>
</snippet>
<snippet id="cl">
<text><![CDATA[close(${1:unit}, status='${2:keep}')]]></text>
<tag>cl</tag>
<description>close</description>
</snippet>
<snippet id="do">
<text><![CDATA[do ${1:i}=$2, $3, ${4:1}
${0:source}
end do]]></text>
<tag>do</tag>
<description>do ... end do</description>
</snippet>
<snippet id="func">
<text><![CDATA[function ${1:name}( ${2:parameter} )
${3:integer/real ::} $1
${4:integer/real ::} $2
${0:source}
$1 = !result
end function]]></text>
<tag>func</tag>
<description>function</description>
</snippet>
<snippet id="ifel">
<text><![CDATA[if( $1 ) then
${2:source}
else
${0:source}
end if]]></text>
<tag>ifel</tag>
<description>if ... else ... end if</description>
</snippet>
<snippet id="if">
<text><![CDATA[if( $1 ) then
${0:source}
end if]]></text>
<tag>if</tag>
<description>if ... end if</description>
</snippet>
<snippet id="i">
<text><![CDATA[integer(kind=${1:4}) :: $0]]></text>
<tag>i</tag>
<description>integer</description>
</snippet>
<snippet id="ida">
<text><![CDATA[integer(kind=${1:4}), dimension(${2::}), allocatable :: $0]]></text>
<tag>ida</tag>
<description>integerdimalloc</description>
</snippet>
<snippet id="id">
<text><![CDATA[integer(kind=${1:4}), dimension(${2::}) :: $0]]></text>
<tag>id</tag>
<description>integerdim</description>
</snippet>
<snippet id="l">
<text><![CDATA[logical(kind=${1:1}) :: $0]]></text>
<tag>l</tag>
<description>logical</description>
</snippet>
<snippet id="mod">
<text><![CDATA[module ${1:name}
implicit none
${2:integer/real ::} $3
${4:contains}
${0:source}
end module]]></text>
<tag>mod</tag>
<description>module</description>
</snippet>
<snippet id="op">
<text><![CDATA[open(${1:unit}, file='${2:name}', status='${3:new}')]]></text>
<tag>op</tag>
<description>open</description>
</snippet>
<snippet id="prog">
<text><![CDATA[program ${1:name}
implicit none
${0:source}
end program]]></text>
<tag>prog</tag>
<description>program</description>
</snippet>
<snippet id="re">
<text><![CDATA[read(unit=${1:*},fmt=${2:*}) $0]]></text>
<tag>re</tag>
<description>read</description>
</snippet>
<snippet id="r">
<text><![CDATA[real(kind=${1:8}) :: $0]]></text>
<tag>r</tag>
<description>real</description>
</snippet>
<snippet id="rda">
<text><![CDATA[real(kind=${1:8}), dimension(${2::}), allocatable :: $0]]></text>
<tag>rda</tag>
<description>realdimalloc</description>
</snippet>
<snippet id="rd">
<text><![CDATA[real(kind=${1:8}), dimension(${2::}) :: $0]]></text>
<tag>rd</tag>
<description>realdim</description>
</snippet>
<snippet id="rec">
<text><![CDATA[recursive function ${1:name}( ${2:parameter} ) result( ${3:res} )
${4:integer/real ::} $3
${5:integer/real ::} $2
${0:source}
$3 = !result
end function]]></text>
<tag>rec</tag>
<description>recursivfunc</description>
</snippet>
<snippet id="sel">
<text><![CDATA[select case( $1 )
case( $2 )
${3:source}
case default
${0:source}
end select]]></text>
<tag>sel</tag>
<description>select</description>
</snippet>
<snippet id="sub">
<text><![CDATA[subroutine ${1:name}( ${2:parameter} )
${3:integer/real ::} $2
${0:source}
end subroutine]]></text>
<tag>sub</tag>
<description>subroutine</description>
</snippet>
<snippet id="t">
<text><![CDATA[type :: ${1:name}
${2:integer/real ::} $0
end type $1]]></text>
<tag>t</tag>
<description>type</description>
</snippet>
<snippet id="dow">
<text><![CDATA[do while( ${1} )
${0:source}
end do]]></text>
<tag>dow</tag>
<description>while</description>
</snippet>
<snippet id="wr">
<text><![CDATA[write(unit=${1:*},fmt=${2:*}) "$3", $0]]></text>
<tag>wr</tag>
<description>write</description>
</snippet>
</snippets>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets/>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets language="Haskell">
<snippet id="mod">
<text><![CDATA[module ${1:Main} where
$0]]></text>
<description>module</description>
<tag>mod</tag>
</snippet>
<snippet id="\">
<text><![CDATA[\\${1:t} -> ${1:t}]]></text>
<description>\t -&gt; t</description>
<tag>\</tag>
</snippet>
</snippets>

246
plugins/snippets/data/html.xml Executable file
View File

@@ -0,0 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets language="HTML">
<snippet id="doctype">
<text><![CDATA[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
]]></text>
<description>HTML — 4.01 Strict</description>
<tag>doctype</tag>
</snippet>
<snippet id="doctype-1">
<text><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
]]></text>
<description>XHTML — 1.0 Frameset</description>
<tag>doctype</tag>
</snippet>
<snippet id="doctype-2">
<text><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
]]></text>
<description>XHTML — 1.0 Strict</description>
<tag>doctype</tag>
</snippet>
<snippet id="doctype-3">
<text><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
]]></text>
<description>XHTML — 1.0 Transitional</description>
<tag>doctype</tag>
</snippet>
<snippet id="doctype-4">
<text><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
]]></text>
<description>XHTML — 1.1</description>
<tag>doctype</tag>
</snippet>
<snippet id="doctype-5">
<text><![CDATA[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
]]></text>
<description>HTML — 4.0 Transitional</description>
<tag>doctype</tag>
</snippet>
<snippet id="author">
<text><![CDATA[<meta name="author" content="${1:author}" />
$0]]></text>
<tag>author</tag>
<description>Author</description>
</snippet>
<snippet id="date">
<text><![CDATA[<meta name="date" content="$<1: import time; return time.strftime("%Y-%m-%d") >" />
$0]]></text>
<tag>date</tag>
<description>Date</description>
</snippet>
<snippet id="ref">
<text><![CDATA[<a href="${1:http://somesite.com/}">${2:$GEDIT_SELECTED_TEXT}</a>
]]></text>
<accelerator><![CDATA[<Shift><Alt>l]]></accelerator>
<description>Wrap Selection as Link</description>
<tag>ref</tag>
</snippet>
<snippet id="open/close">
<text><![CDATA[<${1:p}>$GEDIT_SELECTED_TEXT</${1}>]]></text>
<accelerator><![CDATA[<Shift><Alt>w]]></accelerator>
<description>Wrap Selection in Open/Close Tag</description>
</snippet>
<snippet id="mailto">
<text><![CDATA[<a href="mailto:${1:joe@example.com}?subject=${2:feedback}">${3:email me}</a> $0]]></text>
<description>Mail Anchor</description>
<tag>mailto</tag>
</snippet>
<snippet id="base">
<text><![CDATA[<base href="$1" ${2}/>$0]]></text>
<description>Base</description>
<tag>base</tag>
</snippet>
<snippet id="body">
<text><![CDATA[<body id="${1:ID} " onload="$2"}>
$0
</body>]]></text>
<description>Body</description>
<tag>body</tag>
</snippet>
<snippet id="br">
<text><![CDATA[<br />
$0]]></text>
<accelerator><![CDATA[<Shift><Control>space]]></accelerator>
<description>Br</description>
</snippet>
<snippet id="button">
<text><![CDATA[<button type="button" name="${1:name}" value="${2:caption}" onclick="$3" />$4
]]></text>
<tag>button</tag>
<description>Button</description>
</snippet>
<snippet id="div">
<text><![CDATA[<div ${1}>
${0:$GEDIT_SELECTED_TEXT}
</div>]]></text>
<description>Div</description>
<tag>div</tag>
</snippet>
<snippet id="file">
<text><![CDATA[<input type="file" name="${1:name}" size="$2" accept="$3" />$0
]]></text>
<tag>file</tag>
<description>File</description>
</snippet>
<snippet id="form">
<text><![CDATA[<form action="${1}" method="${2:get}">
$0
<p><input type="submit" value="${3:Continue &rarr;}" /></p>
</form>]]></text>
<description>Form</description>
<tag>form</tag>
</snippet>
<snippet id="h">
<text><![CDATA[<h${1:1} id="${2}">${3:$GEDIT_SELECTED_TEXT}</h${1}>
$0]]></text>
<description>Heading</description>
<tag>h</tag>
</snippet>
<snippet id="head">
<text><![CDATA[<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>${1:Page Title}</title>
$0
</head>]]></text>
<description>Head</description>
<tag>head</tag>
</snippet>
<snippet id="image">
<text><![CDATA[<img src="${1:path/to/file}" alt="${2:description}" title="${3:description}" width="$4" height="$5" />$0]]></text>
<tag>img</tag>
<description>Image</description>
</snippet>
<snippet id="input">
<text><![CDATA[<input type="${1:[button,checkbox,file,hidden,image,password,radio,reset,submit,text]}" name="${2:some_name}" value="$3" id="${5}" />]]></text>
<description>Input</description>
<tag>input</tag>
</snippet>
<snippet id="li">
<text><![CDATA[<li>$1</li>$0]]></text>
<tag>li</tag>
<description>List Element</description>
</snippet>
<snippet id="link">
<text><![CDATA[<link rel="${1:stylesheet}" href="${2:/css/master.css}" type="text/css" media="${3:screen}" title="${4:no title}" charset="${5:utf-8}" />]]></text>
<description>Link</description>
<tag>link</tag>
</snippet>
<snippet id="meta">
<text><![CDATA[<meta name="${1:name}" content="${2:content}" />]]></text>
<description>Meta</description>
<tag>meta</tag>
</snippet>
<snippet id="nbsp">
<text><![CDATA[&nbsp;]]></text>
<accelerator><![CDATA[<Control><Alt>space]]></accelerator>
<description>Non-Breaking Space</description>
</snippet>
<snippet id="noscript">
<text><![CDATA[<noscript>$1</noscript>$0]]></text>
<tag>noscript</tag>
<description>Noscript</description>
</snippet>
<snippet id="option">
<text><![CDATA[<option value="${1:value}">$2</option>$0]]></text>
<tag>option</tag>
<description>Option</description>
</snippet>
<snippet id="script">
<text><![CDATA[<script type="text/javascript" language="javascript" charset="utf-8">
// <![CDATA[
$0
// ]]]]><![CDATA[>
</script>]]></text>
<description>Script</description>
<tag>script</tag>
</snippet>
<snippet id="scriptsrc">
<text><![CDATA[<script src="$1" type="text/javascript" language="${2:javascript}" charset="${3:utf-8}" />]]></text>
<description>Script With External Source</description>
<tag>scriptsrc</tag>
</snippet>
<snippet id="select">
<text><![CDATA[<select name="${1:name}">
<option value="${2:value}">$3</option>
$4
</select>$0
]]></text>
<tag>select</tag>
<description>Select</description>
</snippet>
<snippet id="span">
<text><![CDATA[<span ${1}>$2</span>$0]]></text>
<tag>span</tag>
<description>Span</description>
</snippet>
<snippet id="style">
<text><![CDATA[<style type="text/css" media="screen">
/* <![CDATA[ */
$0
/* ]]]]><![CDATA[> */
</style>
]]></text>
<description>Style</description>
<tag>style</tag>
</snippet>
<snippet id="table">
<text><![CDATA[<table border="${1:0}" cellspacing="${2:0}" cellpadding="${3:0}">
<tr><th>${4:Header}</th></tr>
<tr><td>${5:Data}</td></tr>
$0
</table>]]></text>
<description>Table</description>
<tag>table</tag>
</snippet>
<snippet id="textarea">
<text><![CDATA[<textarea name="${1:Name}" rows="${2:8}" cols="${3:40}">$0</textarea>]]></text>
<description>Text Area</description>
<tag>textarea</tag>
</snippet>
<snippet id="title">
<text><![CDATA[<title>${1:Page Title}</title>]]></text>
<description>Title</description>
<tag>title</tag>
</snippet>
<snippet id="tr">
<text><![CDATA[<tr><td>$1</td></tr>
$0]]></text>
<tag>tr</tag>
<description>Table Row</description>
</snippet>
<snippet id="ul">
<text><![CDATA[<ul>
<li>$1</li>
$2
</ul>
$0]]></text>
<tag>ul</tag>
<description>Unordered List</description>
</snippet>
</snippets>

49
plugins/snippets/data/idl.xml Executable file
View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets language="IDL">
<snippet id="mod">
<text><![CDATA[module ${1:name}
{
$0
};
]]></text>
<tag>mod</tag>
<description>Module</description>
</snippet>
<snippet id="if">
<text><![CDATA[interface ${1:name}
{
$0
};
]]></text>
<tag>if</tag>
<description>Interface</description>
</snippet>
<snippet id="str">
<text><![CDATA[struct ${1:name}
{
$0
};
]]></text>
<tag>str</tag>
<description>Struct</description>
</snippet>
<snippet id="exc">
<text><![CDATA[exception ${1:name}
{
$0
};
]]></text>
<tag>exc</tag>
<description>Exception</description>
</snippet>
<snippet id="seq">
<text><![CDATA[sequence<${1:type}> ]]></text>
<tag>seq</tag>
<description>Sequence</description>
</snippet>
<snippet id="tseq">
<text><![CDATA[typedef sequence<${1:type}> ${0:newtype};]]></text>
<tag>tseq</tag>
<description>Typedef Sequence</description>
</snippet>
</snippets>

91
plugins/snippets/data/java.xml Executable file
View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets language="Java">
<snippet id="cd">
<text><![CDATA[private static final ${1:String} ${2:var} = "$0";]]></text>
<description>const def</description>
<tag>cd</tag>
</snippet>
<snippet id="ife">
<text><![CDATA[if ($1) { // $2
$0
} else { // $3
}
]]></text>
<description>if .. else</description>
<tag>ife</tag>
</snippet>
<snippet id="if">
<text><![CDATA[if ($1) { // $2
$0
}]]></text>
<description>if</description>
<tag>if</tag>
</snippet>
<snippet id="log">
<text><![CDATA[/** Logger for this class and subclasses. */
protected final Log log = LogFactory.getLog(getClass());
]]></text>
<description>logger</description>
<tag>log</tag>
</snippet>
<snippet id="tcf">
<text><![CDATA[try {
$2
} catch (${1:Exception} e) {
$3
} finally {
$4
}
$0]]></text>
<description>try .. catch .. finally</description>
<tag>tcf</tag>
</snippet>
<snippet id="while">
<text><![CDATA[while ($1) { // $2
$0
}]]></text>
<description>while statement</description>
<tag>while</tag>
</snippet>
<snippet id="main">
<text><![CDATA[public static void main(String[] args) {
${1:System.exit(0)};
}]]></text>
<description>main</description>
<tag>main</tag>
</snippet>
<snippet id="sout">
<text><![CDATA[System.out.println("${1}");
$0
]]></text>
<description>System.out.println</description>
<tag>sout</tag>
</snippet>
<snippet id="try/catch">
<text><![CDATA[try {
$GEDIT_SELECTED_TEXT
}
catch (Exception e) {
${1:e.printStackTrace();}
}
$0]]></text>
<accelerator><![CDATA[<Shift><Alt>t]]></accelerator>
<description>Wrap Selection in Try/Catch</description>
</snippet>
<snippet id="tc">
<text><![CDATA[try {
$2
} catch (${1:Exception} e) {
$3
}
$0]]></text>
<tag>tc</tag>
<description>try .. catch</description>
</snippet>
</snippets>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<snippets language="JavaScript">
<snippet id="fun">
<text><![CDATA[function ${1:function_name} (${2:first_argument})
{
${0:# body...}
}]]></text>
<description>function</description>
<tag>fun</tag>
</snippet>
</snippets>

View File

@@ -0,0 +1,9 @@
# Python snippets plugin
lang_DATA = \
snippets.lang
langdir = $(GEDIT_PLUGINS_DATA_DIR)/snippets/lang
EXTRA_DIST = $(lang_DATA)
-include $(top_srcdir)/git.mk

Some files were not shown because too many files have changed in this diff Show More