Created
February 13, 2012 10:22
-
-
Save codebrainz/1815807 to your computer and use it in GitHub Desktop.
Plugin to highlight escape sequences in Geany
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <geanyplugin.h> | |
GeanyPlugin *geany_plugin; | |
GeanyData *geany_data; | |
GeanyFunctions *geany_functions; | |
PLUGIN_VERSION_CHECK(147) | |
PLUGIN_SET_INFO (_("Highlight Escape Sequences"), | |
_("Highlights escape sequences in the text"), | |
"1.0", | |
"Matthew Brush <mbrush@codebrainz.ca>"); | |
#define THIS_INDIC INDIC_MAX - 1 | |
static struct ExtraItem | |
{ | |
const gchar *pattern; | |
GRegex *comp; | |
guint style; | |
guint fore; | |
guint alpha; | |
guint outline_alpha; | |
gboolean under; | |
} | |
extra_items[] = | |
{ | |
{ "\\\\n", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\r", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\t", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\b", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\'", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\v", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\a", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\f", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\\\?", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\\\\\", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\[0-9]{3}", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\x[a-fA-F0-9]{2}", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE }, | |
{ "\\\\x[a-fA-F0-9]{4}", NULL, INDIC_ROUNDBOX, 0x979797, 16, 100, TRUE } | |
}; | |
static const guint num_extra_items = G_N_ELEMENTS (extra_items); | |
static void | |
compile_extra_items (void) | |
{ | |
guint i; | |
for (i = 0; i < num_extra_items; i++) | |
{ | |
if (extra_items[i].comp == NULL) | |
{ | |
GError *error = NULL; | |
extra_items[i].comp = g_regex_new (extra_items[i].pattern, | |
0 /* check me */, | |
0 /* check me */, | |
&error); | |
if (error != NULL) | |
{ | |
g_warning ("There was a problem compiling pattern %d: %s", i+1, error->message); | |
g_error_free (error); | |
} | |
} | |
} | |
} | |
static void | |
free_extra_items (void) | |
{ | |
guint i; | |
for (i = 0; i < num_extra_items; i++) | |
{ | |
if (extra_items[i].comp != NULL) | |
g_regex_unref (extra_items[i].comp); | |
} | |
} | |
static void | |
style_text (ScintillaObject *sci, | |
guint start, | |
guint end, | |
struct ExtraItem *item) | |
{ | |
/* Reset the styling of our indicator */ | |
scintilla_send_message (sci, SCI_INDICSETSTYLE, THIS_INDIC, item->style); | |
scintilla_send_message (sci, SCI_INDICSETFORE, THIS_INDIC, item->fore); | |
scintilla_send_message (sci, SCI_INDICSETALPHA, THIS_INDIC, item->alpha); | |
scintilla_send_message (sci, SCI_INDICSETOUTLINEALPHA, THIS_INDIC, item->outline_alpha); | |
scintilla_send_message (sci, SCI_INDICSETUNDER, THIS_INDIC, item->under); | |
/* Apply our indicator to the found range */ | |
scintilla_send_message (sci, SCI_SETINDICATORCURRENT, THIS_INDIC, 0); | |
scintilla_send_message (sci, SCI_INDICATORFILLRANGE, start, end-start); | |
} | |
static void | |
scan_extra_items (ScintillaObject *sci) | |
{ | |
guint i; | |
gint len; | |
gchar *buffer; | |
GMatchInfo *inf; | |
len = sci_get_length (sci); | |
buffer = sci_get_contents (sci, len + 1); | |
/* Clear out the old indicators */ | |
scintilla_send_message (sci, SCI_SETINDICATORCURRENT, THIS_INDIC, 0); | |
scintilla_send_message (sci, SCI_INDICATORCLEARRANGE, 0, len); | |
for (i = 0; i < num_extra_items; i++) | |
{ | |
g_regex_match (extra_items[i].comp, buffer, 0, &inf); | |
while (g_match_info_matches (inf)) | |
{ | |
gint start=-1, end=-1; | |
if (g_match_info_fetch_pos (inf, 0, &start, &end) && | |
(start >= 0 && end >= 0)) | |
{ | |
style_text (sci, start, end, &extra_items[i]); | |
} | |
g_match_info_next (inf, NULL); | |
} | |
g_match_info_free (inf); | |
} | |
g_free (buffer); | |
} | |
static gboolean | |
on_editor_notify (GObject *obj, | |
GeanyEditor *editor, | |
SCNotification *nt, | |
gpointer user_data) | |
{ | |
if (nt->nmhdr.code == SCN_MODIFIED && ( | |
(nt->modificationType & SC_MOD_INSERTTEXT) || | |
(nt->modificationType & SC_MOD_DELETETEXT))) | |
{ | |
scan_extra_items (editor->sci); | |
} | |
else if (nt->nmhdr.code == SCN_KEY) | |
scan_extra_items (editor->sci); | |
return FALSE; | |
} | |
static void | |
on_document_signal (GObject *obj, | |
GeanyDocument *doc, | |
gpointer user_data) | |
{ | |
if (DOC_VALID (doc)) | |
scan_extra_items (doc->editor->sci); | |
} | |
void plugin_init(GeanyData *data) | |
{ | |
gchar **ptr; | |
static gchar *doc_signals[] = { "document-new", "document-open", | |
"document-reload", "document-activate", "document-filetype-set", | |
NULL }; | |
compile_extra_items (); | |
plugin_signal_connect (geany_plugin, NULL, "editor-notify", | |
TRUE, G_CALLBACK (on_editor_notify), NULL); | |
for (ptr = doc_signals; *ptr != NULL; ptr++) | |
{ | |
plugin_signal_connect (geany_plugin, NULL, *ptr, TRUE, | |
G_CALLBACK (on_document_signal), NULL); | |
} | |
} | |
void plugin_cleanup(void) | |
{ | |
free_extra_items (); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm not sure what this does. Will it color-code log files according to color escape sequences?