summaryrefslogtreecommitdiffstats
path: root/plugins/snippets
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--plugins/snippets/data/c.xml281
-rw-r--r--plugins/snippets/data/chdr.xml258
-rw-r--r--plugins/snippets/data/cpp.xml180
-rw-r--r--plugins/snippets/data/css.xml557
-rw-r--r--plugins/snippets/data/docbook.xml2645
-rw-r--r--plugins/snippets/data/fortran.xml164
-rw-r--r--plugins/snippets/data/global.xml2
-rw-r--r--plugins/snippets/data/haskell.xml14
-rw-r--r--plugins/snippets/data/html.xml252
-rw-r--r--plugins/snippets/data/idl.xml49
-rw-r--r--plugins/snippets/data/java.xml91
-rw-r--r--plugins/snippets/data/javascript.xml10
-rw-r--r--plugins/snippets/data/lang/snippets.lang160
-rw-r--r--plugins/snippets/data/latex.xml38
-rw-r--r--plugins/snippets/data/mallard.xml316
-rw-r--r--plugins/snippets/data/markdown.xml98
-rw-r--r--plugins/snippets/data/perl.xml126
-rw-r--r--plugins/snippets/data/php.xml192
-rw-r--r--plugins/snippets/data/python.xml112
-rw-r--r--plugins/snippets/data/rpmspec.xml22
-rw-r--r--plugins/snippets/data/ruby.xml166
-rw-r--r--plugins/snippets/data/sh.xml47
-rw-r--r--plugins/snippets/data/snippets.xml98
-rw-r--r--plugins/snippets/data/tcl.xml55
-rw-r--r--plugins/snippets/data/xml.xml25
-rw-r--r--plugins/snippets/data/xslt.xml143
-rw-r--r--plugins/snippets/meson.build23
-rw-r--r--plugins/snippets/snippets.plugin.desktop.in9
-rw-r--r--plugins/snippets/snippets/__init__.py26
-rw-r--r--plugins/snippets/snippets/appactivatable.py133
-rw-r--r--plugins/snippets/snippets/completion.py187
-rw-r--r--plugins/snippets/snippets/document.py1097
-rw-r--r--plugins/snippets/snippets/exporter.py122
-rw-r--r--plugins/snippets/snippets/helper.py204
-rw-r--r--plugins/snippets/snippets/importer.py134
-rw-r--r--plugins/snippets/snippets/languagemanager.py40
-rw-r--r--plugins/snippets/snippets/library.py989
-rw-r--r--plugins/snippets/snippets/manager.py1143
-rw-r--r--plugins/snippets/snippets/meson.build39
-rw-r--r--plugins/snippets/snippets/parser.py256
-rw-r--r--plugins/snippets/snippets/placeholder.py714
-rw-r--r--plugins/snippets/snippets/shareddata.py83
-rw-r--r--plugins/snippets/snippets/signals.py90
-rw-r--r--plugins/snippets/snippets/singleton.py27
-rw-r--r--plugins/snippets/snippets/snippet.py360
-rw-r--r--plugins/snippets/snippets/snippets.ui417
-rw-r--r--plugins/snippets/snippets/substitutionparser.py203
-rw-r--r--plugins/snippets/snippets/windowactivatable.py186
48 files changed, 12583 insertions, 0 deletions
diff --git a/plugins/snippets/data/c.xml b/plugins/snippets/data/c.xml
new file mode 100644
index 0000000..f46ceed
--- /dev/null
+++ b/plugins/snippets/data/c.xml
@@ -0,0 +1,281 @@
+<?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, see <http://www.gnu.org/licenses/>.
+ */
+
+$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 ${2}. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+$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()
+>
+
+typedef struct _$<[1]: return camel_str >Private
+{
+} $<[1]: return camel_str >Private;
+
+G_DEFINE_TYPE_WITH_PRIVATE ($<[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;
+}
+
+static void
+$<[1]: return low_str >_init ($<[1]: return camel_str> *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()
+>
+G_DEFINE_INTERFACE ($<[1]: return camel_str >, $<[1]: return low_str >, ${2:G_TYPE_OBJECT})
+
+/* 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);
+}]]></text>
+ <tag>ginterface</tag>
+ <description>GObject interface</description>
+ </snippet>
+ <snippet>
+ <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()
+camel_str = ''
+
+for t in components:
+ camel_str += t.capitalize()
+>
+
+struct _$<[1]: return camel_str >
+{
+};
+
+G_DEFINE_BOXED_TYPE ($<[1]: return camel_str >, $<[1]: return low_str >, $<[1]: return low_str >_${2:copy}, $<[1]: return low_str >_${3:free})
+
+$<[1]: return camel_str > *
+$<[1]: return low_str >_${2:copy} ($<[1]: return camel_str > *${4:boxed_name})
+{
+
+}
+
+void
+$<[1]: return low_str >_${3:free} ($<[1]: return camel_str > *${4:boxed_name})
+{
+
+}]]></text>
+ <tag>gboxed</tag>
+ <description>GBoxed template</description>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/chdr.xml b/plugins/snippets/data/chdr.xml
new file mode 100644
index 0000000..2ce94d7
--- /dev/null
+++ b/plugins/snippets/data/chdr.xml
@@ -0,0 +1,258 @@
+<?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, see <http://www.gnu.org/licenses/>.
+ */
+
+$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 ${2}. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+$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
+$<
+global camel_str, module, name, type_str
+components = $1.split('_')
+module = components[0].upper()
+name = '_'.join(components[1:]).upper()
+type_str = '_'.join([components[0], 'TYPE'] + components[1:]).upper()
+camel_str = ''
+
+for t in components:
+ camel_str += t.capitalize()
+>
+#include <${2:glib-object.h}>
+
+G_BEGIN_DECLS
+
+#define $<[1]: return type_str > ($<[1]: return $1.lower() >_get_type ())
+G_DECLARE_DERIVABLE_TYPE ($<[1]: return camel_str >, $<[1]: return $1.lower() >, $<[1]: return module >, $<[1]: return name >, ${3:GObject})
+
+struct _$<[1]: return camel_str >Class
+{
+ $3Class parent_class;
+};
+
+$<[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>
+ <snippet>
+ <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)', '((' + camel_str + ' *)obj)'], \
+['#define ' + $1 + '_CONST(obj)', '((' + camel_str + ' const *)obj)'], \
+]
+
+return align(items) >
+
+$<[1]:
+items = [ \
+['typedef struct _' + camel_str, camel_str + ';'], \
+]
+
+return align(items) >
+
+GType $< return $1.lower() + '_get_type' > (void) G_GNUC_CONST;
+$<[1]: return camel_str > *$< return $1.lower()>_${3:copy} ($<[1]: return camel_str > *${4:boxed_name});
+void $< return $1.lower()>_${5:free} ($<[1]: return camel_str > *${4:boxed_name});
+
+$0
+G_END_DECLS
+
+#endif /* $1_H */]]></text>
+ <tag>gboxed</tag>
+ <description>GBoxed template</description>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/cpp.xml b/plugins/snippets/data/cpp.xml
new file mode 100644
index 0000000..1d4c31c
--- /dev/null
+++ b/plugins/snippets/data/cpp.xml
@@ -0,0 +1,180 @@
+<?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, see <http://www.gnu.org/licenses/>.
+ */
+
+ $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 ${2}. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+ $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>
diff --git a/plugins/snippets/data/css.xml b/plugins/snippets/data/css.xml
new file mode 100644
index 0000000..babca91
--- /dev/null
+++ b/plugins/snippets/data/css.xml
@@ -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>
diff --git a/plugins/snippets/data/docbook.xml b/plugins/snippets/data/docbook.xml
new file mode 100644
index 0000000..d2a07de
--- /dev/null
+++ b/plugins/snippets/data/docbook.xml
@@ -0,0 +1,2645 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ DocBook 4.5 snippets according to DocBook: The Definitive Guide (v2.0.17)
+ Copyright (C) 2012, 2013 Jaromir Hradilek
+
+ Home Page: https://github.com/jhradilek/gedit-snippets
+ Last Change: 16 February 2013
+-->
+<snippets language="docbook">
+ <!-- Core DocBook Snippets: -->
+ <snippet id="abbrev">
+ <text><![CDATA[<abbrev>${1}</abbrev>]]></text>
+ <tag>abbrev</tag>
+ <description>abbrev</description>
+ </snippet>
+ <snippet id="abstract">
+ <text><![CDATA[<abstract>
+ ${1}
+</abstract>]]></text>
+ <tag>abstract</tag>
+ <description>abstract</description>
+ </snippet>
+ <snippet id="accel">
+ <text><![CDATA[<accel>${1}</accel>]]></text>
+ <tag>accel</tag>
+ <description>accel</description>
+ </snippet>
+ <snippet id="ackno">
+ <text><![CDATA[<ackno>
+ ${1}
+</ackno>]]></text>
+ <tag>ackno</tag>
+ <description>ackno</description>
+ </snippet>
+ <snippet id="acronym">
+ <text><![CDATA[<acronym>${1}</acronym>]]></text>
+ <tag>acronym</tag>
+ <description>acronym</description>
+ </snippet>
+ <snippet id="action">
+ <text><![CDATA[<action>${1}</action>]]></text>
+ <tag>action</tag>
+ <description>action</description>
+ </snippet>
+ <snippet id="address">
+ <text><![CDATA[<address>
+ ${1}
+</address>]]></text>
+ <tag>address</tag>
+ <description>address</description>
+ </snippet>
+ <snippet id="affiliation">
+ <text><![CDATA[<affiliation>
+ ${1}
+</affiliation>]]></text>
+ <tag>affiliation</tag>
+ <description>affiliation</description>
+ </snippet>
+ <snippet id="alt">
+ <text><![CDATA[<alt>${1}</alt>]]></text>
+ <tag>alt</tag>
+ <description>alt</description>
+ </snippet>
+ <snippet id="anchor">
+ <text><![CDATA[<anchor id="${1}" />]]></text>
+ <tag>anchor</tag>
+ <description>anchor</description>
+ </snippet>
+ <snippet id="answer">
+ <text><![CDATA[<answer>
+ ${1}
+</answer>]]></text>
+ <tag>answer</tag>
+ <description>answer</description>
+ </snippet>
+ <snippet id="appendix">
+ <text><![CDATA[<appendix id="${1}">
+ ${2}
+</appendix>]]></text>
+ <tag>appendix</tag>
+ <description>appendix</description>
+ </snippet>
+ <snippet id="appendixinfo">
+ <text><![CDATA[<appendixinfo>
+ ${1}
+</appendixinfo>]]></text>
+ <tag>appendixinfo</tag>
+ <description>appendixinfo</description>
+ </snippet>
+ <snippet id="application">
+ <text><![CDATA[<application>${1}</application>]]></text>
+ <tag>application</tag>
+ <description>application</description>
+ </snippet>
+ <snippet id="area">
+ <text><![CDATA[<area id="${1}" coords="${2}" />]]></text>
+ <tag>area</tag>
+ <description>area</description>
+ </snippet>
+ <snippet id="areaset">
+ <text><![CDATA[<areaset id="${1}" coords="${2}">
+ ${3}
+</areaset>]]></text>
+ <tag>areaset</tag>
+ <description>areaset</description>
+ </snippet>
+ <snippet id="areaspec">
+ <text><![CDATA[<areaspec units="${1}">
+ ${2}
+</areaspec>]]></text>
+ <tag>areaspec</tag>
+ <description>areaspec</description>
+ </snippet>
+ <snippet id="arg">
+ <text><![CDATA[<arg>${1}</arg>]]></text>
+ <tag>arg</tag>
+ <description>arg</description>
+ </snippet>
+ <snippet id="article">
+ <text><![CDATA[<article id="${1}">
+ ${2}
+</article>]]></text>
+ <tag>article</tag>
+ <description>article</description>
+ </snippet>
+ <snippet id="articleinfo">
+ <text><![CDATA[<articleinfo>
+ ${1}
+</articleinfo>]]></text>
+ <tag>articleinfo</tag>
+ <description>articleinfo</description>
+ </snippet>
+ <snippet id="artpagenums">
+ <text><![CDATA[<artpagenums>${1}</artpagenums>]]></text>
+ <tag>artpagenums</tag>
+ <description>artpagenums</description>
+ </snippet>
+ <snippet id="attribution">
+ <text><![CDATA[<attribution>${1}</attribution>]]></text>
+ <tag>attribution</tag>
+ <description>attribution</description>
+ </snippet>
+ <snippet id="audiodata">
+ <text><![CDATA[<audiodata fileref="${1}" />]]></text>
+ <tag>audiodata</tag>
+ <description>audiodata</description>
+ </snippet>
+ <snippet id="audioobject">
+ <text><![CDATA[<audioobject>
+ ${1}
+</audioobject>]]></text>
+ <tag>audioobject</tag>
+ <description>audioobject</description>
+ </snippet>
+ <snippet id="author">
+ <text><![CDATA[<author>
+ ${1}
+</author>]]></text>
+ <tag>author</tag>
+ <description>author</description>
+ </snippet>
+ <snippet id="authorblurb">
+ <text><![CDATA[<authorblurb>
+ ${1}
+</authorblurb>]]></text>
+ <tag>authorblurb</tag>
+ <description>authorblurb</description>
+ </snippet>
+ <snippet id="authorgroup">
+ <text><![CDATA[<authorgroup>
+ ${1}
+</authorgroup>]]></text>
+ <tag>authorgroup</tag>
+ <description>authorgroup</description>
+ </snippet>
+ <snippet id="authorinitials">
+ <text><![CDATA[<authorinitials>${1}</authorinitials>]]></text>
+ <tag>authorinitials</tag>
+ <description>authorinitials</description>
+ </snippet>
+ <snippet id="beginpage">
+ <text><![CDATA[<beginpage pagenum="${1}" />]]></text>
+ <tag>beginpage</tag>
+ <description>beginpage</description>
+ </snippet>
+ <snippet id="bibliocoverage">
+ <text><![CDATA[<bibliocoverage>
+ ${1}
+</bibliocoverage>]]></text>
+ <tag>bibliocoverage</tag>
+ <description>bibliocoverage</description>
+ </snippet>
+ <snippet id="bibliodiv">
+ <text><![CDATA[<bibliodiv>
+ ${1}
+</bibliodiv>]]></text>
+ <tag>bibliodiv</tag>
+ <description>bibliodiv</description>
+ </snippet>
+ <snippet id="biblioentry">
+ <text><![CDATA[<biblioentry>
+ ${1}
+</biblioentry>]]></text>
+ <tag>biblioentry</tag>
+ <description>biblioentry</description>
+ </snippet>
+ <snippet id="bibliography">
+ <text><![CDATA[<bibliography>
+ ${1}
+</bibliography>]]></text>
+ <tag>bibliography</tag>
+ <description>bibliography</description>
+ </snippet>
+ <snippet id="bibliographyinfo">
+ <text><![CDATA[<bibliographyinfo>
+ ${1}
+</bibliographyinfo>]]></text>
+ <tag>bibliographyinfo</tag>
+ <description>bibliographyinfo</description>
+ </snippet>
+ <snippet id="biblioid">
+ <text><![CDATA[<biblioid class="${1:isbn}">${2}</biblioid>]]></text>
+ <tag>biblioid</tag>
+ <description>biblioid</description>
+ </snippet>
+ <snippet id="bibliolist">
+ <text><![CDATA[<bibliolist>
+ ${1}
+</bibliolist>]]></text>
+ <tag>bibliolist</tag>
+ <description>bibliolist</description>
+ </snippet>
+ <snippet id="bibliomisc">
+ <text><![CDATA[<bibliomisc>
+ ${1}
+</bibliomisc>]]></text>
+ <tag>bibliomisc</tag>
+ <description>bibliomisc</description>
+ </snippet>
+ <snippet id="bibliomixed">
+ <text><![CDATA[<bibliomixed>
+ ${1}
+</bibliomixed>]]></text>
+ <tag>bibliomixed</tag>
+ <description>bibliomixed</description>
+ </snippet>
+ <snippet id="bibliomset">
+ <text><![CDATA[<bibliomset relation="${1}">
+ ${2}
+</bibliomset>]]></text>
+ <tag>bibliomset</tag>
+ <description>bibliomset</description>
+ </snippet>
+ <snippet id="biblioref">
+ <text><![CDATA[<biblioref linkend="${1}" />]]></text>
+ <tag>biblioref</tag>
+ <description>biblioref</description>
+ </snippet>
+ <snippet id="bibliorelation">
+ <text><![CDATA[<bibliorelation type="${1}" class="${2}">${3}</bibliorelation>]]></text>
+ <tag>bibliorelation</tag>
+ <description>bibliorelation</description>
+ </snippet>
+ <snippet id="biblioset">
+ <text><![CDATA[<biblioset relation="${1}">
+ ${2}
+</biblioset>]]></text>
+ <tag>biblioset</tag>
+ <description>biblioset</description>
+ </snippet>
+ <snippet id="bibliosource">
+ <text><![CDATA[<bibliosource class="${1:isbn}">${2}</bibliosource>]]></text>
+ <tag>bibliosource</tag>
+ <description>bibliosource</description>
+ </snippet>
+ <snippet id="blockinfo">
+ <text><![CDATA[<blockinfo>
+ ${1}
+</blockinfo>]]></text>
+ <tag>blockinfo</tag>
+ <description>blockinfo</description>
+ </snippet>
+ <snippet id="blockquote">
+ <text><![CDATA[<blockquote>
+ ${1}
+</blockquote>]]></text>
+ <tag>blockquote</tag>
+ <description>blockquote</description>
+ </snippet>
+ <snippet id="book">
+ <text><![CDATA[<book id="${1}">
+ ${2}
+</book>]]></text>
+ <tag>book</tag>
+ <description>book</description>
+ </snippet>
+ <snippet id="bookinfo">
+ <text><![CDATA[<bookinfo>
+ ${1}
+</bookinfo>]]></text>
+ <tag>bookinfo</tag>
+ <description>bookinfo</description>
+ </snippet>
+ <snippet id="bridgehead">
+ <text><![CDATA[<bridgehead id="${1}">${2}</bridgehead>]]></text>
+ <tag>bridgehead</tag>
+ <description>bridgehead</description>
+ </snippet>
+ <snippet id="callout">
+ <text><![CDATA[<callout arearefs="${1}">
+ ${2}
+</callout>]]></text>
+ <tag>callout</tag>
+ <description>callout</description>
+ </snippet>
+ <snippet id="calloutlist">
+ <text><![CDATA[<calloutlist>
+ ${1}
+</calloutlist>]]></text>
+ <tag>calloutlist</tag>
+ <description>calloutlist</description>
+ </snippet>
+ <snippet id="caption">
+ <text><![CDATA[<caption>
+ ${1}
+</caption>]]></text>
+ <tag>caption</tag>
+ <description>caption</description>
+ </snippet>
+ <snippet id="caution">
+ <text><![CDATA[<caution>
+ ${1}
+</caution>]]></text>
+ <tag>caution</tag>
+ <description>caution</description>
+ </snippet>
+ <snippet id="chapter">
+ <text><![CDATA[<chapter id="${1}">
+ ${2}
+</chapter>]]></text>
+ <tag>chapter</tag>
+ <description>chapter</description>
+ </snippet>
+ <snippet id="chapterinfo">
+ <text><![CDATA[<chapterinfo>
+ ${1}
+</chapterinfo>]]></text>
+ <tag>chapterinfo</tag>
+ <description>chapterinfo</description>
+ </snippet>
+ <snippet id="citation">
+ <text><![CDATA[<citation>${1}</citation>]]></text>
+ <tag>citation</tag>
+ <description>citation</description>
+ </snippet>
+ <snippet id="citebiblioid">
+ <text><![CDATA[<citebiblioid class="${1:isbn}">${2}</citebiblioid>]]></text>
+ <tag>citebiblioid</tag>
+ <description>citebiblioid</description>
+ </snippet>
+ <snippet id="citerefentry">
+ <text><![CDATA[<citerefentry>${1}</citerefentry>]]></text>
+ <tag>citerefentry</tag>
+ <description>citerefentry</description>
+ </snippet>
+ <snippet id="citetitle">
+ <text><![CDATA[<citetitle pubwork="${1:book}">${2}</citetitle>]]></text>
+ <tag>citetitle</tag>
+ <description>citetitle</description>
+ </snippet>
+ <snippet id="city">
+ <text><![CDATA[<city>${1}</city>]]></text>
+ <tag>city</tag>
+ <description>city</description>
+ </snippet>
+ <snippet id="classname">
+ <text><![CDATA[<classname>${1}</classname>]]></text>
+ <tag>classname</tag>
+ <description>classname</description>
+ </snippet>
+ <snippet id="classsynopsis">
+ <text><![CDATA[<classsynopsis class="${1}" language="${2}">
+ ${3}
+</classsynopsis>]]></text>
+ <tag>classsynopsis</tag>
+ <description>classsynopsis</description>
+ </snippet>
+ <snippet id="classsynopsisinfo">
+ <text><![CDATA[<classsynopsisinfo>
+ ${1}
+</classsynopsisinfo>]]></text>
+ <tag>classsynopsisinfo</tag>
+ <description>classsynopsisinfo</description>
+ </snippet>
+ <snippet id="cmdsynopsis">
+ <text><![CDATA[<cmdsynopsis>
+ ${1}
+</cmdsynopsis>]]></text>
+ <tag>cmdsynopsis</tag>
+ <description>cmdsynopsis</description>
+ </snippet>
+ <snippet id="co">
+ <text><![CDATA[<co label="${1}" linkends="${2}" />]]></text>
+ <tag>co</tag>
+ <description>co</description>
+ </snippet>
+ <snippet id="code">
+ <text><![CDATA[<code language="${1}">${2}</code>]]></text>
+ <tag>code</tag>
+ <description>code</description>
+ </snippet>
+ <snippet id="col">
+ <text><![CDATA[<col>
+ ${1}
+</col>]]></text>
+ <tag>col</tag>
+ <description>col</description>
+ </snippet>
+ <snippet id="colgroup">
+ <text><![CDATA[<colgroup>
+ ${1}
+</colgroup>]]></text>
+ <tag>colgroup</tag>
+ <description>colgroup</description>
+ </snippet>
+ <snippet id="collab">
+ <text><![CDATA[<collab>
+ ${1}
+</collab>]]></text>
+ <tag>collab</tag>
+ <description>collab</description>
+ </snippet>
+ <snippet id="collabname">
+ <text><![CDATA[<collabname>${1}</collabname>]]></text>
+ <tag>collabname</tag>
+ <description>collabname</description>
+ </snippet>
+ <snippet id="colophon">
+ <text><![CDATA[<colophon>
+ ${1}
+</colophon>]]></text>
+ <tag>colophon</tag>
+ <description>colophon</description>
+ </snippet>
+ <snippet id="colspec">
+ <text><![CDATA[<colspec colname="${1}" colnum="${2}" colwidth="${3}" />]]></text>
+ <tag>colspec</tag>
+ <description>colspec</description>
+ </snippet>
+ <snippet id="command">
+ <text><![CDATA[<command>${1}</command>]]></text>
+ <tag>command</tag>
+ <description>command</description>
+ </snippet>
+ <snippet id="computeroutput">
+ <text><![CDATA[<computeroutput>${1}</computeroutput>]]></text>
+ <tag>computeroutput</tag>
+ <description>computeroutput</description>
+ </snippet>
+ <snippet id="confdates">
+ <text><![CDATA[<confdates>${1}</confdates>]]></text>
+ <tag>confdates</tag>
+ <description>confdates</description>
+ </snippet>
+ <snippet id="confgroup">
+ <text><![CDATA[<confgroup>
+ ${1}
+</confgroup>]]></text>
+ <tag>confgroup</tag>
+ <description>confgroup</description>
+ </snippet>
+ <snippet id="confnum">
+ <text><![CDATA[<confnum>${1}</confnum>]]></text>
+ <tag>confnum</tag>
+ <description>confnum</description>
+ </snippet>
+ <snippet id="confsponsor">
+ <text><![CDATA[<confsponsor>${1}</confsponsor>]]></text>
+ <tag>confsponsor</tag>
+ <description>confsponsor</description>
+ </snippet>
+ <snippet id="conftitle">
+ <text><![CDATA[<conftitle>${1}</conftitle>]]></text>
+ <tag>conftitle</tag>
+ <description>conftitle</description>
+ </snippet>
+ <snippet id="constant">
+ <text><![CDATA[<constant>${1}</constant>]]></text>
+ <tag>constant</tag>
+ <description>constant</description>
+ </snippet>
+ <snippet id="constructorsynopsis">
+ <text><![CDATA[<constructorsynopsis language="${1}">
+ ${2}
+</constructorsynopsis>]]></text>
+ <tag>constructorsynopsis</tag>
+ <description>constructorsynopsis</description>
+ </snippet>
+ <snippet id="contractnum">
+ <text><![CDATA[<contractnum>${1}</contractnum>]]></text>
+ <tag>contractnum</tag>
+ <description>contractnum</description>
+ </snippet>
+ <snippet id="contractsponsor">
+ <text><![CDATA[<contractsponsor>${1}</contractsponsor>]]></text>
+ <tag>contractsponsor</tag>
+ <description>contractsponsor</description>
+ </snippet>
+ <snippet id="contrib">
+ <text><![CDATA[<contrib>${1}</contrib>]]></text>
+ <tag>contrib</tag>
+ <description>contrib</description>
+ </snippet>
+ <snippet id="copyright">
+ <text><![CDATA[<copyright>
+ ${1}
+</copyright>]]></text>
+ <tag>copyright</tag>
+ <description>copyright</description>
+ </snippet>
+ <snippet id="coref">
+ <text><![CDATA[<coref label="${1}" linkend="${1}" />]]></text>
+ <tag>coref</tag>
+ <description>coref</description>
+ </snippet>
+ <snippet id="corpauthor">
+ <text><![CDATA[<corpauthor>${1}</corpauthor>]]></text>
+ <tag>corpauthor</tag>
+ <description>corpauthor</description>
+ </snippet>
+ <snippet id="corpcredit">
+ <text><![CDATA[<corpcredit>${1}</corpcredit>]]></text>
+ <tag>corpcredit</tag>
+ <description>corpcredit</description>
+ </snippet>
+ <snippet id="corpname">
+ <text><![CDATA[<corpname>${1}</corpname>]]></text>
+ <tag>corpname</tag>
+ <description>corpname</description>
+ </snippet>
+ <snippet id="country">
+ <text><![CDATA[<country>${1}</country>]]></text>
+ <tag>country</tag>
+ <description>country</description>
+ </snippet>
+ <snippet id="database">
+ <text><![CDATA[<database class="${1}">${2}</database>]]></text>
+ <tag>database</tag>
+ <description>database</description>
+ </snippet>
+ <snippet id="date">
+ <text><![CDATA[<date>${1}</date>]]></text>
+ <tag>date</tag>
+ <description>date</description>
+ </snippet>
+ <snippet id="dedication">
+ <text><![CDATA[<dedication>
+ ${1}
+</dedication>]]></text>
+ <tag>dedication</tag>
+ <description>dedication</description>
+ </snippet>
+ <snippet id="destructorsynopsis">
+ <text><![CDATA[<destructorsynopsis language="${1}">
+ ${2}
+</destructorsynopsis>]]></text>
+ <tag>destructorsynopsis</tag>
+ <description>destructorsynopsis</description>
+ </snippet>
+ <snippet id="edition">
+ <text><![CDATA[<edition>${1}</edition>]]></text>
+ <tag>edition</tag>
+ <description>edition</description>
+ </snippet>
+ <snippet id="editor">
+ <text><![CDATA[<editor>
+ ${1}
+</editor>]]></text>
+ <tag>editor</tag>
+ <description>editor</description>
+ </snippet>
+ <snippet id="email">
+ <text><![CDATA[<email>${1}</email>]]></text>
+ <tag>email</tag>
+ <description>email</description>
+ </snippet>
+ <snippet id="emphasis">
+ <text><![CDATA[<emphasis>${1}</emphasis>]]></text>
+ <tag>emphasis</tag>
+ <description>emphasis</description>
+ </snippet>
+ <snippet id="entry">
+ <text><![CDATA[<entry>${1}</entry>]]></text>
+ <tag>entry</tag>
+ <description>entry</description>
+ </snippet>
+ <snippet id="entrytbl">
+ <text><![CDATA[<entrytbl cols="${1}">
+ ${2}
+</entrytbl>]]></text>
+ <tag>entrytbl</tag>
+ <description>entrytbl</description>
+ </snippet>
+ <snippet id="envar">
+ <text><![CDATA[<envar>${1}</envar>]]></text>
+ <tag>envar</tag>
+ <description>envar</description>
+ </snippet>
+ <snippet id="epigraph">
+ <text><![CDATA[<epigraph>
+ ${1}
+</epigraph>]]></text>
+ <tag>epigraph</tag>
+ <description>epigraph</description>
+ </snippet>
+ <snippet id="equation">
+ <text><![CDATA[<equation>
+ ${1}
+</equation>]]></text>
+ <tag>equation</tag>
+ <description>equation</description>
+ </snippet>
+ <snippet id="errorcode">
+ <text><![CDATA[<errorcode>${1}</errorcode>]]></text>
+ <tag>errorcode</tag>
+ <description>errorcode</description>
+ </snippet>
+ <snippet id="errorname">
+ <text><![CDATA[<errorname>${1}</errorname>]]></text>
+ <tag>errorname</tag>
+ <description>errorname</description>
+ </snippet>
+ <snippet id="errortext">
+ <text><![CDATA[<errortext>${1}</errortext>]]></text>
+ <tag>errortext</tag>
+ <description>errortext</description>
+ </snippet>
+ <snippet id="errortype">
+ <text><![CDATA[<errortype>${1}</errortype>]]></text>
+ <tag>errortype</tag>
+ <description>errortype</description>
+ </snippet>
+ <snippet id="example">
+ <text><![CDATA[<example id="${1}">
+ ${2}
+</example>]]></text>
+ <tag>example</tag>
+ <description>example</description>
+ </snippet>
+ <snippet id="exceptionname">
+ <text><![CDATA[<exceptionname>${1}</exceptionname>]]></text>
+ <tag>exceptionname</tag>
+ <description>exceptionname</description>
+ </snippet>
+ <snippet id="fax">
+ <text><![CDATA[<fax>${1}</fax>]]></text>
+ <tag>fax</tag>
+ <description>fax</description>
+ </snippet>
+ <snippet id="fieldsynopsis">
+ <text><![CDATA[<fieldsynopsis language="${1}">
+ ${2}
+</fieldsynopsis>]]></text>
+ <tag>fieldsynopsis</tag>
+ <description>fieldsynopsis</description>
+ </snippet>
+ <snippet id="figure">
+ <text><![CDATA[<figure id="${1}">
+ ${2}
+</figure>]]></text>
+ <tag>figure</tag>
+ <description>figure</description>
+ </snippet>
+ <snippet id="filename">
+ <text><![CDATA[<filename>${1}</filename>]]></text>
+ <tag>filename</tag>
+ <description>filename</description>
+ </snippet>
+ <snippet id="firstname">
+ <text><![CDATA[<firstname>${1}</firstname>]]></text>
+ <tag>firstname</tag>
+ <description>firstname</description>
+ </snippet>
+ <snippet id="firstterm">
+ <text><![CDATA[<firstterm>${1}</firstterm>]]></text>
+ <tag>firstterm</tag>
+ <description>firstterm</description>
+ </snippet>
+ <snippet id="footnote">
+ <text><![CDATA[<footnote>
+ ${1}
+</footnote>]]></text>
+ <tag>footnote</tag>
+ <description>footnote</description>
+ </snippet>
+ <snippet id="footnoteref">
+ <text><![CDATA[<footnoteref linkend="${1}" />]]></text>
+ <tag>footnoteref</tag>
+ <description>footnoteref</description>
+ </snippet>
+ <snippet id="foreignphrase">
+ <text><![CDATA[<foreignphrase>${1}</foreignphrase>]]></text>
+ <tag>foreignphrase</tag>
+ <description>foreignphrase</description>
+ </snippet>
+ <snippet id="formalpara">
+ <text><![CDATA[<formalpara>
+ ${1}
+</formalpara>]]></text>
+ <tag>formalpara</tag>
+ <description>formalpara</description>
+ </snippet>
+ <snippet id="funcdef">
+ <text><![CDATA[<funcdef>${1}</funcdef>]]></text>
+ <tag>funcdef</tag>
+ <description>funcdef</description>
+ </snippet>
+ <snippet id="funcparams">
+ <text><![CDATA[<funcparams>${1}</funcparams>]]></text>
+ <tag>funcparams</tag>
+ <description>funcparams</description>
+ </snippet>
+ <snippet id="funcprototype">
+ <text><![CDATA[<funcprototype>
+ ${1}
+</funcprototype>]]></text>
+ <tag>funcprototype</tag>
+ <description>funcprototype</description>
+ </snippet>
+ <snippet id="funcsynopsis">
+ <text><![CDATA[<funcsynopsis>
+ ${1}
+</funcsynopsis>]]></text>
+ <tag>funcsynopsis</tag>
+ <description>funcsynopsis</description>
+ </snippet>
+ <snippet id="funcsynopsisinfo">
+ <text><![CDATA[<funcsynopsisinfo>
+ ${1}
+</funcsynopsisinfo>]]></text>
+ <tag>funcsynopsisinfo</tag>
+ <description>funcsynopsisinfo</description>
+ </snippet>
+ <snippet id="function">
+ <text><![CDATA[<function>${1}</function>]]></text>
+ <tag>function</tag>
+ <description>function</description>
+ </snippet>
+ <snippet id="glossary">
+ <text><![CDATA[<glossary id="${1}">
+ ${2}
+</glossary>]]></text>
+ <tag>glossary</tag>
+ <description>glossary</description>
+ </snippet>
+ <snippet id="glossaryinfo">
+ <text><![CDATA[<glossaryinfo>
+ ${1}
+</glossaryinfo>]]></text>
+ <tag>glossaryinfo</tag>
+ <description>glossaryinfo</description>
+ </snippet>
+ <snippet id="glossdef">
+ <text><![CDATA[<glossdef>
+ ${1}
+</glossdef>]]></text>
+ <tag>glossdef</tag>
+ <description>glossdef</description>
+ </snippet>
+ <snippet id="glossdiv">
+ <text><![CDATA[<glossdiv>
+ ${1}
+</glossdiv>]]></text>
+ <tag>glossdiv</tag>
+ <description>glossdiv</description>
+ </snippet>
+ <snippet id="glossentry">
+ <text><![CDATA[<glossentry>
+ ${1}
+</glossentry>]]></text>
+ <tag>glossentry</tag>
+ <description>glossentry</description>
+ </snippet>
+ <snippet id="glosslist">
+ <text><![CDATA[<glosslist>
+ ${1}
+</glosslist>]]></text>
+ <tag>glosslist</tag>
+ <description>glosslist</description>
+ </snippet>
+ <snippet id="glosssee">
+ <text><![CDATA[<glosssee otherterm="${1}">${2}</glosssee>]]></text>
+ <tag>glosssee</tag>
+ <description>glosssee</description>
+ </snippet>
+ <snippet id="glossseealso">
+ <text><![CDATA[<glossseealso otherterm="${1}">${2}</glossseealso>]]></text>
+ <tag>glossseealso</tag>
+ <description>glossseealso</description>
+ </snippet>
+ <snippet id="glossterm">
+ <text><![CDATA[<glossterm>${1}</glossterm>]]></text>
+ <tag>glossterm</tag>
+ <description>glossterm</description>
+ </snippet>
+ <snippet id="graphic">
+ <text><![CDATA[<graphic fileref="${1}" />]]></text>
+ <tag>graphic</tag>
+ <description>graphic</description>
+ </snippet>
+ <snippet id="graphicco">
+ <text><![CDATA[<graphicco>
+ ${1}
+</graphicco>]]></text>
+ <tag>graphicco</tag>
+ <description>graphicco</description>
+ </snippet>
+ <snippet id="group">
+ <text><![CDATA[<group>
+ ${1}
+</group>]]></text>
+ <tag>group</tag>
+ <description>group</description>
+ </snippet>
+ <snippet id="guibutton">
+ <text><![CDATA[<guibutton>${1}</guibutton>]]></text>
+ <tag>guibutton</tag>
+ <description>guibutton</description>
+ </snippet>
+ <snippet id="guiicon">
+ <text><![CDATA[<guiicon>${1}</guiicon>]]></text>
+ <tag>guiicon</tag>
+ <description>guiicon</description>
+ </snippet>
+ <snippet id="guilabel">
+ <text><![CDATA[<guilabel>${1}</guilabel>]]></text>
+ <tag>guilabel</tag>
+ <description>guilabel</description>
+ </snippet>
+ <snippet id="guimenu">
+ <text><![CDATA[<guimenu>${1}</guimenu>]]></text>
+ <tag>guimenu</tag>
+ <description>guimenu</description>
+ </snippet>
+ <snippet id="guimenuitem">
+ <text><![CDATA[<guimenuitem>${1}</guimenuitem>]]></text>
+ <tag>guimenuitem</tag>
+ <description>guimenuitem</description>
+ </snippet>
+ <snippet id="guisubmenu">
+ <text><![CDATA[<guisubmenu>${1}</guisubmenu>]]></text>
+ <tag>guisubmenu</tag>
+ <description>guisubmenu</description>
+ </snippet>
+ <snippet id="hardware">
+ <text><![CDATA[<hardware>${1}</hardware>]]></text>
+ <tag>hardware</tag>
+ <description>hardware</description>
+ </snippet>
+ <snippet id="highlights">
+ <text><![CDATA[<highlights>
+ ${1}
+</highlights>]]></text>
+ <tag>highlights</tag>
+ <description>highlights</description>
+ </snippet>
+ <snippet id="holder">
+ <text><![CDATA[<holder>${1}</holder>]]></text>
+ <tag>holder</tag>
+ <description>holder</description>
+ </snippet>
+ <snippet id="honorific">
+ <text><![CDATA[<honorific>${1}</honorific>]]></text>
+ <tag>honorific</tag>
+ <description>honorific</description>
+ </snippet>
+ <snippet id="imagedata">
+ <text><![CDATA[<imagedata fileref="${1}" format="${2:PNG}" scalefit="${3:0}" />]]></text>
+ <tag>imagedata</tag>
+ <description>imagedata</description>
+ </snippet>
+ <snippet id="imageobject">
+ <text><![CDATA[<imageobject>
+ ${1}
+</imageobject>]]></text>
+ <tag>imageobject</tag>
+ <description>imageobject</description>
+ </snippet>
+ <snippet id="imageobjectco">
+ <text><![CDATA[<imageobjectco>
+ ${1}
+</imageobjectco>]]></text>
+ <tag>imageobjectco</tag>
+ <description>imageobjectco</description>
+ </snippet>
+ <snippet id="important">
+ <text><![CDATA[<important>
+ ${1}
+</important>]]></text>
+ <tag>important</tag>
+ <description>important</description>
+ </snippet>
+ <snippet id="index">
+ <text><![CDATA[<index>
+ ${1}
+</index>]]></text>
+ <tag>index</tag>
+ <description>index</description>
+ </snippet>
+ <snippet id="indexdiv">
+ <text><![CDATA[<indexdiv>
+ ${1}
+</indexdiv>]]></text>
+ <tag>indexdiv</tag>
+ <description>indexdiv</description>
+ </snippet>
+ <snippet id="indexentry">
+ <text><![CDATA[<indexentry>
+ ${1}
+</indexentry>]]></text>
+ <tag>indexentry</tag>
+ <description>indexentry</description>
+ </snippet>
+ <snippet id="indexinfo">
+ <text><![CDATA[<indexinfo>
+ ${1}
+</indexinfo>]]></text>
+ <tag>indexinfo</tag>
+ <description>indexinfo</description>
+ </snippet>
+ <snippet id="indexterm">
+ <text><![CDATA[<indexterm>
+ ${1}
+</indexterm>]]></text>
+ <tag>indexterm</tag>
+ <description>indexterm</description>
+ </snippet>
+ <snippet id="informalequation">
+ <text><![CDATA[<informalequation>
+ ${1}
+</informalequation>]]></text>
+ <tag>informalequation</tag>
+ <description>informalequation</description>
+ </snippet>
+ <snippet id="informalexample">
+ <text><![CDATA[<informalexample>
+ ${1}
+</informalexample>]]></text>
+ <tag>informalexample</tag>
+ <description>informalexample</description>
+ </snippet>
+ <snippet id="informalfigure">
+ <text><![CDATA[<informalfigure>
+ ${1}
+</informalfigure>]]></text>
+ <tag>informalfigure</tag>
+ <description>informalfigure</description>
+ </snippet>
+ <snippet id="informaltable">
+ <text><![CDATA[<informaltable>
+ ${1}
+</informaltable>]]></text>
+ <tag>informaltable</tag>
+ <description>informaltable</description>
+ </snippet>
+ <snippet id="initializer">
+ <text><![CDATA[<initializer>${1}</initializer>]]></text>
+ <tag>initializer</tag>
+ <description>initializer</description>
+ </snippet>
+ <snippet id="inlineequation">
+ <text><![CDATA[<inlineequation>
+ ${1}
+</inlineequation>]]></text>
+ <tag>inlineequation</tag>
+ <description>inlineequation</description>
+ </snippet>
+ <snippet id="inlinegraphic">
+ <text><![CDATA[<inlinegraphic fileref="${1}" format="${2:PNG}" scalefit="${3:0}" />]]></text>
+ <tag>inlinegraphic</tag>
+ <description>inlinegraphic</description>
+ </snippet>
+ <snippet id="inlinemediaobject">
+ <text><![CDATA[<inlinemediaobject>
+ ${1}
+</inlinemediaobject>]]></text>
+ <tag>inlinemediaobject</tag>
+ <description>inlinemediaobject</description>
+ </snippet>
+ <snippet id="interface">
+ <text><![CDATA[<interface>${1}</interface>]]></text>
+ <tag>interface</tag>
+ <description>interface</description>
+ </snippet>
+ <snippet id="interfacename">
+ <text><![CDATA[<interfacename>${1}</interfacename>]]></text>
+ <tag>interfacename</tag>
+ <description>interfacename</description>
+ </snippet>
+ <snippet id="invpartnumber">
+ <text><![CDATA[<invpartnumber>${1}</invpartnumber>]]></text>
+ <tag>invpartnumber</tag>
+ <description>invpartnumber</description>
+ </snippet>
+ <snippet id="isbn">
+ <text><![CDATA[<isbn>${1}</isbn>]]></text>
+ <tag>isbn</tag>
+ <description>isbn</description>
+ </snippet>
+ <snippet id="issn">
+ <text><![CDATA[<issn>${1}</issn>]]></text>
+ <tag>issn</tag>
+ <description>issn</description>
+ </snippet>
+ <snippet id="issuenum">
+ <text><![CDATA[<issuenum>${1}</issuenum>]]></text>
+ <tag>issuenum</tag>
+ <description>issuenum</description>
+ </snippet>
+ <snippet id="itemizedlist">
+ <text><![CDATA[<itemizedlist>
+ ${1}
+</itemizedlist>]]></text>
+ <tag>itemizedlist</tag>
+ <description>itemizedlist</description>
+ </snippet>
+ <snippet id="itermset">
+ <text><![CDATA[<itermset>
+ ${1}
+</itermset>]]></text>
+ <tag>itermset</tag>
+ <description>itermset</description>
+ </snippet>
+ <snippet id="jobtitle">
+ <text><![CDATA[<jobtitle>${1}</jobtitle>]]></text>
+ <tag>jobtitle</tag>
+ <description>jobtitle</description>
+ </snippet>
+ <snippet id="keycap">
+ <text><![CDATA[<keycap>${1}</keycap>]]></text>
+ <tag>keycap</tag>
+ <description>keycap</description>
+ </snippet>
+ <snippet id="keycode">
+ <text><![CDATA[<keycode>${1}</keycode>]]></text>
+ <tag>keycode</tag>
+ <description>keycode</description>
+ </snippet>
+ <snippet id="keycombo">
+ <text><![CDATA[<keycombo>${1}</keycombo>]]></text>
+ <tag>keycombo</tag>
+ <description>keycombo</description>
+ </snippet>
+ <snippet id="keysym">
+ <text><![CDATA[<keysym>${1}</keysym>]]></text>
+ <tag>keysym</tag>
+ <description>keysym</description>
+ </snippet>
+ <snippet id="keyword">
+ <text><![CDATA[<keyword>${1}</keyword>]]></text>
+ <tag>keyword</tag>
+ <description>keyword</description>
+ </snippet>
+ <snippet id="keywordset">
+ <text><![CDATA[<keywordset>
+ ${1}
+</keywordset>]]></text>
+ <tag>keywordset</tag>
+ <description>keywordset</description>
+ </snippet>
+ <snippet id="label">
+ <text><![CDATA[<label>${1}</label>]]></text>
+ <tag>label</tag>
+ <description>label</description>
+ </snippet>
+ <snippet id="legalnotice">
+ <text><![CDATA[<legalnotice>
+ ${1}
+</legalnotice>]]></text>
+ <tag>legalnotice</tag>
+ <description>legalnotice</description>
+ </snippet>
+ <snippet id="lineage">
+ <text><![CDATA[<lineage>${1}</lineage>]]></text>
+ <tag>lineage</tag>
+ <description>lineage</description>
+ </snippet>
+ <snippet id="lineannotation">
+ <text><![CDATA[<lineannotation>${1}</lineannotation>]]></text>
+ <tag>lineannotation</tag>
+ <description>lineannotation</description>
+ </snippet>
+ <snippet id="link">
+ <text><![CDATA[<link linkend="${1}">${2}</link>]]></text>
+ <tag>link</tag>
+ <description>link</description>
+ </snippet>
+ <snippet id="listitem">
+ <text><![CDATA[<listitem>
+ ${1}
+</listitem>]]></text>
+ <tag>listitem</tag>
+ <description>listitem</description>
+ </snippet>
+ <snippet id="literal">
+ <text><![CDATA[<literal>${1}</literal>]]></text>
+ <tag>literal</tag>
+ <description>literal</description>
+ </snippet>
+ <snippet id="literallayout">
+ <text><![CDATA[<literallayout>${1}</literallayout>]]></text>
+ <tag>literallayout</tag>
+ <description>literallayout</description>
+ </snippet>
+ <snippet id="lot">
+ <text><![CDATA[<lot>
+ ${1}
+</lot>]]></text>
+ <tag>lot</tag>
+ <description>lot</description>
+ </snippet>
+ <snippet id="lotentry">
+ <text><![CDATA[<lotentry linkend="${1}">
+ ${2}
+</lotentry>]]></text>
+ <tag>lotentry</tag>
+ <description>lotentry</description>
+ </snippet>
+ <snippet id="manvolnum">
+ <text><![CDATA[<manvolnum>${1}</manvolnum>]]></text>
+ <tag>manvolnum</tag>
+ <description>manvolnum</description>
+ </snippet>
+ <snippet id="markup">
+ <text><![CDATA[<markup>${1}</markup>]]></text>
+ <tag>markup</tag>
+ <description>markup</description>
+ </snippet>
+ <snippet id="mathphrase">
+ <text><![CDATA[<mathphrase>${1}</mathphrase>]]></text>
+ <tag>mathphrase</tag>
+ <description>mathphrase</description>
+ </snippet>
+ <snippet id="medialabel">
+ <text><![CDATA[<medialabel>${1}</medialabel>]]></text>
+ <tag>medialabel</tag>
+ <description>medialabel</description>
+ </snippet>
+ <snippet id="mediaobject">
+ <text><![CDATA[<mediaobject>
+ ${1}
+</mediaobject>]]></text>
+ <tag>mediaobject</tag>
+ <description>mediaobject</description>
+ </snippet>
+ <snippet id="mediaobjectco">
+ <text><![CDATA[<mediaobjectco>
+ ${1}
+</mediaobjectco>]]></text>
+ <tag>mediaobjectco</tag>
+ <description>mediaobjectco</description>
+ </snippet>
+ <snippet id="member">
+ <text><![CDATA[<member>
+ ${1}
+</member>]]></text>
+ <tag>member</tag>
+ <description>member</description>
+ </snippet>
+ <snippet id="menuchoice">
+ <text><![CDATA[<menuchoice>${1}</menuchoice>]]></text>
+ <tag>menuchoice</tag>
+ <description>menuchoice</description>
+ </snippet>
+ <snippet id="methodname">
+ <text><![CDATA[<methodname>${1}</methodname>]]></text>
+ <tag>methodname</tag>
+ <description>methodname</description>
+ </snippet>
+ <snippet id="methodparam">
+ <text><![CDATA[<methodparam>${1}</methodparam>]]></text>
+ <tag>methodparam</tag>
+ <description>methodparam</description>
+ </snippet>
+ <snippet id="methodsynopsis">
+ <text><![CDATA[<methodsynopsis language="${1}">
+ ${2}
+</methodsynopsis>]]></text>
+ <tag>methodsynopsis</tag>
+ <description>methodsynopsis</description>
+ </snippet>
+ <snippet id="modespec">
+ <text><![CDATA[<modespec application="${1}">${2}</modespec>]]></text>
+ <tag>modespec</tag>
+ <description>modespec</description>
+ </snippet>
+ <snippet id="modifier">
+ <text><![CDATA[<modifier>${1}</modifier>]]></text>
+ <tag>modifier</tag>
+ <description>modifier</description>
+ </snippet>
+ <snippet id="mousebutton">
+ <text><![CDATA[<mousebutton>${1}</mousebutton>]]></text>
+ <tag>mousebutton</tag>
+ <description>mousebutton</description>
+ </snippet>
+ <snippet id="msg">
+ <text><![CDATA[<msg>
+ ${1}
+</msg>]]></text>
+ <tag>msg</tag>
+ <description>msg</description>
+ </snippet>
+ <snippet id="msgaud">
+ <text><![CDATA[<msgaud>${1}</msgaud>]]></text>
+ <tag>msgaud</tag>
+ <description>msgaud</description>
+ </snippet>
+ <snippet id="msgentry">
+ <text><![CDATA[<msgentry>
+ ${1}
+</msgentry>]]></text>
+ <tag>msgentry</tag>
+ <description>msgentry</description>
+ </snippet>
+ <snippet id="msgexplan">
+ <text><![CDATA[<msgexplan>
+ ${1}
+</msgexplan>]]></text>
+ <tag>msgexplan</tag>
+ <description>msgexplan</description>
+ </snippet>
+ <snippet id="msginfo">
+ <text><![CDATA[<msginfo>
+ ${1}
+</msginfo>]]></text>
+ <tag>msginfo</tag>
+ <description>msginfo</description>
+ </snippet>
+ <snippet id="msglevel">
+ <text><![CDATA[<msglevel>${1}</msglevel>]]></text>
+ <tag>msglevel</tag>
+ <description>msglevel</description>
+ </snippet>
+ <snippet id="msgmain">
+ <text><![CDATA[<msgmain>
+ ${1}
+</msgmain>]]></text>
+ <tag>msgmain</tag>
+ <description>msgmain</description>
+ </snippet>
+ <snippet id="msgorig">
+ <text><![CDATA[<msgorig>${1}</msgorig>]]></text>
+ <tag>msgorig</tag>
+ <description>msgorig</description>
+ </snippet>
+ <snippet id="msgrel">
+ <text><![CDATA[<msgrel>
+ ${1}
+</msgrel>]]></text>
+ <tag>msgrel</tag>
+ <description>msgrel</description>
+ </snippet>
+ <snippet id="msgset">
+ <text><![CDATA[<msgset>
+ ${1}
+</msgset>]]></text>
+ <tag>msgset</tag>
+ <description>msgset</description>
+ </snippet>
+ <snippet id="msgsub">
+ <text><![CDATA[<msgsub>
+ ${1}
+</msgsub>]]></text>
+ <tag>msgsub</tag>
+ <description>msgsub</description>
+ </snippet>
+ <snippet id="msgtext">
+ <text><![CDATA[<msgtext>
+ ${1}
+</msgtext>]]></text>
+ <tag>msgtext</tag>
+ <description>msgtext</description>
+ </snippet>
+ <snippet id="note">
+ <text><![CDATA[<note>
+ ${1}
+</note>]]></text>
+ <tag>note</tag>
+ <description>note</description>
+ </snippet>
+ <snippet id="objectinfo">
+ <text><![CDATA[<objectinfo>
+ ${1}
+</objectinfo>]]></text>
+ <tag>objectinfo</tag>
+ <description>objectinfo</description>
+ </snippet>
+ <snippet id="olink">
+ <text><![CDATA[<olink targetdocent="${1}">${2}</olink>]]></text>
+ <tag>olink</tag>
+ <description>olink</description>
+ </snippet>
+ <snippet id="ooclass">
+ <text><![CDATA[<ooclass>${1}</ooclass>]]></text>
+ <tag>ooclass</tag>
+ <description>ooclass</description>
+ </snippet>
+ <snippet id="ooexception">
+ <text><![CDATA[<ooexception>${1}</ooexception>]]></text>
+ <tag>ooexception</tag>
+ <description>ooexception</description>
+ </snippet>
+ <snippet id="oointerface">
+ <text><![CDATA[<oointerface>${1}</oointerface>]]></text>
+ <tag>oointerface</tag>
+ <description>oointerface</description>
+ </snippet>
+ <snippet id="option">
+ <text><![CDATA[<option>${1}</option>]]></text>
+ <tag>option</tag>
+ <description>option</description>
+ </snippet>
+ <snippet id="optional">
+ <text><![CDATA[<optional>${1}</optional>]]></text>
+ <tag>optional</tag>
+ <description>optional</description>
+ </snippet>
+ <snippet id="orderedlist">
+ <text><![CDATA[<orderedlist>
+ ${1}
+</orderedlist>]]></text>
+ <tag>orderedlist</tag>
+ <description>orderedlist</description>
+ </snippet>
+ <snippet id="orgdiv">
+ <text><![CDATA[<orgdiv>${1}</orgdiv>]]></text>
+ <tag>orgdiv</tag>
+ <description>orgdiv</description>
+ </snippet>
+ <snippet id="orgname">
+ <text><![CDATA[<orgname>${1}</orgname>]]></text>
+ <tag>orgname</tag>
+ <description>orgname</description>
+ </snippet>
+ <snippet id="otheraddr">
+ <text><![CDATA[<otheraddr>${1}</otheraddr>]]></text>
+ <tag>otheraddr</tag>
+ <description>otheraddr</description>
+ </snippet>
+ <snippet id="othercredit">
+ <text><![CDATA[<othercredit>
+ ${1}
+</othercredit>]]></text>
+ <tag>othercredit</tag>
+ <description>othercredit</description>
+ </snippet>
+ <snippet id="othername">
+ <text><![CDATA[<othername>${1}</othername>]]></text>
+ <tag>othername</tag>
+ <description>othername</description>
+ </snippet>
+ <snippet id="package">
+ <text><![CDATA[<package>${1}</package>]]></text>
+ <tag>package</tag>
+ <description>package</description>
+ </snippet>
+ <snippet id="pagenums">
+ <text><![CDATA[<pagenums>${1}</pagenums>]]></text>
+ <tag>pagenums</tag>
+ <description>pagenums</description>
+ </snippet>
+ <snippet id="para">
+ <text><![CDATA[<para>
+ ${1}
+</para>]]></text>
+ <tag>para</tag>
+ <description>para</description>
+ </snippet>
+ <snippet id="paramdef">
+ <text><![CDATA[<paramdef>${1}</paramdef>]]></text>
+ <tag>paramdef</tag>
+ <description>paramdef</description>
+ </snippet>
+ <snippet id="parameter">
+ <text><![CDATA[<parameter class="${1:function}">${2}</parameter>]]></text>
+ <tag>parameter</tag>
+ <description>parameter</description>
+ </snippet>
+ <snippet id="part">
+ <text><![CDATA[<part id="${1}">
+ ${2}
+</part>]]></text>
+ <tag>part</tag>
+ <description>part</description>
+ </snippet>
+ <snippet id="partinfo">
+ <text><![CDATA[<partinfo>
+ ${1}
+</partinfo>]]></text>
+ <tag>partinfo</tag>
+ <description>partinfo</description>
+ </snippet>
+ <snippet id="partintro">
+ <text><![CDATA[<partintro>
+ ${1}
+</partintro>]]></text>
+ <tag>partintro</tag>
+ <description>partintro</description>
+ </snippet>
+ <snippet id="personblurb">
+ <text><![CDATA[<personblurb>
+ ${1}
+</personblurb>]]></text>
+ <tag>personblurb</tag>
+ <description>personblurb</description>
+ </snippet>
+ <snippet id="personname">
+ <text><![CDATA[<personname>${1}</personname>]]></text>
+ <tag>personname</tag>
+ <description>personname</description>
+ </snippet>
+ <snippet id="phone">
+ <text><![CDATA[<phone>${1}</phone>]]></text>
+ <tag>phone</tag>
+ <description>phone</description>
+ </snippet>
+ <snippet id="phrase">
+ <text><![CDATA[<phrase>${1}</phrase>]]></text>
+ <tag>phrase</tag>
+ <description>phrase</description>
+ </snippet>
+ <snippet id="pob">
+ <text><![CDATA[<pob>${1}</pob>]]></text>
+ <tag>pob</tag>
+ <description>pob</description>
+ </snippet>
+ <snippet id="postcode">
+ <text><![CDATA[<postcode>${1}</postcode>]]></text>
+ <tag>postcode</tag>
+ <description>postcode</description>
+ </snippet>
+ <snippet id="preface">
+ <text><![CDATA[<preface id="${1}">
+ ${2}
+</preface>]]></text>
+ <tag>preface</tag>
+ <description>preface</description>
+ </snippet>
+ <snippet id="prefaceinfo">
+ <text><![CDATA[<prefaceinfo>
+ ${1}
+</prefaceinfo>]]></text>
+ <tag>prefaceinfo</tag>
+ <description>prefaceinfo</description>
+ </snippet>
+ <snippet id="primary">
+ <text><![CDATA[<primary>${1}</primary>]]></text>
+ <tag>primary</tag>
+ <description>primary</description>
+ </snippet>
+ <snippet id="primaryie">
+ <text><![CDATA[<primaryie>${1}</primaryie>]]></text>
+ <tag>primaryie</tag>
+ <description>primaryie</description>
+ </snippet>
+ <snippet id="printhistory">
+ <text><![CDATA[<printhistory>
+ ${1}
+</printhistory>]]></text>
+ <tag>printhistory</tag>
+ <description>printhistory</description>
+ </snippet>
+ <snippet id="procedure">
+ <text><![CDATA[<procedure>
+ ${1}
+</procedure>]]></text>
+ <tag>procedure</tag>
+ <description>procedure</description>
+ </snippet>
+ <snippet id="productname">
+ <text><![CDATA[<productname class="${1:trade}">${2}</productname>]]></text>
+ <tag>productname</tag>
+ <description>productname</description>
+ </snippet>
+ <snippet id="productnumber">
+ <text><![CDATA[<productnumber>${1}</productnumber>]]></text>
+ <tag>productnumber</tag>
+ <description>productnumber</description>
+ </snippet>
+ <snippet id="programlisting">
+ <text><![CDATA[<programlisting language="${1}">${2}</programlisting>]]></text>
+ <tag>programlisting</tag>
+ <description>programlisting</description>
+ </snippet>
+ <snippet id="programlistingco">
+ <text><![CDATA[<programlistingco>
+ ${1}
+</programlistingco>]]></text>
+ <tag>programlistingco</tag>
+ <description>programlistingco</description>
+ </snippet>
+ <snippet id="prompt">
+ <text><![CDATA[<prompt>${1}</prompt>]]></text>
+ <tag>prompt</tag>
+ <description>prompt</description>
+ </snippet>
+ <snippet id="property">
+ <text><![CDATA[<property>${1}</property>]]></text>
+ <tag>property</tag>
+ <description>property</description>
+ </snippet>
+ <snippet id="pubdate">
+ <text><![CDATA[<pubdate>${1}</pubdate>]]></text>
+ <tag>pubdate</tag>
+ <description>pubdate</description>
+ </snippet>
+ <snippet id="publisher">
+ <text><![CDATA[<publisher>
+ ${1}
+</publisher>]]></text>
+ <tag>publisher</tag>
+ <description>publisher</description>
+ </snippet>
+ <snippet id="publishername">
+ <text><![CDATA[<publishername>${1}</publishername>]]></text>
+ <tag>publishername</tag>
+ <description>publishername</description>
+ </snippet>
+ <snippet id="pubsnumber">
+ <text><![CDATA[<pubsnumber>${1}</pubsnumber>]]></text>
+ <tag>pubsnumber</tag>
+ <description>pubsnumber</description>
+ </snippet>
+ <snippet id="qandadiv">
+ <text><![CDATA[<qandadiv>
+ ${1}
+</qandadiv>]]></text>
+ <tag>qandadiv</tag>
+ <description>qandadiv</description>
+ </snippet>
+ <snippet id="qandaentry">
+ <text><![CDATA[<qandaentry>
+ ${1}
+</qandaentry>]]></text>
+ <tag>qandaentry</tag>
+ <description>qandaentry</description>
+ </snippet>
+ <snippet id="qandaset">
+ <text><![CDATA[<qandaset>
+ ${1}
+</qandaset>]]></text>
+ <tag>qandaset</tag>
+ <description>qandaset</description>
+ </snippet>
+ <snippet id="question">
+ <text><![CDATA[<question>
+ ${1}
+</question>]]></text>
+ <tag>question</tag>
+ <description>question</description>
+ </snippet>
+ <snippet id="quote">
+ <text><![CDATA[<quote>${1}</quote>]]></text>
+ <tag>quote</tag>
+ <description>quote</description>
+ </snippet>
+ <snippet id="refclass">
+ <text><![CDATA[<refclass>${1}</refclass>]]></text>
+ <tag>refclass</tag>
+ <description>refclass</description>
+ </snippet>
+ <snippet id="refdescriptor">
+ <text><![CDATA[<refdescriptor>${1}</refdescriptor>]]></text>
+ <tag>refdescriptor</tag>
+ <description>refdescriptor</description>
+ </snippet>
+ <snippet id="refentry">
+ <text><![CDATA[<refentry>
+ ${1}
+</refentry>]]></text>
+ <tag>refentry</tag>
+ <description>refentry</description>
+ </snippet>
+ <snippet id="refentryinfo">
+ <text><![CDATA[<refentryinfo>
+ ${1}
+</refentryinfo>]]></text>
+ <tag>refentryinfo</tag>
+ <description>refentryinfo</description>
+ </snippet>
+ <snippet id="refentrytitle">
+ <text><![CDATA[<refentrytitle>${1}</refentrytitle>]]></text>
+ <tag>refentrytitle</tag>
+ <description>refentrytitle</description>
+ </snippet>
+ <snippet id="reference">
+ <text><![CDATA[<reference>
+ ${1}
+</reference>]]></text>
+ <tag>reference</tag>
+ <description>reference</description>
+ </snippet>
+ <snippet id="referenceinfo">
+ <text><![CDATA[<referenceinfo>
+ ${1}
+</referenceinfo>]]></text>
+ <tag>referenceinfo</tag>
+ <description>referenceinfo</description>
+ </snippet>
+ <snippet id="refmeta">
+ <text><![CDATA[<refmeta>
+ ${1}
+</refmeta>]]></text>
+ <tag>refmeta</tag>
+ <description>refmeta</description>
+ </snippet>
+ <snippet id="refmiscinfo">
+ <text><![CDATA[<refmiscinfo>
+ ${1}
+</refmiscinfo>]]></text>
+ <tag>refmiscinfo</tag>
+ <description>refmiscinfo</description>
+ </snippet>
+ <snippet id="refname">
+ <text><![CDATA[<refname>${1}</refname>]]></text>
+ <tag>refname</tag>
+ <description>refname</description>
+ </snippet>
+ <snippet id="refnamediv">
+ <text><![CDATA[<refnamediv>
+ ${1}
+</refnamediv>]]></text>
+ <tag>refnamediv</tag>
+ <description>refnamediv</description>
+ </snippet>
+ <snippet id="refpurpose">
+ <text><![CDATA[<refpurpose>${1}</refpurpose>]]></text>
+ <tag>refpurpose</tag>
+ <description>refpurpose</description>
+ </snippet>
+ <snippet id="refsect1">
+ <text><![CDATA[<refsect1>
+ ${1}
+</refsect1>]]></text>
+ <tag>refsect1</tag>
+ <description>refsect1</description>
+ </snippet>
+ <snippet id="refsect1info">
+ <text><![CDATA[<refsect1info>
+ ${1}
+</refsect1info>]]></text>
+ <tag>refsect1info</tag>
+ <description>refsect1info</description>
+ </snippet>
+ <snippet id="refsect2">
+ <text><![CDATA[<refsect2>
+ ${1}
+</refsect2>]]></text>
+ <tag>refsect2</tag>
+ <description>refsect2</description>
+ </snippet>
+ <snippet id="refsect2info">
+ <text><![CDATA[<refsect2info>
+ ${1}
+</refsect2info>]]></text>
+ <tag>refsect2info</tag>
+ <description>refsect2info</description>
+ </snippet>
+ <snippet id="refsect3">
+ <text><![CDATA[<refsect3>
+ ${1}
+</refsect3>]]></text>
+ <tag>refsect3</tag>
+ <description>refsect3</description>
+ </snippet>
+ <snippet id="refsect3info">
+ <text><![CDATA[<refsect3info>
+ ${1}
+</refsect3info>]]></text>
+ <tag>refsect3info</tag>
+ <description>refsect3info</description>
+ </snippet>
+ <snippet id="refsection">
+ <text><![CDATA[<refsection>
+ ${1}
+</refsection>]]></text>
+ <tag>refsection</tag>
+ <description>refsection</description>
+ </snippet>
+ <snippet id="refsectioninfo">
+ <text><![CDATA[<refsectioninfo>
+ ${1}
+</refsectioninfo>]]></text>
+ <tag>refsectioninfo</tag>
+ <description>refsectioninfo</description>
+ </snippet>
+ <snippet id="refsynopsisdiv">
+ <text><![CDATA[<refsynopsisdiv>
+ ${1}
+</refsynopsisdiv>]]></text>
+ <tag>refsynopsisdiv</tag>
+ <description>refsynopsisdiv</description>
+ </snippet>
+ <snippet id="refsynopsisdivinfo">
+ <text><![CDATA[<refsynopsisdivinfo>
+ ${1}
+</refsynopsisdivinfo>]]></text>
+ <tag>refsynopsisdivinfo</tag>
+ <description>refsynopsisdivinfo</description>
+ </snippet>
+ <snippet id="releaseinfo">
+ <text><![CDATA[<releaseinfo>${1}</releaseinfo>]]></text>
+ <tag>releaseinfo</tag>
+ <description>releaseinfo</description>
+ </snippet>
+ <snippet id="remark">
+ <text><![CDATA[<remark>${1}</remark>]]></text>
+ <tag>remark</tag>
+ <description>remark</description>
+ </snippet>
+ <snippet id="replaceable">
+ <text><![CDATA[<replaceable>${1}</replaceable>]]></text>
+ <tag>replaceable</tag>
+ <description>replaceable</description>
+ </snippet>
+ <snippet id="returnvalue">
+ <text><![CDATA[<returnvalue>${1}</returnvalue>]]></text>
+ <tag>returnvalue</tag>
+ <description>returnvalue</description>
+ </snippet>
+ <snippet id="revdescription">
+ <text><![CDATA[<revdescription>
+ ${1}
+</revdescription>]]></text>
+ <tag>revdescription</tag>
+ <description>revdescription</description>
+ </snippet>
+ <snippet id="revhistory">
+ <text><![CDATA[<revhistory>
+ ${1}
+</revhistory>]]></text>
+ <tag>revhistory</tag>
+ <description>revhistory</description>
+ </snippet>
+ <snippet id="revision">
+ <text><![CDATA[<revision>
+ ${1}
+</revision>]]></text>
+ <tag>revision</tag>
+ <description>revision</description>
+ </snippet>
+ <snippet id="revnumber">
+ <text><![CDATA[<revnumber>${1}</revnumber>]]></text>
+ <tag>revnumber</tag>
+ <description>revnumber</description>
+ </snippet>
+ <snippet id="revremark">
+ <text><![CDATA[<revremark>${1}</revremark>]]></text>
+ <tag>revremark</tag>
+ <description>revremark</description>
+ </snippet>
+ <snippet id="row">
+ <text><![CDATA[<row>
+ ${1}
+</row>]]></text>
+ <tag>row</tag>
+ <description>row</description>
+ </snippet>
+ <snippet id="sbr">
+ <text><![CDATA[<sbr />]]></text>
+ <tag>sbr</tag>
+ <description>sbr</description>
+ </snippet>
+ <snippet id="screen">
+ <text><![CDATA[<screen>${1}</screen>]]></text>
+ <tag>screen</tag>
+ <description>screen</description>
+ </snippet>
+ <snippet id="screenco">
+ <text><![CDATA[<screenco>
+ ${1}
+</screenco>]]></text>
+ <tag>screenco</tag>
+ <description>screenco</description>
+ </snippet>
+ <snippet id="screeninfo">
+ <text><![CDATA[<screeninfo>${1}</screeninfo>]]></text>
+ <tag>screeninfo</tag>
+ <description>screeninfo</description>
+ </snippet>
+ <snippet id="screenshot">
+ <text><![CDATA[<screenshot>
+ ${1}
+</screenshot>]]></text>
+ <tag>screenshot</tag>
+ <description>screenshot</description>
+ </snippet>
+ <snippet id="secondary">
+ <text><![CDATA[<secondary>${1}</secondary>]]></text>
+ <tag>secondary</tag>
+ <description>secondary</description>
+ </snippet>
+ <snippet id="secondaryie">
+ <text><![CDATA[<secondaryie>${1}</secondaryie>]]></text>
+ <tag>secondaryie</tag>
+ <description>secondaryie</description>
+ </snippet>
+ <snippet id="sect1">
+ <text><![CDATA[<sect1 id="${1}">
+ ${2}
+</sect1>]]></text>
+ <tag>sect1</tag>
+ <description>sect1</description>
+ </snippet>
+ <snippet id="sect1info">
+ <text><![CDATA[<sect1info>
+ ${1}
+</sect1info>]]></text>
+ <tag>sect1info</tag>
+ <description>sect1info</description>
+ </snippet>
+ <snippet id="sect2">
+ <text><![CDATA[<sect2 id="${1}">
+ ${2}
+</sect2>]]></text>
+ <tag>sect2</tag>
+ <description>sect2</description>
+ </snippet>
+ <snippet id="sect2info">
+ <text><![CDATA[<sect2info>
+ ${1}
+</sect2info>]]></text>
+ <tag>sect2info</tag>
+ <description>sect2info</description>
+ </snippet>
+ <snippet id="sect3">
+ <text><![CDATA[<sect3 id="${1}">
+ ${2}
+</sect3>]]></text>
+ <tag>sect3</tag>
+ <description>sect3</description>
+ </snippet>
+ <snippet id="sect3info">
+ <text><![CDATA[<sect3info>
+ ${1}
+</sect3info>]]></text>
+ <tag>sect3info</tag>
+ <description>sect3info</description>
+ </snippet>
+ <snippet id="sect4">
+ <text><![CDATA[<sect4 id="${1}">
+ ${2}
+</sect4>]]></text>
+ <tag>sect4</tag>
+ <description>sect4</description>
+ </snippet>
+ <snippet id="sect4info">
+ <text><![CDATA[<sect4info>
+ ${1}
+</sect4info>]]></text>
+ <tag>sect4info</tag>
+ <description>sect4info</description>
+ </snippet>
+ <snippet id="sect5">
+ <text><![CDATA[<sect5 id="${1}">
+ ${2}
+</sect5>]]></text>
+ <tag>sect5</tag>
+ <description>sect5</description>
+ </snippet>
+ <snippet id="sect5info">
+ <text><![CDATA[<sect5info>
+ ${1}
+</sect5info>]]></text>
+ <tag>sect5info</tag>
+ <description>sect5info</description>
+ </snippet>
+ <snippet id="section">
+ <text><![CDATA[<section id="${1}">
+ ${2}
+</section>]]></text>
+ <tag>section</tag>
+ <description>section</description>
+ </snippet>
+ <snippet id="sectioninfo">
+ <text><![CDATA[<sectioninfo>
+ ${1}
+</sectioninfo>]]></text>
+ <tag>sectioninfo</tag>
+ <description>sectioninfo</description>
+ </snippet>
+ <snippet id="see">
+ <text><![CDATA[<see>${1}</see>]]></text>
+ <tag>see</tag>
+ <description>see</description>
+ </snippet>
+ <snippet id="seealso">
+ <text><![CDATA[<seealso>${1}</seealso>]]></text>
+ <tag>seealso</tag>
+ <description>seealso</description>
+ </snippet>
+ <snippet id="seealsoie">
+ <text><![CDATA[<seealsoie>${1}</seealsoie>]]></text>
+ <tag>seealsoie</tag>
+ <description>seealsoie</description>
+ </snippet>
+ <snippet id="seeie">
+ <text><![CDATA[<seeie>${1}</seeie>]]></text>
+ <tag>seeie</tag>
+ <description>seeie</description>
+ </snippet>
+ <snippet id="seg">
+ <text><![CDATA[<seg>${1}</seg>]]></text>
+ <tag>seg</tag>
+ <description>seg</description>
+ </snippet>
+ <snippet id="seglistitem">
+ <text><![CDATA[<seglistitem>
+ ${1}
+</seglistitem>]]></text>
+ <tag>seglistitem</tag>
+ <description>seglistitem</description>
+ </snippet>
+ <snippet id="segmentedlist">
+ <text><![CDATA[<segmentedlist>
+ ${1}
+</segmentedlist>]]></text>
+ <tag>segmentedlist</tag>
+ <description>segmentedlist</description>
+ </snippet>
+ <snippet id="segtitle">
+ <text><![CDATA[<segtitle>${1}</segtitle>]]></text>
+ <tag>segtitle</tag>
+ <description>segtitle</description>
+ </snippet>
+ <snippet id="seriesvolnums">
+ <text><![CDATA[<seriesvolnums>${1}</seriesvolnums>]]></text>
+ <tag>seriesvolnums</tag>
+ <description>seriesvolnums</description>
+ </snippet>
+ <snippet id="set">
+ <text><![CDATA[<set>
+ ${1}
+</set>]]></text>
+ <tag>set</tag>
+ <description>set</description>
+ </snippet>
+ <snippet id="setindex">
+ <text><![CDATA[<setindex>
+ ${1}
+</setindex>]]></text>
+ <tag>setindex</tag>
+ <description>setindex</description>
+ </snippet>
+ <snippet id="setindexinfo">
+ <text><![CDATA[<setindexinfo>
+ ${1}
+</setindexinfo>]]></text>
+ <tag>setindexinfo</tag>
+ <description>setindexinfo</description>
+ </snippet>
+ <snippet id="setinfo">
+ <text><![CDATA[<setinfo>
+ ${1}
+</setinfo>]]></text>
+ <tag>setinfo</tag>
+ <description>setinfo</description>
+ </snippet>
+ <snippet id="sgmltag">
+ <text><![CDATA[<sgmltag>${1}</sgmltag>]]></text>
+ <tag>sgmltag</tag>
+ <description>sgmltag</description>
+ </snippet>
+ <snippet id="shortaffil">
+ <text><![CDATA[<shortaffil>${1}</shortaffil>]]></text>
+ <tag>shortaffil</tag>
+ <description>shortaffil</description>
+ </snippet>
+ <snippet id="shortcut">
+ <text><![CDATA[<shortcut>${1}</shortcut>]]></text>
+ <tag>shortcut</tag>
+ <description>shortcut</description>
+ </snippet>
+ <snippet id="sidebar">
+ <text><![CDATA[<sidebar>
+ ${1}
+</sidebar>]]></text>
+ <tag>sidebar</tag>
+ <description>sidebar</description>
+ </snippet>
+ <snippet id="sidebarinfo">
+ <text><![CDATA[<sidebarinfo>
+ ${1}
+</sidebarinfo>]]></text>
+ <tag>sidebarinfo</tag>
+ <description>sidebarinfo</description>
+ </snippet>
+ <snippet id="simpara">
+ <text><![CDATA[<simpara>
+ ${1}
+</simpara>]]></text>
+ <tag>simpara</tag>
+ <description>simpara</description>
+ </snippet>
+ <snippet id="simplelist">
+ <text><![CDATA[<simplelist>
+ ${1}
+</simplelist>]]></text>
+ <tag>simplelist</tag>
+ <description>simplelist</description>
+ </snippet>
+ <snippet id="simplemsgentry">
+ <text><![CDATA[<simplemsgentry>
+ ${1}
+</simplemsgentry>]]></text>
+ <tag>simplemsgentry</tag>
+ <description>simplemsgentry</description>
+ </snippet>
+ <snippet id="simplesect">
+ <text><![CDATA[<simplesect id="${1}">
+ ${2}
+</simplesect>]]></text>
+ <tag>simplesect</tag>
+ <description>simplesect</description>
+ </snippet>
+ <snippet id="spanspec">
+ <text><![CDATA[<spanspec spanname="${1}" namest="${2}" nameend="${3}" />]]></text>
+ <tag>spanspec</tag>
+ <description>spanspec</description>
+ </snippet>
+ <snippet id="state">
+ <text><![CDATA[<state>${1}</state>]]></text>
+ <tag>state</tag>
+ <description>state</description>
+ </snippet>
+ <snippet id="step">
+ <text><![CDATA[<step>
+ ${1}
+</step>]]></text>
+ <tag>step</tag>
+ <description>step</description>
+ </snippet>
+ <snippet id="stepalternatives">
+ <text><![CDATA[<stepalternatives>
+ ${1}
+</stepalternatives>]]></text>
+ <tag>stepalternatives</tag>
+ <description>stepalternatives</description>
+ </snippet>
+ <snippet id="street">
+ <text><![CDATA[<street>${1}</street>]]></text>
+ <tag>street</tag>
+ <description>street</description>
+ </snippet>
+ <snippet id="structfield">
+ <text><![CDATA[<structfield>${1}</structfield>]]></text>
+ <tag>structfield</tag>
+ <description>structfield</description>
+ </snippet>
+ <snippet id="structname">
+ <text><![CDATA[<structname>${1}</structname>]]></text>
+ <tag>structname</tag>
+ <description>structname</description>
+ </snippet>
+ <snippet id="subject">
+ <text><![CDATA[<subject>
+ ${1}
+</subject>]]></text>
+ <tag>subject</tag>
+ <description>subject</description>
+ </snippet>
+ <snippet id="subjectset">
+ <text><![CDATA[<subjectset>
+ ${1}
+</subjectset>]]></text>
+ <tag>subjectset</tag>
+ <description>subjectset</description>
+ </snippet>
+ <snippet id="subjectterm">
+ <text><![CDATA[<subjectterm>${1}</subjectterm>]]></text>
+ <tag>subjectterm</tag>
+ <description>subjectterm</description>
+ </snippet>
+ <snippet id="subscript">
+ <text><![CDATA[<subscript>${1}</subscript>]]></text>
+ <tag>subscript</tag>
+ <description>subscript</description>
+ </snippet>
+ <snippet id="substeps">
+ <text><![CDATA[<substeps>
+ ${1}
+</substeps>]]></text>
+ <tag>substeps</tag>
+ <description>substeps</description>
+ </snippet>
+ <snippet id="subtitle">
+ <text><![CDATA[<subtitle>${1}</subtitle>]]></text>
+ <tag>subtitle</tag>
+ <description>subtitle</description>
+ </snippet>
+ <snippet id="superscript">
+ <text><![CDATA[<superscript>${1}</superscript>]]></text>
+ <tag>superscript</tag>
+ <description>superscript</description>
+ </snippet>
+ <snippet id="surname">
+ <text><![CDATA[<surname>${1}</surname>]]></text>
+ <tag>surname</tag>
+ <description>surname</description>
+ </snippet>
+ <snippet id="symbol">
+ <text><![CDATA[<symbol>${1}</symbol>]]></text>
+ <tag>symbol</tag>
+ <description>symbol</description>
+ </snippet>
+ <snippet id="synopfragment">
+ <text><![CDATA[<synopfragment id="${1}">
+ ${2}
+</synopfragment>]]></text>
+ <tag>synopfragment</tag>
+ <description>synopfragment</description>
+ </snippet>
+ <snippet id="synopfragmentref">
+ <text><![CDATA[<synopfragmentref linkend="${1}">
+ ${2}
+</synopfragmentref>]]></text>
+ <tag>synopfragmentref</tag>
+ <description>synopfragmentref</description>
+ </snippet>
+ <snippet id="synopsis">
+ <text><![CDATA[<synopsis>${1}</synopsis>]]></text>
+ <tag>synopsis</tag>
+ <description>synopsis</description>
+ </snippet>
+ <snippet id="systemitem">
+ <text><![CDATA[<systemitem>${1}</systemitem>]]></text>
+ <tag>systemitem</tag>
+ <description>systemitem</description>
+ </snippet>
+ <snippet id="table">
+ <text><![CDATA[<table id="${1}">
+ ${2}
+</table>]]></text>
+ <tag>table</tag>
+ <description>table</description>
+ </snippet>
+ <snippet id="task">
+ <text><![CDATA[<task>
+ ${1}
+</task>]]></text>
+ <tag>task</tag>
+ <description>task</description>
+ </snippet>
+ <snippet id="taskprerequisites">
+ <text><![CDATA[<taskprerequisites>
+ ${1}
+</taskprerequisites>]]></text>
+ <tag>taskprerequisites</tag>
+ <description>taskprerequisites</description>
+ </snippet>
+ <snippet id="taskrelated">
+ <text><![CDATA[<taskrelated>
+ ${1}
+</taskrelated>]]></text>
+ <tag>taskrelated</tag>
+ <description>taskrelated</description>
+ </snippet>
+ <snippet id="tasksummary">
+ <text><![CDATA[<tasksummary>
+ ${1}
+</tasksummary>]]></text>
+ <tag>tasksummary</tag>
+ <description>tasksummary</description>
+ </snippet>
+ <snippet id="tbody">
+ <text><![CDATA[<tbody>
+ ${1}
+</tbody>]]></text>
+ <tag>tbody</tag>
+ <description>tbody</description>
+ </snippet>
+ <snippet id="td">
+ <text><![CDATA[<td>
+ ${1}
+</td>]]></text>
+ <tag>td</tag>
+ <description>td</description>
+ </snippet>
+ <snippet id="term">
+ <text><![CDATA[<term>${1}</term>]]></text>
+ <tag>term</tag>
+ <description>term</description>
+ </snippet>
+ <snippet id="termdef">
+ <text><![CDATA[<termdef>${1}</termdef>]]></text>
+ <tag>termdef</tag>
+ <description>termdef</description>
+ </snippet>
+ <snippet id="tertiary">
+ <text><![CDATA[<tertiary>${1}</tertiary>]]></text>
+ <tag>tertiary</tag>
+ <description>tertiary</description>
+ </snippet>
+ <snippet id="tertiaryie">
+ <text><![CDATA[<tertiaryie>${1}</tertiaryie>]]></text>
+ <tag>tertiaryie</tag>
+ <description>tertiaryie</description>
+ </snippet>
+ <snippet id="textdata">
+ <text><![CDATA[<textdata fileref="${1}" />]]></text>
+ <tag>textdata</tag>
+ <description>textdata</description>
+ </snippet>
+ <snippet id="textobject">
+ <text><![CDATA[<textobject>
+ ${1}
+</textobject>]]></text>
+ <tag>textobject</tag>
+ <description>textobject</description>
+ </snippet>
+ <snippet id="tfoot">
+ <text><![CDATA[<tfoot>
+ ${1}
+</tfoot>]]></text>
+ <tag>tfoot</tag>
+ <description>tfoot</description>
+ </snippet>
+ <snippet id="tgroup">
+ <text><![CDATA[<tgroup cols="${1}">
+ ${2}
+</tgroup>]]></text>
+ <tag>tgroup</tag>
+ <description>tgroup</description>
+ </snippet>
+ <snippet id="th">
+ <text><![CDATA[<th>
+ ${1}
+</th>]]></text>
+ <tag>th</tag>
+ <description>th</description>
+ </snippet>
+ <snippet id="thead">
+ <text><![CDATA[<thead>
+ ${1}
+</thead>]]></text>
+ <tag>thead</tag>
+ <description>thead</description>
+ </snippet>
+ <snippet id="tip">
+ <text><![CDATA[<tip>
+ ${1}
+</tip>]]></text>
+ <tag>tip</tag>
+ <description>tip</description>
+ </snippet>
+ <snippet id="title">
+ <text><![CDATA[<title>${1}</title>]]></text>
+ <tag>title</tag>
+ <description>title</description>
+ </snippet>
+ <snippet id="titleabbrev">
+ <text><![CDATA[<titleabbrev>${1}</titleabbrev>]]></text>
+ <tag>titleabbrev</tag>
+ <description>titleabbrev</description>
+ </snippet>
+ <snippet id="toc">
+ <text><![CDATA[<toc>
+ ${1}
+</toc>]]></text>
+ <tag>toc</tag>
+ <description>toc</description>
+ </snippet>
+ <snippet id="tocback">
+ <text><![CDATA[<tocback linkend="${1}">${2}</tocback>]]></text>
+ <tag>tocback</tag>
+ <description>tocback</description>
+ </snippet>
+ <snippet id="tocchap">
+ <text><![CDATA[<tocchap>
+ ${1}
+</tocchap>]]></text>
+ <tag>tocchap</tag>
+ <description>tocchap</description>
+ </snippet>
+ <snippet id="tocentry">
+ <text><![CDATA[<tocentry linkend="${1}">${2}</tocentry>]]></text>
+ <tag>tocentry</tag>
+ <description>tocentry</description>
+ </snippet>
+ <snippet id="tocfront">
+ <text><![CDATA[<tocfront linkend="${1}">${2}</tocfront>]]></text>
+ <tag>tocfront</tag>
+ <description>tocfront</description>
+ </snippet>
+ <snippet id="toclevel1">
+ <text><![CDATA[<toclevel1>
+ ${1}
+</toclevel1>]]></text>
+ <tag>toclevel1</tag>
+ <description>toclevel1</description>
+ </snippet>
+ <snippet id="toclevel2">
+ <text><![CDATA[<toclevel2>
+ ${1}
+</toclevel2>]]></text>
+ <tag>toclevel2</tag>
+ <description>toclevel2</description>
+ </snippet>
+ <snippet id="toclevel3">
+ <text><![CDATA[<toclevel3>
+ ${1}
+</toclevel3>]]></text>
+ <tag>toclevel3</tag>
+ <description>toclevel3</description>
+ </snippet>
+ <snippet id="toclevel4">
+ <text><![CDATA[<toclevel4>
+ ${1}
+</toclevel4>]]></text>
+ <tag>toclevel4</tag>
+ <description>toclevel4</description>
+ </snippet>
+ <snippet id="toclevel5">
+ <text><![CDATA[<toclevel5>
+ ${1}
+</toclevel5>]]></text>
+ <tag>toclevel5</tag>
+ <description>toclevel5</description>
+ </snippet>
+ <snippet id="tocpart">
+ <text><![CDATA[<tocpart>
+ ${1}
+</tocpart>]]></text>
+ <tag>tocpart</tag>
+ <description>tocpart</description>
+ </snippet>
+ <snippet id="token">
+ <text><![CDATA[<token>${1}</token>]]></text>
+ <tag>token</tag>
+ <description>token</description>
+ </snippet>
+ <snippet id="tr">
+ <text><![CDATA[<tr>
+ ${1}
+</tr>]]></text>
+ <tag>tr</tag>
+ <description>tr</description>
+ </snippet>
+ <snippet id="trademark">
+ <text><![CDATA[<trademark class="${1:trade}">${2}</trademark>]]></text>
+ <tag>trademark</tag>
+ <description>trademark</description>
+ </snippet>
+ <snippet id="type">
+ <text><![CDATA[<type>${1}</type>]]></text>
+ <tag>type</tag>
+ <description>type</description>
+ </snippet>
+ <snippet id="ulink">
+ <text><![CDATA[<ulink url="${1}">${2}</ulink>]]></text>
+ <tag>ulink</tag>
+ <description>ulink</description>
+ </snippet>
+ <snippet id="uri">
+ <text><![CDATA[<uri>${1}</uri>]]></text>
+ <tag>uri</tag>
+ <description>uri</description>
+ </snippet>
+ <snippet id="userinput">
+ <text><![CDATA[<userinput>${1}</userinput>]]></text>
+ <tag>userinput</tag>
+ <description>userinput</description>
+ </snippet>
+ <snippet id="varargs">
+ <text><![CDATA[<varargs />]]></text>
+ <tag>varargs</tag>
+ <description>varargs</description>
+ </snippet>
+ <snippet id="variablelist">
+ <text><![CDATA[<variablelist>
+ ${1}
+</variablelist>]]></text>
+ <tag>variablelist</tag>
+ <description>variablelist</description>
+ </snippet>
+ <snippet id="varlistentry">
+ <text><![CDATA[<varlistentry>
+ ${1}
+</varlistentry>]]></text>
+ <tag>varlistentry</tag>
+ <description>varlistentry</description>
+ </snippet>
+ <snippet id="varname">
+ <text><![CDATA[<varname>${1}</varname>]]></text>
+ <tag>varname</tag>
+ <description>varname</description>
+ </snippet>
+ <snippet id="videodata">
+ <text><![CDATA[<videodata fileref="${1}" scalefit="${2:0}" />]]></text>
+ <tag>videodata</tag>
+ <description>videodata</description>
+ </snippet>
+ <snippet id="videoobject">
+ <text><![CDATA[<videoobject>
+ ${1}
+</videoobject>]]></text>
+ <tag>videoobject</tag>
+ <description>videoobject</description>
+ </snippet>
+ <snippet id="void">
+ <text><![CDATA[<void />]]></text>
+ <tag>void</tag>
+ <description>void</description>
+ </snippet>
+ <snippet id="volumenum">
+ <text><![CDATA[<volumenum>${1}</volumenum>]]></text>
+ <tag>volumenum</tag>
+ <description>volumenum</description>
+ </snippet>
+ <snippet id="warning">
+ <text><![CDATA[<warning>
+ ${1}
+</warning>]]></text>
+ <tag>warning</tag>
+ <description>warning</description>
+ </snippet>
+ <snippet id="wordasword">
+ <text><![CDATA[<wordasword>${1}</wordasword>]]></text>
+ <tag>wordasword</tag>
+ <description>wordasword</description>
+ </snippet>
+ <snippet id="xref">
+ <text><![CDATA[<xref linkend="${1}" />]]></text>
+ <tag>xref</tag>
+ <description>xref</description>
+ </snippet>
+ <snippet id="year">
+ <text><![CDATA[<year>${1}</year>]]></text>
+ <tag>year</tag>
+ <description>year</description>
+ </snippet>
+ <!-- DocBook Element Aliases: -->
+ <snippet id="bold">
+ <text><![CDATA[<emphasis role="bold">${1}</emphasis>]]></text>
+ <tag>bold</tag>
+ <description>emphasis, role bold</description>
+ </snippet>
+ <snippet id="strong">
+ <text><![CDATA[<emphasis role="strong">${1}</emphasis>]]></text>
+ <tag>strong</tag>
+ <description>emphasis, role strong</description>
+ </snippet>
+ <snippet id="devicefile">
+ <text><![CDATA[<filename class="devicefile">${1}</filename>]]></text>
+ <tag>devicefile</tag>
+ <description>filename, class devicefile</description>
+ </snippet>
+ <snippet id="directory">
+ <text><![CDATA[<filename class="directory">${1}</filename>]]></text>
+ <tag>directory</tag>
+ <description>filename, class directory</description>
+ </snippet>
+ <snippet id="extension">
+ <text><![CDATA[<filename class="extension">${1}</filename>]]></text>
+ <tag>extension</tag>
+ <description>filename, class extension</description>
+ </snippet>
+ <snippet id="headerfile">
+ <text><![CDATA[<filename class="headerfile">${1}</filename>]]></text>
+ <tag>headerfile</tag>
+ <description>filename, class headerfile</description>
+ </snippet>
+ <snippet id="libraryfile">
+ <text><![CDATA[<filename class="libraryfile">${1}</filename>]]></text>
+ <tag>libraryfile</tag>
+ <description>filename, class libraryfile</description>
+ </snippet>
+ <snippet id="partition">
+ <text><![CDATA[<filename class="partition">${1}</filename>]]></text>
+ <tag>partition</tag>
+ <description>filename, class partition</description>
+ </snippet>
+ <snippet id="symlink">
+ <text><![CDATA[<filename class="symlink">${1}</filename>]]></text>
+ <tag>symlink</tag>
+ <description>filename, class symlink</description>
+ </snippet>
+ <snippet id="cartridge">
+ <text><![CDATA[<medialabel class="cartridge">${1}</medialabel>]]></text>
+ <tag>cartridge</tag>
+ <description>medialabel, class cartridge</description>
+ </snippet>
+ <snippet id="cdrom">
+ <text><![CDATA[<medialabel class="cdrom">${1}</medialabel>]]></text>
+ <tag>cdrom</tag>
+ <description>medialabel, class cdrom</description>
+ </snippet>
+ <snippet id="disk">
+ <text><![CDATA[<medialabel class="disk">${1}</medialabel>]]></text>
+ <tag>disk</tag>
+ <description>medialabel, class disk</description>
+ </snippet>
+ <snippet id="tape">
+ <text><![CDATA[<medialabel class="tape">${1}</medialabel>]]></text>
+ <tag>tape</tag>
+ <description>medialabel, class tape</description>
+ </snippet>
+ <snippet id="daemon">
+ <text><![CDATA[<systemitem class="daemon">${1}</systemitem>]]></text>
+ <tag>daemon</tag>
+ <description>systemitem, class daemon</description>
+ </snippet>
+ <snippet id="domainname">
+ <text><![CDATA[<systemitem class="domainname">${1}</systemitem>]]></text>
+ <tag>domainname</tag>
+ <description>systemitem, class domainname</description>
+ </snippet>
+ <snippet id="etheraddress">
+ <text><![CDATA[<systemitem class="etheraddress">${1}</systemitem>]]></text>
+ <tag>etheraddress</tag>
+ <description>systemitem, class etheraddress</description>
+ </snippet>
+ <snippet id="eventhandler">
+ <text><![CDATA[<systemitem class="eventhandler">${1}</systemitem>]]></text>
+ <tag>eventhandler</tag>
+ <description>systemitem, class eventhandler</description>
+ </snippet>
+ <snippet id="event">
+ <text><![CDATA[<systemitem class="event">${1}</systemitem>]]></text>
+ <tag>event</tag>
+ <description>systemitem, class event</description>
+ </snippet>
+ <snippet id="filesystem">
+ <text><![CDATA[<systemitem class="filesystem">${1}</systemitem>]]></text>
+ <tag>filesystem</tag>
+ <description>systemitem, class filesystem</description>
+ </snippet>
+ <snippet id="fqdomainname">
+ <text><![CDATA[<systemitem class="fqdomainname">${1}</systemitem>]]></text>
+ <tag>fqdomainname</tag>
+ <description>systemitem, class fqdomainname</description>
+ </snippet>
+ <snippet id="groupname">
+ <text><![CDATA[<systemitem class="groupname">${1}</systemitem>]]></text>
+ <tag>groupname</tag>
+ <description>systemitem, class groupname</description>
+ </snippet>
+ <snippet id="ipaddress">
+ <text><![CDATA[<systemitem class="ipaddress">${1}</systemitem>]]></text>
+ <tag>ipaddress</tag>
+ <description>systemitem, class ipaddress</description>
+ </snippet>
+ <snippet id="library">
+ <text><![CDATA[<systemitem class="library">${1}</systemitem>]]></text>
+ <tag>library</tag>
+ <description>systemitem, class library</description>
+ </snippet>
+ <snippet id="macro">
+ <text><![CDATA[<systemitem class="macro">${1}</systemitem>]]></text>
+ <tag>macro</tag>
+ <description>systemitem, class macro</description>
+ </snippet>
+ <snippet id="netmask">
+ <text><![CDATA[<systemitem class="netmask">${1}</systemitem>]]></text>
+ <tag>netmask</tag>
+ <description>systemitem, class netmask</description>
+ </snippet>
+ <snippet id="newsgroup">
+ <text><![CDATA[<systemitem class="newsgroup">${1}</systemitem>]]></text>
+ <tag>newsgroup</tag>
+ <description>systemitem, class newsgroup</description>
+ </snippet>
+ <snippet id="osname">
+ <text><![CDATA[<systemitem class="osname">${1}</systemitem>]]></text>
+ <tag>osname</tag>
+ <description>systemitem, class osname</description>
+ </snippet>
+ <snippet id="process">
+ <text><![CDATA[<systemitem class="process">${1}</systemitem>]]></text>
+ <tag>process</tag>
+ <description>systemitem, class process</description>
+ </snippet>
+ <snippet id="protocol">
+ <text><![CDATA[<systemitem class="protocol">${1}</systemitem>]]></text>
+ <tag>protocol</tag>
+ <description>systemitem, class protocol</description>
+ </snippet>
+ <snippet id="resource">
+ <text><![CDATA[<systemitem class="resource">${1}</systemitem>]]></text>
+ <tag>resource</tag>
+ <description>systemitem, class resource</description>
+ </snippet>
+ <snippet id="server">
+ <text><![CDATA[<systemitem class="server">${1}</systemitem>]]></text>
+ <tag>server</tag>
+ <description>systemitem, class server</description>
+ </snippet>
+ <snippet id="service">
+ <text><![CDATA[<systemitem class="service">${1}</systemitem>]]></text>
+ <tag>service</tag>
+ <description>systemitem, class service</description>
+ </snippet>
+ <snippet id="systemname">
+ <text><![CDATA[<systemitem class="systemname">${1}</systemitem>]]></text>
+ <tag>systemname</tag>
+ <description>systemitem, class systemname</description>
+ </snippet>
+ <snippet id="username">
+ <text><![CDATA[<systemitem class="username">${1}</systemitem>]]></text>
+ <tag>username</tag>
+ <description>systemitem, class username</description>
+ </snippet>
+ <!-- XML-related Snippets: -->
+ <snippet id="include">
+ <text><![CDATA[<xi:include href="${1}.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />]]></text>
+ <tag>include</tag>
+ <description>xi:include</description>
+ </snippet>
+ <snippet id="fallback">
+ <text><![CDATA[<xi:fallback xmlns:xi="http://www.w3.org/2001/XInclude">
+ ${1}
+</xi:fallback>]]></text>
+ <tag>fallback</tag>
+ <description>xi:fallback</description>
+ </snippet>
+ <snippet id="xml">
+ <text><![CDATA[<?xml version='1.0' encoding='utf-8' ?>]]></text>
+ <tag>xml</tag>
+ <description>xml</description>
+ </snippet>
+ <snippet id="doctype">
+ <text><![CDATA[<!DOCTYPE ${1:chapter} PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "${2}.ent">
+%BOOK_ENTITIES;
+]>]]></text>
+ <tag>doctype</tag>
+ <description>DOCTYPE</description>
+ </snippet>
+ <snippet id="entity">
+ <text><![CDATA[<!ENTITY ${1} "${2}">]]></text>
+ <tag>entity</tag>
+ <description>ENTITY</description>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/fortran.xml b/plugins/snippets/data/fortran.xml
new file mode 100644
index 0000000..205abe6
--- /dev/null
+++ b/plugins/snippets/data/fortran.xml
@@ -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>
diff --git a/plugins/snippets/data/global.xml b/plugins/snippets/data/global.xml
new file mode 100644
index 0000000..afe3c0b
--- /dev/null
+++ b/plugins/snippets/data/global.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets/>
diff --git a/plugins/snippets/data/haskell.xml b/plugins/snippets/data/haskell.xml
new file mode 100644
index 0000000..54a8e7d
--- /dev/null
+++ b/plugins/snippets/data/haskell.xml
@@ -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>
diff --git a/plugins/snippets/data/html.xml b/plugins/snippets/data/html.xml
new file mode 100644
index 0000000..dd9faea
--- /dev/null
+++ b/plugins/snippets/data/html.xml
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="HTML">
+ <snippet id="doctype">
+ <text><![CDATA[<!DOCTYPE html>
+]]></text>
+ <description>HTML5 Doctype</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="doctype-6">
+ <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="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}">
+ $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 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:tool tip}" width="$4" height="$5" />$0]]></text>
+ <tag>img</tag>
+ <description>Image</description>
+ </snippet>
+ <snippet id="input">
+ <text><![CDATA[<input type="${1:[button,checkbox,color,date,datetime,datetime-local,email,file,hidden,image,month,number,password,radio,range,reset,search,submit,tel,text,url,week]}" name="${2:some_name}" value="${3:default_value}" placeholder="${4:default_placeholder}" 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}">
+$0]]></text>
+ <description>Link</description>
+ <tag>link</tag>
+ </snippet>
+ <snippet id="meta">
+ <text><![CDATA[<meta name="${1:name}" content="${2:content}" />
+$0]]></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">
+ $0
+</script>]]></text>
+ <description>Script</description>
+ <tag>script</tag>
+ </snippet>
+ <snippet id="scriptsrc">
+ <text><![CDATA[<script src="$1" type="text/javascript"></script>]]></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">
+ $0
+</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>
+$0]]></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>
+ <li>$2</li>
+ $3
+</ul>
+$0]]></text>
+ <tag>ul</tag>
+ <description>Unordered List</description>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/idl.xml b/plugins/snippets/data/idl.xml
new file mode 100644
index 0000000..2b6ef30
--- /dev/null
+++ b/plugins/snippets/data/idl.xml
@@ -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>
diff --git a/plugins/snippets/data/java.xml b/plugins/snippets/data/java.xml
new file mode 100644
index 0000000..f7f11c0
--- /dev/null
+++ b/plugins/snippets/data/java.xml
@@ -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>
diff --git a/plugins/snippets/data/javascript.xml b/plugins/snippets/data/javascript.xml
new file mode 100644
index 0000000..b55c5b3
--- /dev/null
+++ b/plugins/snippets/data/javascript.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="js">
+ <snippet id="fun">
+ <text><![CDATA[function ${1:function_name}(${2:first_argument}) {
+ $0
+}]]></text>
+ <description>function</description>
+ <tag>fun</tag>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/lang/snippets.lang b/plugins/snippets/data/lang/snippets.lang
new file mode 100644
index 0000000..7b755cd
--- /dev/null
+++ b/plugins/snippets/data/lang/snippets.lang
@@ -0,0 +1,160 @@
+<?xml version="1.0"?>
+<!--
+
+ Author: Jesse van den Kieboom <jesse@icecrew.nl>
+ Copyright (C) 2007-2008 Jesse van den Kieboom <jesse@icecrew.nl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="snippets" name="Snippets" hidden="true" version="2.0">
+ <styles>
+ <style id="placeholder-bounds" name="Placeholder begin and end" map-to="def:function"/>
+ <style id="default-value" name="Default Value" map-to="def:string"/>
+ <style id="single-placeholder" name="Single Placeholder" map-to="def:decimal"/>
+ <style id="shell-placeholder" name="Shell Placeholder" map-to="def:preprocessor"/>
+ <style id="python-placeholder" name="Python Placeholder" map-to="def:preprocessor"/>
+ <style id="regex-placeholder" name="Regular Expression Placeholder" map-to="def:preprocessor"/>
+ <style id="tabstop" name="Tabstop" map-to="def:decimal"/>
+ <style id="placeholder-ref" name="Placeholder Reference" map-to="def:decimal"/>
+ <style id="placeholder-def" name="Placeholder Default" map-to="def:string"/>
+ <style id="escape" name="Escape" map-to="def:special-char"/>
+ <style id="environmental-var" name="Environmental Variable" map-to="def:string"/>
+ <style id="seperator" name="Seperator" map-to="def:shebang"/>
+ <style id="regex-pattern" name="Regular Expression Pattern" map-to="def:string"/>
+ <style id="replace-pattern" name="Regular Expression Replace Pattern" map-to="def:string"/>
+ <style id="modifier" name="Modifier" map-to="def:keyword"/>
+ </styles>
+
+ <definitions>
+ <define-regex id="number">[0-9]+</define-regex>
+ <define-regex id="tabstop">\s*((\%{number})(:))</define-regex>
+ <define-regex id="number-list" extended="true">\s*(\[(\%{number}(,\%{number})*)\](:))</define-regex>
+ <define-regex id="environment">\$[A-Z_]+</define-regex>
+ <define-regex id="regex-pattern">((?:\\[/]|\\}|[^/}])+)</define-regex>
+
+ <context id="escape" style-ref="escape">
+ <match>\\\$</match>
+ </context>
+ <context id="single-placeholder" style-ref="single-placeholder">
+ <match>\$\%{number}|\${\%{number}}</match>
+ </context>
+ <context id="simple-placeholder-def" style-ref="default-value">
+ <start>\${\%{tabstop}</start>
+ <end>}</end>
+ <include>
+ <context sub-pattern="0" style-ref="placeholder-bounds" where="start"/>
+ <context sub-pattern="0" style-ref="placeholder-bounds" where="end"/>
+ <context sub-pattern="2" where="start" style-ref="tabstop"/>
+ <context sub-pattern="3" where="start" style-ref="seperator"/>
+ <context>
+ <match>\\}</match>
+ </context>
+ <context ref="escape"/>
+ <context ref="environmental-variable"/>
+ </include>
+ </context>
+ <context id="simple-placeholder">
+ <include>
+ <context ref="single-placeholder"/>
+ <context ref="simple-placeholder-def"/>
+ </include>
+ </context>
+ <context id="shell-placeholder-contents">
+ <include>
+ <context ref="escape"/>
+ <context ref="environmental-variable"/>
+ <context ref="single-placeholder"/>
+ </include>
+ </context>
+ <context id="shell-placeholder">
+ <include>
+ <context style-ref="shell-placeholder">
+ <start>\$\(\%{tabstop}?</start>
+ <end>\)</end>
+ <include>
+ <context sub-pattern="0" style-ref="placeholder-bounds" where="start"/>
+ <context sub-pattern="0" style-ref="placeholder-bounds" where="end"/>
+ <context sub-pattern="2" where="start" style-ref="tabstop"/>
+ <context sub-pattern="3" where="start" style-ref="seperator"/>
+ <context ref="shell-placeholder-contents"/>
+ <context>
+ <match>\\\)</match>
+ </context>
+ </include>
+ </context>
+ <context style-ref="shell-placeholder">
+ <start>`\%{tabstop}?</start>
+ <end>`</end>
+ <include>
+ <context sub-pattern="0" style-ref="placeholder-bounds" where="start"/>
+ <context sub-pattern="0" style-ref="placeholder-bounds" where="end"/>
+ <context sub-pattern="2" where="start" style-ref="tabstop"/>
+ <context sub-pattern="3" where="start" style-ref="seperator"/>
+ <context ref="shell-placeholder-contents"/>
+ <context>
+ <match>\\`</match>
+ </context>
+ </include>
+ </context>
+ </include>
+ </context>
+ <context id="python-placeholder">
+ <start>\$&lt;\%{tabstop}?\%{number-list}?</start>
+ <end>&gt;</end>
+ <include>
+ <context sub-pattern="0" style-ref="placeholder-bounds" where="start"/>
+ <context sub-pattern="0" style-ref="placeholder-bounds" where="end"/>
+ <context sub-pattern="2" where="start" style-ref="tabstop"/>
+ <context sub-pattern="3" where="start" style-ref="seperator"/>
+ <context sub-pattern="5" where="start" style-ref="tabstop"/>
+ <context sub-pattern="7" where="start" style-ref="seperator"/>
+ <context>
+ <match>\\&gt;</match>
+ </context>
+ <context ref="escape"/>
+ <context ref="environmental-variable"/>
+ <context ref="single-placeholder"/>
+ <context ref="python:python"/>
+ </include>
+ </context>
+ <context id="regex-placeholder" style-ref="regex-placeholder">
+ <match>(\${)\%{tabstop}?(?:\s*(?:(\%{number})|(\%{environment})))/\%{regex-pattern}/\%{regex-pattern}(?:[/]([a-zA-Z]*))?(})</match>
+ <include>
+ <context sub-pattern="1" style-ref="placeholder-bounds"/>
+ <context sub-pattern="10" style-ref="placeholder-bounds"/>
+ <context sub-pattern="3" style-ref="tabstop"/>
+ <context sub-pattern="4" style-ref="seperator"/>
+ <context sub-pattern="5" style-ref="tabstop"/>
+ <context sub-pattern="6" style-ref="environmental-var"/>
+ <context sub-pattern="7" style-ref="regex-pattern"/>
+ <context sub-pattern="8" style-ref="replace-pattern"/>
+ <context sub-pattern="9" style-ref="modifier"/>
+ </include>
+ </context>
+ <context id="environmental-variable" style-ref="environmental-var">
+ <match>\%{environment}</match>
+ </context>
+ <context id="snippets">
+ <include>
+ <context ref="escape"/>
+ <context ref="regex-placeholder"/>
+ <context ref="simple-placeholder"/>
+ <context ref="shell-placeholder"/>
+ <context ref="python-placeholder"/>
+ <context ref="environmental-variable"/>
+ </include>
+ </context>
+ </definitions>
+</language>
diff --git a/plugins/snippets/data/latex.xml b/plugins/snippets/data/latex.xml
new file mode 100644
index 0000000..71672ec
--- /dev/null
+++ b/plugins/snippets/data/latex.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="LaTeX">
+ <snippet id="command">
+ <text><![CDATA[{\\${1:bf} $GEDIT_SELECTED_TEXT}]]></text>
+ <accelerator><![CDATA[<Shift><Alt>w]]></accelerator>
+ <description>Wrap Selection in Command</description>
+ </snippet>
+ <snippet id="$">
+ <text><![CDATA[\[
+ $1
+\]]]></text>
+ <description>Displaymath</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="itd">
+ <text><![CDATA[\item[${1:description}] ${0:item}]]></text>
+ <description>\item[description]</description>
+ <tag>itd</tag>
+ </snippet>
+ <snippet id="sec">
+ <text><![CDATA[\section{${1:section name}}\label{${2:label}}
+]]></text>
+ <description>Section</description>
+ <tag>sec</tag>
+ </snippet>
+ <snippet id="sub">
+ <text><![CDATA[\subsection{${1:subsection name}}\label{${2:label}}
+]]></text>
+ <description>Sub Section</description>
+ <tag>sub</tag>
+ </snippet>
+ <snippet id="ssub">
+ <text><![CDATA[\subsubsection{${1:subsubsection name}}\label{${2:label}}
+]]></text>
+ <description>Sub Sub Section</description>
+ <tag>ssub</tag>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/mallard.xml b/plugins/snippets/data/mallard.xml
new file mode 100644
index 0000000..bb08b43
--- /dev/null
+++ b/plugins/snippets/data/mallard.xml
@@ -0,0 +1,316 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ Mallard 1.0 snippets according to Mallard 1.0 DRAFT (as of 2013-02-11)
+ Copyright (C) 2013 Jaromir Hradilek
+
+ Home Page: https://github.com/jhradilek/gedit-snippets
+ Last Change: 12 February 2013
+-->
+<snippets language="mallard">
+ <snippet id="app">
+ <text><![CDATA[<app>${1}</app>]]></text>
+ <tag>app</tag>
+ <description>app</description>
+ </snippet>
+ <snippet id="cite">
+ <text><![CDATA[<cite>${1}</cite>]]></text>
+ <tag>cite</tag>
+ <description>cite</description>
+ </snippet>
+ <snippet id="cmd">
+ <text><![CDATA[<cmd>${1}</cmd>]]></text>
+ <tag>cmd</tag>
+ <description>cmd</description>
+ </snippet>
+ <snippet id="code">
+ <text><![CDATA[<code>${1}</code>]]></text>
+ <tag>code</tag>
+ <description>code</description>
+ </snippet>
+ <snippet id="col">
+ <text><![CDATA[<col/>${1}]]></text>
+ <tag>col</tag>
+ <description>col</description>
+ </snippet>
+ <snippet id="colgroup">
+ <text><![CDATA[<colgroup>${1}</colgroup>]]></text>
+ <tag>colgroup</tag>
+ <description>colgroup</description>
+ </snippet>
+ <snippet id="comment">
+ <text><![CDATA[<comment>
+ ${1}
+</comment>]]></text>
+ <tag>comment</tag>
+ <description>comment</description>
+ </snippet>
+ <snippet id="credit">
+ <text><![CDATA[<credit type="${1:author}">
+ ${2}
+</credit>]]></text>
+ <tag>credit</tag>
+ <description>credit</description>
+ </snippet>
+ <snippet id="desc">
+ <text><![CDATA[<desc>${1}</desc>]]></text>
+ <tag>desc</tag>
+ <description>desc</description>
+ </snippet>
+ <snippet id="em">
+ <text><![CDATA[<em>${1}</em>]]></text>
+ <tag>em</tag>
+ <description>em</description>
+ </snippet>
+ <snippet id="email">
+ <text><![CDATA[<email>${1}</email>]]></text>
+ <tag>email</tag>
+ <description>email</description>
+ </snippet>
+ <snippet id="example">
+ <text><![CDATA[<example>
+ ${1}
+</example>]]></text>
+ <tag>example</tag>
+ <description>example</description>
+ </snippet>
+ <snippet id="figure">
+ <text><![CDATA[<figure>
+ ${1}
+</figure>]]></text>
+ <tag>figure</tag>
+ <description>figure</description>
+ </snippet>
+ <snippet id="file">
+ <text><![CDATA[<file>${1}</file>]]></text>
+ <tag>file</tag>
+ <description>file</description>
+ </snippet>
+ <snippet id="gui">
+ <text><![CDATA[<gui>${1}</gui>]]></text>
+ <tag>gui</tag>
+ <description>gui</description>
+ </snippet>
+ <snippet id="guiseq">
+ <text><![CDATA[<guiseq>${1}</guiseq>]]></text>
+ <tag>guiseq</tag>
+ <description>guiseq</description>
+ </snippet>
+ <snippet id="info">
+ <text><![CDATA[<info>
+ ${1}
+</info>]]></text>
+ <tag>info</tag>
+ <description>info</description>
+ </snippet>
+ <snippet id="input">
+ <text><![CDATA[<input>${1}</input>]]></text>
+ <tag>input</tag>
+ <description>input</description>
+ </snippet>
+ <snippet id="item">
+ <text><![CDATA[<item>${1}</item>]]></text>
+ <tag>item</tag>
+ <description>item</description>
+ </snippet>
+ <snippet id="key">
+ <text><![CDATA[<key>${1}</key>]]></text>
+ <tag>key</tag>
+ <description>key</description>
+ </snippet>
+ <snippet id="keyseq">
+ <text><![CDATA[<keyseq type="${1:combo}">${2}</keyseq>]]></text>
+ <tag>keyseq</tag>
+ <description>keyseq</description>
+ </snippet>
+ <snippet id="license">
+ <text><![CDATA[<license href="${1}">
+ ${2}
+</license>]]></text>
+ <tag>license</tag>
+ <description>license</description>
+ </snippet>
+ <snippet id="link">
+ <text><![CDATA[<link type="${1:guide}" xref="${2:index}" group="${3}"/>]]></text>
+ <tag>link</tag>
+ <description>link</description>
+ </snippet>
+ <snippet id="links">
+ <text><![CDATA[<links type="${1:topic}" groups="${2}">
+ ${3}
+</links>]]></text>
+ <tag>links</tag>
+ <description>links</description>
+ </snippet>
+ <snippet id="list">
+ <text><![CDATA[<list type="${1:disc}">
+ ${2}
+</list>]]></text>
+ <tag>list</tag>
+ <description>list</description>
+ </snippet>
+ <snippet id="listing">
+ <text><![CDATA[<listing>
+ ${1}
+</listing>]]></text>
+ <tag>listing</tag>
+ <description>listing</description>
+ </snippet>
+ <snippet id="media">
+ <text><![CDATA[<media type="${1:image}" mime="${2:image/png}" src="${3}">
+ ${4}
+</media>]]></text>
+ <tag>media</tag>
+ <description>media</description>
+ </snippet>
+ <snippet id="name">
+ <text><![CDATA[<name>${1}</name>]]></text>
+ <tag>name</tag>
+ <description>name</description>
+ </snippet>
+ <snippet id="note">
+ <text><![CDATA[<note style="${1:advanced}">
+ ${2}
+</note>]]></text>
+ <tag>note</tag>
+ <description>note</description>
+ </snippet>
+ <snippet id="output">
+ <text><![CDATA[<output>${1}</output>]]></text>
+ <tag>output</tag>
+ <description>output</description>
+ </snippet>
+ <snippet id="p">
+ <text><![CDATA[<p>${1}</p>]]></text>
+ <tag>p</tag>
+ <description>p</description>
+ </snippet>
+ <snippet id="page">
+ <text><![CDATA[<page xmlns="http://projectmallard.org/1.0/" type="${1:topic}" id="${2}">
+ ${3}
+</page>]]></text>
+ <tag>page</tag>
+ <description>page</description>
+ </snippet>
+ <snippet id="quote">
+ <text><![CDATA[<quote>
+ ${1}
+</quote>]]></text>
+ <tag>quote</tag>
+ <description>quote</description>
+ </snippet>
+ <snippet id="revision">
+ <text><![CDATA[<revision version="${1:0.1}" date="$(2:date +%Y-%m-%d)" status="${3:stub}"/>]]></text>
+ <tag>revision</tag>
+ <description>revision</description>
+ </snippet>
+ <snippet id="screen">
+ <text><![CDATA[<screen>${1}</screen>]]></text>
+ <tag>screen</tag>
+ <description>screen</description>
+ </snippet>
+ <snippet id="section">
+ <text><![CDATA[<section id="${1}">
+ ${2}
+</section>]]></text>
+ <tag>section</tag>
+ <description>section</description>
+ </snippet>
+ <snippet id="span">
+ <text><![CDATA[<span>${1}</span>]]></text>
+ <tag>span</tag>
+ <description>span</description>
+ </snippet>
+ <snippet id="steps">
+ <text><![CDATA[<steps>
+ ${1}
+</steps>]]></text>
+ <tag>steps</tag>
+ <description>steps</description>
+ </snippet>
+ <snippet id="subtitle">
+ <text><![CDATA[<subtitle>${1}</subtitle>]]></text>
+ <tag>subtitle</tag>
+ <description>subtitle</description>
+ </snippet>
+ <snippet id="synopsis">
+ <text><![CDATA[<synopsis>
+ ${1}
+</synopsis>]]></text>
+ <tag>synopsis</tag>
+ <description>synopsis</description>
+ </snippet>
+ <snippet id="sys">
+ <text><![CDATA[<sys>${1}</sys>]]></text>
+ <tag>sys</tag>
+ <description>sys</description>
+ </snippet>
+ <snippet id="table">
+ <text><![CDATA[<table frame="${1:all}" rules="${2:all}" shade="${3:none}">
+ ${4}
+</table>]]></text>
+ <tag>table</tag>
+ <description>table</description>
+ </snippet>
+ <snippet id="tbody">
+ <text><![CDATA[<tbody>
+ ${1}
+</tbody>]]></text>
+ <tag>tbody</tag>
+ <description>tbody</description>
+ </snippet>
+ <snippet id="td">
+ <text><![CDATA[<td>${1}</td>]]></text>
+ <tag>td</tag>
+ <description>td</description>
+ </snippet>
+ <snippet id="terms">
+ <text><![CDATA[<terms>
+ ${1}
+</terms>]]></text>
+ <tag>terms</tag>
+ <description>terms</description>
+ </snippet>
+ <snippet id="tfoot">
+ <text><![CDATA[<tfoot>
+ ${1}
+</tfoot>]]></text>
+ <tag>tfoot</tag>
+ <description>tfoot</description>
+ </snippet>
+ <snippet id="thead">
+ <text><![CDATA[<thead>
+ ${1}
+</thead>]]></text>
+ <tag>thead</tag>
+ <description>thead</description>
+ </snippet>
+ <snippet id="title">
+ <text><![CDATA[<title>${1}</title>]]></text>
+ <tag>title</tag>
+ <description>title</description>
+ </snippet>
+ <snippet id="tr">
+ <text><![CDATA[<tr>
+ ${1}
+</tr>]]></text>
+ <tag>tr</tag>
+ <description>tr</description>
+ </snippet>
+ <snippet id="tree">
+ <text><![CDATA[<tree>
+ ${1}
+</tree>]]></text>
+ <tag>tree</tag>
+ <description>tree</description>
+ </snippet>
+ <snippet id="var">
+ <text><![CDATA[<var>${1}</var>]]></text>
+ <tag>var</tag>
+ <description>var</description>
+ </snippet>
+ <snippet id="years">
+ <text><![CDATA[<years>$(1:date +%Y)</years>]]></text>
+ <tag>years</tag>
+ <description>years</description>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/markdown.xml b/plugins/snippets/data/markdown.xml
new file mode 100644
index 0000000..e49209b
--- /dev/null
+++ b/plugins/snippets/data/markdown.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="Markdown">
+ <snippet id="atx-header">
+ <text><![CDATA[${1:#} ${2:Header} $1
+
+]]></text>
+ <tag>h</tag>
+ <description>Header (atx-style)</description>
+ </snippet>
+
+ <snippet id="setext-header-1">
+ <text><![CDATA[${1:Header}
+===============
+
+]]></text>
+ <tag>Hs</tag>
+ <description>Header 1 (setext-style)</description>
+ </snippet>
+
+ <snippet id="setext-header-2">
+ <text><![CDATA[${1:Header}
+---------------
+
+]]></text>
+ <tag>hs</tag>
+ <description>Header 2 (setext-style)</description>
+ </snippet>
+
+ <snippet id="horizontal-rule">
+ <text><![CDATA[***************
+
+$0]]></text>
+ <tag>hr</tag>
+ <description>Horizontal Rule</description>
+ </snippet>
+
+ <snippet id="unordered-list">
+ <text><![CDATA[* $1
+* $2
+* $3
+* $4
+
+]]></text>
+ <tag>ul</tag>
+ <description>Unordered List</description>
+ </snippet>
+
+ <snippet id="ordered-list">
+ <text><![CDATA[1. $1
+2. $2
+3. $3
+4. $4
+
+]]></text>
+ <tag>ol</tag>
+ <description>Ordered List</description>
+ </snippet>
+
+ <snippet id="code-span">
+ <text><![CDATA[\`${1:$GEDIT_SELECTED_TEXT}\`]]></text>
+ <tag>code</tag>
+ <description>Wrap Selection as Code Span</description>
+ <accelerator><![CDATA[<Control><Alt>c]]></accelerator>
+ </snippet>
+
+ <snippet id="inline-link">
+ <text><![CDATA[[${1:$GEDIT_SELECTED_TEXT}](${2:URL})]]></text>
+ <tag>a</tag>
+ <description>Wrap Selection as Inline Link</description>
+ <accelerator><![CDATA[<Control><Alt>a]]></accelerator>
+ </snippet>
+
+ <snippet id="reference-link">
+ <text><![CDATA[[${1:$GEDIT_SELECTED_TEXT}][${2:link label}]]]></text>
+ <tag>aref</tag>
+ <description>Wrap Selection as Reference Link</description>
+ <accelerator><![CDATA[<Control><Alt>r]]></accelerator>
+ </snippet>
+
+ <snippet id="link-definition">
+ <text><![CDATA[[${1:link label}]: ${2:URL}
+]]></text>
+ <tag>adef</tag>
+ <description>Link Definition</description>
+ </snippet>
+
+ <snippet id="inline-image">
+ <text><![CDATA[![${1:alt text}](${2:URL})]]></text>
+ <tag>img</tag>
+ <description>Inline Image</description>
+ </snippet>
+
+ <snippet id="reference-image">
+ <text><![CDATA[![${1:alt text}][${2:image label}]]]></text>
+ <tag>iref</tag>
+ <description>Reference Image</description>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/perl.xml b/plugins/snippets/data/perl.xml
new file mode 100644
index 0000000..add148f
--- /dev/null
+++ b/plugins/snippets/data/perl.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="Perl">
+ <snippet id="perl">
+ <text><![CDATA[#!/usr/bin/perl
+$0]]></text>
+ <tag>perl</tag>
+ <description>#!/usr/bin/perl</description>
+ </snippet>
+ <snippet id="ife">
+ <text><![CDATA[if ($1) {
+ ${2:# body...}
+} else {
+ ${3:# else...}
+}
+]]></text>
+ <description>Conditional if..else</description>
+ <tag>ife</tag>
+ </snippet>
+ <snippet id="ifee">
+ <text><![CDATA[if ($1) {
+ ${2:# body...}
+} elsif ($3) {
+ ${4:# elsif...}
+} else {
+ ${5:# else...}
+}
+]]></text>
+ <description>Conditional if..elsif..else</description>
+ <tag>ifee</tag>
+ </snippet>
+ <snippet id="xunless">
+ <text><![CDATA[${1:expression} unless ${2:condition};
+]]></text>
+ <description>Conditional one-line</description>
+ <tag>xunless</tag>
+ </snippet>
+ <snippet id="xif">
+ <text><![CDATA[${1:expression} if ${2:condition};
+]]></text>
+ <description>Conditional one-line</description>
+ <tag>xif</tag>
+ </snippet>
+ <snippet id="eval">
+ <text><![CDATA[eval {
+ ${1:# do something risky...}
+};
+if ($@) {
+ ${2:# handle failure...}
+}
+]]></text>
+ <description>Try/Except</description>
+ <tag>eval</tag>
+ </snippet>
+ <snippet id="fore">
+ <text><![CDATA[foreach ${1:my $${2:x} }(@${3:array}) {
+ ${4:# body...}
+}
+]]></text>
+ <description>Loop</description>
+ <tag>fore</tag>
+ </snippet>
+ <snippet id="for">
+ <text><![CDATA[for (my $${1:var} = 0; $$1 < ${2:expression}; $$1++) {
+ ${3:# body...}
+}
+]]></text>
+ <description>Loop</description>
+ <tag>for</tag>
+ </snippet>
+ <snippet id="sub">
+ <text><![CDATA[sub ${1:function_name} {
+ ${2:# body...}
+}
+]]></text>
+ <description>Function</description>
+ <tag>sub</tag>
+ </snippet>
+ <snippet id="hashpointer">
+ <text><![CDATA[ => ]]></text>
+ <accelerator><![CDATA[<Shift><Alt>l]]></accelerator>
+ <description>hash pointer</description>
+ </snippet>
+ <snippet id="if">
+ <text><![CDATA[if ($1) {
+ ${2:# body...}
+}
+]]></text>
+ <description>Conditional</description>
+ <tag>if</tag>
+ </snippet>
+ <snippet id="xfore">
+ <text><![CDATA[${1:expression} foreach @${2:array};
+]]></text>
+ <description>Loop one-line</description>
+ <tag>xfore</tag>
+ </snippet>
+ <snippet id="xwhile">
+ <text><![CDATA[${1:expression} while ${2:condition};
+]]></text>
+ <description>Loop one-line</description>
+ <tag>xwhile</tag>
+ </snippet>
+ <snippet id="slurp">
+ <text><![CDATA[my $${1:var};
+{ local $/ = undef; local *FILE; open FILE, "<${2:file}"; $$1 = <FILE>; close FILE }
+]]></text>
+ <description>Read File</description>
+ <tag>slurp</tag>
+ </snippet>
+ <snippet id="unless">
+ <text><![CDATA[unless ($1) {
+ ${2:# body...}
+}
+]]></text>
+ <description>Conditional</description>
+ <tag>unless</tag>
+ </snippet>
+ <snippet id="while">
+ <text><![CDATA[while ($1) {
+ ${2:# body...}
+}
+]]></text>
+ <description>Loop</description>
+ <tag>while</tag>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/php.xml b/plugins/snippets/data/php.xml
new file mode 100644
index 0000000..89b27e7
--- /dev/null
+++ b/plugins/snippets/data/php.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="PHP">
+ <snippet id="class">
+ <text><![CDATA[class ${1:ClassName}${2: extends AnotherClass}
+{
+ function __construct(${3:argument})
+ {
+ $0
+ }
+}]]></text>
+ <description>class ..</description>
+ <tag>class</tag>
+ </snippet>
+ <snippet id="$">
+ <text><![CDATA[\$_COOKIE['${1:variable}']]]></text>
+ <description>COOKIE['..']</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="do">
+ <text><![CDATA[do {
+ $0
+} while (${1:$a <= 10});]]></text>
+ <description>do .. while ..</description>
+ <tag>do</tag>
+ </snippet>
+ <snippet id="elseif">
+ <text><![CDATA[elseif (${1:condition}) {
+ $0
+}]]></text>
+ <description>elseif ..</description>
+ <tag>elseif</tag>
+ </snippet>
+ <snippet id="else">
+ <text><![CDATA[else {
+ $0
+}]]></text>
+ <description>else ..</description>
+ <tag>else</tag>
+ </snippet>
+ <snippet id="$-1">
+ <text><![CDATA[\$_ENV['${1:variable}']]]></text>
+ <description>ENV['..']</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-2">
+ <text><![CDATA[\$_FILES['${1:variable}']]]></text>
+ <description>FILES['..']</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="foreach">
+ <text><![CDATA[foreach ($${1:variable} as $${2:key} => $${3:value}) {
+ $0
+}]]></text>
+ <description>foreach ..</description>
+ <tag>foreach</tag>
+ </snippet>
+ <snippet id="for">
+ <text><![CDATA[for ($${1:i} = ${2:0}; $${1:i} < $3; $${1:i}++) {
+ $0
+}]]></text>
+ <description>for ..</description>
+ <tag>for</tag>
+ </snippet>
+ <snippet id="function">
+ <text><![CDATA[${1:public }function ${2:FunctionName}($3)
+{
+ ${0:# code...}
+}]]></text>
+ <description>function ..</description>
+ <tag>function</tag>
+ </snippet>
+ <snippet id="$-3">
+ <text><![CDATA[\$_GET['${1:variable}']]]></text>
+ <description>GET['..']</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="globals">
+ <text><![CDATA[\$GLOBALS['${1:variable}']${2: =} ${3:something} ${4:;}]]></text>
+ <description>$GLOBALS['..']</description>
+ <tag>globals</tag>
+ </snippet>
+ <snippet id="if?">
+ <text><![CDATA[$${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b};]]></text>
+ <description>$.. =</description>
+ <tag>iff</tag>
+ </snippet>
+ <snippet id="ifelse">
+ <text><![CDATA[if (${1:condition}) {
+ ${2}
+} else {
+ ${3}
+}
+$0]]></text>
+ <description>if .. else ..</description>
+ <tag>ifelse</tag>
+ </snippet>
+ <snippet id="if">
+ <text><![CDATA[if (${1:condition}) {
+ $0
+}]]></text>
+ <description>if ..</description>
+ <tag>if</tag>
+ </snippet>
+ <snippet id="incl1">
+ <text><![CDATA[include_once('${1:file}');$0]]></text>
+ <description>include_once</description>
+ <tag>inclo</tag>
+ </snippet>
+ <snippet id="incl">
+ <text><![CDATA[include('${1:file}');$0]]></text>
+ <description>include</description>
+ <tag>incl</tag>
+ </snippet>
+ <snippet id="array">
+ <text><![CDATA[$${1:arrayName} = array('$2'${3:,});]]></text>
+ <description>$.. = array</description>
+ <tag>array</tag>
+ </snippet>
+ <snippet id="php">
+ <text><![CDATA[<?php
+
+ $0
+
+?>]]></text>
+ <description>&lt;?php .. ?&gt;</description>
+ <tag>php</tag>
+ </snippet>
+ <snippet id="$-4">
+ <text><![CDATA[\$_POST['${1:variable}']]]></text>
+ <description>POST['..']</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="print">
+ <text><![CDATA[print "${1:string}"${2: . };]]></text>
+ <description>print ".."</description>
+ <tag>print</tag>
+ </snippet>
+ <snippet id="$-5">
+ <text><![CDATA[\$_REQUEST['${1:variable}']]]></text>
+ <description>REQUEST['..']</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="req1">
+ <text><![CDATA[require_once('${1:file}');]]></text>
+ <description>require_once</description>
+ <tag>reqo</tag>
+ </snippet>
+ <snippet id="req">
+ <text><![CDATA[require('${1:file}');]]></text>
+ <description>require</description>
+ <tag>req</tag>
+ </snippet>
+ <snippet id="$-6">
+ <text><![CDATA[\$_SERVER['${1:variable}']]]></text>
+ <description>SERVER['..']</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-7">
+ <text><![CDATA[\$_SESSION['${1:variable}']]]></text>
+ <description>SESSION['..']</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="case">
+ <text><![CDATA[case '${1:variable}':
+ $0
+ break;]]></text>
+ <description>case ..</description>
+ <tag>case</tag>
+ </snippet>
+ <snippet id="switch">
+ <text><![CDATA[switch (${1:variable}) {
+ case '${2:value}':
+ ${3}
+ break;
+
+ $0
+
+ default:
+ ${4}
+ break;
+}]]></text>
+ <description>switch ..</description>
+ <tag>switch</tag>
+ </snippet>
+ <snippet id="while">
+ <text><![CDATA[while (${1:$a <= 10}) {
+ $0
+}]]></text>
+ <description>while ..</description>
+ <tag>while</tag>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/python.xml b/plugins/snippets/data/python.xml
new file mode 100644
index 0000000..a25617b
--- /dev/null
+++ b/plugins/snippets/data/python.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="Python">
+ <snippet id="py">
+ <text><![CDATA[#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+$0]]></text>
+ <description>#!/usr/bin/env python</description>
+ <tag>py</tag>
+ </snippet>
+ <snippet id="def">
+ <text><![CDATA[def ${1:fname}(${2:self}):
+ ${3:pass}]]></text>
+ <description>New Function</description>
+ <tag>def</tag>
+ </snippet>
+ <snippet id="doc">
+ <text><![CDATA["""
+ $1
+"""
+$0]]></text>
+ <description>doc string</description>
+ <tag>doc</tag>
+ </snippet>
+ <snippet id="get">
+ <text><![CDATA[def get$1(self): return self._$1]]></text>
+ <description>New Get Method</description>
+ <tag>get</tag>
+ </snippet>
+ <snippet id="class">
+ <text><![CDATA[class ${1:ClassName} (${2:object}):
+
+ def __init__(self${3:,}):
+ ${4:pass}
+
+$0]]></text>
+ <description>New Class</description>
+ <tag>class</tag>
+ </snippet>
+ <snippet id="for">
+ <text><![CDATA[for ${1:i} in ${2:xrange}(${3:count}):
+ $0]]></text>
+ <description>for loop</description>
+ <tag>for</tag>
+ </snippet>
+ <snippet id="from">
+ <text><![CDATA[from $1 import $2
+$0]]></text>
+ <description>from</description>
+ <tag>from</tag>
+ </snippet>
+ <snippet id="if">
+ <text><![CDATA[if ${1:condition}:
+ $0]]></text>
+ <description>if</description>
+ <tag>if</tag>
+ </snippet>
+ <snippet id="elif">
+ <text><![CDATA[elif ${1:condition}:
+ $0]]></text>
+ <description>elif</description>
+ <tag>elif</tag>
+ </snippet>
+ <snippet id="else">
+ <text><![CDATA[else:
+ $0]]></text>
+ <description>else</description>
+ <tag>else</tag>
+ </snippet>
+ <snippet id="while">
+ <text><![CDATA[while ${1:condition}:
+ $0]]></text>
+ <tag>while</tag>
+ <description>while loop</description>
+ </snippet>
+ <snippet id="insert">
+ <text><![CDATA["${1:$GEDIT_SELECTED_TEXT}"]]></text>
+ <accelerator><![CDATA[<Control>2]]></accelerator>
+ <description>Inside String: Insert "…"</description>
+ </snippet>
+ <snippet id="insert-1">
+ <text><![CDATA['${1:$GEDIT_SELECTED_TEXT}']]></text>
+ <accelerator><![CDATA[<Control>apostrophe]]></accelerator>
+ <description>Inside String: Insert '…'</description>
+ </snippet>
+ <snippet id=".">
+ <text><![CDATA[self.]]></text>
+ <description>self</description>
+ <tag>.</tag>
+ </snippet>
+ <snippet id="set">
+ <text><![CDATA[def set$1(self, ${2:newValue}): self._$1 = $2]]></text>
+ <description>New Set Method</description>
+ <tag>set</tag>
+ </snippet>
+ <snippet id="try">
+ <text><![CDATA[try:
+ $1
+except ${2:Error}:
+ $0]]></text>
+ <tag>try</tag>
+ <description>Try... Except</description>
+ </snippet>
+ <snippet id="main">
+ <text><![CDATA[if __name__ == '__main__':
+ ${1:sys.exit(main())}
+
+$0]]></text>
+ <description>main</description>
+ <tag>main</tag>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/rpmspec.xml b/plugins/snippets/data/rpmspec.xml
new file mode 100644
index 0000000..eb3396d
--- /dev/null
+++ b/plugins/snippets/data/rpmspec.xml
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- requires rpm-python package installed -->
+<snippets language="rpmspec">
+ <snippet id="ch">
+ <text><![CDATA[$<
+import rpm
+import datetime
+
+spec = rpm.spec($GEDIT_CURRENT_DOCUMENT_PATH)
+date = datetime.date.today().strftime("%a %b %d %Y")
+headers = spec.packages[0].header
+version = headers['Version']
+release = ".".join(headers['Release'].split(".")[:-1])
+packager = headers['Packager']
+newheader = "* %s %s - %s-%s\n- " % (date, packager, version, release)
+return newheader
+>
+]]></text>
+ <tag>ch</tag>
+ <description>changelog entry</description>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/ruby.xml b/plugins/snippets/data/ruby.xml
new file mode 100644
index 0000000..db13e69
--- /dev/null
+++ b/plugins/snippets/data/ruby.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="Ruby">
+ <snippet id="forin">
+ <text><![CDATA[for ${1:element} in ${2:collection}
+ ${1:element}.$0
+end]]></text>
+ <description>for .. in .. end</description>
+ <tag>forin</tag>
+ </snippet>
+ <snippet id="inject">
+ <text><![CDATA[inject(${1:object}) { |${2:injection}, ${3:element}| $0 }]]></text>
+ <description>inject object</description>
+ <tag>inject</tag>
+ </snippet>
+ <snippet id="reject">
+ <text><![CDATA[reject { |${1:element}| ${1:element}.$0 }]]></text>
+ <description>reject element</description>
+ <tag>reject</tag>
+ </snippet>
+ <snippet id="select">
+ <text><![CDATA[select { |${1:element}| ${1:element}.$0 }]]></text>
+ <description>select element</description>
+ <tag>select</tag>
+ </snippet>
+ <snippet id="ife">
+ <text><![CDATA[if ${1:condition}
+ $2
+else
+ $3
+end]]></text>
+ <description>if .. else .. end</description>
+ <tag>ife</tag>
+ </snippet>
+ <snippet id="if">
+ <text><![CDATA[if ${1:condition}
+ $0
+end]]></text>
+ <description>if .. end</description>
+ <tag>if</tag>
+ </snippet>
+ <snippet id="case">
+ <text><![CDATA[case ${1:object}
+ when ${2:condition}
+ $0
+end]]></text>
+ <description>case .. end</description>
+ <tag>case</tag>
+ </snippet>
+ <snippet id="begin">
+ <text><![CDATA[begin
+ $1
+rescue ${2:Exception} => ${3:e}
+ $0
+end]]></text>
+ <description>begin .. rescue .. end</description>
+ <tag>begin</tag>
+ </snippet>
+ <snippet id="class">
+ <text><![CDATA[class ${1:class_name}
+ $0
+end]]></text>
+ <description>class .. end</description>
+ <tag>class</tag>
+ </snippet>
+ <snippet id="collecto">
+ <text><![CDATA[collect do |${1:element}|
+ ${1:element}.$0
+end]]></text>
+ <description>collect element do</description>
+ <tag>collecto</tag>
+ </snippet>
+ <snippet id="collect">
+ <text><![CDATA[collect { |${1:element}| ${1:element}.$0 }]]></text>
+ <description>collect element</description>
+ <tag>collect</tag>
+ </snippet>
+ <snippet id="def">
+ <text><![CDATA[def ${1:method_name}
+ $0
+end]]></text>
+ <description>def .. end</description>
+ <tag>def</tag>
+ </snippet>
+ <snippet id="do">
+ <text><![CDATA[do
+ $0
+end]]></text>
+ <description>do .. end</description>
+ <tag>do</tag>
+ </snippet>
+ <snippet id="doo">
+ <text><![CDATA[do |${1:object}|
+ $0
+end]]></text>
+ <description>do |object| .. end</description>
+ <tag>doo</tag>
+ </snippet>
+ <snippet id="eacho">
+ <text><![CDATA[each do |${1:element}|
+ ${1:element}.$0
+end]]></text>
+ <description>each element do</description>
+ <tag>eacho</tag>
+ </snippet>
+ <snippet id="each">
+ <text><![CDATA[each { |${1:element}| ${1:element}.$0 }]]></text>
+ <description>each element</description>
+ <tag>each</tag>
+ </snippet>
+ <snippet id="each_with_indexo">
+ <text><![CDATA[each_with_index do |${1:element}, ${2:idx}|
+ ${1:element}.$0
+end]]></text>
+ <description>each_with_index do</description>
+ <tag>eachwithindexo</tag>
+ </snippet>
+ <snippet id="each_with_index">
+ <text><![CDATA[each_with_index { |${1:element}, ${2:idx}| ${1:element}.$0 }]]></text>
+ <description>each_with_index</description>
+ <tag>eachwithindex</tag>
+ </snippet>
+ <snippet id=":">
+ <text><![CDATA[:${1:key} => ${2:"value"}${3:, }]]></text>
+ <description>hash pair</description>
+ <tag>:</tag>
+ </snippet>
+ <snippet id="hashpointer">
+ <text><![CDATA[ => ]]></text>
+ <accelerator><![CDATA[<Shift><Alt>l]]></accelerator>
+ <description>hash pointer</description>
+ </snippet>
+ <snippet id="injecto">
+ <text><![CDATA[inject(${1:object}) do |${2:injection}, ${3:element}|
+ $0
+end]]></text>
+ <description>inject object do</description>
+ <tag>injecto</tag>
+ </snippet>
+ <snippet id="rejecto">
+ <text><![CDATA[reject do |${1:element}|
+ ${1:element}.$0
+end]]></text>
+ <description>reject element do</description>
+ <tag>rejecto</tag>
+ </snippet>
+ <snippet id="selecto">
+ <text><![CDATA[select do |${1:element}|
+ ${1:element}.$0
+end]]></text>
+ <description>select element do</description>
+ <tag>selecto</tag>
+ </snippet>
+ <snippet id="unless">
+ <text><![CDATA[unless ${1:condition}
+ $0
+end]]></text>
+ <description>unless</description>
+ <tag>unless</tag>
+ </snippet>
+ <snippet id="when">
+ <text><![CDATA[when ${1:condition}
+ $0]]></text>
+ <description>when</description>
+ <tag>when</tag>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/sh.xml b/plugins/snippets/data/sh.xml
new file mode 100644
index 0000000..b8fc0a6
--- /dev/null
+++ b/plugins/snippets/data/sh.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="sh">
+ <snippet id="elif">
+ <text><![CDATA[elif [[ ${1:condition} ]]; then
+ $0]]></text>
+ <description>elif ..</description>
+ <tag>elif</tag>
+ </snippet>
+ <snippet id="case">
+ <text><![CDATA[case ${1:choice} in
+${2:first})
+ $3
+ ;;
+*)
+ $4
+ ;;
+esac]]></text>
+ <description>case ..</description>
+ <tag>case</tag>
+ </snippet>
+ <snippet id="for">
+ <text><![CDATA[for (( ${1:i = 0}; ${2:i < 10}; ${3:i++} )); do
+ $0
+done]]></text>
+ <description>for .. done</description>
+ <tag>for</tag>
+ </snippet>
+ <snippet id="if">
+ <text><![CDATA[if [[ ${1:condition} ]]; then
+ $0
+fi]]></text>
+ <description>if .. then</description>
+ <tag>if</tag>
+ </snippet>
+ <snippet id="sh">
+ <text><![CDATA[#!/bin/sh
+$0]]></text>
+ <description>#!/bin/sh</description>
+ <tag>sh</tag>
+ </snippet>
+ <snippet id="bash">
+ <text><![CDATA[#!/bin/bash
+$0]]></text>
+ <description>#!/bin/bash</description>
+ <tag>bash</tag>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/snippets.xml b/plugins/snippets/data/snippets.xml
new file mode 100644
index 0000000..ee405e6
--- /dev/null
+++ b/plugins/snippets/data/snippets.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="snippets">
+ <snippet id="simple">
+ <text><![CDATA[\${${1:n:default}}]]></text>
+ <description>Simple Placeholder</description>
+ <tag>simple</tag>
+ </snippet>
+ <snippet id="simple-fallback">
+ <text><![CDATA[\${${1:n:}[${2:default1,default2}]}]]></text>
+ <description>Simple Fallback Placeholder</description>
+ <tag>simplef</tag>
+ </snippet>
+ <snippet id="shell">
+ <text><![CDATA[\$(${1:n:} ${2:shell code})]]></text>
+ <description>Shell Placeholder</description>
+ <tag>shell</tag>
+ </snippet>
+ <snippet id="python">
+ <text><![CDATA[\$<${1:n:} ${2:[refs]:} return 'python code' >]]></text>
+ <description>Python Placeholder</description>
+ <tag>python</tag>
+ </snippet>
+ <snippet id="regex">
+ <text><![CDATA[\${${1:n:} ${2:input}/${3:regex-pattern}/${4:replacement}/${5:modifiers}}]]></text>
+ <description>Regular Expression Placeholder</description>
+ <tag>regex</tag>
+ </snippet>
+ <snippet id="$-CURRENT_DOCUMENT_PATH">
+ <text><![CDATA[\$GEDIT_CURRENT_DOCUMENT_PATH]]></text>
+ <description>Gedit Current Document Path Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-CURRENT_DOCUMENT_NAME">
+ <text><![CDATA[\$GEDIT_CURRENT_DOCUMENT_NAME]]></text>
+ <description>Gedit Current Document Name Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-CURRENT_DOCUMENT_URI">
+ <text><![CDATA[\$GEDIT_CURRENT_DOCUMENT_URI]]></text>
+ <description>Gedit Current Document Uri Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-CURRENT_DOCUMENT_SCHEME">
+ <text><![CDATA[\$GEDIT_CURRENT_DOCUMENT_SCHEME]]></text>
+ <description>Gedit Current Document Scheme Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-CURRENT_DOCUMENT_TYPE">
+ <text><![CDATA[\$GEDIT_CURRENT_DOCUMENT_TYPE]]></text>
+ <description>Gedit Current Document Type Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-DOCUMENTS_URI">
+ <text><![CDATA[\$GEDIT_DOCUMENTS_URI]]></text>
+ <description>Gedit Documents Uri Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-DOCUMENTS_PATH">
+ <text><![CDATA[\$GEDIT_DOCUMENTS_PATH]]></text>
+ <description>Gedit Documents Path Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-SELECTED_TEXT">
+ <text><![CDATA[\$GEDIT_SELECTED_TEXT]]></text>
+ <description>Gedit Selected Text Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-CURRENT_WORD">
+ <text><![CDATA[\$GEDIT_CURRENT_WORD]]></text>
+ <description>Gedit Current Word Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-CURRENT_LINE">
+ <text><![CDATA[\$GEDIT_CURRENT_LINE]]></text>
+ <description>Gedit Current Line Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-CURRENT_LINE_NUMBER">
+ <text><![CDATA[\$GEDIT_CURRENT_LINE_NUMBER]]></text>
+ <description>Gedit Current Line Number Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-DROP_FILENAME">
+ <text><![CDATA[\$GEDIT_DROP_FILENAME]]></text>
+ <description>Gedit Drop Filename Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-DROP_REL_FILENAME">
+ <text><![CDATA[\$GEDIT_DROP_REL_FILENAME]]></text>
+ <description>Gedit Drop Relative Filename Variable</description>
+ <tag>$</tag>
+ </snippet>
+ <snippet id="$-DROP_MIME_TYPE">
+ <text><![CDATA[\$GEDIT_DROP_MIME_TYPE]]></text>
+ <description>Gedit Drop Mime Type Variable</description>
+ <tag>$</tag>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/tcl.xml b/plugins/snippets/data/tcl.xml
new file mode 100644
index 0000000..73a50c0
--- /dev/null
+++ b/plugins/snippets/data/tcl.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="Tcl">
+ <snippet id="foreach">
+ <text><![CDATA[foreach ${1:var} ${2:$list} {
+ ${3}
+}
+]]></text>
+ <description>foreach...</description>
+ <tag>foreach</tag>
+ </snippet>
+ <snippet id="for">
+ <text><![CDATA[for {${1:set i 0}} {${2:$i < $n}} {${3:incr i}} {
+ ${4}
+}
+]]></text>
+ <description>for...</description>
+ <tag>for</tag>
+ </snippet>
+ <snippet id="if">
+ <text><![CDATA[if {${1:condition}} {
+ ${2}
+}
+]]></text>
+ <description>if...</description>
+ <tag>if</tag>
+ </snippet>
+ <snippet id="proc">
+ <text><![CDATA[proc ${1:name} {${2:args}} \
+{
+ ${3}
+}
+]]></text>
+ <description>proc...</description>
+ <tag>proc</tag>
+ </snippet>
+ <snippet id="switch">
+ <text><![CDATA[switch ${1:-exact} -- ${2:$var} {
+ ${3:match} {
+ ${4}
+ }
+ default {${5}}
+}
+]]></text>
+ <description>switch...</description>
+ <tag>switch</tag>
+ </snippet>
+ <snippet id="while">
+ <text><![CDATA[while {${1:condition}} {
+ ${2}
+}
+]]></text>
+ <description>while...</description>
+ <tag>while</tag>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/xml.xml b/plugins/snippets/data/xml.xml
new file mode 100644
index 0000000..a53d565
--- /dev/null
+++ b/plugins/snippets/data/xml.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="XML">
+ <snippet id="&quot;">
+ <text><![CDATA[<${1:name} ${2:attr}="${3:value}">$0</${1}>]]></text>
+ <description>Long Attribute Tag</description>
+ <tag>"</tag>
+ </snippet>
+ <snippet id="&lt;">
+ <text><![CDATA[<${1:name}>$0</${1}>
+
+]]></text>
+ <description>Long Tag</description>
+ <tag>&lt;</tag>
+ </snippet>
+ <snippet id="&gt;">
+ <text><![CDATA[<${1:name} />]]></text>
+ <description>Short Tag</description>
+ <tag>&gt;</tag>
+ </snippet>
+ <snippet id="cdata">
+ <text><![CDATA[<![CDATA[$0]]]]><![CDATA[>]]></text>
+ <tag>cdata</tag>
+ <description>CDATA</description>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/data/xslt.xml b/plugins/snippets/data/xslt.xml
new file mode 100644
index 0000000..0ff5cc1
--- /dev/null
+++ b/plugins/snippets/data/xslt.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<snippets language="xslt">
+ <snippet id="stylesheet">
+ <text><![CDATA[<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+$0
+</xsl:stylesheet>
+]]></text>
+ <description>StyleSheet</description>
+ <tag>stylesheet</tag>
+ </snippet>
+ <snippet id="include">
+ <text><![CDATA[<xsl:include href="$1"/>
+]]></text>
+ <description>Include</description>
+ <tag>inc</tag>
+ </snippet>
+ <snippet id="import">
+ <text><![CDATA[<xsl:import href="$1"/>
+]]></text>
+ <description>Import</description>
+ <tag>imp</tag>
+ </snippet>
+ <snippet id="param">
+ <text><![CDATA[<xsl:param name="$1"/>
+]]></text>
+ <description>Parameter</description>
+ <tag>param</tag>
+ </snippet>
+ <snippet id="template">
+ <text><![CDATA[<xsl:template ${1:[match,name]}="$2" ${3:mode=""}>
+ $0
+</xsl:template>
+]]></text>
+ <description>Template</description>
+ <tag>templ</tag>
+ </snippet>
+ <snippet id="variable-1">
+ <text><![CDATA[<xsl:variable name="$1">
+ $0
+</xsl:variable>
+]]></text>
+ <description>Variable</description>
+ <tag>var</tag>
+ </snippet>
+ <snippet id="variable-2">
+ <text><![CDATA[<xsl:variable name="$1" select="$2"/>
+$0]]></text>
+ <description>Variable with Select Attribute</description>
+ <tag>var</tag>
+ </snippet>
+ <snippet id="choose">
+ <text><![CDATA[<xsl:choose>
+ <xsl:when test="$1">
+ $2
+ </xsl:when>
+ $3
+</xsl:choose>
+]]></text>
+ <description>Choose</description>
+ <tag>choose</tag>
+ </snippet>
+ <snippet id="when">
+ <text><![CDATA[<xsl:when test="$1">
+ $2
+</xsl:when>
+$0]]></text>
+ <description>When</description>
+ <tag>when</tag>
+ </snippet>
+ <snippet id="otherwise">
+ <text><![CDATA[<xsl:otherwise>
+ $1
+</xsl:otherwise>
+$0]]></text>
+ <description>Otherwise</description>
+ <tag>otherwise</tag>
+ </snippet>
+ <snippet id="if">
+ <text><![CDATA[<xsl:if test="$1">
+ $2
+</xsl:if>
+$0]]></text>
+ <description>If</description>
+ <tag>if</tag>
+ </snippet>
+ <snippet id="value-of">
+ <text><![CDATA[<xsl:value-of select="$1"/>
+]]></text>
+ <description>Value of</description>
+ <tag>val</tag>
+ </snippet>
+ <snippet id="element">
+ <text><![CDATA[<xsl:element name="$1">
+</xsl:element>
+$0]]></text>
+ <description>Element</description>
+ <tag>elem</tag>
+ </snippet>
+ <snippet id="attribute">
+ <text><![CDATA[<xsl:attribute name="$1">$2</xsl:attribute>
+$0]]></text>
+ <description>Attribute</description>
+ <tag>attr</tag>
+ </snippet>
+ <snippet id="text">
+ <text><![CDATA[<xsl:text>${1:$GEDIT_SELECTED_TEXT}</xsl:text>
+]]></text>
+ <description>Text</description>
+ <tag>text</tag>
+ </snippet>
+ <snippet id="comment">
+ <text><![CDATA[<xsl:comment>${1:$GEDIT_SELECTED_TEXT}</xsl:comment>
+]]></text>
+ <description>Comment</description>
+ <tag>comment</tag>
+ </snippet>
+ <snippet id="call-template">
+ <text><![CDATA[<xsl:call-template name="$1"/>
+]]></text>
+ <description>Call Template</description>
+ <tag>call</tag>
+ </snippet>
+ <snippet id="apply-templates">
+ <text><![CDATA[<xsl:apply-templates mode="$1" select="$2"/>
+$0]]></text>
+ <description>Apply Templates</description>
+ <tag>applyt</tag>
+ </snippet>
+ <snippet id="apply-imports">
+ <text><![CDATA[<xsl:apply-imports/>
+]]></text>
+ <description>Apply Imports</description>
+ <tag>applyimp</tag>
+ </snippet>
+ <snippet id="with-param">
+ <text><![CDATA[<xsl:with-param name="$1">
+ $2
+</xsl:with-param>
+$0]]></text>
+ <description>With Param</description>
+ <tag>with</tag>
+ </snippet>
+</snippets>
diff --git a/plugins/snippets/meson.build b/plugins/snippets/meson.build
new file mode 100644
index 0000000..91401d1
--- /dev/null
+++ b/plugins/snippets/meson.build
@@ -0,0 +1,23 @@
+subdir('snippets')
+
+install_subdir(
+ 'data',
+ strip_directory : true,
+ install_dir: join_paths(
+ pkgdatadir,
+ 'plugins',
+ 'snippets',
+ )
+)
+
+custom_target(
+ 'snippets.plugin',
+ input: 'snippets.plugin.desktop.in',
+ output: 'snippets.plugin',
+ command: msgfmt_plugin_cmd,
+ install: true,
+ install_dir: join_paths(
+ pkglibdir,
+ 'plugins',
+ )
+)
diff --git a/plugins/snippets/snippets.plugin.desktop.in b/plugins/snippets/snippets.plugin.desktop.in
new file mode 100644
index 0000000..129db21
--- /dev/null
+++ b/plugins/snippets/snippets.plugin.desktop.in
@@ -0,0 +1,9 @@
+[Plugin]
+Loader=python3
+Module=snippets
+IAge=3
+Name=Snippets
+Description=Insert often-used pieces of text in a fast way.
+Authors=Jesse van den Kieboom <jesse@icecrew.nl>
+Copyright=Copyright © 2005 Jesse van den Kieboom
+Website=http://www.gedit.org
diff --git a/plugins/snippets/snippets/__init__.py b/plugins/snippets/snippets/__init__.py
new file mode 100644
index 0000000..147aa69
--- /dev/null
+++ b/plugins/snippets/snippets/__init__.py
@@ -0,0 +1,26 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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 gi
+gi.require_version('Gedit', '3.0')
+gi.require_version('Gtk', '3.0')
+
+from .appactivatable import AppActivatable
+from .windowactivatable import WindowActivatable
+from .document import Document
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/appactivatable.py b/plugins/snippets/snippets/appactivatable.py
new file mode 100644
index 0000000..fb56e51
--- /dev/null
+++ b/plugins/snippets/snippets/appactivatable.py
@@ -0,0 +1,133 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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 platform
+from gi.repository import Gedit, Gtk, Gdk, GObject, Gio, GLib
+from .library import Library
+from .shareddata import SharedData
+
+try:
+ import gettext
+ gettext.bindtextdomain('gedit')
+ gettext.textdomain('gedit')
+ _ = gettext.gettext
+except:
+ _ = lambda s: s
+
+class AppActivatable(GObject.Object, Gedit.AppActivatable):
+ __gtype_name__ = "GeditSnippetsAppActivatable"
+
+ app = GObject.Property(type=Gedit.App)
+
+ def __init__(self):
+ GObject.Object.__init__(self)
+
+ def do_activate(self):
+ # Initialize snippets library
+ library = Library()
+
+ if platform.system() == 'Windows':
+ snippetsdir = os.path.expanduser('~/gedit/snippets')
+ else:
+ snippetsdir = os.path.join(GLib.get_user_config_dir(), 'gedit/snippets')
+
+ library.set_dirs(snippetsdir, self.system_dirs())
+
+ self.css = Gtk.CssProvider()
+ self.css.load_from_data("""
+.gedit-snippet-manager-paned {
+ border-style: solid;
+ border-color: @borders;
+}
+.gedit-snippet-manager-paned:dir(ltr) {
+ border-width: 0 1px 0 0;
+}
+
+.gedit-snippet-manager-paned:dir(rtl) {
+ border-width: 0 0 0 1px;
+}
+
+.gedit-snippet-manager-view {
+ border-width: 0 0 1px 0;
+}
+
+.gedit-snippet-manager-treeview {
+ border-top-width: 0;
+}
+
+.gedit-snippet-manager-treeview:dir(ltr) {
+ border-left-width: 0;
+}
+
+.gedit-snippet-manager-treeview:dir(rtl) {
+ border-right-width: 0;
+}
+""".encode('utf-8'))
+ Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
+ self.css, 600)
+
+ action = Gio.SimpleAction(name="snippets")
+ action.connect('activate', self.on_action_snippets_activate)
+ self.app.add_action(action)
+
+ item = Gio.MenuItem.new(_("Manage _Snippets…"), "app.snippets")
+ self.menu = self.extend_menu("preferences-section")
+ self.menu.append_menu_item(item)
+
+ def do_deactivate(self):
+ self.app.remove_action("snippets")
+ self.menu = None
+ Gtk.StyleContext.remove_provider_for_screen(Gdk.Screen.get_default(),
+ self.css)
+
+ def system_dirs(self):
+ dirs = []
+
+ if 'XDG_DATA_DIRS' in os.environ:
+ datadirs = os.environ['XDG_DATA_DIRS']
+ elif platform.system() != 'Windows':
+ datadirs = '/usr/local/share' + os.pathsep + '/usr/share'
+ else:
+ datadirs = GLib.win32_get_package_installation_directory_of_module(None)
+
+ for d in datadirs.split(os.pathsep):
+ d = os.path.join(d, 'gedit', 'plugins', 'snippets')
+
+ if os.path.isdir(d):
+ dirs.append(d)
+
+ dirs.append(self.plugin_info.get_data_dir())
+ return dirs
+
+ def accelerator_activated(self, group, obj, keyval, mod):
+ activatable = SharedData().lookup_window_activatable(obj)
+
+ ret = False
+
+ if activatable:
+ ret = activatable.accelerator_activated(keyval, mod)
+
+ return ret
+
+ def create_configure_dialog(self):
+ SharedData().show_manager(self.app.get_active_window(), self.plugin_info.get_data_dir())
+
+ def on_action_snippets_activate(self, action, parameter):
+ self.create_configure_dialog()
+
+# vi:ex:ts=4:et
diff --git a/plugins/snippets/snippets/completion.py b/plugins/snippets/snippets/completion.py
new file mode 100644
index 0000000..562b268
--- /dev/null
+++ b/plugins/snippets/snippets/completion.py
@@ -0,0 +1,187 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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
+
+from gi.repository import GObject, Gtk, GtkSource, Gedit
+
+from .library import Library
+from .languagemanager import get_language_manager
+from .snippet import Snippet
+
+class Proposal(GObject.Object, GtkSource.CompletionProposal):
+ __gtype_name__ = "GeditSnippetsProposal"
+
+ def __init__(self, snippet):
+ super(Proposal, self).__init__()
+ self._snippet = Snippet(snippet)
+
+ def snippet(self):
+ return self._snippet.data
+
+ # Interface implementation
+ def do_get_markup(self):
+ return self._snippet.display()
+
+ def do_get_info(self):
+ return self._snippet.data['text']
+
+class Provider(GObject.Object, GtkSource.CompletionProvider):
+ __gtype_name__ = "GeditSnippetsProvider"
+
+ def __init__(self, name, language_id, handler):
+ super(Provider, self).__init__()
+
+ self.name = name
+ self.info_widget = None
+ self.proposals = []
+ self.language_id = language_id
+ self.handler = handler
+ self.info_widget = None
+ self.mark = None
+
+ theme = Gtk.IconTheme.get_default()
+ f, w, h = Gtk.icon_size_lookup(Gtk.IconSize.MENU)
+
+ try:
+ self.icon = theme.load_icon(Gtk.STOCK_JUSTIFY_LEFT, w, 0)
+ except:
+ self.icon = None
+
+ def __del__(self):
+ if self.mark:
+ self.mark.get_buffer().delete_mark(self.mark)
+
+ def set_proposals(self, proposals):
+ self.proposals = proposals
+
+ def mark_position(self, it):
+ if not self.mark:
+ self.mark = it.get_buffer().create_mark(None, it, True)
+ else:
+ self.mark.get_buffer().move_mark(self.mark, it)
+
+ def get_word(self, context):
+ (valid_context, it) = context.get_iter()
+ if not valid_context:
+ return None
+
+ if it.starts_word() or it.starts_line() or not it.ends_word():
+ return None
+
+ start = it.copy()
+
+ if start.backward_word_start():
+ self.mark_position(start)
+ return start.get_text(it)
+ else:
+ return None
+
+ def do_get_start_iter(self, context, proposal):
+ if not self.mark or self.mark.get_deleted():
+ return (False, None)
+
+ return (True, self.mark.get_buffer().get_iter_at_mark(self.mark))
+
+ def do_match(self, context):
+ return True
+
+ def get_proposals(self, word):
+ if self.proposals:
+ proposals = self.proposals
+ else:
+ proposals = Library().get_snippets(None)
+
+ if self.language_id:
+ proposals += Library().get_snippets(self.language_id)
+
+ # Filter based on the current word
+ if word:
+ proposals = (x for x in proposals if x['tag'].startswith(word))
+
+ return [Proposal(x) for x in proposals]
+
+ def do_populate(self, context):
+ proposals = self.get_proposals(self.get_word(context))
+ context.add_proposals(self, proposals, True)
+
+ def do_get_name(self):
+ return self.name
+
+ def do_activate_proposal(self, proposal, piter):
+ return self.handler(proposal, piter)
+
+ def do_get_info_widget(self, proposal):
+ if not self.info_widget:
+ view = Gedit.View.new_with_buffer(Gedit.Document())
+ manager = get_language_manager()
+
+ lang = manager.get_language('snippets')
+ view.get_buffer().set_language(lang)
+
+ sw = Gtk.ScrolledWindow()
+ sw.add(view)
+ sw.show_all()
+
+ # Fixed size
+ sw.set_size_request(300, 200)
+
+ self.info_view = view
+ self.info_widget = sw
+
+ return self.info_widget
+
+ def do_update_info(self, proposal, info):
+ buf = self.info_view.get_buffer()
+
+ buf.set_text(proposal.get_info())
+ buf.move_mark(buf.get_insert(), buf.get_start_iter())
+ buf.move_mark(buf.get_selection_bound(), buf.get_start_iter())
+ self.info_view.scroll_to_iter(buf.get_start_iter(), 0.0, False, 0.5, 0.5)
+
+ def do_get_icon(self):
+ return self.icon
+
+ def do_get_activation(self):
+ return GtkSource.CompletionActivation.USER_REQUESTED
+
+class Defaults(GObject.Object, GtkSource.CompletionProvider):
+ __gtype_name__ = "GeditSnippetsDefaultsProvider"
+
+ def __init__(self, handler):
+ GObject.Object.__init__(self)
+
+ self.handler = handler
+ self.proposals = []
+
+ def set_defaults(self, defaults):
+ self.proposals = []
+
+ for d in defaults:
+ self.proposals.append(GtkSource.CompletionItem.new(d, d, None, None))
+
+ def do_get_name(self):
+ return ""
+
+ def do_activate_proposal(self, proposal, piter):
+ return self.handler(proposal, piter)
+
+ def do_populate(self, context):
+ context.add_proposals(self, self.proposals, True)
+
+ def do_get_activation(self):
+ return GtkSource.CompletionActivation.USER_REQUESTED
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/document.py b/plugins/snippets/snippets/document.py
new file mode 100644
index 0000000..23df280
--- /dev/null
+++ b/plugins/snippets/snippets/document.py
@@ -0,0 +1,1097 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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
+
+from gi.repository import Gtk, Gdk, Gio, GLib, Gedit, GObject
+
+from .library import Library
+from .snippet import Snippet
+from .placeholder import PlaceholderEnd
+from . import completion
+from .signals import Signals
+from .shareddata import SharedData
+from . import helper
+
+try:
+ import gettext
+ gettext.bindtextdomain('gedit')
+ gettext.textdomain('gedit')
+ _ = gettext.gettext
+except:
+ _ = lambda s: s
+
+class DynamicSnippet(dict):
+ def __init__(self, text):
+ self['text'] = text
+ self.valid = True
+
+class Document(GObject.Object, Gedit.ViewActivatable, Signals):
+ TAB_KEY_VAL = (Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab)
+ SPACE_KEY_VAL = (Gdk.KEY_space,)
+
+ view = GObject.Property(type=Gedit.View)
+
+ def __init__(self):
+ GObject.Object.__init__(self)
+ Signals.__init__(self)
+
+ self.placeholders = []
+ self.active_snippets = []
+ self.active_placeholder = None
+
+ self.ordered_placeholders = []
+ self.update_placeholders = []
+ self.jump_placeholders = []
+ self.language_id = 0
+ self.timeout_update_id = 0
+
+ self.provider = completion.Provider(_('Snippets'), self.language_id, self.on_proposal_activated)
+
+ def do_activate(self):
+ # Always have a reference to the global snippets
+ Library().ref(None)
+
+ buf = self.view.get_buffer()
+
+ self.connect_signal(self.view, 'key-press-event', self.on_view_key_press)
+ self.connect_signal(buf, 'notify::language', self.on_notify_language)
+ self.connect_signal(self.view, 'drag-data-received', self.on_drag_data_received)
+
+ self.connect_signal_after(self.view, 'draw', self.on_draw)
+
+ self.update_language()
+
+ completion = self.view.get_completion()
+ completion.add_provider(self.provider)
+
+ SharedData().register_controller(self.view, self)
+
+ def do_deactivate(self):
+ if self.timeout_update_id != 0:
+ GLib.source_remove(self.timeout_update_id)
+ self.timeout_update_id = 0
+
+ del self.update_placeholders[:]
+ del self.jump_placeholders[:]
+
+ # Always release the reference to the global snippets
+ Library().unref(None)
+ self.active_placeholder = None
+
+ self.disconnect_signals(self.view)
+ self.disconnect_signals(self.view.get_buffer())
+
+ # Remove all active snippets
+ for snippet in list(self.active_snippets):
+ self.deactivate_snippet(snippet, True)
+
+ completion = self.view.get_completion()
+
+ if completion:
+ completion.remove_provider(self.provider)
+
+ if self.language_id != 0:
+ Library().unref(self.language_id)
+
+ SharedData().unregister_controller(self.view, self)
+
+ # Call this whenever the language in the view changes. This makes sure that
+ # the correct language is used when finding snippets
+ def update_language(self):
+ lang = self.view.get_buffer().get_language()
+
+ if lang is None and self.language_id is None:
+ return
+ elif lang and lang.get_id() == self.language_id:
+ return
+
+ langid = self.language_id
+
+ if lang:
+ self.language_id = lang.get_id()
+ else:
+ self.language_id = None
+
+ if langid != 0:
+ Library().unref(langid)
+
+ Library().ref(self.language_id)
+ self.provider.language_id = self.language_id
+
+ SharedData().update_state(self.view.get_toplevel())
+
+ def accelerator_activate(self, keyval, mod):
+ if not self.view or not self.view.get_editable():
+ return False
+
+ accelerator = Gtk.accelerator_name(keyval, mod)
+ snippets = Library().from_accelerator(accelerator, \
+ self.language_id)
+
+ if len(snippets) == 0:
+ return False
+ elif len(snippets) == 1:
+ self.apply_snippet(snippets[0])
+ else:
+ # Do the fancy completion dialog
+ provider = completion.Provider(_('Snippets'), self.language_id, self.on_proposal_activated)
+ provider.set_proposals(snippets)
+
+ cm = self.view.get_completion()
+ cm.show([provider], cm.create_context(None))
+
+ return True
+
+ def first_snippet_inserted(self):
+ buf = self.view.get_buffer()
+
+ self.connect_signal(buf, 'changed', self.on_buffer_changed)
+ self.connect_signal(buf, 'cursor-moved', self.on_buffer_cursor_moved)
+ self.connect_signal_after(buf, 'insert-text', self.on_buffer_insert_text)
+
+ def last_snippet_removed(self):
+ buf = self.view.get_buffer()
+ self.disconnect_signal(buf, 'changed')
+ self.disconnect_signal(buf, 'cursor-moved')
+ self.disconnect_signal(buf, 'insert-text')
+
+ def current_placeholder(self):
+ buf = self.view.get_buffer()
+
+ piter = buf.get_iter_at_mark(buf.get_insert())
+ found = []
+
+ for placeholder in self.placeholders:
+ begin = placeholder.begin_iter()
+ end = placeholder.end_iter()
+
+ if piter.compare(begin) >= 0 and piter.compare(end) <= 0:
+ found.append(placeholder)
+
+ if self.active_placeholder in found:
+ return self.active_placeholder
+ elif len(found) > 0:
+ return found[0]
+ else:
+ return None
+
+ def advance_placeholder(self, direction):
+ # Returns (CurrentPlaceholder, NextPlaceholder), depending on direction
+ buf = self.view.get_buffer()
+
+ piter = buf.get_iter_at_mark(buf.get_insert())
+ found = current = next = None
+ length = len(self.placeholders)
+
+ placeholders = list(self.placeholders)
+
+ if self.active_placeholder:
+ begin = self.active_placeholder.begin_iter()
+ end = self.active_placeholder.end_iter()
+
+ if piter.compare(begin) >= 0 and piter.compare(end) <= 0:
+ current = self.active_placeholder
+ currentIndex = placeholders.index(self.active_placeholder)
+
+ if direction == 1:
+ # w = piter, x = begin, y = end, z = found
+ nearest = lambda w, x, y, z: (w.compare(x) <= 0 and (not z or \
+ x.compare(z.begin_iter()) < 0))
+ indexer = lambda x: x < length - 1
+ else:
+ # w = piter, x = begin, y = end, z = prev
+ nearest = lambda w, x, y, z: (w.compare(x) >= 0 and (not z or \
+ x.compare(z.begin_iter()) >= 0))
+ indexer = lambda x: x > 0
+
+ for index in range(0, length):
+ placeholder = placeholders[index]
+ begin = placeholder.begin_iter()
+ end = placeholder.end_iter()
+
+ # Find the nearest placeholder
+ if nearest(piter, begin, end, found):
+ found = placeholder
+
+ # Find the current placeholder
+ if piter.compare(begin) >= 0 and \
+ piter.compare(end) <= 0 and \
+ current is None:
+ currentIndex = index
+ current = placeholder
+
+ if current and current != found and \
+ (current.begin_iter().compare(found.begin_iter()) == 0 or \
+ current.end_iter().compare(found.begin_iter()) == 0) and \
+ self.active_placeholder and \
+ current.begin_iter().compare(self.active_placeholder.begin_iter()) == 0:
+ # if current and found are at the same place, then
+ # resolve the 'hugging' problem
+ current = self.active_placeholder
+ currentIndex = placeholders.index(current)
+
+ if current:
+ if indexer(currentIndex):
+ next = placeholders[currentIndex + direction]
+ elif found:
+ next = found
+ elif length > 0:
+ next = self.placeholders[0]
+
+ return current, next
+
+ def next_placeholder(self):
+ return self.advance_placeholder(1)
+
+ def previous_placeholder(self):
+ return self.advance_placeholder(-1)
+
+ def cursor_on_screen(self):
+ buf = self.view.get_buffer()
+ self.view.scroll_mark_onscreen(buf.get_insert())
+
+ def set_active_placeholder(self, placeholder):
+ self.active_placeholder = placeholder
+
+ def goto_placeholder(self, current, next):
+ last = None
+
+ if current:
+ # Signal this placeholder to end action
+ self.view.get_completion().hide()
+ current.leave()
+
+ if current.__class__ == PlaceholderEnd:
+ last = current
+
+ self.set_active_placeholder(next)
+
+ if next:
+ next.enter()
+
+ if next.__class__ == PlaceholderEnd:
+ last = next
+ elif len(next.defaults) > 1 and next.get_text() == next.default:
+ provider = completion.Defaults(self.on_default_activated)
+ provider.set_defaults(next.defaults)
+
+ cm = self.view.get_completion()
+ cm.show([provider], cm.create_context(None))
+
+ if last:
+ # This is the end of the placeholder, remove the snippet etc
+ for snippet in list(self.active_snippets):
+ if snippet.placeholders[0] == last:
+ self.deactivate_snippet(snippet)
+ break
+
+ self.cursor_on_screen()
+
+ return next != None
+
+ def skip_to_next_placeholder(self):
+ (current, next) = self.next_placeholder()
+ return self.goto_placeholder(current, next)
+
+ def skip_to_previous_placeholder(self):
+ (current, prev) = self.previous_placeholder()
+ return self.goto_placeholder(current, prev)
+
+ def string_in_native_doc_encoding(self, buf, s):
+ enc = buf.get_file().get_encoding()
+
+ if not enc or enc.get_charset() == 'UTF-8':
+ return s
+
+ try:
+ cv = GLib.convert(s, -1, enc.get_charset(), 'UTF-8')
+ return cv[0]
+ except GLib.GError:
+ pass
+
+ return s
+
+ def env_get_selected_text(self, buf):
+ bounds = buf.get_selection_bounds()
+
+ if bounds:
+ u8 = buf.get_text(bounds[0], bounds[1], False)
+
+ return {'utf8': u8, 'noenc': self.string_in_native_doc_encoding(buf, u8)}
+ else:
+ return ''
+
+ def env_get_current_word(self, buf):
+ start, end = helper.buffer_word_boundary(buf)
+
+ u8 = buf.get_text(start, end, False)
+
+ return {'utf8': u8, 'noenc': self.string_in_native_doc_encoding(buf, u8)}
+
+ def env_get_current_line(self, buf):
+ start, end = helper.buffer_line_boundary(buf)
+
+ u8 = buf.get_text(start, end, False)
+
+ return {'utf8': u8, 'noenc': self.string_in_native_doc_encoding(buf, u8)}
+
+ def env_get_current_line_number(self, buf):
+ start, end = helper.buffer_line_boundary(buf)
+
+ return str(start.get_line() + 1)
+
+ def location_uri_for_env(self, location):
+ if not location:
+ return {'utf8': '', 'noenc': ''}
+
+ u8 = location.get_parse_name()
+
+ if location.has_uri_scheme('file'):
+ u8 = "file://" + u8
+
+ return {'utf8': u8, 'noenc': location.get_uri()}
+
+ def location_name_for_env(self, location):
+ if location:
+ try:
+ info = location.query_info("standard::display-name", 0, None)
+ display_name = info.get_display_name()
+ except:
+ display_name = ''
+
+ return {'utf8': display_name,
+ 'noenc': location.get_basename()}
+ else:
+ return ''
+
+ def location_scheme_for_env(self, location):
+ if location:
+ return location.get_uri_scheme()
+ else:
+ return ''
+
+ def location_path_for_env(self, location):
+ if location and location.has_uri_scheme('file'):
+ return {'utf8': location.get_parse_name(),
+ 'noenc': location.get_path()}
+ else:
+ return ''
+
+ def location_dir_for_env(self, location):
+ if location:
+ parent = location.get_parent()
+
+ if parent and parent.has_uri_scheme('file'):
+ return {'utf8': parent.get_parse_name(),
+ 'noenc': parent.get_path()}
+
+ return ''
+
+ def env_add_for_location(self, environ, location, prefix):
+ parts = {'URI': self.location_uri_for_env,
+ 'NAME': self.location_name_for_env,
+ 'SCHEME': self.location_scheme_for_env,
+ 'PATH': self.location_path_for_env,
+ 'DIR': self.location_dir_for_env}
+
+ for k in parts:
+ v = parts[k](location)
+ key = prefix + '_' + k
+
+ if isinstance(v, dict):
+ environ['utf8'][key] = v['utf8']
+ environ['noenc'][key] = v['noenc']
+ else:
+ environ['utf8'][key] = v
+ environ['noenc'][key] = str(v)
+
+ return environ
+
+ def env_get_document_type(self, buf):
+ typ = buf.get_mime_type()
+
+ if typ:
+ return typ
+ else:
+ return ''
+
+ def env_get_documents_uri(self, buf):
+ toplevel = self.view.get_toplevel()
+
+ documents_uri = {'utf8': [], 'noenc': []}
+
+ if isinstance(toplevel, Gedit.Window):
+ for doc in toplevel.get_documents():
+ r = self.location_uri_for_env(doc.get_file().get_location())
+
+ if isinstance(r, dict):
+ documents_uri['utf8'].append(r['utf8'])
+ documents_uri['noenc'].append(r['noenc'])
+ else:
+ documents_uri['utf8'].append(r)
+ documents_uri['noenc'].append(str(r))
+
+ return {'utf8': ' '.join(documents_uri['utf8']),
+ 'noenc': ' '.join(documents_uri['noenc'])}
+
+ def env_get_documents_path(self, buf):
+ toplevel = self.view.get_toplevel()
+
+ documents_path = {'utf8': [], 'noenc': []}
+
+ if isinstance(toplevel, Gedit.Window):
+ for doc in toplevel.get_documents():
+ r = self.location_path_for_env(doc.get_file().get_location())
+
+ if isinstance(r, dict):
+ documents_path['utf8'].append(r['utf8'])
+ documents_path['noenc'].append(r['noenc'])
+ else:
+ documents_path['utf8'].append(r)
+ documents_path['noenc'].append(str(r))
+
+ return {'utf8': ' '.join(documents_path['utf8']),
+ 'noenc': ' '.join(documents_path['noenc'])}
+
+ def get_environment(self):
+ buf = self.view.get_buffer()
+ environ = {'utf8': {}, 'noenc': {}}
+
+ for k in os.environ:
+ # Get the original environment, as utf-8
+ v = os.environ[k]
+ environ['noenc'][k] = v
+ environ['utf8'][k] = os.environ[k].encode('utf-8')
+
+ variables = {'GEDIT_SELECTED_TEXT': self.env_get_selected_text,
+ 'GEDIT_CURRENT_WORD': self.env_get_current_word,
+ 'GEDIT_CURRENT_LINE': self.env_get_current_line,
+ 'GEDIT_CURRENT_LINE_NUMBER': self.env_get_current_line_number,
+ 'GEDIT_CURRENT_DOCUMENT_TYPE': self.env_get_document_type,
+ 'GEDIT_DOCUMENTS_URI': self.env_get_documents_uri,
+ 'GEDIT_DOCUMENTS_PATH': self.env_get_documents_path}
+
+ for var in variables:
+ v = variables[var](buf)
+
+ if isinstance(v, dict):
+ environ['utf8'][var] = v['utf8']
+ environ['noenc'][var] = v['noenc']
+ else:
+ environ['utf8'][var] = v
+ environ['noenc'][var] = str(v)
+
+ self.env_add_for_location(environ, buf.get_file().get_location(), 'GEDIT_CURRENT_DOCUMENT')
+
+ return environ
+
+ def uses_current_word(self, snippet):
+ matches = re.findall('(\\\\*)\\$GEDIT_CURRENT_WORD', snippet['text'])
+
+ for match in matches:
+ if len(match) % 2 == 0:
+ return True
+
+ return False
+
+ def uses_current_line(self, snippet):
+ matches = re.findall('(\\\\*)\\$GEDIT_CURRENT_LINE', snippet['text'])
+
+ for match in matches:
+ if len(match) % 2 == 0:
+ return True
+
+ return False
+
+ def apply_snippet(self, snippet, start = None, end = None, environ = {}):
+ if not snippet.valid:
+ return False
+
+ # Set environmental variables
+ env = self.get_environment()
+
+ if environ:
+ for k in environ['utf8']:
+ env['utf8'][k] = environ['utf8'][k]
+
+ for k in environ['noenc']:
+ env['noenc'][k] = environ['noenc'][k]
+
+ buf = self.view.get_buffer()
+ s = Snippet(snippet, env)
+
+ if not start:
+ start = buf.get_iter_at_mark(buf.get_insert())
+
+ if not end:
+ end = buf.get_iter_at_mark(buf.get_selection_bound())
+
+ if start.equal(end) and self.uses_current_word(s):
+ # There is no tab trigger and no selection and the snippet uses
+ # the current word. Set start and end to the word boundary so that
+ # it will be removed
+ start, end = helper.buffer_word_boundary(buf)
+ elif start.equal(end) and self.uses_current_line(s):
+ # There is no tab trigger and no selection and the snippet uses
+ # the current line. Set start and end to the line boundary so that
+ # it will be removed
+ start, end = helper.buffer_line_boundary(buf)
+
+ # You know, we could be in an end placeholder
+ (current, next) = self.next_placeholder()
+ if current and current.__class__ == PlaceholderEnd:
+ self.goto_placeholder(current, None)
+
+ if len(self.active_snippets) > 0:
+ self.block_signal(buf, 'cursor-moved')
+
+ buf.begin_user_action()
+
+ # Remove the tag, selection or current word
+ buf.delete(start, end)
+
+ # Insert the snippet
+ if len(self.active_snippets) == 0:
+ self.first_snippet_inserted()
+ self.block_signal(buf, 'cursor-moved')
+
+ sn = s.insert_into(self, start)
+ self.active_snippets.append(sn)
+
+ # Put cursor at first tab placeholder
+ keys = [x for x in sn.placeholders.keys() if x > 0]
+
+ if len(keys) == 0:
+ if 0 in sn.placeholders:
+ self.goto_placeholder(self.active_placeholder, sn.placeholders[0])
+ else:
+ buf.place_cursor(sn.begin_iter())
+ else:
+ self.goto_placeholder(self.active_placeholder, sn.placeholders[keys[0]])
+
+ self.unblock_signal(buf, 'cursor-moved')
+
+ if sn in self.active_snippets:
+ # Check if we can get end_iter in view without moving the
+ # current cursor position out of view
+ cur = buf.get_iter_at_mark(buf.get_insert())
+ last = sn.end_iter()
+
+ curloc = self.view.get_iter_location(cur)
+ lastloc = self.view.get_iter_location(last)
+
+ if (lastloc.y + lastloc.height) - curloc.y <= \
+ self.view.get_visible_rect().height:
+ self.view.scroll_mark_onscreen(sn.end_mark)
+
+ buf.end_user_action()
+ self.view.grab_focus()
+
+ return True
+
+ def get_tab_tag(self, buf, end = None):
+ if not end:
+ end = buf.get_iter_at_mark(buf.get_insert())
+
+ start = end.copy()
+ word = None
+ first = True
+
+ # Move start backward as long as there is a valid character
+ while start.backward_char():
+ c = start.get_char()
+
+ if not helper.is_tab_trigger_character(c):
+ # Check this for a single special char
+ if first and helper.is_tab_trigger(c):
+ break
+
+ # Make sure first char is valid
+ while not start.equal(end) and \
+ not helper.is_first_tab_trigger_character(start.get_char()):
+ start.forward_char()
+
+ break
+
+ first = False
+
+ if not start.equal(end):
+ word = buf.get_text(start, end, False)
+
+ if word and word != '':
+ return (word, start, end)
+
+ return (None, None, None)
+
+ def parse_and_run_snippet(self, data, iter):
+ if not self.view.get_editable():
+ return
+
+ self.apply_snippet(DynamicSnippet(data), iter, iter)
+
+ def run_snippet_trigger(self, trigger, bounds):
+ if not self.view:
+ return False
+
+ if not self.view.get_editable():
+ return False
+
+ buf = self.view.get_buffer()
+
+ if buf.get_has_selection():
+ return False
+
+ snippets = Library().from_tag(trigger, self.language_id)
+
+ if snippets:
+ if len(snippets) == 1:
+ return self.apply_snippet(snippets[0], bounds[0], bounds[1])
+ else:
+ # Do the fancy completion dialog
+ provider = completion.Provider(_('Snippets'), self.language_id, self.on_proposal_activated)
+ provider.set_proposals(snippets)
+
+ cm = self.view.get_completion()
+ cm.show([provider], cm.create_context(None))
+
+ return True
+
+ return False
+
+ def run_snippet(self):
+ if not self.view:
+ return False
+
+ if not self.view.get_editable():
+ return False
+
+ buf = self.view.get_buffer()
+
+ # get the word preceding the current insertion position
+ (word, start, end) = self.get_tab_tag(buf)
+
+ if not word:
+ return self.skip_to_next_placeholder()
+
+ if not self.run_snippet_trigger(word, (start, end)):
+ return self.skip_to_next_placeholder()
+ else:
+ return True
+
+ def deactivate_snippet(self, snippet, force = False):
+ remove = []
+ ordered_remove = []
+
+ for tabstop in snippet.placeholders:
+ if tabstop == -1:
+ placeholders = snippet.placeholders[-1]
+ else:
+ placeholders = [snippet.placeholders[tabstop]]
+
+ for placeholder in placeholders:
+ if placeholder in self.placeholders:
+ if placeholder in self.update_placeholders:
+ placeholder.update_contents()
+
+ self.update_placeholders.remove(placeholder)
+ elif placeholder in self.jump_placeholders:
+ placeholder[0].leave()
+
+ remove.append(placeholder)
+ elif placeholder in self.ordered_placeholders:
+ ordered_remove.append(placeholder)
+
+ for placeholder in remove:
+ if placeholder == self.active_placeholder:
+ self.active_placeholder = None
+
+ self.placeholders.remove(placeholder)
+ self.ordered_placeholders.remove(placeholder)
+
+ placeholder.remove(force)
+
+ for placeholder in ordered_remove:
+ self.ordered_placeholders.remove(placeholder)
+ placeholder.remove(force)
+
+ snippet.deactivate()
+ self.active_snippets.remove(snippet)
+
+ if len(self.active_snippets) == 0:
+ self.last_snippet_removed()
+
+ self.view.queue_draw()
+
+ def update_snippet_contents(self):
+ self.timeout_update_id = 0
+
+ for placeholder in self.update_placeholders:
+ placeholder.update_contents()
+
+ for placeholder in self.jump_placeholders:
+ self.goto_placeholder(placeholder[0], placeholder[1])
+
+ del self.update_placeholders[:]
+ del self.jump_placeholders[:]
+
+ return False
+
+ def on_buffer_cursor_moved(self, buf):
+ piter = buf.get_iter_at_mark(buf.get_insert())
+
+ # Check for all snippets if the cursor is outside its scope
+ for snippet in list(self.active_snippets):
+ if snippet.begin_mark.get_deleted() or snippet.end_mark.get_deleted():
+ self.deactivate(snippet)
+ else:
+ begin = snippet.begin_iter()
+ end = snippet.end_iter()
+
+ if piter.compare(begin) < 0 or piter.compare(end) > 0:
+ # Oh no! Remove the snippet this instant!!
+ self.deactivate_snippet(snippet)
+
+ current = self.current_placeholder()
+
+ if current != self.active_placeholder:
+ self.jump_placeholders.append((self.active_placeholder, current))
+
+ if self.timeout_update_id == 0:
+ self.timeout_update_id = GLib.timeout_add(0,
+ self.update_snippet_contents)
+
+ def on_buffer_changed(self, buf):
+ for snippet in list(self.active_snippets):
+ begin = snippet.begin_iter()
+ end = snippet.end_iter()
+
+ if begin.compare(end) >= 0:
+ # Begin collapsed on end, just remove it
+ self.deactivate_snippet(snippet)
+
+ current = self.current_placeholder()
+
+ if current:
+ if not current in self.update_placeholders:
+ self.update_placeholders.append(current)
+
+ if self.timeout_update_id == 0:
+ self.timeout_update_id = GLib.timeout_add(0, \
+ self.update_snippet_contents)
+
+ def on_buffer_insert_text(self, buf, piter, text, length):
+ ctx = helper.get_buffer_context(buf)
+
+ # do nothing special if there is no context and no active
+ # placeholder
+ if (not ctx) and (not self.active_placeholder):
+ return
+
+ if not ctx:
+ ctx = self.active_placeholder
+
+ if not ctx in self.ordered_placeholders:
+ return
+
+ # move any marks that were incorrectly moved by this insertion
+ # back to where they belong
+ begin = ctx.begin_iter()
+ end = ctx.end_iter()
+ idx = self.ordered_placeholders.index(ctx)
+
+ for placeholder in self.ordered_placeholders:
+ if placeholder == ctx:
+ continue
+
+ ob = placeholder.begin_iter()
+ oe = placeholder.end_iter()
+
+ if ob.compare(begin) == 0 and ((not oe) or oe.compare(end) == 0):
+ oidx = self.ordered_placeholders.index(placeholder)
+
+ if oidx > idx and ob:
+ buf.move_mark(placeholder.begin, end)
+ elif oidx < idx and oe:
+ buf.move_mark(placeholder.end, begin)
+ elif ob.compare(begin) >= 0 and ob.compare(end) < 0 and (oe and oe.compare(end) >= 0):
+ buf.move_mark(placeholder.begin, end)
+ elif (oe and oe.compare(begin) > 0) and ob.compare(begin) <= 0:
+ buf.move_mark(placeholder.end, begin)
+
+ def on_notify_language(self, buf, spec):
+ self.update_language()
+
+ def on_view_key_press(self, view, event):
+ library = Library()
+
+ state = event.get_state()
+
+ if not self.view.get_editable():
+ return False
+
+ if not (state & Gdk.ModifierType.CONTROL_MASK) and \
+ not (state & Gdk.ModifierType.MOD1_MASK) and \
+ event.keyval in self.TAB_KEY_VAL:
+ if not state & Gdk.ModifierType.SHIFT_MASK:
+ return self.run_snippet()
+ else:
+ return self.skip_to_previous_placeholder()
+ elif not library.loaded and \
+ library.valid_accelerator(event.keyval, state):
+ library.ensure_files()
+ library.ensure(self.language_id)
+ self.accelerator_activate(event.keyval, \
+ state & Gtk.accelerator_get_default_mod_mask())
+
+ return False
+
+ def path_split(self, path, components=[]):
+ head, tail = os.path.split(path)
+
+ if not tail and head:
+ return [head] + components
+ elif tail:
+ return self.path_split(head, [tail] + components)
+ else:
+ return components
+
+ def apply_uri_snippet(self, snippet, mime, uri):
+ # Remove file scheme
+ gfile = Gio.file_new_for_uri(uri)
+
+ environ = {'utf8': {'GEDIT_DROP_DOCUMENT_TYPE': mime.encode('utf-8')},
+ 'noenc': {'GEDIT_DROP_DOCUMENT_TYPE': mime}}
+
+ self.env_add_for_location(environ, gfile, 'GEDIT_DROP_DOCUMENT')
+
+ buf = self.view.get_buffer()
+ location = buf.get_file().get_location()
+
+ relpath = location.get_relative_path(gfile)
+
+ # CHECK: what is the encoding of relpath?
+ environ['utf8']['GEDIT_DROP_DOCUMENT_RELATIVE_PATH'] = relpath.encode('utf-8')
+ environ['noenc']['GEDIT_DROP_DOCUMENT_RELATIVE_PATH'] = relpath
+
+ mark = buf.get_mark('gtk_drag_target')
+
+ if not mark:
+ mark = buf.get_insert()
+
+ piter = buf.get_iter_at_mark(mark)
+ self.apply_snippet(snippet, piter, piter, environ)
+
+ def in_bounds(self, x, y):
+ rect = self.view.get_visible_rect()
+ rect.x, rect.y = self.view.buffer_to_window_coords(Gtk.TextWindowType.WIDGET, rect.x, rect.y)
+
+ return not (x < rect.x or x > rect.x + rect.width or y < rect.y or y > rect.y + rect.height)
+
+ def on_drag_data_received(self, view, context, x, y, data, info, timestamp):
+ if not self.view.get_editable():
+ return
+
+ uris = helper.drop_get_uris(data)
+ if not uris:
+ return
+
+ if not self.in_bounds(x, y):
+ return
+
+ uris.reverse()
+ stop = False
+
+ for uri in uris:
+ try:
+ mime = Gio.content_type_guess(uri)
+ except:
+ mime = None
+
+ if not mime:
+ continue
+
+ snippets = Library().from_drop_target(mime, self.language_id)
+
+ if snippets:
+ stop = True
+ self.apply_uri_snippet(snippets[0], mime, uri)
+
+ if stop:
+ context.finish(True, False, timestamp)
+ view.stop_emission('drag-data-received')
+ view.get_toplevel().present()
+ view.grab_focus()
+
+ def find_uri_target(self, context):
+ lst = Gtk.target_list_add_uri_targets((), 0)
+
+ return self.view.drag_dest_find_target(context, lst)
+
+ def on_proposal_activated(self, proposal, piter):
+ if not self.view.get_editable():
+ return False
+
+ buf = self.view.get_buffer()
+ bounds = buf.get_selection_bounds()
+
+ if bounds:
+ self.apply_snippet(proposal.snippet(), None, None)
+ else:
+ (word, start, end) = self.get_tab_tag(buf, piter)
+ self.apply_snippet(proposal.snippet(), start, end)
+
+ return True
+
+ def on_default_activated(self, proposal, piter):
+ buf = self.view.get_buffer()
+ bounds = buf.get_selection_bounds()
+
+ if bounds:
+ buf.begin_user_action()
+ buf.delete(bounds[0], bounds[1])
+ buf.insert(bounds[0], proposal.props.label)
+ buf.end_user_action()
+
+ return True
+ else:
+ return False
+
+ def iter_coords(self, piter):
+ rect = self.view.get_iter_location(piter)
+ rect.x, rect.y = self.view.buffer_to_window_coords(Gtk.TextWindowType.TEXT, rect.x, rect.y)
+
+ return rect
+
+ def placeholder_in_area(self, placeholder, area):
+ start = placeholder.begin_iter()
+ end = placeholder.end_iter()
+
+ if not start or not end:
+ return False
+
+ # Test if start is before bottom, and end is after top
+ start_rect = self.iter_coords(start)
+ end_rect = self.iter_coords(end)
+
+ return start_rect.y <= area.y + area.height and \
+ end_rect.y + end_rect.height >= area.y
+
+ def draw_placeholder_rect(self, ctx, placeholder):
+ start = placeholder.begin_iter()
+ start_rect = self.iter_coords(start)
+ start_line = start.get_line()
+
+ end = placeholder.end_iter()
+ end_rect = self.iter_coords(end)
+ end_line = end.get_line()
+
+ line = start.copy()
+ line.set_line_offset(0)
+ geom = self.view.get_window(Gtk.TextWindowType.TEXT).get_geometry()
+
+ ctx.translate(0.5, 0.5)
+
+ while line.get_line() <= end_line:
+ ypos, height = self.view.get_line_yrange(line)
+ x_, ypos = self.view.window_to_buffer_coords(Gtk.TextWindowType.TEXT, 0, ypos)
+
+ if line.get_line() == start_line and line.get_line() == end_line:
+ # Simply draw a box, both are on the same line
+ ctx.rectangle(start_rect.x, start_rect.y, end_rect.x - start_rect.x, start_rect.height - 1)
+ ctx.stroke()
+ elif line.get_line() == start_line or line.get_line() == end_line:
+ if line.get_line() == start_line:
+ rect = start_rect
+ else:
+ rect = end_rect
+
+ ctx.move_to(0, rect.y + rect.height - 1)
+ ctx.rel_line_to(rect.x, 0)
+ ctx.rel_line_to(0, -rect.height + 1)
+ ctx.rel_line_to(geom[2], 0)
+ ctx.stroke()
+
+ if not line.forward_line():
+ break
+
+ def draw_placeholder_bar(self, ctx, placeholder):
+ start = placeholder.begin_iter()
+ start_rect = self.iter_coords(start)
+
+ ctx.translate(0.5, 0.5)
+ extend_width = 2.5
+
+ ctx.move_to(start_rect.x - extend_width, start_rect.y)
+ ctx.rel_line_to(extend_width * 2, 0)
+
+ ctx.move_to(start_rect.x, start_rect.y)
+ ctx.rel_line_to(0, start_rect.height - 1)
+
+ ctx.rel_move_to(-extend_width, 0)
+ ctx.rel_line_to(extend_width * 2, 0)
+ ctx.stroke()
+
+ def draw_placeholder(self, ctx, placeholder):
+ if isinstance(placeholder, PlaceholderEnd):
+ return
+
+ col = self.view.get_style_context().get_color(Gtk.StateFlags.INSENSITIVE)
+ col.alpha = 0.5
+ Gdk.cairo_set_source_rgba(ctx, col)
+
+ if placeholder.tabstop > 0:
+ ctx.set_dash([], 0)
+ else:
+ ctx.set_dash([2], 0)
+
+ start = placeholder.begin_iter()
+ end = placeholder.end_iter()
+
+ if start.equal(end):
+ self.draw_placeholder_bar(ctx, placeholder)
+ else:
+ self.draw_placeholder_rect(ctx, placeholder)
+
+ def on_draw(self, view, ctx):
+ window = view.get_window(Gtk.TextWindowType.TEXT)
+
+ if not Gtk.cairo_should_draw_window(ctx, window):
+ return False
+
+ # Draw something
+ ctx.set_line_width(1.0)
+
+ Gtk.cairo_transform_to_window(ctx, view, window)
+
+ clipped, clip = Gdk.cairo_get_clip_rectangle(ctx)
+
+ if not clipped:
+ return False
+
+ for placeholder in self.ordered_placeholders:
+ if not self.placeholder_in_area(placeholder, clip):
+ continue
+
+ ctx.save()
+ self.draw_placeholder(ctx, placeholder)
+ ctx.restore()
+
+ return False
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/exporter.py b/plugins/snippets/snippets/exporter.py
new file mode 100644
index 0000000..8f8249e
--- /dev/null
+++ b/plugins/snippets/snippets/exporter.py
@@ -0,0 +1,122 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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 tempfile
+import shutil
+
+import xml.etree.ElementTree as et
+from . import helper
+
+try:
+ import gettext
+ gettext.bindtextdomain('gedit')
+ gettext.textdomain('gedit')
+ _ = gettext.gettext
+except:
+ _ = lambda s: s
+
+class Exporter:
+ def __init__(self, filename, snippets):
+ self.filename = filename
+ self.set_snippets(snippets)
+
+ def set_snippets(self, snippets):
+ self.snippets = {}
+
+ for snippet in snippets:
+ lang = snippet.language()
+
+ if lang in self.snippets:
+ self.snippets[lang].append(snippet)
+ else:
+ self.snippets[lang] = [snippet]
+
+ def export_xml(self, dirname, language, snippets):
+ # Create the root snippets node
+ root = et.Element('snippets')
+
+ # Create filename based on language
+ if language:
+ filename = os.path.join(dirname, language + '.xml')
+
+ # Set the language attribute
+ root.attrib['language'] = language
+ else:
+ filename = os.path.join(dirname, 'global.xml')
+
+ # Add all snippets to the root node
+ for snippet in snippets:
+ root.append(snippet.to_xml())
+
+ # Write xml
+ helper.write_xml(root, filename, ('text', 'accelerator'))
+
+ def export_archive(self, cmd):
+ dirname = tempfile.mkdtemp()
+
+ # Save current working directory and change to temporary directory
+ curdir = os.getcwd()
+
+ try:
+ os.chdir(dirname)
+
+ # Write snippet xml files
+ for language, snippets in self.snippets.items():
+ self.export_xml(dirname, language , snippets)
+
+ # Archive files
+ status = os.system('%s "%s" *.xml' % (cmd, self.filename))
+ finally:
+ os.chdir(curdir)
+
+ if status != 0:
+ return _('The archive “%s” could not be created' % self.filename)
+
+ # Remove the temporary directory
+ shutil.rmtree(dirname)
+
+ def export_targz(self):
+ self.export_archive('tar -c --gzip -f')
+
+ def export_tarbz2(self):
+ self.export_archive('tar -c --bzip2 -f')
+
+ def export_tar(self):
+ self.export_archive('tar -cf')
+
+ def run(self):
+ dirname = os.path.dirname(self.filename)
+ if not os.path.exists(dirname):
+ return _('Target directory “%s” does not exist') % dirname
+
+ if not os.path.isdir(dirname):
+ return _('Target directory “%s” is not a valid directory') % dirname
+
+ (root, ext) = os.path.splitext(self.filename)
+
+ actions = {'.tar.gz': self.export_targz,
+ '.tar.bz2': self.export_tarbz2,
+ '.tar': self.export_tar}
+
+ for k, v in actions.items():
+ if self.filename.endswith(k):
+ return v()
+
+ return self.export_targz()
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/helper.py b/plugins/snippets/snippets/helper.py
new file mode 100644
index 0000000..2fa3b3f
--- /dev/null
+++ b/plugins/snippets/snippets/helper.py
@@ -0,0 +1,204 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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
+
+from xml.sax import saxutils
+import xml.etree.ElementTree as et
+import re
+import codecs
+
+from gi.repository import Gtk
+
+def message_dialog(par, typ, msg):
+ d = Gtk.MessageDialog(par, Gtk.DialogFlags.MODAL, typ, Gtk.ButtonsType.OK, msg)
+ d.set_property('use-markup', True)
+
+ d.run()
+ d.destroy()
+
+def compute_indentation(view, piter):
+ line = piter.get_line()
+ start = view.get_buffer().get_iter_at_line(line)
+ end = start.copy()
+
+ ch = end.get_char()
+
+ while (ch.isspace() and ch != '\r' and ch != '\n' and \
+ end.compare(piter) < 0):
+ if not end.forward_char():
+ break;
+
+ ch = end.get_char()
+
+ if start.equal(end):
+ return ''
+
+ return start.get_slice(end)
+
+def markup_escape(text):
+ return saxutils.escape(text)
+
+def spaces_instead_of_tabs(view, text):
+ if not view.get_insert_spaces_instead_of_tabs():
+ return text
+
+ return text.replace("\t", view.get_tab_width() * ' ')
+
+def insert_with_indent(view, piter, text, indentfirst = True, context = None):
+ text = spaces_instead_of_tabs(view, text)
+ lines = text.split('\n')
+ buf = view.get_buffer()
+
+ buf._snippets_context = context
+
+ if len(lines) == 1:
+ view.get_buffer().insert(piter, text)
+ else:
+ # Compute indentation
+ indent = compute_indentation(view, piter)
+ text = ''
+
+ for i in range(0, len(lines)):
+ if indentfirst or i > 0:
+ text += indent + lines[i] + '\n'
+ else:
+ text += lines[i] + '\n'
+
+ buf.insert(piter, text[:-1])
+
+ buf._snippets_context = None
+
+def get_buffer_context(buf):
+ if hasattr(buf, "_snippets_context"):
+ return buf._snippets_context
+ return None
+
+def snippets_debug(*s):
+ return
+
+def write_xml(node, f, cdata_nodes=()):
+ assert node is not None
+
+ if not hasattr(f, "write"):
+ f = codecs.open(f, "wb", encoding="utf-8")
+
+ # Encoding
+ f.write("<?xml version='1.0' encoding='utf-8'?>\n")
+
+ _write_node(node, f, cdata_nodes)
+
+def _write_indent(file, text, indent):
+ file.write(' ' * indent + text)
+
+def _write_node(node, file, cdata_nodes=(), indent=0):
+ # write XML to file
+ tag = node.tag
+
+ if node is et.Comment:
+ _write_indent(file, "<!-- %s -->\n" % saxutils.escape(node.text), indent)
+ elif node is et.ProcessingInstruction:
+ _write_indent(file, "<?%s?>\n" % saxutils.escape(node.text), indent)
+ else:
+ items = node.items()
+
+ if items or node.text or len(node):
+ _write_indent(file, "<" + tag, indent)
+
+ if items:
+ items.sort() # lexical order
+ for k, v in items:
+ file.write(" %s=%s" % (k, saxutils.quoteattr(v)))
+ if node.text or len(node):
+ file.write(">")
+ if node.text and node.text.strip() != "":
+ if tag in cdata_nodes:
+ file.write(_cdata(node.text))
+ else:
+ file.write(saxutils.escape(node.text))
+ else:
+ file.write("\n")
+
+ for n in node:
+ _write_node(n, file, cdata_nodes, indent + 1)
+
+ if not len(node):
+ file.write("</" + tag + ">\n")
+ else:
+ _write_indent(file, "</" + tag + ">\n", \
+ indent)
+ else:
+ file.write(" />\n")
+
+ if node.tail and node.tail.strip() != "":
+ file.write(saxutils.escape(node.tail))
+
+def _cdata(text):
+ return '<![CDATA[' + text.replace(']]>', ']]]]><![CDATA[>') + ']]>'
+
+def is_tab_trigger(w):
+ if len(w) == 1 and not (w.isalnum() or w.isspace()):
+ return True
+
+ if not is_first_tab_trigger_character(w[0]):
+ return False
+
+ for c in w:
+ if not is_tab_trigger_character(c):
+ return False
+
+ return True
+
+def is_first_tab_trigger_character(c):
+ return c.isalpha() or c in '_:.'
+
+def is_tab_trigger_character(c):
+ return c.isalnum() or c in '_:.'
+
+def buffer_word_boundary(buf):
+ iter = buf.get_iter_at_mark(buf.get_insert())
+ start = iter.copy()
+
+ if not iter.starts_word() and (iter.inside_word() or iter.ends_word()):
+ start.backward_word_start()
+
+ if not iter.ends_word() and iter.inside_word():
+ iter.forward_word_end()
+
+ return (start, iter)
+
+def buffer_line_boundary(buf):
+ iter = buf.get_iter_at_mark(buf.get_insert())
+ start = iter.copy()
+ start.set_line_offset(0)
+
+ if not iter.ends_line():
+ iter.forward_to_line_end()
+
+ return (start, iter)
+
+def drop_get_uris(selection):
+ uris = []
+ if selection.targets_include_uri():
+ data = selection.get_data()
+ lines = re.split('\\s*[\\n\\r]+\\s*', data.strip())
+
+ for line in lines:
+ if not line.startswith('#'):
+ uris.append(line)
+
+ return uris
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/importer.py b/plugins/snippets/snippets/importer.py
new file mode 100644
index 0000000..2718596
--- /dev/null
+++ b/plugins/snippets/snippets/importer.py
@@ -0,0 +1,134 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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 errno
+import tempfile
+import sys
+import shutil
+
+from .library import Library
+
+try:
+ import gettext
+ gettext.bindtextdomain('gedit')
+ gettext.textdomain('gedit')
+ _ = gettext.gettext
+except:
+ _ = lambda s: s
+
+class Importer:
+ def __init__(self, filename):
+ self.filename = filename
+
+ def import_destination(self, filename):
+ userdir = Library().userdir
+
+ filename = os.path.basename(filename)
+ (root, ext) = os.path.splitext(filename)
+
+ filename = os.path.join(userdir, root + ext)
+ i = 1
+
+ while os.path.exists(filename):
+ filename = os.path.join(userdir, root + '_' + str(i) + ext)
+ i += 1
+
+ return (userdir, filename)
+
+ def import_file(self, filename):
+ if not os.path.exists(filename):
+ return _('File “%s” does not exist') % filename
+
+ if not os.path.isfile(filename):
+ return _('File “%s” is not a valid snippets file') % filename
+
+ # Find destination for file to copy to
+ destdir, dest = self.import_destination(filename)
+
+ # Make sure dir exists
+ try:
+ os.makedirs(destdir)
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+
+ # Copy file
+ shutil.copy(filename, dest)
+
+ # Add library
+ if not Library().add_user_library(dest):
+ return _('Imported file “%s” is not a valid snippets file') % os.path.basename(dest)
+
+ def import_xml(self):
+ return self.import_file(self.filename)
+
+ def import_archive(self, cmd):
+ dirname = tempfile.mkdtemp()
+ status = os.system('cd %s; %s "%s"' % (dirname, cmd, self.filename))
+
+ if status != 0:
+ return _('The archive “%s” could not be extracted' % self.filename)
+
+ errors = []
+
+ # Now import all the files from the archive
+ for f in os.listdir(dirname):
+ f = os.path.join(dirname, f)
+
+ if os.path.isfile(f):
+ if self.import_file(f):
+ errors.append(os.path.basename(f))
+ else:
+ sys.stderr.write('Skipping %s, not a valid snippets file' % os.path.basename(f))
+
+ # Remove the temporary directory
+ shutil.rmtree(dirname)
+
+ if len(errors) > 0:
+ return _('The following files could not be imported: %s') % ', '.join(errors)
+
+ def import_targz(self):
+ self.import_archive('tar -x --gzip -f')
+
+ def import_tarbz2(self):
+ self.import_archive('tar -x --bzip2 -f')
+
+ def import_tar(self):
+ self.import_archive('tar -xf')
+
+ def run(self):
+ if not os.path.exists(self.filename):
+ return _('File “%s” does not exist') % self.filename
+
+ if not os.path.isfile(self.filename):
+ return _('File “%s” is not a valid snippets archive') % self.filename
+
+ (root, ext) = os.path.splitext(self.filename)
+
+ actions = {'.tar.gz': self.import_targz,
+ '.tar.bz2': self.import_tarbz2,
+ '.xml': self.import_xml,
+ '.tar': self.import_tar}
+
+ for k, v in actions.items():
+ if self.filename.endswith(k):
+ return v()
+
+ return _('File “%s” is not a valid snippets archive') % self.filename
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/languagemanager.py b/plugins/snippets/snippets/languagemanager.py
new file mode 100644
index 0000000..6f74319
--- /dev/null
+++ b/plugins/snippets/snippets/languagemanager.py
@@ -0,0 +1,40 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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
+
+from gi.repository import GtkSource
+import os
+
+from .library import Library
+
+global manager
+manager = None
+
+def get_language_manager():
+ global manager
+
+ if not manager:
+ dirs = []
+
+ for d in Library().systemdirs:
+ dirs.append(os.path.join(d, 'lang'))
+
+ manager = GtkSource.LanguageManager()
+ manager.set_search_path(dirs + manager.get_search_path())
+
+ return manager
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/library.py b/plugins/snippets/snippets/library.py
new file mode 100644
index 0000000..7ce163b
--- /dev/null
+++ b/plugins/snippets/snippets/library.py
@@ -0,0 +1,989 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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 weakref
+import sys
+import re
+
+from gi.repository import Gdk, Gtk
+
+import xml.etree.ElementTree as et
+from . import helper
+
+class NamespacedId:
+ def __init__(self, namespace, id):
+ if not id:
+ self.id = None
+ else:
+ if namespace:
+ self.id = namespace + '-'
+ else:
+ self.id = 'global-'
+
+ self.id += id
+
+class SnippetData:
+ PROPS = {'tag': '', 'text': '', 'description': 'New snippet',
+ 'accelerator': '', 'drop-targets': ''}
+
+ def __init__(self, node, library):
+ self.priv_id = node.attrib.get('id')
+
+ self.set_library(library)
+ self.valid = False
+ self.set_node(node)
+
+ def can_modify(self):
+ return (self.library and (isinstance(self.library(), SnippetsUserFile)))
+
+ def set_library(self, library):
+ if library:
+ self.library = weakref.ref(library)
+ else:
+ self.library = None
+
+ self.id = NamespacedId(self.language(), self.priv_id).id
+
+ def set_node(self, node):
+ if self.can_modify():
+ self.node = node
+ else:
+ self.node = None
+
+ self.init_snippet_data(node)
+
+ def init_snippet_data(self, node):
+ if node is None:
+ return
+
+ self.override = node.attrib.get('override')
+
+ self.properties = {}
+ props = SnippetData.PROPS.copy()
+
+ # Store all properties present
+ for child in node:
+ if child.tag in props:
+ del props[child.tag]
+
+ # Normalize accelerator
+ if child.tag == 'accelerator' and child.text != None:
+ keyval, mod = Gtk.accelerator_parse(child.text)
+
+ if Gtk.accelerator_valid(keyval, mod):
+ child.text = Gtk.accelerator_name(keyval, mod)
+ else:
+ child.text = ''
+
+ if self.can_modify():
+ self.properties[child.tag] = child
+ else:
+ self.properties[child.tag] = child.text or ''
+
+ # Create all the props that were not found so we stay consistent
+ for prop in props:
+ if self.can_modify():
+ child = et.SubElement(node, prop)
+
+ child.text = props[prop]
+ self.properties[prop] = child
+ else:
+ self.properties[prop] = props[prop]
+
+ self.check_validation()
+
+ def check_validation(self):
+ if not self['tag'] and not self['accelerator'] and not self['drop-targets']:
+ return False
+
+ library = Library()
+ keyval, mod = Gtk.accelerator_parse(self['accelerator'])
+
+ self.valid = library.valid_tab_trigger(self['tag']) and \
+ (not self['accelerator'] or library.valid_accelerator(keyval, mod))
+
+ def _format_prop(self, prop, value):
+ if prop == 'drop-targets' and value != '':
+ return re.split('\\s*[,;]\\s*', value)
+ else:
+ return value
+
+ def __getitem__(self, prop):
+ if prop in self.properties:
+ if self.can_modify():
+ return self._format_prop(prop, self.properties[prop].text or '')
+ else:
+ return self._format_prop(prop, self.properties[prop] or '')
+
+ return self._format_prop(prop, '')
+
+ def __setitem__(self, prop, value):
+ if not prop in self.properties:
+ return
+
+ if isinstance(value, list):
+ value = ','.join(value)
+
+ if not self.can_modify() and self.properties[prop] != value:
+ # ohoh, this is not can_modify, but it needs to be changed...
+ # make sure it is transfered to the changes file and set all the
+ # fields.
+ # This snippet data container will effectively become the container
+ # for the newly created node, but transparently to whoever uses
+ # it
+ self._override()
+
+ if self.can_modify() and self.properties[prop].text != value:
+ if self.library():
+ self.library().tainted = True
+
+ oldvalue = self.properties[prop].text
+ self.properties[prop].text = value
+
+ if prop == 'tag' or prop == 'accelerator' or prop == 'drop-targets':
+ container = Library().container(self.language())
+ container.prop_changed(self, prop, oldvalue)
+
+ self.check_validation()
+
+ def language(self):
+ if self.library and self.library():
+ return self.library().language
+ else:
+ return None
+
+ def is_override(self):
+ return self.override and Library().overridden[self.override]
+
+ def to_xml(self):
+ return self._create_xml()
+
+ def _create_xml(self, parent=None, update=False, attrib={}):
+ # Create a new node
+ if parent != None:
+ element = et.SubElement(parent, 'snippet', attrib)
+ else:
+ element = et.Element('snippet')
+
+ # Create all the properties
+ for p in self.properties:
+ prop = et.SubElement(element, p)
+ prop.text = self[p]
+
+ if update:
+ self.properties[p] = prop
+
+ return element
+
+ def _override(self):
+ # Find the user file
+ target = Library().get_user_library(self.language())
+
+ # Create a new node there with override
+ element = self._create_xml(target.root, True, {'override': self.id})
+
+ # Create an override snippet data, feed it element so that it stores
+ # all the values and then set the node to None so that it only contains
+ # the values in .properties
+ override = SnippetData(element, self.library())
+ override.set_node(None)
+ override.id = self.id
+
+ # Set our node to the new element
+ self.node = element
+
+ # Set the override to our id
+ self.override = self.id
+ self.id = None
+
+ # Set the new library
+ self.set_library(target)
+
+ # The library is tainted because we added this snippet
+ target.tainted = True
+
+ # Add the override
+ Library().overridden[self.override] = override
+
+ def revert(self, snippet):
+ userlib = self.library()
+ self.set_library(snippet.library())
+
+ userlib.remove(self.node)
+
+ self.set_node(None)
+
+ # Copy the properties
+ self.properties = snippet.properties
+
+ # Set the id
+ self.id = snippet.id
+
+ # Reset the override flag
+ self.override = None
+
+class SnippetsTreeBuilder(et.TreeBuilder):
+ def __init__(self, start=None, end=None):
+ et.TreeBuilder.__init__(self)
+ self.set_start(start)
+ self.set_end(end)
+
+ def set_start(self, start):
+ self._start_cb = start
+
+ def set_end(self, end):
+ self._end_cb = end
+
+ def start(self, tag, attrs):
+ result = et.TreeBuilder.start(self, tag, attrs)
+
+ if self._start_cb:
+ self._start_cb(result)
+
+ return result
+
+ def end(self, tag):
+ result = et.TreeBuilder.end(self, tag)
+
+ if self._end_cb:
+ self._end_cb(result)
+
+ return result
+
+class LanguageContainer:
+ def __init__(self, language):
+ self.language = language
+ self.snippets = []
+ self.snippets_by_prop = {'tag': {}, 'accelerator': {}, 'drop-targets': {}}
+ self.accel_group = Gtk.AccelGroup()
+ self._refs = 0
+
+ def _add_prop(self, snippet, prop, value=0):
+ if value == 0:
+ value = snippet[prop]
+
+ if not value or value == '':
+ return
+
+ helper.snippets_debug('Added ', prop ,' ', value, ' to ', str(self.language))
+
+ if prop == 'accelerator':
+ keyval, mod = Gtk.accelerator_parse(value)
+ self.accel_group.connect(keyval, mod, 0, \
+ Library().accelerator_activated)
+
+ snippets = self.snippets_by_prop[prop]
+
+ if not isinstance(value, list):
+ value = [value]
+
+ for val in value:
+ if val in snippets:
+ snippets[val].append(snippet)
+ else:
+ snippets[val] = [snippet]
+
+ def _remove_prop(self, snippet, prop, value=0):
+ if value == 0:
+ value = snippet[prop]
+
+ if not value or value == '':
+ return
+
+ helper.snippets_debug('Removed ', prop, ' ', value, ' from ', str(self.language))
+
+ if prop == 'accelerator':
+ keyval, mod = Gtk.accelerator_parse(value)
+ self.accel_group.disconnect_key(keyval, mod)
+
+ snippets = self.snippets_by_prop[prop]
+
+ if not isinstance(value, list):
+ value = [value]
+
+ for val in value:
+ try:
+ snippets[val].remove(snippet)
+ except:
+ True
+
+ def append(self, snippet):
+ self.snippets.append(snippet)
+
+ self._add_prop(snippet, 'tag')
+ self._add_prop(snippet, 'accelerator')
+ self._add_prop(snippet, 'drop-targets')
+
+ return snippet
+
+ def remove(self, snippet):
+ try:
+ self.snippets.remove(snippet)
+ except:
+ True
+
+ self._remove_prop(snippet, 'tag')
+ self._remove_prop(snippet, 'accelerator')
+ self._remove_prop(snippet, 'drop-targets')
+
+ def prop_changed(self, snippet, prop, oldvalue):
+ helper.snippets_debug('PROP CHANGED (', prop, ')', oldvalue)
+
+ self._remove_prop(snippet, prop, oldvalue)
+ self._add_prop(snippet, prop)
+
+ def from_prop(self, prop, value):
+ snippets = self.snippets_by_prop[prop]
+
+ if prop == 'drop-targets':
+ s = []
+
+ # FIXME: change this to use
+ # gnomevfs.mime_type_get_equivalence when it comes
+ # available
+ for key, val in snippets.items():
+ if not value.startswith(key):
+ continue
+
+ for snippet in snippets[key]:
+ if not snippet in s:
+ s.append(snippet)
+
+ return s
+ else:
+ if value in snippets:
+ return snippets[value]
+ else:
+ return []
+
+ def ref(self):
+ self._refs += 1
+
+ return True
+
+ def unref(self):
+ if self._refs > 0:
+ self._refs -= 1
+
+ return self._refs != 0
+
+class SnippetsSystemFile:
+ def __init__(self, path=None):
+ self.path = path
+ self.loaded = False
+ self.language = None
+ self.ok = True
+ self.need_id = True
+
+ def load_error(self, message):
+ sys.stderr.write("An error occurred loading " + self.path + ":\n")
+ sys.stderr.write(message + "\nSnippets in this file will not be " \
+ "available, please correct or remove the file.\n")
+
+ def _add_snippet(self, element):
+ if not self.need_id or element.attrib.get('id'):
+ self.loading_elements.append(element)
+
+ def set_language(self, element):
+ self.language = element.attrib.get('language')
+
+ if self.language:
+ self.language = self.language.lower()
+
+ def _set_root(self, element):
+ self.set_language(element)
+
+ def _preprocess_element(self, element):
+ if not self.loaded:
+ if not element.tag == "snippets":
+ self.load_error("Root element should be `snippets' instead " \
+ "of `%s'" % element.tag)
+ return False
+ else:
+ self._set_root(element)
+ self.loaded = True
+ elif element.tag != 'snippet' and not self.insnippet:
+ self.load_error("Element should be `snippet' instead of `%s'" \
+ % element.tag)
+ return False
+ else:
+ self.insnippet = True
+
+ return True
+
+ def _process_element(self, element):
+ if element.tag == 'snippet':
+ self._add_snippet(element)
+ self.insnippet = False
+
+ return True
+
+ def ensure(self):
+ if not self.ok or self.loaded:
+ return
+
+ self.load()
+
+ def parse_xml(self, readsize=16384):
+ if not self.path:
+ return
+
+ elements = []
+
+ builder = SnippetsTreeBuilder( \
+ lambda node: elements.append((node, True)), \
+ lambda node: elements.append((node, False)))
+
+ parser = et.XMLParser(target=builder)
+ self.insnippet = False
+
+ try:
+ f = open(self.path, "r", encoding='utf-8')
+ except IOError:
+ self.ok = False
+ return
+
+ while True:
+ try:
+ data = f.read(readsize)
+ except IOError:
+ self.ok = False
+ break
+
+ if not data:
+ break
+
+ try:
+ parser.feed(data)
+ except Exception:
+ self.ok = False
+ break
+
+ for element in elements:
+ yield element
+
+ del elements[:]
+
+ f.close()
+
+ def load(self):
+ if not self.ok:
+ return
+
+ helper.snippets_debug("Loading library (" + str(self.language) + "): " + \
+ self.path)
+
+ self.loaded = False
+ self.ok = False
+ self.loading_elements = []
+
+ for element in self.parse_xml():
+ if element[1]:
+ if not self._preprocess_element(element[0]):
+ del self.loading_elements[:]
+ return
+ else:
+ if not self._process_element(element[0]):
+ del self.loading_elements[:]
+ return
+
+ for element in self.loading_elements:
+ Library().add_snippet(self, element)
+
+ del self.loading_elements[:]
+ self.ok = True
+
+ # This function will get the language for a file by just inspecting the
+ # root element of the file. This is provided so that a cache can be built
+ # for which file contains which language.
+ # It returns the name of the language
+ def ensure_language(self):
+ if not self.loaded:
+ self.ok = False
+
+ for element in self.parse_xml(256):
+ if element[1]:
+ if element[0].tag == 'snippets':
+ self.set_language(element[0])
+ self.ok = True
+
+ break
+
+ def unload(self):
+ helper.snippets_debug("Unloading library (" + str(self.language) + "): " + \
+ self.path)
+ self.language = None
+ self.loaded = False
+ self.ok = True
+
+class SnippetsUserFile(SnippetsSystemFile):
+ def __init__(self, path=None):
+ SnippetsSystemFile.__init__(self, path)
+ self.tainted = False
+ self.need_id = False
+
+ def _set_root(self, element):
+ SnippetsSystemFile._set_root(self, element)
+ self.root = element
+
+ def add_prop(self, node, tag, data):
+ if data[tag]:
+ prop = et.SubElement(node, tag)
+ prop.text = data[tag]
+
+ return prop
+ else:
+ return None
+
+ def new_snippet(self, properties=None):
+ if (not self.ok) or self.root is None:
+ return None
+
+ element = et.SubElement(self.root, 'snippet')
+
+ if properties:
+ for prop in properties:
+ sub = et.SubElement(element, prop)
+ sub.text = properties[prop]
+
+ self.tainted = True
+
+ return Library().add_snippet(self, element)
+
+ def set_language(self, element):
+ SnippetsSystemFile.set_language(self, element)
+
+ filename = os.path.basename(self.path).lower()
+
+ if not self.language and filename == "global.xml":
+ self.modifier = True
+ elif self.language and filename == self.language + ".xml":
+ self.modifier = True
+ else:
+ self.modifier = False
+
+ def create_root(self, language):
+ if self.loaded:
+ helper.snippets_debug('Not creating root, already loaded')
+ return
+
+ if language:
+ root = et.Element('snippets', {'language': language})
+ self.path = os.path.join(Library().userdir, language.lower() + '.xml')
+ else:
+ root = et.Element('snippets')
+ self.path = os.path.join(Library().userdir, 'global.xml')
+
+ self._set_root(root)
+ self.loaded = True
+ self.ok = True
+ self.tainted = True
+ self.save()
+
+ def remove(self, element):
+ try:
+ self.root.remove(element)
+ self.tainted = True
+ except:
+ return
+
+ try:
+ self.root[0]
+ except:
+ # No more elements, this library is useless now
+ Library().remove_library(self)
+
+ def save(self):
+ if not self.ok or self.root is None or not self.tainted:
+ return
+
+ path = os.path.dirname(self.path)
+
+ try:
+ if not os.path.isdir(path):
+ os.makedirs(path, 0o755)
+ except OSError:
+ # TODO: this is bad...
+ sys.stderr.write("Error in making dirs\n")
+
+ try:
+ helper.write_xml(self.root, self.path, ('text', 'accelerator'))
+ self.tainted = False
+ except IOError:
+ # Couldn't save, what to do
+ sys.stderr.write("Could not save user snippets file to " + \
+ self.path + "\n")
+
+ def unload(self):
+ SnippetsSystemFile.unload(self)
+ self.root = None
+
+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 Library(Singleton):
+ def __init_once__(self):
+ self._accelerator_activated_cb = []
+ self.loaded = False
+ self.check_buffer = Gtk.TextBuffer()
+
+ def set_dirs(self, userdir, systemdirs):
+ self.userdir = userdir
+ self.systemdirs = systemdirs
+
+ self.libraries = {}
+ self.containers = {}
+ self.overridden = {}
+ self.loaded_ids = []
+
+ self.loaded = False
+
+ def add_accelerator_callback(self, cb):
+ self._accelerator_activated_cb.append(cb)
+
+ def remove_accelerator_callback(self, cb):
+ self._accelerator_activated_cb.remove(cb)
+
+ def accelerator_activated(self, group, obj, keyval, mod):
+ ret = False
+
+ for cb in self._accelerator_activated_cb:
+ ret = cb(group, obj, keyval, mod)
+
+ if ret:
+ break
+
+ return ret
+
+ def add_snippet(self, library, element):
+ container = self.container(library.language)
+ overrided = self.overrided(library, element)
+
+ if overrided:
+ overrided.set_library(library)
+ helper.snippets_debug('Snippet is overriden: ' + overrided['description'])
+ return None
+
+ snippet = SnippetData(element, library)
+
+ if snippet.id in self.loaded_ids:
+ helper.snippets_debug('Not added snippet ' + str(library.language) + \
+ '::' + snippet['description'] + ' (duplicate)')
+ return None
+
+ snippet = container.append(snippet)
+ helper.snippets_debug('Added snippet ' + str(library.language) + '::' + \
+ snippet['description'])
+
+ if snippet and snippet.override:
+ self.add_override(snippet)
+
+ if snippet.id:
+ self.loaded_ids.append(snippet.id)
+
+ return snippet
+
+ def container(self, language):
+ language = self.normalize_language(language)
+
+ if not language in self.containers:
+ self.containers[language] = LanguageContainer(language)
+
+ return self.containers[language]
+
+ def get_user_library(self, language):
+ target = None
+
+ if language in self.libraries:
+ for library in self.libraries[language]:
+ if isinstance(library, SnippetsUserFile) and library.modifier:
+ target = library
+ elif not isinstance(library, SnippetsUserFile):
+ break
+
+ if not target:
+ # Create a new user file then
+ helper.snippets_debug('Creating a new user file for language ' + \
+ str(language))
+ target = SnippetsUserFile()
+ target.create_root(language)
+ self.add_library(target)
+
+ return target
+
+ def new_snippet(self, language, properties=None):
+ language = self.normalize_language(language)
+ library = self.get_user_library(language)
+
+ return library.new_snippet(properties)
+
+ def revert_snippet(self, snippet):
+ # This will revert the snippet to the one it overrides
+ if not snippet.can_modify() or not snippet.override in self.overridden:
+ # It can't be reverted, shouldn't happen, but oh..
+ return
+
+ # The snippet in self.overriden only contains the property contents and
+ # the library it belongs to
+ revertto = self.overridden[snippet.override]
+ del self.overridden[snippet.override]
+
+ if revertto:
+ snippet.revert(revertto)
+
+ if revertto.id:
+ self.loaded_ids.append(revertto.id)
+
+ def remove_snippet(self, snippet):
+ if not snippet.can_modify() or snippet.is_override():
+ return
+
+ # Remove from the library
+ userlib = snippet.library()
+ userlib.remove(snippet.node)
+
+ # Remove from the container
+ container = self.containers[userlib.language]
+ container.remove(snippet)
+
+ def overrided(self, library, element):
+ id = NamespacedId(library.language, element.attrib.get('id')).id
+
+ if id in self.overridden:
+ snippet = SnippetData(element, None)
+ snippet.set_node(None)
+
+ self.overridden[id] = snippet
+ return snippet
+ else:
+ return None
+
+ def add_override(self, snippet):
+ helper.snippets_debug('Add override:', snippet.override)
+ if not snippet.override in self.overridden:
+ self.overridden[snippet.override] = None
+
+ def add_library(self, library):
+ library.ensure_language()
+
+ if not library.ok:
+ helper.snippets_debug('Library in wrong format, ignoring')
+ return False
+
+ helper.snippets_debug('Adding library (' + str(library.language) + '): ' + \
+ library.path)
+
+ if library.language in self.libraries:
+ # Make sure all the user files are before the system files
+ if isinstance(library, SnippetsUserFile):
+ self.libraries[library.language].insert(0, library)
+ else:
+ self.libraries[library.language].append(library)
+ else:
+ self.libraries[library.language] = [library]
+
+ return True
+
+ def remove_library(self, library):
+ if not library.ok:
+ return
+
+ if library.path and os.path.isfile(library.path):
+ os.unlink(library.path)
+
+ try:
+ self.libraries[library.language].remove(library)
+ except KeyError:
+ True
+
+ container = self.containers[library.language]
+
+ for snippet in list(container.snippets):
+ if snippet.library() == library:
+ container.remove(snippet)
+
+ def add_user_library(self, path):
+ library = SnippetsUserFile(path)
+ return self.add_library(library)
+
+ def add_system_library(self, path):
+ library = SnippetsSystemFile(path)
+ return self.add_library(library)
+
+ def find_libraries(self, path, searched, addcb):
+ helper.snippets_debug("Finding in: " + path)
+
+ if not os.path.isdir(path):
+ return searched
+
+ files = os.listdir(path)
+ searched.append(path)
+
+ for f in files:
+ f = os.path.realpath(os.path.join(path, f))
+
+ # Determine what language this file provides snippets for
+ if os.path.isfile(f):
+ addcb(f)
+
+ return searched
+
+ def normalize_language(self, language):
+ if language:
+ return language.lower()
+
+ return language
+
+ def remove_container(self, language):
+ for snippet in self.containers[language].snippets:
+ if snippet.id in self.loaded_ids:
+ self.loaded_ids.remove(snippet.id)
+
+ if snippet.override in self.overridden:
+ del self.overridden[snippet.override]
+
+ del self.containers[language]
+
+ def get_accel_group(self, language):
+ language = self.normalize_language(language)
+ container = self.container(language)
+
+ self.ensure(language)
+ return container.accel_group
+
+ def save(self, language):
+ language = self.normalize_language(language)
+
+ if language in self.libraries:
+ for library in self.libraries[language]:
+ if isinstance(library, SnippetsUserFile):
+ library.save()
+ else:
+ break
+
+ def ref(self, language):
+ language = self.normalize_language(language)
+
+ helper.snippets_debug('Ref:', language)
+ self.container(language).ref()
+
+ def unref(self, language):
+ language = self.normalize_language(language)
+
+ helper.snippets_debug('Unref:', language)
+
+ if language in self.containers:
+ if not self.containers[language].unref() and \
+ language in self.libraries:
+
+ for library in self.libraries[language]:
+ library.unload()
+
+ self.remove_container(language)
+
+ def ensure(self, language):
+ self.ensure_files()
+ language = self.normalize_language(language)
+
+ # Ensure language as well as the global snippets (None)
+ for lang in (None, language):
+ if lang in self.libraries:
+ # Ensure the container exists
+ self.container(lang)
+
+ for library in self.libraries[lang]:
+ library.ensure()
+
+ def ensure_files(self):
+ if self.loaded:
+ return
+
+ searched = []
+ searched = self.find_libraries(self.userdir, searched, \
+ self.add_user_library)
+
+ for d in self.systemdirs:
+ searched = self.find_libraries(d, searched, \
+ self.add_system_library)
+
+ self.loaded = True
+
+ def valid_accelerator(self, keyval, mod):
+ mod &= Gtk.accelerator_get_default_mod_mask()
+
+ return (mod and (Gdk.keyval_to_unicode(keyval) or \
+ keyval in range(Gdk.KEY_F1, Gdk.KEY_F12 + 1)))
+
+ def valid_tab_trigger(self, trigger):
+ if not trigger:
+ return True
+
+ return helper.is_tab_trigger(trigger)
+
+ # Snippet getters
+ # ===============
+ def _from_prop(self, prop, value, language=None):
+ self.ensure_files()
+
+ result = []
+ language = self.normalize_language(language)
+
+ if not language in self.containers:
+ return []
+
+ self.ensure(language)
+ result = self.containers[language].from_prop(prop, value)
+
+ if len(result) == 0 and language and None in self.containers:
+ result = self.containers[None].from_prop(prop, value)
+
+ return result
+
+ # Get snippets for a given language
+ def get_snippets(self, language=None):
+ self.ensure_files()
+ language = self.normalize_language(language)
+
+ if not language in self.libraries:
+ return []
+
+ self.ensure(language)
+
+ return list(self.containers[language].snippets)
+
+ # Get snippets for a given accelerator
+ def from_accelerator(self, accelerator, language=None):
+ return self._from_prop('accelerator', accelerator, language)
+
+ # Get snippets for a given tag
+ def from_tag(self, tag, language=None):
+ return self._from_prop('tag', tag, language)
+
+ # Get snippets for a given drop target
+ def from_drop_target(self, drop_target, language=None):
+ return self._from_prop('drop-targets', drop_target, language)
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/manager.py b/plugins/snippets/snippets/manager.py
new file mode 100644
index 0000000..ca64f18
--- /dev/null
+++ b/plugins/snippets/snippets/manager.py
@@ -0,0 +1,1143 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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 tempfile
+import shutil
+
+from gi.repository import Gtk, Gio, Gdk, GObject
+
+from .snippet import Snippet
+from . import helper
+from .library import Library
+from .importer import Importer
+from .exporter import Exporter
+from .languagemanager import get_language_manager
+
+try:
+ import gettext
+ gettext.bindtextdomain('gedit')
+ gettext.textdomain('gedit')
+ _ = gettext.gettext
+except:
+ _ = lambda s: s
+
+class Manager(Gtk.Window, Gtk.Buildable):
+ NAME_COLUMN = 0
+ SORT_COLUMN = 1
+ LANG_COLUMN = 2
+ SNIPPET_COLUMN = 3
+ TARGET_URI = 105
+
+ __gtype_name__ = "GeditSnippetsManager"
+
+ model = None
+ drag_icons = ('gnome-mime-application-x-tarz', 'gnome-package', 'package')
+ default_export_name = _('Snippets archive') + '.tar.gz'
+ dragging = False
+
+ def __init__(self):
+ self.snippet = None
+ self._temp_export = None
+ self._size = (0, 0)
+
+ self.key_press_id = 0
+ self.dnd_target_list = Gtk.TargetList.new([])
+ self.dnd_target_list.add(Gdk.atom_intern("text/uri-list", True), 0, self.TARGET_URI)
+
+ def get_final_size(self):
+ return self._size
+
+ def get_language_snippets(self, path, name = None):
+ library = Library()
+
+ name = self.get_language(path)
+ nodes = library.get_snippets(name)
+
+ return nodes
+
+ def add_new_snippet_node(self, parent):
+ return self.model.append(parent, ('<i>' + _('Add a new snippet…') + \
+ '</i>', '', None, None))
+
+ def fill_language(self, piter, expand=True):
+ # Remove all children
+ child = self.model.iter_children(piter)
+
+ while child and self.model.remove(child):
+ True
+
+ path = self.model.get_path(piter)
+ nodes = self.get_language_snippets(path)
+ language = self.get_language(path)
+
+ Library().ref(language)
+
+ if nodes:
+ for node in nodes:
+ self.add_snippet(piter, node)
+ else:
+ # Add node that tells there are no snippets currently
+ self.add_new_snippet_node(piter)
+
+ if expand:
+ self.tree_view.expand_row(path, False)
+
+ def build_model(self, force_reload = False):
+ window = Gio.Application.get_default().get_active_window()
+ if window:
+ view = window.get_active_view()
+
+ if not view:
+ current_lang = None
+ else:
+ current_lang = view.get_buffer().get_language()
+ else:
+ current_lang = None
+
+ tree_view = self['tree_view_snippets']
+ expand = None
+
+ if not self.model or force_reload:
+ self.model = Gtk.TreeStore(str, str, GObject.Object, object)
+ self.model.set_sort_column_id(self.SORT_COLUMN, Gtk.SortType.ASCENDING)
+
+ manager = get_language_manager()
+
+ langs = [manager.get_language(x) for x in manager.get_language_ids()]
+ langs.sort(key=lambda x: x.get_name())
+
+ piter = self.model.append(None, (_('Global'), '', None, None))
+
+ # Add dummy node
+ self.model.append(piter, ('', '', None, None))
+
+ nm = None
+
+ if current_lang:
+ nm = current_lang.get_name()
+
+ for lang in langs:
+ name = lang.get_name()
+ parent = self.model.append(None, (name, name, lang, None))
+
+ # Add dummy node
+ self.model.append(parent, ('', '', None, None))
+
+ if (nm == name):
+ expand = parent
+ else:
+ if current_lang:
+ piter = self.model.get_iter_first()
+ nm = current_lang.get_name()
+
+ while piter:
+ lang = self.model.get_value(piter, \
+ self.SORT_COLUMN)
+
+ if lang == nm:
+ expand = piter
+ break;
+
+ piter = self.model.iter_next(piter)
+
+ tree_view.set_model(self.model)
+
+ if not expand:
+ expand = self.model.get_iter_first()
+
+ tree_view.expand_row(self.model.get_path(expand), False)
+ self.select_iter(expand)
+
+ def get_cell_data_pixbuf_cb(self, column, cell, model, iter, data):
+ snippet = model.get_value(iter, self.SNIPPET_COLUMN)
+
+ if snippet and not snippet.valid:
+ cell.set_property('icon-name', 'dialog-error')
+ else:
+ cell.set_property('icon-name', None)
+
+ cell.set_property('xalign', 1.0)
+
+ def get_cell_data_cb(self, column, cell, model, iter, data):
+ snippet = model.get_value(iter, self.SNIPPET_COLUMN)
+
+ cell.set_property('editable', snippet != None)
+ cell.set_property('markup', model.get_value(iter, self.NAME_COLUMN))
+
+ def on_tree_view_drag_data_get(self, widget, context, selection_data, info, time):
+ gfile = Gio.file_new_for_path(self._temp_export)
+ selection_data.set_uris([gfile.get_uri()])
+
+ def on_tree_view_drag_begin(self, widget, context):
+ self.dragging = True
+
+ if self._temp_export:
+ shutil.rmtree(os.path.dirname(self._temp_export))
+ self._temp_export = None
+
+ if self.dnd_name:
+ Gtk.drag_set_icon_name(context, self.dnd_name, 0, 0)
+
+ dirname = tempfile.mkdtemp()
+ filename = os.path.join(dirname, self.default_export_name)
+
+ # Generate temporary file name
+ self.export_snippets(filename, False)
+ self._temp_export = filename
+
+ def on_tree_view_drag_end(self, widget, context):
+ self.dragging = False
+
+ def on_tree_view_drag_data_received(self, widget, context, x, y, selection, info, timestamp):
+ uris = selection.get_uris()
+
+ files = [Gio.file_new_for_uri(u) for u in uris]
+
+ self.import_snippets(files)
+
+ def on_tree_view_drag_motion(self, widget, context, x, y, timestamp):
+ # Return False if we are dragging
+ if self.dragging:
+ return False
+
+ # Check uri target
+ if not Gtk.targets_include_uri(context.targets):
+ return False
+
+ # Check action
+ action = None
+ if context.suggested_action == Gdk.DragAction.COPY:
+ action = Gdk.DragAction.COPY
+ else:
+ for act in context.actions:
+ if act == Gdk.DragAction.COPY:
+ action = Gdk.DragAction.COPY
+ break
+
+ if action == Gdk.DragAction.COPY:
+ context.drag_status(Gdk.DragAction.COPY, timestamp)
+ return True
+ else:
+ return False
+
+ def build_dnd(self):
+ tv = self.tree_view
+
+ # Set it as a drag source for exporting snippets
+ tv.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [], Gdk.DragAction.DEFAULT | Gdk.DragAction.COPY)
+ tv.drag_source_set_target_list(self.dnd_target_list)
+
+ # Set it as a drag destination for importing snippets
+ tv.drag_dest_set(Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP,
+ [], Gdk.DragAction.DEFAULT | Gdk.DragAction.COPY)
+
+ tv.drag_dest_set_target_list(self.dnd_target_list)
+
+ tv.connect('drag_data_get', self.on_tree_view_drag_data_get)
+ tv.connect('drag_begin', self.on_tree_view_drag_begin)
+ tv.connect('drag_end', self.on_tree_view_drag_end)
+ tv.connect('drag_data_received', self.on_tree_view_drag_data_received)
+ tv.connect('drag_motion', self.on_tree_view_drag_motion)
+
+ theme = Gtk.IconTheme.get_for_screen(tv.get_screen())
+
+ self.dnd_name = None
+ for name in self.drag_icons:
+ icon = theme.lookup_icon(name, Gtk.IconSize.DND, 0)
+
+ if icon:
+ self.dnd_name = name
+ break
+
+ def build_tree_view(self):
+ self.tree_view = self['tree_view_snippets']
+
+ self.column = Gtk.TreeViewColumn(None)
+
+ self.renderer = Gtk.CellRendererText()
+ self.column.pack_start(self.renderer, False)
+ self.column.set_cell_data_func(self.renderer, self.get_cell_data_cb, None)
+
+ renderer = Gtk.CellRendererPixbuf()
+ self.column.pack_start(renderer, True)
+ self.column.set_cell_data_func(renderer, self.get_cell_data_pixbuf_cb, None)
+
+ self.tree_view.append_column(self.column)
+
+ self.renderer.connect('edited', self.on_cell_edited)
+ self.renderer.connect('editing-started', self.on_cell_editing_started)
+
+ selection = self.tree_view.get_selection()
+ selection.set_mode(Gtk.SelectionMode.MULTIPLE)
+ selection.connect('changed', self.on_tree_view_selection_changed)
+
+ self.build_dnd()
+
+ def do_parser_finished(self, builder):
+ self.builder = builder
+
+ handlers_dic = {
+ 'on_add_snippet_button_clicked': self.on_add_snippet_button_clicked,
+ 'on_remove_snippet_button_clicked': self.on_remove_snippet_button_clicked,
+ 'on_import_snippets_button_clicked': self.on_import_snippets_button_clicked,
+ 'on_export_snippets_button_clicked': self.on_export_snippets_button_clicked,
+ 'on_entry_tab_trigger_focus_out': self.on_entry_tab_trigger_focus_out,
+ 'on_entry_tab_trigger_changed': self.on_entry_tab_trigger_changed,
+ 'on_entry_accelerator_focus_out': self.on_entry_accelerator_focus_out,
+ 'on_entry_accelerator_focus_in': self.on_entry_accelerator_focus_in,
+ 'on_entry_accelerator_key_press': self.on_entry_accelerator_key_press,
+ 'on_source_view_snippet_focus_out': self.on_source_view_snippet_focus_out,
+ 'on_tree_view_snippets_row_expanded': self.on_tree_view_snippets_row_expanded,
+ 'on_tree_view_snippets_key_press': self.on_tree_view_snippets_key_press}
+
+ self.builder.connect_signals(handlers_dic)
+
+ self.build_tree_view()
+ self.build_model()
+
+ # join treeview and toolbar
+ context = self['scrolled_window_snippets'].get_style_context()
+ context.set_junction_sides(Gtk.JunctionSides.BOTTOM)
+ context = self['toolbar'].get_style_context()
+ context.set_junction_sides(Gtk.JunctionSides.TOP)
+ context.set_junction_sides(Gtk.JunctionSides.BOTTOM)
+
+ source_view = self['source_view_snippet']
+ manager = get_language_manager()
+ lang = manager.get_language('snippets')
+
+ if lang:
+ source_view.get_buffer().set_highlight_syntax(True)
+ source_view.get_buffer().set_language(lang)
+
+ combo = self['combo_drop_targets']
+
+ entry = combo.get_child()
+ entry.connect('focus-out-event', self.on_entry_drop_targets_focus_out)
+ entry.connect('drag-data-received', self.on_entry_drop_targets_drag_data_received)
+
+ lst = entry.drag_dest_get_target_list()
+ lst.add_uri_targets(self.TARGET_URI)
+
+ def do_configure_event(self, event):
+ if self.get_realized():
+ alloc = self.get_allocation()
+ self._size = (alloc.width, alloc.height)
+
+ return Gtk.Dialog.do_configure_event(self, event)
+
+ def __getitem__(self, key):
+ return self.builder.get_object(key)
+
+ def is_filled(self, piter):
+ if not self.model.iter_has_child(piter):
+ return True
+
+ child = self.model.iter_children(piter)
+ nm = self.model.get_value(child, self.NAME_COLUMN)
+ lang = self.model.get_value(child, self.LANG_COLUMN)
+ snippet = self.model.get_value(child, self.SNIPPET_COLUMN)
+
+ return (lang or snippet or nm)
+
+ def fill_if_needed(self, piter, expand=True):
+ if not self.is_filled(piter):
+ self.fill_language(piter, expand)
+
+ def find_iter(self, parent, snippet):
+ self.fill_if_needed(parent)
+ piter = self.model.iter_children(parent)
+
+ while (piter):
+ sn = self.model.get_value(piter, self.SNIPPET_COLUMN)
+
+ if sn == snippet.data:
+ return piter
+
+ piter = self.model.iter_next(piter)
+
+ return None
+
+ def selected_snippets_state(self):
+ snippets = self.selected_snippets(False)
+ override = False
+ remove = False
+ system = False
+
+ for snippet in snippets:
+ if not snippet:
+ continue
+
+ if snippet.is_override():
+ override = True
+ elif snippet.can_modify():
+ remove = True
+ else:
+ system = True
+
+ # No need to continue if both are found
+ if override and remove:
+ break
+
+ return (override, remove, system)
+
+ def update_toolbar_buttons(self):
+ button_add = self['add_snippet_button']
+ button_remove = self['remove_snippet_button']
+
+ button_add.set_sensitive(self.language_path != None)
+ override, remove, system = self.selected_snippets_state()
+
+ if not (override ^ remove) or system:
+ button_remove.set_sensitive(False)
+ button_remove.set_icon_name('list-remove-symbolic')
+ else:
+ button_remove.set_sensitive(True)
+
+ if override:
+ button_remove.set_icon_name('edit-undo-symbolic')
+ tooltip = _('Revert selected snippet')
+ else:
+ button_remove.set_icon_name('list-remove-symbolic')
+ tooltip = _('Delete selected snippet')
+
+ button_remove.set_tooltip_text(tooltip)
+
+ def snippet_changed(self, piter = None):
+ if piter:
+ node = self.model.get_value(piter, self.SNIPPET_COLUMN)
+ s = Snippet(node)
+ else:
+ s = self.snippet
+ piter = self.find_iter(self.model.get_iter(self.language_path), s)
+
+ if piter:
+ nm = s.display()
+
+ self.model.set_value(piter, self.NAME_COLUMN, nm)
+ self.model.set_value(piter, self.SORT_COLUMN, nm)
+ self.update_toolbar_buttons()
+ self.entry_tab_trigger_update_valid()
+
+ return piter
+
+ def add_snippet(self, parent, snippet):
+ piter = self.model.append(parent, ('', '', None, snippet))
+
+ return self.snippet_changed(piter)
+
+ def snippet_from_iter(self, model, piter):
+ parent = model.iter_parent(piter)
+
+ if parent:
+ return model.get_value(piter, self.SNIPPET_COLUMN)
+ else:
+ return None
+
+ def language_snippets(self, model, parent, as_path=False):
+ self.fill_if_needed(parent, False)
+ piter = model.iter_children(parent)
+ snippets = []
+
+ if not piter:
+ return snippets
+
+ while piter:
+ snippet = self.snippet_from_iter(model, piter)
+
+ if snippet:
+ if as_path:
+ snippets.append(model.get_path(piter))
+ else:
+ snippets.append(snippet)
+
+ piter = model.iter_next(piter)
+
+ return snippets
+
+ def selected_snippets(self, include_languages=True, as_path=False):
+ selection = self.tree_view.get_selection()
+ (model, paths) = selection.get_selected_rows()
+ snippets = []
+
+ if paths and len(paths) != 0:
+ for p in paths:
+ piter = model.get_iter(p)
+ parent = model.iter_parent(piter)
+
+ if not piter:
+ continue
+
+ if parent:
+ snippet = self.snippet_from_iter(model, piter)
+
+ if not snippet:
+ continue
+
+ if as_path:
+ snippets.append(p)
+ else:
+ snippets.append(snippet)
+ elif include_languages:
+ snippets += self.language_snippets(model, piter, as_path)
+
+ return snippets
+
+ def selected_snippet(self):
+ selection = self.tree_view.get_selection()
+ (model, paths) = selection.get_selected_rows()
+
+ if len(paths) == 1:
+ piter = model.get_iter(paths[0])
+ parent = model.iter_parent(piter)
+ snippet = self.snippet_from_iter(model, piter)
+
+ return parent, piter, snippet
+ else:
+ return None, None, None
+
+ def selection_changed(self):
+ if not self.snippet:
+ sens = False
+
+ self['entry_tab_trigger'].set_text('')
+ self['entry_accelerator'].set_text('')
+ buf = self['source_view_snippet'].get_buffer()
+ buf.begin_not_undoable_action()
+ buf.set_text('')
+ buf.end_not_undoable_action()
+ self['combo_drop_targets'].get_child().set_text('')
+
+ else:
+ sens = True
+
+ self['entry_tab_trigger'].set_text(self.snippet['tag'])
+ self['entry_accelerator'].set_text( \
+ self.snippet.accelerator_display())
+ self['combo_drop_targets'].get_child().set_text(', '.join(self.snippet['drop-targets']))
+
+ buf = self['source_view_snippet'].get_buffer()
+ buf.begin_not_undoable_action()
+ buf.set_text(self.snippet['text'])
+ buf.end_not_undoable_action()
+
+
+ for name in ['source_view_snippet', 'label_tab_trigger',
+ 'entry_tab_trigger', 'label_accelerator',
+ 'entry_accelerator', 'label_drop_targets',
+ 'combo_drop_targets']:
+ self[name].set_sensitive(sens)
+
+ self.update_toolbar_buttons()
+
+ def select_iter(self, piter, unselect=True):
+ selection = self.tree_view.get_selection()
+
+ if unselect:
+ selection.unselect_all()
+
+ selection.select_iter(piter)
+
+ self.tree_view.scroll_to_cell(self.model.get_path(piter), None, \
+ True, 0.5, 0.5)
+
+ def get_language(self, path):
+ if path.get_indices()[0] == 0:
+ return None
+ else:
+ return self.model.get_value(self.model.get_iter(path),
+ self.LANG_COLUMN).get_id()
+
+ def new_snippet(self, properties=None):
+ if not self.language_path:
+ return None
+
+ snippet = Library().new_snippet(self.get_language(self.language_path), properties)
+
+ return Snippet(snippet)
+
+ def get_dummy(self, parent):
+ if not self.model.iter_n_children(parent) == 1:
+ return None
+
+ dummy = self.model.iter_children(parent)
+
+ if not self.model.get_value(dummy, self.SNIPPET_COLUMN):
+ return dummy
+
+ return None
+
+ def unref_languages(self):
+ piter = self.model.get_iter_first()
+ library = Library()
+
+ while piter:
+ if self.is_filled(piter):
+ language = self.get_language(self.model.get_path(piter))
+ library.save(language)
+
+ library.unref(language)
+
+ piter = self.model.iter_next(piter)
+
+ # Callbacks
+ def do_destroy(self):
+ Gtk.Dialog.do_destroy(self)
+
+ if not self.model:
+ return
+
+ # Remove temporary drag export
+ if self._temp_export:
+ shutil.rmtree(os.path.dirname(self._temp_export))
+ self._temp_export = None
+
+ self.unref_languages()
+ self.snippet = None
+ self.model = None
+
+ def on_cell_editing_started(self, renderer, editable, path):
+ piter = self.model.get_iter(path)
+
+ if not self.model.iter_parent(piter):
+ renderer.stop_editing(True)
+ editable.remove_widget()
+ elif isinstance(editable, Gtk.Entry):
+ if self.snippet:
+ editable.set_text(self.snippet['description'])
+ else:
+ # This is the `Add a new snippet...` item
+ editable.set_text('')
+
+ editable.grab_focus()
+
+ def on_cell_edited(self, cell, path, new_text):
+ if new_text != '':
+ piter = self.model.get_iter(path)
+ node = self.model.get_value(piter, self.SNIPPET_COLUMN)
+
+ if node:
+ if node == self.snippet.data:
+ s = self.snippet
+ else:
+ s = Snippet(node)
+
+ s['description'] = new_text
+ self.snippet_changed(piter)
+ self.select_iter(piter)
+ else:
+ # This is the `Add a new snippet...` item
+ # We create a new snippet
+ snippet = self.new_snippet({'description': new_text})
+
+ if snippet:
+ self.model.set_value(piter, self.SNIPPET_COLUMN, snippet.data)
+ self.snippet_changed(piter)
+ self.snippet = snippet
+ self.selection_changed()
+
+ def on_entry_accelerator_focus_out(self, entry, event):
+ if not self.snippet:
+ return
+
+ entry.set_text(self.snippet.accelerator_display())
+
+ def entry_tab_trigger_update_valid(self):
+ entry = self['entry_tab_trigger']
+ text = entry.get_text()
+
+ if text and not Library().valid_tab_trigger(text):
+ img = self['image_tab_trigger']
+ img.set_from_icon_name('dialog-error', Gtk.IconSize.BUTTON)
+ img.show()
+
+ #self['hbox_tab_trigger'].set_spacing(3)
+ tip = _('This is not a valid Tab trigger. Triggers can either contain alphanumeric characters (or _, : and .) or a single (non-alphanumeric) character like: {, [, etc.')
+
+ entry.set_tooltip_text(tip)
+ img.set_tooltip_text(tip)
+ else:
+ self['image_tab_trigger'].hide()
+ #self['hbox_tab_trigger'].set_spacing(0)
+ entry.set_tooltip_text(_('Single word the snippet is activated with after pressing Tab'))
+
+ return False
+
+ def on_entry_tab_trigger_focus_out(self, entry, event):
+ if not self.snippet:
+ return
+
+ text = entry.get_text()
+
+ # save tag
+ self.snippet['tag'] = text
+ self.snippet_changed()
+
+ def on_entry_drop_targets_focus_out(self, entry, event):
+ if not self.snippet:
+ return
+
+ text = entry.get_text()
+
+ # save drop targets
+ self.snippet['drop-targets'] = text
+ self.snippet_changed()
+
+ def on_entry_tab_trigger_changed(self, entry):
+ self.entry_tab_trigger_update_valid()
+
+ def on_source_view_snippet_focus_out(self, source_view, event):
+ if not self.snippet:
+ return
+
+ buf = source_view.get_buffer()
+ text = buf.get_text(buf.get_start_iter(), \
+ buf.get_end_iter(), False)
+
+ self.snippet['text'] = text
+ self.snippet_changed()
+
+ def on_add_snippet_button_clicked(self, button):
+ snippet = self.new_snippet()
+
+ if not snippet:
+ return
+
+ parent = self.model.get_iter(self.language_path)
+ path = self.model.get_path(parent)
+
+ dummy = self.get_dummy(parent)
+
+ if dummy:
+ # Remove the dummy
+ self.model.remove(dummy)
+
+ # Add the snippet
+ piter = self.add_snippet(parent, snippet.data)
+ self.select_iter(piter)
+
+ if not self.tree_view.row_expanded(path):
+ self.tree_view.expand_row(path, False)
+ self.select_iter(piter)
+
+ self.tree_view.grab_focus()
+
+ path = self.model.get_path(piter)
+ self.tree_view.set_cursor(path, self.column, True)
+
+ def file_filter(self, name, pattern):
+ fil = Gtk.FileFilter()
+ fil.set_name(name)
+
+ for p in pattern:
+ fil.add_pattern(p)
+
+ return fil
+
+ def import_snippets(self, files):
+ success = True
+
+ for gfile in files:
+ if not gfile.has_uri_scheme('file'):
+ continue
+
+ # Remove file://
+ filename = gfile.get_path()
+
+ importer = Importer(filename)
+ error = importer.run()
+
+ if error:
+ message = _('The following error occurred while importing: %s') % error
+ success = False
+ helper.message_dialog(self.get_toplevel(), Gtk.MessageType.ERROR, message)
+
+ self.build_model(True)
+
+ if success:
+ message = _('Import successfully completed')
+ helper.message_dialog(self.get_toplevel(), Gtk.MessageType.INFO, message)
+
+ def on_import_response(self, dialog, response):
+ if response == Gtk.ResponseType.CANCEL or response == Gtk.ResponseType.CLOSE:
+ dialog.destroy()
+ return
+
+ f = dialog.get_files()
+ dialog.destroy()
+
+ self.import_snippets(f)
+
+ def on_import_snippets_button_clicked(self, button):
+ dlg = Gtk.FileChooserDialog(parent=self.get_toplevel(), title=_("Import snippets"),
+ action=Gtk.FileChooserAction.OPEN,
+ buttons=(_("_Cancel"), Gtk.ResponseType.CANCEL,
+ _("_Open"), Gtk.ResponseType.OK))
+
+ dlg.add_filter(self.file_filter(_('All supported archives'), ('*.gz','*.bz2','*.tar', '*.xml')))
+ dlg.add_filter(self.file_filter(_('Gzip compressed archive'), ('*.tar.gz',)))
+ dlg.add_filter(self.file_filter(_('Bzip2 compressed archive'), ('*.tar.bz2',)))
+ dlg.add_filter(self.file_filter(_('Single snippets file'), ('*.xml',)))
+ dlg.add_filter(self.file_filter(_('All files'), '*'))
+
+ dlg.connect('response', self.on_import_response)
+ dlg.set_local_only(True)
+
+ dlg.show()
+
+ def export_snippets_real(self, filename, snippets, show_dialogs=True):
+ export = Exporter(filename, snippets)
+ error = export.run()
+
+ if error:
+ message = _('The following error occurred while exporting: %s') % error
+ msgtype = Gtk.MessageType.ERROR
+ retval = False
+ else:
+ message = _('Export successfully completed')
+ msgtype = Gtk.MessageType.INFO
+ retval = True
+
+ if show_dialogs:
+ helper.message_dialog(self.get_toplevel(), msgtype, message)
+
+ return retval
+
+ def on_export_response(self, dialog, response):
+ filename = dialog.get_filename()
+ snippets = dialog._export_snippets
+
+ dialog.destroy()
+
+ if response != Gtk.ResponseType.OK:
+ return
+
+ self.export_snippets_real(filename, snippets);
+
+ def export_snippets(self, filename=None, show_dialogs=True):
+ snippets = self.selected_snippets()
+
+ if not snippets or len(snippets) == 0:
+ return False
+
+ usersnippets = []
+ systemsnippets = []
+
+ # Iterate through snippets and look for system snippets
+ for snippet in snippets:
+ if snippet.can_modify():
+ usersnippets.append(snippet)
+ else:
+ systemsnippets.append(snippet)
+
+ export_snippets = snippets
+
+ if len(systemsnippets) != 0 and show_dialogs:
+ # Ask if system snippets should also be exported
+ message = _('Do you want to include selected <b>system</b> snippets in your export?')
+ mes = Gtk.MessageDialog(flags=Gtk.DialogFlags.MODAL,
+ type=Gtk.MessageType.QUESTION,
+ buttons=Gtk.ButtonsType.YES_NO,
+ message_format=message)
+ mes.set_property('use-markup', True)
+ resp = mes.run()
+ mes.destroy()
+
+ if resp == Gtk.ResponseType.NO:
+ export_snippets = usersnippets
+ elif resp != Gtk.ResponseType.YES:
+ return False
+
+ if len(export_snippets) == 0 and show_dialogs:
+ message = _('There are no snippets selected to be exported')
+ helper.message_dialog(self.get_toplevel(), Gtk.MessageType.QUESTION, message)
+ return False
+
+ if not filename:
+ dlg = Gtk.FileChooserDialog(parent=self.get_toplevel(), title=_('Export snippets'),
+ action=Gtk.FileChooserAction.SAVE,
+ buttons=(_("_Cancel"), Gtk.ResponseType.CANCEL,
+ _("_Save"), Gtk.ResponseType.OK))
+
+ dlg._export_snippets = export_snippets
+ dlg.add_filter(self.file_filter(_('All supported archives'), ('*.gz','*.bz2','*.tar')))
+ dlg.add_filter(self.file_filter(_('Gzip compressed archive'), ('*.tar.gz',)))
+ dlg.add_filter(self.file_filter(_('Bzip2 compressed archive'), ('*.tar.bz2',)))
+
+ dlg.add_filter(self.file_filter(_('All files'), '*'))
+ dlg.set_do_overwrite_confirmation(True)
+ dlg.set_current_name(self.default_export_name)
+
+ dlg.connect('response', self.on_export_response)
+ dlg.set_local_only(True)
+
+ dlg.show()
+ return True
+ else:
+ return self.export_snippets_real(filename, export_snippets, show_dialogs)
+
+ def on_export_snippets_button_clicked(self, button):
+ snippets = self.selected_snippets()
+
+ if not snippets or len(snippets) == 0:
+ return
+
+ usersnippets = []
+ systemsnippets = []
+
+ # Iterate through snippets and look for system snippets
+ for snippet in snippets:
+ if snippet.can_modify():
+ usersnippets.append(snippet)
+ else:
+ systemsnippets.append(snippet)
+
+ dlg = Gtk.FileChooserDialog(parent=self.get_toplevel(), title=_('Export snippets'),
+ action=Gtk.FileChooserAction.SAVE,
+ buttons=(_('_Cancel'), Gtk.ResponseType.CANCEL,
+ _('_Save'), Gtk.ResponseType.OK))
+
+ dlg._export_snippets = snippets
+
+ if len(systemsnippets) != 0:
+ # Ask if system snippets should also be exported
+ message = _('Do you want to include selected <b>system</b> snippets in your export?')
+ mes = Gtk.MessageDialog(flags=Gtk.DialogFlags.MODAL,
+ type=Gtk.MessageType.QUESTION,
+ buttons=Gtk.ButtonsType.YES_NO,
+ message_format=message)
+ mes.set_property('use-markup', True)
+ resp = mes.run()
+ mes.destroy()
+
+ if resp == Gtk.ResponseType.NO:
+ dlg._export_snippets = usersnippets
+ elif resp != Gtk.ResponseType.YES:
+ dlg.destroy()
+ return
+
+ if len(dlg._export_snippets) == 0:
+ dlg.destroy()
+
+ message = _('There are no snippets selected to be exported')
+ helper.message_dialog(self.get_toplevel(), Gtk.MessageType.QUESTION, message)
+ return
+
+ dlg.add_filter(self.file_filter(_('All supported archives'), ('*.gz','*.bz2','*.tar')))
+ dlg.add_filter(self.file_filter(_('Gzip compressed archive'), ('*.tar.gz',)))
+ dlg.add_filter(self.file_filter(_('Bzip2 compressed archive'), ('*.tar.bz2',)))
+
+ dlg.add_filter(self.file_filter(_('All files'), '*'))
+ dlg.set_do_overwrite_confirmation(True)
+ dlg.set_current_name(self.default_export_name)
+
+ dlg.connect('response', self.on_export_response)
+ dlg.set_local_only(True)
+
+ dlg.show()
+
+ def remove_snippet_revert(self, path, piter):
+ node = self.snippet_from_iter(self.model, piter)
+ Library().revert_snippet(node)
+
+ return piter
+
+ def remove_snippet_delete(self, path, piter):
+ node = self.snippet_from_iter(self.model, piter)
+ parent = self.model.iter_parent(piter)
+
+ Library().remove_snippet(node)
+ idx = path.get_indices()
+
+ if self.model.remove(piter):
+ return piter
+ elif idx[-1] != 0:
+ self.select_iter(self.model.get_iter((idx[0], idx[1] - 1)))
+ else:
+ dummy = self.add_new_snippet_node(parent)
+ self.tree_view.expand_row(self.model.get_path(parent), False)
+ return dummy
+
+ def on_remove_snippet_button_clicked(self, button):
+ override, remove, system = self.selected_snippets_state()
+
+ if not (override ^ remove) or system:
+ return
+
+ paths = self.selected_snippets(include_languages=False, as_path=True)
+
+ if override:
+ action = self.remove_snippet_revert
+ else:
+ action = self.remove_snippet_delete
+
+ # Remove selection
+ self.tree_view.get_selection().unselect_all()
+
+ # Create tree row references
+ references = []
+ for path in paths:
+ # FIXME: this should be fixed in pygobject or something
+ references.append(Gtk.TreeRowReference.new(self.model, path))
+
+ # Remove/revert snippets
+ select = None
+ for reference in references:
+ path = reference.get_path()
+ piter = self.model.get_iter(path)
+
+ res = action(path, piter)
+
+ if res:
+ select = res
+
+ if select:
+ self.select_iter(select)
+
+ self.selection_changed()
+
+ def set_accelerator(self, keyval, mod):
+ accelerator = Gtk.accelerator_name(keyval, mod)
+ self.snippet['accelerator'] = accelerator
+
+ return True
+
+ def on_entry_accelerator_key_press(self, entry, event):
+ if event.keyval == Gdk.keyval_from_name('Escape'):
+ # Reset
+ entry.set_text(self.snippet.accelerator_display())
+ self.tree_view.grab_focus()
+
+ return True
+ elif event.keyval == Gdk.keyval_from_name('Delete') or \
+ event.keyval == Gdk.keyval_from_name('BackSpace'):
+ # Remove the accelerator
+ entry.set_text('')
+ self.snippet['accelerator'] = ''
+ self.tree_view.grab_focus()
+
+ self.snippet_changed()
+ return True
+ elif Library().valid_accelerator(event.keyval, event.get_state()):
+ # New accelerator
+ self.set_accelerator(event.keyval, \
+ event.get_state() & Gtk.accelerator_get_default_mod_mask())
+ entry.set_text(self.snippet.accelerator_display())
+ self.snippet_changed()
+ self.tree_view.grab_focus()
+
+ else:
+ return True
+
+ def on_entry_accelerator_focus_in(self, entry, event):
+ if self.snippet['accelerator']:
+ entry.set_text(_('Type a new shortcut, or press Backspace to clear'))
+ else:
+ entry.set_text(_('Type a new shortcut'))
+
+ def update_language_path(self):
+ model, paths = self.tree_view.get_selection().get_selected_rows()
+
+ # Check if all have the same language parent
+ current_parent = None
+
+ for path in paths:
+ piter = model.get_iter(path)
+ parent = model.iter_parent(piter)
+
+ if parent:
+ path = model.get_path(parent)
+
+ if current_parent != None and current_parent != path:
+ current_parent = None
+ break
+ else:
+ current_parent = path
+
+ self.language_path = current_parent
+
+ def on_tree_view_selection_changed(self, selection):
+ parent, piter, node = self.selected_snippet()
+
+ if self.snippet:
+ self.on_entry_tab_trigger_focus_out(self['entry_tab_trigger'],
+ None)
+ self.on_source_view_snippet_focus_out(self['source_view_snippet'],
+ None)
+ self.on_entry_drop_targets_focus_out(self['combo_drop_targets'].get_child(),
+ None)
+
+ self.update_language_path()
+
+ if node:
+ self.snippet = Snippet(node)
+ else:
+ self.snippet = None
+
+ self.selection_changed()
+
+ def iter_after(self, target, after):
+ if not after:
+ return True
+
+ tp = self.model.get_path(target)
+ ap = self.model.get_path(after)
+
+ if tp[0] > ap[0] or (tp[0] == ap[0] and (len(ap) == 1 or tp[1] > ap[1])):
+ return True
+
+ return False
+
+ def on_tree_view_snippets_key_press(self, treeview, event):
+ if event.keyval == Gdk.keyval_from_name('Delete'):
+ self.on_remove_snippet_button_clicked(None)
+ return True
+
+ def on_tree_view_snippets_row_expanded(self, treeview, piter, path):
+ # Check if it is already filled
+ self.fill_if_needed(piter)
+ self.select_iter(piter)
+
+ def on_entry_drop_targets_drag_data_received(self, entry, context, x, y, selection_data, info, timestamp):
+ uris = helper.drop_get_uris(selection_data)
+ if not uris:
+ return
+
+ text = entry.get_text()
+
+ if text:
+ mimes = [text]
+ else:
+ mimes = []
+
+ for uri in uris:
+ try:
+ mime = Gio.content_type_guess(uri)
+ except:
+ mime = None
+
+ if mime:
+ mimes.append(mime)
+
+ entry.set_text(', '.join(mimes))
+ self.on_entry_drop_targets_focus_out(entry, None)
+ context.finish(True, False, timestamp)
+
+ entry.stop_emission('drag_data_received')
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/meson.build b/plugins/snippets/snippets/meson.build
new file mode 100644
index 0000000..1ca34de
--- /dev/null
+++ b/plugins/snippets/snippets/meson.build
@@ -0,0 +1,39 @@
+snippets_sources = [
+ '__init__.py',
+ 'appactivatable.py',
+ 'completion.py',
+ 'document.py',
+ 'exporter.py',
+ 'helper.py',
+ 'importer.py',
+ 'languagemanager.py',
+ 'library.py',
+ 'manager.py',
+ 'parser.py',
+ 'placeholder.py',
+ 'shareddata.py',
+ 'signals.py',
+ 'singleton.py',
+ 'snippet.py',
+ 'substitutionparser.py',
+ 'windowactivatable.py',
+]
+
+install_data(
+ snippets_sources,
+ install_dir: join_paths(
+ pkglibdir,
+ 'plugins',
+ 'snippets',
+ )
+)
+
+install_data(
+ 'snippets.ui',
+ install_dir: join_paths(
+ pkgdatadir,
+ 'plugins',
+ 'snippets',
+ 'ui',
+ )
+)
diff --git a/plugins/snippets/snippets/parser.py b/plugins/snippets/snippets/parser.py
new file mode 100644
index 0000000..2b6043d
--- /dev/null
+++ b/plugins/snippets/snippets/parser.py
@@ -0,0 +1,256 @@
+# Gedit snippets plugin
+# Copyright (C) 2006-2007 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 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 Token:
+ def __init__(self, klass, data):
+ self.klass = klass
+ self.data = data
+
+ def __str__(self):
+ return '%s: [%s]' % (self.klass, self.data)
+
+ def __eq__(self, other):
+ return self.klass == other.klass and self.data == other.data
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+class Parser:
+ SREG_ENV = '[A-Z_]+'
+ SREG_ID = '[0-9]+'
+
+ REG_ESCAPE = re.compile('(\\$(%s|\\(|\\{|<|%s)|`|\\\\)' % (SREG_ENV, SREG_ID))
+
+ def __init__(self, **kwargs):
+ for k, v in kwargs.items():
+ setattr(self, k, v)
+
+ self.position = 0
+ self.data_length = len(self.data)
+
+ self.RULES = (self._match_env, self._match_regex, self._match_placeholder, self._match_shell, self._match_eval, self._text)
+
+ def remains(self):
+ return self.data[self.position:]
+
+ def next_char(self):
+ if self.position + 1 >= self.data_length:
+ return ''
+ else:
+ return self.data[self.position + 1]
+
+ def char(self):
+ if self.position >= self.data_length:
+ return ''
+ else:
+ return self.data[self.position]
+
+ def token(self):
+ self.tktext = ''
+
+ while self.position < self.data_length:
+ try:
+ # Get first character
+ func = {'$': self._rule,
+ '`': self._try_match_shell}[self.char()]
+ except:
+ func = self._text
+
+ # Detect end of text token
+ if func != self._text and self.tktext != '':
+ return Token('text', self.tktext)
+
+ tk = func()
+
+ if tk:
+ return tk
+
+ if self.tktext != '':
+ return Token('text', self.tktext)
+
+ def _need_escape(self):
+ text = self.remains()[1:]
+
+ if text == '':
+ return False
+
+ return self.REG_ESCAPE.match(text)
+
+ def _escape(self):
+ if not self._need_escape():
+ return
+
+ # Increase position with 1
+ self.position += 1
+
+ def _text(self):
+ if self.char() == '\\':
+ self._escape()
+
+ self.tktext += self.char()
+ self.position += 1
+
+ def _rule(self):
+ for rule in self.RULES:
+ res = rule()
+
+ if res:
+ return res
+
+ def _match_env(self):
+ text = self.remains()
+ match = re.match('\\$(%s)' % self.SREG_ENV, text) or re.match('\\${(%s)}' % self.SREG_ENV, text)
+
+ if match:
+ self.position += len(match.group(0))
+ return Token('environment', match.group(1))
+
+ def _parse_list(self, lst):
+ pos = 0
+ length = len(lst)
+ items = []
+ last = None
+
+ while pos < length:
+ char = lst[pos]
+ next = pos < length - 1 and lst[pos + 1]
+
+ if char == '\\' and (next == ',' or next == ']'):
+ char = next
+ pos += 1
+ elif char == ',':
+ if last != None:
+ items.append(last)
+
+ last = None
+ pos += 1
+ continue
+
+ last = (last != None and last + char) or char
+ pos += 1
+
+ if last != None:
+ items.append(last)
+
+ return items
+
+ def _parse_default(self, default):
+ match = re.match('^\\s*(\\\\)?(\\[((\\\\]|[^\\]])+)\\]\\s*)$', default)
+
+ if not match:
+ return [default]
+
+ groups = match.groups()
+
+ if groups[0]:
+ return [groups[1]]
+
+ return self._parse_list(groups[2])
+
+ def _match_placeholder(self):
+ text = self.remains()
+
+ match = re.match('\\${(%s)(:((\\\\\\}|[^}])+))?}' % self.SREG_ID, text) or re.match('\\$(%s)' % self.SREG_ID, text)
+
+ if not match:
+ return None
+
+ groups = match.groups()
+ default = ''
+ tabstop = int(groups[0])
+ self.position += len(match.group(0))
+
+ if len(groups) > 1 and groups[2]:
+ default = self._parse_default(groups[2].replace('\\}', '}'))
+
+ return Token('placeholder', {'tabstop': tabstop, 'default': default})
+
+ def _match_shell(self):
+ text = self.remains()
+ match = re.match('`((%s):)?((\\\\`|[^`])+?)`' % self.SREG_ID, text) or re.match('\\$\\(((%s):)?((\\\\\\)|[^\\)])+?)\\)' % self.SREG_ID, text)
+
+ if not match:
+ return None
+
+ groups = match.groups()
+ tabstop = (groups[1] and int(groups[1])) or -1
+ self.position += len(match.group(0))
+
+ if text[0] == '`':
+ contents = groups[2].replace('\\`', '`')
+ else:
+ contents = groups[2].replace('\\)', ')')
+
+ return Token('shell', {'tabstop': tabstop, 'contents': contents})
+
+ def _try_match_shell(self):
+ return self._match_shell() or self._text()
+
+ def _eval_options(self, options):
+ reg = re.compile(self.SREG_ID)
+ tabstop = -1
+ depend = []
+
+ options = options.split(':')
+
+ for opt in options:
+ if reg.match(opt):
+ tabstop = int(opt)
+ else:
+ depend += self._parse_list(opt[1:-1])
+
+ return (tabstop, depend)
+
+ def _match_eval(self):
+ text = self.remains()
+
+ options = '((%s)|\\[([0-9, ]+)\\])' % self.SREG_ID
+ match = re.match('\\$<((%s:)*)((\\\\>|[^>])+?)>' % options, text)
+
+ if not match:
+ return None
+
+ groups = match.groups()
+ (tabstop, depend) = (groups[0] and self._eval_options(groups[0][:-1])) or (-1, [])
+ self.position += len(match.group(0))
+
+ return Token('eval', {'tabstop': tabstop, 'dependencies': depend, 'contents': groups[5].replace('\\>', '>')})
+
+ def _match_regex(self):
+ text = self.remains()
+
+ content = '((?:\\\\[/]|\\\\}|[^/}])+)'
+ match = re.match('\\${(?:(%s):)?\\s*(%s|\\$([A-Z_]+))?[/]%s[/]%s(?:[/]([a-zA-Z]*))?}' % (self.SREG_ID, self.SREG_ID, content, content), text)
+
+ if not match:
+ return None
+
+ groups = match.groups()
+ tabstop = (groups[0] and int(groups[0])) or -1
+ inp = (groups[2] or (groups[1] and int(groups[1]))) or ''
+
+ pattern = re.sub('\\\\([/}])', '\\1', groups[3])
+ substitution = re.sub('\\\\([/}])', '\\1', groups[4])
+ modifiers = groups[5] or ''
+
+ self.position += len(match.group(0))
+
+ return Token('regex', {'tabstop': tabstop, 'input': inp, 'pattern': pattern, 'substitution': substitution, 'modifiers': modifiers})
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/placeholder.py b/plugins/snippets/snippets/placeholder.py
new file mode 100644
index 0000000..e70a31e
--- /dev/null
+++ b/plugins/snippets/snippets/placeholder.py
@@ -0,0 +1,714 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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 traceback
+import re
+import sys
+import signal
+import locale
+import subprocess
+from gi.repository import GObject, Gtk
+
+from . import helper
+from .substitutionparser import SubstitutionParser
+
+try:
+ import gettext
+ gettext.bindtextdomain('gedit')
+ gettext.textdomain('gedit')
+ _ = gettext.gettext
+except:
+ _ = lambda s: s
+
+# These are places in a view where the cursor can go and do things
+class Placeholder:
+ def __init__(self, view, tabstop, environ, defaults, begin):
+ self.ok = True
+ self.done = False
+ self.buf = view.get_buffer()
+ self.view = view
+ self.has_references = False
+ self.mirrors = []
+ self.leave_mirrors = []
+ self.tabstop = tabstop
+ self.environ = environ
+ self.set_default(defaults)
+ self.prev_contents = self.default
+ self.set_mark_gravity()
+
+ if begin:
+ self.begin = self.buf.create_mark(None, begin, self.mark_gravity[0])
+ else:
+ self.begin = None
+
+ self.end = None
+
+ def get_environ(self):
+ return self.environ['utf8']
+
+ def __str__(self):
+ return '%s (%s)' % (str(self.__class__), str(self.default))
+
+ def set_mark_gravity(self):
+ self.mark_gravity = [True, False]
+
+ def set_default(self, defaults):
+ self.default = None
+ self.defaults = []
+
+ if not defaults:
+ return
+
+ for d in defaults:
+ dm = self.expand_environment(d)
+
+ if dm:
+ self.defaults.append(dm)
+
+ if not self.default:
+ self.default = dm
+
+ if dm != d:
+ break
+
+ def literal(self, s):
+ return repr(s)
+
+ def format_environment(self, s):
+ return s
+
+ def re_environment(self, m):
+ env = self.get_environ()
+
+ if m.group(1) or not m.group(2) in env:
+ return '$' + m.group(2)
+ else:
+ return self.format_environment(env[m.group(2)])
+
+ def expand_environment(self, text):
+ if not text:
+ return text
+
+ return re.sub('(\\\\)?\\$([A-Z_]+)', self.re_environment, text)
+
+ def get_iter(self, mark):
+ if mark and not mark.get_deleted():
+ return self.buf.get_iter_at_mark(mark)
+ else:
+ return None
+
+ def begin_iter(self):
+ return self.get_iter(self.begin)
+
+ def end_iter(self):
+ return self.get_iter(self.end)
+
+ def run_last(self, placeholders):
+ begin = self.begin_iter()
+ self.end = self.buf.create_mark(None, begin, self.mark_gravity[1])
+
+ if self.default:
+ helper.insert_with_indent(self.view, begin, self.default, False, self)
+
+ def remove(self, force = False):
+ if self.begin and not self.begin.get_deleted():
+ self.buf.delete_mark(self.begin)
+
+ if self.end and not self.end.get_deleted():
+ self.buf.delete_mark(self.end)
+
+ # Do something on beginning this placeholder
+ def enter(self):
+ if not self.begin or self.begin.get_deleted():
+ return
+
+ self.buf.move_mark(self.buf.get_insert(), self.begin_iter())
+
+ if self.end:
+ self.buf.move_mark(self.buf.get_selection_bound(), self.end_iter())
+ else:
+ self.buf.move_mark(self.buf.get_selection_bound(), self.begin_iter())
+
+ def get_text(self):
+ if self.begin and self.end:
+ biter = self.begin_iter()
+ eiter = self.end_iter()
+
+ if biter and eiter:
+ return self.buf.get_text(self.begin_iter(), self.end_iter(), False)
+ else:
+ return ''
+ else:
+ return ''
+
+ def add_mirror(self, mirror, onleave = False):
+ mirror.has_references = True
+
+ if onleave:
+ self.leave_mirrors.append(mirror)
+ else:
+ self.mirrors.append(mirror)
+
+ def set_text(self, text):
+ if self.begin.get_deleted() or self.end.get_deleted():
+ return
+
+ # Set from self.begin to self.end to text!
+ self.buf.begin_user_action()
+ # Remove everything between self.begin and self.end
+ begin = self.begin_iter()
+ self.buf.delete(begin, self.end_iter())
+
+ # Insert the text from the mirror
+ helper.insert_with_indent(self.view, begin, text, True, self)
+ self.buf.end_user_action()
+
+ self.update_contents()
+
+ def update_contents(self):
+ prev = self.prev_contents
+ self.prev_contents = self.get_text()
+
+ if prev != self.get_text():
+ for mirror in self.mirrors:
+ if not mirror.update(self):
+ return
+
+ def update_leave_mirrors(self):
+ # Notify mirrors
+ for mirror in self.leave_mirrors:
+ if not mirror.update(self):
+ return
+
+ # Do something on ending this placeholder
+ def leave(self):
+ self.update_leave_mirrors()
+
+ def find_mirrors(self, text, placeholders):
+ mirrors = []
+
+ while (True):
+ m = re.search('(\\\\)?\\$(?:{([0-9]+)}|([0-9]+))', text)
+
+ if not m:
+ break
+
+ # Skip escaped mirrors
+ if m.group(1):
+ text = text[m.end():]
+ continue
+
+ tabstop = int(m.group(2) or m.group(3))
+
+ if tabstop in placeholders:
+ if not tabstop in mirrors:
+ mirrors.append(tabstop)
+
+ text = text[m.end():]
+ else:
+ self.ok = False
+ return None
+
+ return mirrors
+
+# This is an placeholder which inserts a mirror of another Placeholder
+class PlaceholderMirror(Placeholder):
+ def __init__(self, view, tabstop, environ, begin):
+ Placeholder.__init__(self, view, -1, environ, None, begin)
+ self.mirror_stop = tabstop
+
+ def update(self, mirror):
+ self.set_text(mirror.get_text())
+ return True
+
+ def run_last(self, placeholders):
+ Placeholder.run_last(self, placeholders)
+
+ if self.mirror_stop in placeholders:
+ mirror = placeholders[self.mirror_stop]
+
+ mirror.add_mirror(self)
+
+ if mirror.default:
+ self.set_text(mirror.default)
+ else:
+ self.ok = False
+
+# This placeholder indicates the end of a snippet
+class PlaceholderEnd(Placeholder):
+ def __init__(self, view, environ, begin, default):
+ Placeholder.__init__(self, view, 0, environ, default, begin)
+
+ def run_last(self, placeholders):
+ Placeholder.run_last(self, placeholders)
+
+ # Remove the begin mark and set the begin mark
+ # to the end mark, this is needed so the end placeholder won't contain
+ # any text
+
+ if not self.default:
+ self.mark_gravity[0] = False
+ self.buf.delete_mark(self.begin)
+ self.begin = self.buf.create_mark(None, self.end_iter(), self.mark_gravity[0])
+
+ def enter(self):
+ if self.begin and not self.begin.get_deleted():
+ self.buf.move_mark(self.buf.get_insert(), self.begin_iter())
+
+ if self.end and not self.end.get_deleted():
+ self.buf.move_mark(self.buf.get_selection_bound(), self.end_iter())
+
+ def leave(self):
+ self.enter()
+
+# This placeholder is used to expand a command with embedded mirrors
+class PlaceholderExpand(Placeholder):
+ def __init__(self, view, tabstop, environ, begin, s):
+ Placeholder.__init__(self, view, tabstop, environ, None, begin)
+
+ self.mirror_text = {0: ''}
+ self.timeout_id = None
+ self.cmd = s
+ self.instant_update = False
+
+ def __str__(self):
+ s = Placeholder.__str__(self)
+
+ return s + ' ' + self.cmd
+
+ def get_mirrors(self, placeholders):
+ return self.find_mirrors(self.cmd, placeholders)
+
+ # Check if all substitution placeholders are accounted for
+ def run_last(self, placeholders):
+ Placeholder.run_last(self, placeholders)
+
+ self.ok = True
+ mirrors = self.get_mirrors(placeholders)
+
+ if mirrors:
+ allDefault = True
+
+ for mirror in mirrors:
+ p = placeholders[mirror]
+ p.add_mirror(self, not self.instant_update)
+ self.mirror_text[p.tabstop] = p.default
+
+ if not p.default and not isinstance(p, PlaceholderExpand):
+ allDefault = False
+
+ if allDefault:
+ self.update(None)
+ self.default = self.get_text() or None
+ else:
+ self.update(None)
+ self.default = self.get_text() or None
+
+ if self.tabstop == -1:
+ self.done = True
+
+ def re_placeholder(self, m, formatter):
+ if m.group(1):
+ return '"$' + m.group(2) + '"'
+ else:
+ if m.group(3):
+ index = int(m.group(3))
+ else:
+ index = int(m.group(4))
+
+ return formatter(self.mirror_text[index])
+
+ def remove_timeout(self):
+ if self.timeout_id != None:
+ GObject.source_remove(self.timeout_id)
+ self.timeout_id = None
+
+ def install_timeout(self):
+ self.remove_timeout()
+ self.timeout_id = GObject.timeout_add(1000, self.timeout_cb)
+
+ def timeout_cb(self):
+ self.timeout_id = None
+
+ return False
+
+ def format_environment(self, text):
+ return self.literal(text)
+
+ def substitute(self, text, formatter = None):
+ formatter = formatter or self.literal
+
+ # substitute all mirrors, but also environmental variables
+ text = re.sub('(\\\\)?\\$({([0-9]+)}|([0-9]+))', lambda m: self.re_placeholder(m, formatter),
+ text)
+
+ return self.expand_environment(text)
+
+ def run_update(self):
+ text = self.substitute(self.cmd)
+
+ if text:
+ ret = self.expand(text)
+
+ if ret:
+ self.update_leave_mirrors()
+ else:
+ ret = True
+
+ return ret
+
+ def update(self, mirror):
+ if mirror:
+ self.mirror_text[mirror.tabstop] = mirror.get_text()
+
+ # Check if all substitutions have been made
+ for tabstop in self.mirror_text:
+ if tabstop == 0:
+ continue
+
+ if self.mirror_text[tabstop] is None:
+ return False
+
+ return self.run_update()
+
+ def expand(self, text):
+ return True
+
+# The shell placeholder executes commands in a subshell
+class PlaceholderShell(PlaceholderExpand):
+ def __init__(self, view, tabstop, environ, begin, s):
+ PlaceholderExpand.__init__(self, view, tabstop, environ, begin, s)
+
+ self.shell = None
+ self.remove_me = False
+
+ def get_environ(self):
+ return self.environ['noenc']
+
+ def close_shell(self):
+ self.shell.stdout.close()
+ self.shell = None
+
+ def timeout_cb(self):
+ PlaceholderExpand.timeout_cb(self)
+ self.remove_timeout()
+
+ if not self.shell:
+ return False
+
+ GObject.source_remove(self.watch_id)
+ self.close_shell()
+
+ if self.remove_me:
+ PlaceholderExpand.remove(self)
+
+ helper.message_dialog(None, Gtk.MessageType.ERROR, 'Execution of the shell ' \
+ 'command (%s) exceeded the maximum time; ' \
+ 'execution aborted.' % self.command)
+
+ return False
+
+ def process_close(self):
+ self.close_shell()
+ self.remove_timeout()
+
+ self.set_text(str.join('', self.shell_output).rstrip('\n'))
+
+ if self.default is None:
+ self.default = self.get_text()
+ self.leave()
+
+ if self.remove_me:
+ PlaceholderExpand.remove(self, True)
+
+ def process_cb(self, source, condition):
+ if condition & GObject.IO_IN:
+ line = source.readline()
+
+ if len(line) > 0:
+ try:
+ line = line.decode('utf-8')
+ except UnicodeDecodeError:
+ line = line.decode(locale.getdefaultlocale()[1], errors='replace')
+
+ self.shell_output += line
+ self.install_timeout()
+
+ return True
+
+ self.process_close()
+ return False
+
+ def literal_replace(self, match):
+ return "\\%s" % (match.group(0))
+
+ def literal(self, text):
+ return '"' + re.sub('([\\\\"])', self.literal_replace, text) + '"'
+
+ def expand(self, text):
+ self.remove_timeout()
+
+ if self.shell:
+ GObject.source_remove(self.watch_id)
+ self.close_shell()
+
+ popen_args = {
+ 'cwd': None,
+ 'shell': True,
+ 'env': self.get_environ(),
+ 'stdout': subprocess.PIPE
+ }
+
+ self.command = text
+ self.shell = subprocess.Popen(text, **popen_args)
+ self.shell_output = ''
+ self.watch_id = GObject.io_add_watch(self.shell.stdout, GObject.IO_IN | \
+ GObject.IO_HUP, self.process_cb)
+ self.install_timeout()
+
+ return True
+
+ def remove(self, force = False):
+ if not force and self.shell:
+ # Still executing shell command
+ self.remove_me = True
+ else:
+ if force:
+ self.remove_timeout()
+
+ if self.shell:
+ self.close_shell()
+
+ PlaceholderExpand.remove(self, force)
+
+class TimeoutError(Exception):
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return repr(self.value)
+
+# The python placeholder evaluates commands in python
+class PlaceholderEval(PlaceholderExpand):
+ def __init__(self, view, tabstop, environ, refs, begin, s, namespace):
+ PlaceholderExpand.__init__(self, view, tabstop, environ, begin, s)
+
+ self.fdread = 0
+ self.remove_me = False
+ self.namespace = namespace
+
+ self.refs = []
+
+ if refs:
+ for ref in refs:
+ self.refs.append(int(ref.strip()))
+
+ def get_mirrors(self, placeholders):
+ mirrors = PlaceholderExpand.get_mirrors(self, placeholders)
+
+ if not self.ok:
+ return None
+
+ for ref in self.refs:
+ if ref in placeholders:
+ if ref not in mirrors:
+ mirrors.append(ref)
+ else:
+ self.ok = False
+ return None
+
+ return mirrors
+
+ # SIGALRM is not supported on all platforms (e.g. windows). Timeout
+ # with SIGALRM will not be used on those platforms. This will
+ # potentially block gedit if you have a placeholder which gets stuck,
+ # but it's better than not supporting them at all. At some point we
+ # might have proper thread support and we can fix this in a better way
+ def timeout_supported(self):
+ return hasattr(signal, 'SIGALRM')
+
+ def timeout_cb(self, signum = 0, frame = 0):
+ raise TimeoutError("Operation timed out (>2 seconds)")
+
+ def install_timeout(self):
+ if not self.timeout_supported():
+ return
+
+ if self.timeout_id != None:
+ self.remove_timeout()
+
+ self.timeout_id = signal.signal(signal.SIGALRM, self.timeout_cb)
+ signal.alarm(2)
+
+ def remove_timeout(self):
+ if not self.timeout_supported():
+ return
+
+ if self.timeout_id != None:
+ signal.alarm(0)
+
+ signal.signal(signal.SIGALRM, self.timeout_id)
+
+ self.timeout_id = None
+
+ def expand(self, text):
+ self.remove_timeout()
+
+ text = text.strip()
+ self.command = text
+
+ if not self.command or self.command == '':
+ self.set_text('')
+ return
+
+ text = "def process_snippet():\n\t" + "\n\t".join(text.split("\n"))
+
+ if 'process_snippet' in self.namespace:
+ del self.namespace['process_snippet']
+
+ try:
+ exec(text, self.namespace)
+ except:
+ traceback.print_exc()
+
+ if 'process_snippet' in self.namespace:
+ try:
+ # Install a sigalarm signal. This is a HACK to make sure
+ # gedit doesn't get freezed by someone creating a python
+ # placeholder which for instance loops indefinately. Since
+ # the code is executed synchronously it will hang gedit. With
+ # the alarm signal we raise an exception and catch this
+ # (see below). We show an error message and return False.
+ # ___this is a HACK___ and should be fixed properly (I just
+ # don't know how)
+ self.install_timeout()
+ result = self.namespace['process_snippet']()
+ self.remove_timeout()
+ except TimeoutError:
+ self.remove_timeout()
+
+ helper.message_dialog(None, Gtk.MessageType.ERROR, \
+ _('Execution of the Python command (%s) exceeds the maximum ' \
+ 'time, execution aborted.') % self.command)
+
+ return False
+ except Exception as detail:
+ self.remove_timeout()
+
+ helper.message_dialog(None, Gtk.MessageType.ERROR,
+ _('Execution of the Python command (%s) failed: %s') %
+ (self.command, detail))
+
+ return False
+
+ if result is None:
+ # sys.stderr.write("%s:\n>> %s\n" % (_('The following python code, run in a snippet, does not return a value'), "\n>> ".join(self.command.split("\n"))))
+ result = ''
+
+ self.set_text(str(result))
+
+ return True
+
+# Regular expression placeholder
+class PlaceholderRegex(PlaceholderExpand):
+ def __init__(self, view, tabstop, environ, begin, inp, pattern, substitution, modifiers):
+ PlaceholderExpand.__init__(self, view, tabstop, environ, begin, '')
+
+ self.instant_update = True
+ self.inp = inp
+ self.pattern = pattern
+ self.substitution = substitution
+
+ self.init_modifiers(modifiers)
+
+ def init_modifiers(self, modifiers):
+ mods = {'I': re.I,
+ 'L': re.L,
+ 'M': re.M,
+ 'S': re.S,
+ 'U': re.U,
+ 'X': re.X}
+
+ self.modifiers = 0
+
+ for modifier in modifiers:
+ if modifier in mods:
+ self.modifiers |= mods[modifier]
+
+ def get_mirrors(self, placeholders):
+ mirrors = self.find_mirrors(self.pattern, placeholders) + self.find_mirrors(self.substitution, placeholders)
+
+ if isinstance(self.inp, int):
+ if self.inp not in placeholders:
+ self.ok = False
+ return None
+ elif self.inp not in mirrors:
+ mirrors.append(self.inp)
+
+ return mirrors
+
+ def literal(self, s):
+ return re.escape(s)
+
+ def get_input(self):
+ env = self.get_environ()
+
+ if isinstance(self.inp, int):
+ return self.mirror_text[self.inp]
+ elif self.inp in env:
+ return env[self.inp]
+ else:
+ return ''
+
+ def run_update(self):
+ pattern = self.substitute(self.pattern)
+ substitution = self.substitute(self.substitution, SubstitutionParser.escape_substitution)
+
+ if pattern:
+ return self.expand(pattern, substitution)
+
+ return True
+
+ def expand(self, pattern, substitution):
+ # Try to compile pattern
+ try:
+ regex = re.compile(pattern, self.modifiers)
+ except re.error as message:
+ sys.stderr.write('Could not compile regular expression: %s\n%s\n' % (pattern, message))
+ return False
+
+ inp = self.get_input()
+ match = regex.search(inp)
+
+ if not match:
+ self.set_text(inp)
+ else:
+ groups = match.groupdict()
+
+ idx = 0
+ for group in match.groups():
+ groups[str(idx + 1)] = group
+ idx += 1
+
+ groups['0'] = match.group(0)
+
+ parser = SubstitutionParser(substitution, groups)
+ self.set_text(parser.parse())
+
+ return True
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/shareddata.py b/plugins/snippets/snippets/shareddata.py
new file mode 100644
index 0000000..be6fd14
--- /dev/null
+++ b/plugins/snippets/snippets/shareddata.py
@@ -0,0 +1,83 @@
+# Gedit snippets plugin
+# Copyright (C) 2011 Jesse van den Kieboom <jessevdk@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 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
+
+from .singleton import Singleton
+import os
+
+from gi.repository import Gtk
+
+# To register the GeditSnippetsManager type
+from .manager import Manager
+
+class SharedData(object, metaclass=Singleton):
+ def __init__(self):
+ self.dlg = None
+ self.dlg_default_size = None
+ self.controller_registry = {}
+ self.windows = {}
+
+ def register_controller(self, view, controller):
+ self.controller_registry[view] = controller
+
+ def unregister_controller(self, view, controller):
+ if self.controller_registry[view] == controller:
+ del self.controller_registry[view]
+
+ def register_window(self, window):
+ self.windows[window.window] = window
+
+ def unregister_window(self, window):
+ if window.window in self.windows:
+ del self.windows[window.window]
+
+ def update_state(self, window):
+ if window in self.windows:
+ self.windows[window].do_update_state()
+
+ def get_active_controller(self, window):
+ view = window.get_active_view()
+
+ if not view or not view in self.controller_registry:
+ return None
+
+ return self.controller_registry[view]
+
+ def get_controller(self, view):
+ if view in self.controller_registry:
+ return self.controller_registry[view]
+ else:
+ return None
+
+ def manager_destroyed(self, dlg):
+ self.dlg_default_size = dlg.get_final_size()
+ self.dlg = None
+
+ def show_manager(self, window, datadir):
+ if not self.dlg:
+ builder = Gtk.Builder()
+ builder.add_from_file(os.path.join(datadir, 'ui', 'snippets.ui'))
+
+ self.dlg = builder.get_object('snippets_manager')
+ self.dlg.connect('destroy', self.manager_destroyed)
+
+ if self.dlg_default_size:
+ self.dlg.set_default_size(self.dlg_default_size[0], self.dlg_default_size[1])
+
+ self.dlg.set_transient_for(window)
+ self.dlg.present()
+
+# vi:ex:ts=4:et
diff --git a/plugins/snippets/snippets/signals.py b/plugins/snippets/snippets/signals.py
new file mode 100644
index 0000000..647b616
--- /dev/null
+++ b/plugins/snippets/snippets/signals.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+#
+# signals.py
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+class Signals:
+ def __init__(self):
+ self._signals = {}
+
+ def _connect(self, obj, name, handler, connector):
+ ret = self._signals.setdefault(obj, {})
+
+ hid = connector(name, handler)
+ ret.setdefault(name, []).append(hid)
+
+ return hid
+
+ def connect_signal(self, obj, name, handler):
+ return self._connect(obj, name, handler, obj.connect)
+
+ def connect_signal_after(self, obj, name, handler):
+ return self._connect(obj, name, handler, obj.connect_after)
+
+ def disconnect_signals(self, obj):
+ if obj not in self._signals:
+ return False
+
+ for name in self._signals[obj]:
+ for hid in self._signals[obj][name]:
+ obj.disconnect(hid)
+
+ del self._signals[obj]
+ return True
+
+ def block_signal(self, obj, name):
+ if obj not in self._signals:
+ return False
+
+ if name not in self._signals[obj]:
+ return False
+
+ for hid in self._signals[obj][name]:
+ obj.handler_block(hid)
+
+ return True
+
+ def unblock_signal(self, obj, name):
+ if obj not in self._signals:
+ return False
+
+ if name not in self._signals[obj]:
+ return False
+
+ for hid in self._signals[obj][name]:
+ obj.handler_unblock(hid)
+
+ return True
+
+ def disconnect_signal(self, obj, name):
+ if obj not in self._signals:
+ return False
+
+ if name not in self._signals[obj]:
+ return False
+
+ for hid in self._signals[obj][name]:
+ obj.disconnect(hid)
+
+ del self._signals[obj][name]
+
+ if len(self._signals[obj]) == 0:
+ del self._signals[obj]
+
+ return True
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/singleton.py b/plugins/snippets/snippets/singleton.py
new file mode 100644
index 0000000..9bc346d
--- /dev/null
+++ b/plugins/snippets/snippets/singleton.py
@@ -0,0 +1,27 @@
+# Gedit snippets plugin
+# Copyright (C) 2011 Jesse van den Kieboom <jessevdk@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 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
+
+class Singleton(type):
+ def __init__(cls, name, bases, dict):
+ super(Singleton, cls).__init__(name, bases, dict)
+ cls.instance = None
+
+ def __call__(cls, *args, **kw):
+ if cls.instance is None:
+ cls.instance = super(Singleton, cls).__call__(*args, **kw)
+
+ return cls.instance
diff --git a/plugins/snippets/snippets/snippet.py b/plugins/snippets/snippets/snippet.py
new file mode 100644
index 0000000..6b18156
--- /dev/null
+++ b/plugins/snippets/snippets/snippet.py
@@ -0,0 +1,360 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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
+
+from gi.repository import Gio, Gtk
+
+import sys
+
+from .placeholder import PlaceholderEnd, PlaceholderMirror, Placeholder, PlaceholderShell, PlaceholderEval, PlaceholderRegex, PlaceholderExpand
+from .parser import Parser
+from . import helper
+
+class EvalUtilities:
+ def __init__(self, view=None):
+ self.view = view
+ self._init_namespace()
+
+ def _init_namespace(self):
+ self.namespace = {
+ '__builtins__': __builtins__,
+ 'align': self.util_align,
+ 'readfile': self.util_readfile,
+ 'filesize': self.util_filesize
+ }
+
+ def _real_len(self, s, tablen = 0):
+ if tablen == 0:
+ tablen = self.view.get_tab_width()
+
+ return len(s.expandtabs(tablen))
+
+ def _filename_to_uri(self, filename):
+ gfile = Gio.file_new_for_path(filename)
+
+ return gfile.get_uri()
+
+ def util_readfile(self, filename):
+ stream = Gio.file_new_for_path(filename).read()
+
+ if not stream:
+ return ''
+
+ res = stream.read()
+ stream.close()
+
+ return res
+
+ def util_filesize(self, filename):
+ gfile = Gio.file_new_for_path(filename)
+ info = gfile.query_info(Gio.FILE_ATTRIBUTE_STANDARD_SIZE)
+
+ if not info:
+ return 0
+
+ return info.get_size()
+
+ def util_align(self, items):
+ maxlen = []
+ tablen = self.view.get_tab_width()
+
+ for row in range(0, len(items)):
+ for col in range(0, len(items[row]) - 1):
+ if row == 0:
+ maxlen.append(0)
+
+ items[row][col] += "\t"
+ rl = self._real_len(items[row][col], tablen)
+
+ if (rl > maxlen[col]):
+ maxlen[col] = rl
+
+ result = ''
+
+ for row in range(0, len(items)):
+ for col in range(0, len(items[row]) - 1):
+ item = items[row][col]
+
+ result += item + ("\t" * int(((maxlen[col] - \
+ self._real_len(item, tablen)) / tablen)))
+
+ result += items[row][len(items[row]) - 1]
+
+ if row != len(items) - 1:
+ result += "\n"
+
+ return result
+
+class Snippet:
+ def __init__(self, data, environ = {}):
+ self.data = data
+ self.environ = environ
+
+ def __getitem__(self, prop):
+ return self.data[prop]
+
+ def __setitem__(self, prop, value):
+ self.data[prop] = value
+
+ def accelerator_display(self):
+ accel = self['accelerator']
+
+ if accel:
+ keyval, mod = Gtk.accelerator_parse(accel)
+ accel = Gtk.accelerator_get_label(keyval, mod)
+
+ return accel or ''
+
+ def display(self):
+ nm = helper.markup_escape(self['description'])
+
+ tag = self['tag']
+ accel = self.accelerator_display()
+ detail = []
+
+ if tag and tag != '':
+ detail.append(tag)
+
+ if accel and accel != '':
+ detail.append(accel)
+
+ if not detail:
+ return nm
+ else:
+ return nm + ' (<b>' + helper.markup_escape(', '.join(detail)) + \
+ '</b>)'
+
+ def _add_placeholder(self, placeholder):
+ if placeholder.tabstop in self.placeholders:
+ if placeholder.tabstop == -1:
+ self.placeholders[-1].append(placeholder)
+ self.plugin_data.ordered_placeholders.append(placeholder)
+ elif placeholder.tabstop == -1:
+ self.placeholders[-1] = [placeholder]
+ self.plugin_data.ordered_placeholders.append(placeholder)
+ else:
+ self.placeholders[placeholder.tabstop] = placeholder
+ self.plugin_data.ordered_placeholders.append(placeholder)
+
+ def _insert_text(self, text):
+ # Insert text keeping indentation in mind
+ indented = str.join('\n' + self._indent, helper.spaces_instead_of_tabs(self._view, text).split('\n'))
+ self._view.get_buffer().insert(self._insert_iter(), indented)
+
+ def _insert_iter(self):
+ return self._view.get_buffer().get_iter_at_mark(self._insert_mark)
+
+ def _create_environment(self, data):
+ if data in self.environ['utf8']:
+ val = self.environ['utf8'][data]
+ else:
+ val = ''
+
+ # Get all the current indentation
+ all_indent = helper.compute_indentation(self._view, self._insert_iter())
+
+ # Substract initial indentation to get the snippet indentation
+ indent = all_indent[len(self._indent):]
+
+ # Keep indentation
+ return str.join('\n' + indent, val.split('\n'))
+
+ def _create_placeholder(self, data):
+ tabstop = data['tabstop']
+ begin = self._insert_iter()
+
+ if tabstop == 0:
+ # End placeholder
+ return PlaceholderEnd(self._view, self.environ, begin, data['default'])
+ elif tabstop in self.placeholders:
+ # Mirror placeholder
+ return PlaceholderMirror(self._view, tabstop, self.environ, begin)
+ else:
+ # Default placeholder
+ return Placeholder(self._view, tabstop, self.environ, data['default'], begin)
+
+ def _create_shell(self, data):
+ begin = self._insert_iter()
+ return PlaceholderShell(self._view, data['tabstop'], self.environ, begin, data['contents'])
+
+ def _create_eval(self, data):
+ begin = self._insert_iter()
+ return PlaceholderEval(self._view, data['tabstop'], self.environ, data['dependencies'], begin, data['contents'], self._utils.namespace)
+
+ def _create_regex(self, data):
+ begin = self._insert_iter()
+ return PlaceholderRegex(self._view, data['tabstop'], self.environ, begin, data['input'], data['pattern'], data['substitution'], data['modifiers'])
+
+ def _create_text(self, data):
+ return data
+
+ def _invalid_placeholder(self, placeholder, remove):
+ buf = self._view.get_buffer()
+
+ # Remove the text because this placeholder is invalid
+ if placeholder.default and remove:
+ buf.delete(placeholder.begin_iter(), placeholder.end_iter())
+
+ placeholder.remove()
+
+ if placeholder.tabstop == -1:
+ index = self.placeholders[-1].index(placeholder)
+ del self.placeholders[-1][index]
+ else:
+ del self.placeholders[placeholder.tabstop]
+
+ self.plugin_data.ordered_placeholders.remove(placeholder)
+
+ def _parse(self, plugin_data):
+ # Initialize current variables
+ self._view = plugin_data.view
+ self._indent = helper.compute_indentation(self._view, self._view.get_buffer().get_iter_at_mark(self.begin_mark))
+ self._utils = EvalUtilities(self._view)
+ self.placeholders = {}
+ self._insert_mark = self.end_mark
+ self.plugin_data = plugin_data
+
+ # Create parser
+ parser = Parser(data=self['text'])
+
+ # Parse tokens
+ while (True):
+ token = parser.token()
+
+ if not token:
+ break
+
+ try:
+ val = {'environment': self._create_environment,
+ 'placeholder': self._create_placeholder,
+ 'shell': self._create_shell,
+ 'eval': self._create_eval,
+ 'regex': self._create_regex,
+ 'text': self._create_text}[token.klass](token.data)
+ except KeyError:
+ sys.stderr.write('Token class not supported: %s (%s)\n' % token.klass)
+ continue
+
+ if isinstance(val, str):
+ # Insert text
+ self._insert_text(val)
+ else:
+ # Insert placeholder
+ self._add_placeholder(val)
+
+ # Create end placeholder if there isn't one yet
+ if 0 not in self.placeholders:
+ self.placeholders[0] = PlaceholderEnd(self._view, self.environ, self.end_iter(), None)
+ self.plugin_data.ordered_placeholders.append(self.placeholders[0])
+
+ # Make sure run_last is ran for all placeholders and remove any
+ # non `ok` placeholders
+ for tabstop in self.placeholders.copy():
+ ph = (tabstop == -1 and list(self.placeholders[-1])) or [self.placeholders[tabstop]]
+
+ for placeholder in ph:
+ placeholder.run_last(self.placeholders)
+
+ if not placeholder.ok or placeholder.done:
+ self._invalid_placeholder(placeholder, not placeholder.ok)
+
+ # Remove all the Expand placeholders which have a tabstop because
+ # they can be used to mirror, but they shouldn't be real tabstops
+ # (if they have mirrors installed). This is problably a bit of
+ # a dirty hack :)
+ if -1 not in self.placeholders:
+ self.placeholders[-1] = []
+
+ for tabstop in self.placeholders.copy():
+ placeholder = self.placeholders[tabstop]
+
+ if tabstop != -1:
+ if isinstance(placeholder, PlaceholderExpand) and \
+ placeholder.has_references:
+ # Add to anonymous placeholders
+ self.placeholders[-1].append(placeholder)
+
+ # Remove placeholder
+ del self.placeholders[tabstop]
+
+ self.plugin_data = None
+
+ def insert_into(self, plugin_data, insert):
+ buf = plugin_data.view.get_buffer()
+ last_index = 0
+
+ # Find closest mark at current insertion, so that we may insert
+ # our marks in the correct order
+ (current, next) = plugin_data.next_placeholder()
+
+ if current:
+ # Insert AFTER current
+ last_index = plugin_data.placeholders.index(current) + 1
+ elif next:
+ # Insert BEFORE next
+ last_index = plugin_data.placeholders.index(next)
+ else:
+ # Insert at first position
+ last_index = 0
+
+ # lastIndex now contains the position of the last mark
+ # Create snippet bounding marks
+ self.begin_mark = buf.create_mark(None, insert, True)
+ self.end_mark = buf.create_mark(None, insert, False)
+
+ # Now parse the contents of this snippet, create Placeholders
+ # and insert the placholder marks in the marks array of plugin_data
+ self._parse(plugin_data)
+
+ # So now all of the snippet is in the buffer, we have all our
+ # placeholders right here, what's next, put all marks in the
+ # plugin_data.marks
+ k = sorted(self.placeholders.keys(), reverse=True)
+
+ plugin_data.placeholders.insert(last_index, self.placeholders[0])
+ last_iter = self.placeholders[0].end_iter()
+
+ for tabstop in k:
+ if tabstop != -1 and tabstop != 0:
+ placeholder = self.placeholders[tabstop]
+ end_iter = placeholder.end_iter()
+
+ if last_iter.compare(end_iter) < 0:
+ last_iter = end_iter
+
+ # Inserting placeholder
+ plugin_data.placeholders.insert(last_index, placeholder)
+
+ # Move end mark to last placeholder
+ buf.move_mark(self.end_mark, last_iter)
+
+ return self
+
+ def deactivate(self):
+ buf = self.begin_mark.get_buffer()
+
+ buf.delete_mark(self.begin_mark)
+ buf.delete_mark(self.end_mark)
+
+ self.placeholders = {}
+
+ def begin_iter(self):
+ return self.begin_mark.get_buffer().get_iter_at_mark(self.begin_mark)
+
+ def end_iter(self):
+ return self.end_mark.get_buffer().get_iter_at_mark(self.end_mark)
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/snippets.ui b/plugins/snippets/snippets/snippets.ui
new file mode 100644
index 0000000..e80d633
--- /dev/null
+++ b/plugins/snippets/snippets/snippets.ui
@@ -0,0 +1,417 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.16.0 -->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkListStore" id="model1">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0">text</col>
+ </row>
+ <row>
+ <col id="0">text/plain</col>
+ </row>
+ <row>
+ <col id="0">text/xml</col>
+ </row>
+ <row>
+ <col id="0">image</col>
+ </row>
+ <row>
+ <col id="0">image/png</col>
+ </row>
+ <row>
+ <col id="0">image/jpeg</col>
+ </row>
+ <row>
+ <col id="0">audio</col>
+ </row>
+ <row>
+ <col id="0">video</col>
+ </row>
+ </data>
+ </object>
+ <object class="GeditDocument" id="source_buffer"/>
+ <object class="GeditSnippetsManager" id="snippets_manager">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Manage Snippets</property>
+ <property name="default_width">800</property>
+ <property name="default_height">600</property>
+ <property name="type_hint">dialog</property>
+ <child type="titlebar">
+ <object class="GtkHeaderBar" id="headerbar">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Manage Snippets</property>
+ <property name="show_close_button">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkPaned" id="hpaned_paned">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="position">275</property>
+ <style>
+ <class name="gedit-snippet-manager-paned"/>
+ </style>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolled_window_snippets">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <style>
+ <class name="gedit-snippet-manager-treeview"/>
+ </style>
+ <child>
+ <object class="GtkTreeView" id="tree_view_snippets">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ <signal name="key-press-event" handler="on_tree_view_snippets_key_press" swapped="no"/>
+ <signal name="row-expanded" handler="on_tree_view_snippets_row_expanded" swapped="no"/>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="toolbar_style">icons</property>
+ <property name="icon_size">1</property>
+ <child>
+ <object class="GtkToolButton" id="add_snippet_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Create new snippet</property>
+ <property name="tooltip_text" translatable="yes">Create new snippet</property>
+ <property name="label" translatable="yes">Add Snippet</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">list-add-symbolic</property>
+ <signal name="clicked" handler="on_add_snippet_button_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="remove_snippet_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Delete selected snippet</property>
+ <property name="tooltip_text" translatable="yes">Delete selected snippet</property>
+ <property name="label" translatable="yes">Remove Snippet</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">list-remove-symbolic</property>
+ <signal name="clicked" handler="on_remove_snippet_button_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="import_snippets_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Import snippets</property>
+ <property name="tooltip_text" translatable="yes">Import snippets</property>
+ <property name="label" translatable="yes">Import Snippets</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">document-open-symbolic</property>
+ <signal name="clicked" handler="on_import_snippets_button_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="export_snippets_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Export selected snippets</property>
+ <property name="tooltip_text" translatable="yes">Export selected snippets</property>
+ <property name="label" translatable="yes">Export Snippets</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">document-save-as-symbolic</property>
+ <signal name="clicked" handler="on_export_snippets_button_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <style>
+ <class name="inline-toolbar"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">False</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox_snippet">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolled_window_snippet">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <style>
+ <class name="gedit-snippet-manager-view"/>
+ </style>
+ <child>
+ <object class="GeditView" id="source_view_snippet">
+ <property name="buffer">source_buffer</property>
+ <property name="visible">True</property>
+ <signal handler="on_source_view_snippet_focus_out" name="focus_out_event"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Activation</property>
+ <property name="use_markup">True</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label"> </property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label_tab_trigger">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" comments="&quot;tab&quot; here means the tab key, not the notebook tab!">_Tab trigger:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_tab_trigger</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="hbox_tab_trigger">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="entry_tab_trigger">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Single word the snippet is activated with after pressing Tab</property>
+ <signal name="changed" handler="on_entry_tab_trigger_changed" swapped="no"/>
+ <signal name="focus-out-event" handler="on_entry_tab_trigger_focus_out" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="image_tab_trigger">
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">3</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_accelerator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">S_hortcut key:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_accelerator</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_accelerator">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Shortcut key with which the snippet is activated</property>
+ <property name="editable">False</property>
+ <signal name="focus-in-event" handler="on_entry_accelerator_focus_in" swapped="no"/>
+ <signal name="focus-out-event" handler="on_entry_accelerator_focus_out" swapped="no"/>
+ <signal name="key-press-event" handler="on_entry_accelerator_key_press" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_drop_targets">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Drop targets:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_accelerator</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combo_drop_targets">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model1</property>
+ <property name="has_entry">True</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="combobox-entry">
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/plugins/snippets/snippets/substitutionparser.py b/plugins/snippets/snippets/substitutionparser.py
new file mode 100644
index 0000000..8469dd3
--- /dev/null
+++ b/plugins/snippets/snippets/substitutionparser.py
@@ -0,0 +1,203 @@
+# Gedit snippets plugin
+# Copyright (C) 2006-2007 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 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 ParseError(Exception):
+ def __str__(self):
+ return 'Parse error, resume next'
+
+class Modifiers:
+ def _first_char(s):
+ first = (s != '' and s[0]) or ''
+ rest = (len(s) > 1 and s[1:]) or ''
+
+ return first, rest
+
+ def upper_first(s):
+ first, rest = Modifiers._first_char(s)
+
+ return '%s%s' % (first.upper(), rest)
+
+ def upper(s):
+ return s.upper()
+
+ def lower_first(s):
+ first, rest = Modifiers._first_char(s)
+
+ return '%s%s' % (first.lower(), rest)
+
+ def lower(s):
+ return s.lower()
+
+ def title(s):
+ return s.title()
+
+ upper_first = staticmethod(upper_first)
+ upper = staticmethod(upper)
+ lower_first = staticmethod(lower_first)
+ lower = staticmethod(lower)
+ title = staticmethod(title)
+ _first_char = staticmethod(_first_char)
+
+class SubstitutionParser:
+ REG_ID = '[0-9]+'
+ REG_NAME = '[a-zA-Z_]+'
+ REG_MOD = '[a-zA-Z]+'
+ REG_ESCAPE = '\\\\|\\(\\?|,|\\)'
+
+ REG_GROUP = '(?:(%s)|<(%s|%s)(?:,(%s))?>)' % (REG_ID, REG_ID, REG_NAME, REG_MOD)
+
+ def __init__(self, pattern, groups = {}, modifiers = {}):
+ self.pattern = pattern
+ self.groups = groups
+
+ self.modifiers = {'u': Modifiers.upper_first,
+ 'U': Modifiers.upper,
+ 'l': Modifiers.lower_first,
+ 'L': Modifiers.lower,
+ 't': Modifiers.title}
+
+ for k, v in modifiers.items():
+ self.modifiers[k] = v
+
+ def parse(self):
+ result, tokens = self._parse(self.pattern, None)
+
+ return result
+
+ def _parse(self, tokens, terminator):
+ result = ''
+
+ while tokens != '':
+ if self._peek(tokens) == '' or self._peek(tokens) == terminator:
+ tokens = self._remains(tokens)
+ break
+
+ try:
+ res, tokens = self._expr(tokens, terminator)
+ except ParseError:
+ res, tokens = self._text(tokens)
+
+ result += res
+
+ return result, tokens
+
+ def _peek(self, tokens, num = 0):
+ return (num < len(tokens) and tokens[num])
+
+ def _token(self, tokens):
+ if tokens == '':
+ return '', '';
+
+ return tokens[0], (len(tokens) > 1 and tokens[1:]) or ''
+
+ def _remains(self, tokens, num = 1):
+ return (num < len(tokens) and tokens[num:]) or ''
+
+ def _expr(self, tokens, terminator):
+ if tokens == '':
+ return ''
+
+ try:
+ return {'\\': self._escape,
+ '(': self._condition}[self._peek(tokens)](tokens, terminator)
+ except KeyError:
+ raise ParseError
+
+ def _text(self, tokens):
+ return self._token(tokens)
+
+ def _substitute(self, group, modifiers = ''):
+ result = (self.groups.has_key(group) and self.groups[group]) or ''
+
+ for modifier in modifiers:
+ if self.modifiers.has_key(modifier):
+ result = self.modifiers[modifier](result)
+
+ return result
+
+ def _match_group(self, tokens):
+ match = re.match('\\\\%s' % self.REG_GROUP, tokens)
+
+ if not match:
+ return None, tokens
+
+ return self._substitute(match.group(1) or match.group(2), match.group(3) or ''), tokens[match.end():]
+
+ def _escape(self, tokens, terminator):
+ # Try to match a group
+ result, tokens = self._match_group(tokens)
+
+ if result != None:
+ return result, tokens
+
+ s = self.REG_GROUP
+
+ if terminator:
+ s += '|%s' % re.escape(terminator)
+
+ match = re.match('\\\\(\\\\%s|%s)' % (s, self.REG_ESCAPE), tokens)
+
+ if not match:
+ raise ParseError
+
+ return match.group(1), tokens[match.end():]
+
+ def _condition_value(self, tokens):
+ match = re.match('\\\\?%s\s*' % self.REG_GROUP, tokens)
+
+ if not match:
+ return None, tokens
+
+ groups = match.groups()
+ name = groups[0] or groups[1]
+
+ return self.groups.has_key(name) and self.groups[name] != None, tokens[match.end():]
+
+ def _condition(self, tokens, terminator):
+ # Match ? after (
+ if self._peek(tokens, 1) != '?':
+ raise ParseError
+
+ # Remove initial (? token
+ tokens = self._remains(tokens, 2)
+ condition, tokens = self._condition_value(tokens)
+
+ if condition is None or self._peek(tokens) != ',':
+ raise ParseError
+
+ truepart, tokens = self._parse(self._remains(tokens), ',')
+
+ if truepart is None:
+ raise ParseError
+
+ falsepart, tokens = self._parse(tokens, ')')
+
+ if falsepart is None:
+ raise ParseError
+
+ if condition:
+ return truepart, tokens
+ else:
+ return falsepart, tokens
+
+ @staticmethod
+ def escape_substitution(substitution):
+ return re.sub('(%s|%s)' % (SubstitutionParser.REG_GROUP, SubstitutionParser.REG_ESCAPE), '\\\\\\1', substitution)
+
+# ex:ts=4:et:
diff --git a/plugins/snippets/snippets/windowactivatable.py b/plugins/snippets/snippets/windowactivatable.py
new file mode 100644
index 0000000..6729a69
--- /dev/null
+++ b/plugins/snippets/snippets/windowactivatable.py
@@ -0,0 +1,186 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-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 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
+
+from gi.repository import Gtk, Gedit, GObject
+from .snippet import Snippet
+from .library import Library
+from .shareddata import SharedData
+from .signals import Signals
+
+
+class Message(Gedit.Message):
+ view = GObject.Property(type=Gedit.View)
+ iter = GObject.Property(type=Gtk.TextIter)
+
+class Activate(Message):
+ trigger = GObject.Property(type=str)
+
+class ParseAndActivate(Message):
+ snippet = GObject.Property(type=str)
+
+class WindowActivatable(GObject.Object, Gedit.WindowActivatable, Signals):
+ __gtype_name__ = "GeditSnippetsWindowActivatable"
+
+ window = GObject.Property(type=Gedit.Window)
+
+ def __init__(self):
+ GObject.Object.__init__(self)
+ Signals.__init__(self)
+
+ self.current_language_accel_group = None
+
+ def do_activate(self):
+ self.register_messages()
+
+ library = Library()
+ library.add_accelerator_callback(self.accelerator_activated)
+
+ self.accel_group = Library().get_accel_group(None)
+
+ if self.accel_group:
+ self.window.add_accel_group(self.accel_group)
+
+ self.connect_signal(self.window,
+ 'active-tab-changed',
+ self.on_active_tab_changed)
+
+ self.do_update_state()
+
+ SharedData().register_window(self)
+
+ def do_deactivate(self):
+ if self.accel_group:
+ self.window.remove_accel_group(self.accel_group)
+
+ self.accel_group = None
+
+ self.unregister_messages()
+
+ library = Library()
+ library.remove_accelerator_callback(self.accelerator_activated)
+
+ self.disconnect_signals(self.window)
+
+ SharedData().unregister_window(self)
+
+ def do_update_state(self):
+ controller = SharedData().get_active_controller(self.window)
+
+ self.update_language(controller)
+
+ def register_messages(self):
+ bus = self.window.get_message_bus()
+
+ bus.register(Activate, '/plugins/snippets', 'activate')
+ bus.register(ParseAndActivate, '/plugins/snippets', 'parse-and-activate')
+
+ self.signal_ids = set()
+
+ sid = bus.connect('/plugins/snippets', 'activate', self.on_message_activate, None)
+ self.signal_ids.add(sid)
+
+ sid = bus.connect('/plugins/snippets', 'parse-and-activate', self.on_message_parse_and_activate, None)
+ self.signal_ids.add(sid)
+
+ def unregister_messages(self):
+ bus = self.window.get_message_bus()
+ for sid in self.signal_ids:
+ bus.disconnect(sid)
+ self.signal_ids = set()
+ bus.unregister_all('/plugins/snippets')
+
+ def on_message_activate(self, bus, message, userdata):
+ view = message.props.view
+
+ if not view:
+ view = self.window.get_active_view()
+
+ controller = SharedData().get_controller(view)
+
+ if not controller:
+ return
+
+ iter = message.props.iter
+
+ if not iter:
+ iter = view.get_buffer().get_iter_at_mark(view.get_buffer().get_insert())
+
+ controller.run_snippet_trigger(message.props.trigger, (iter, iter))
+
+ def on_message_parse_and_activate(self, bus, message, userdata):
+ view = message.props.view
+
+ if not view:
+ view = self.window.get_active_view()
+
+ controller = SharedData().get_controller(view)
+
+ if not controller:
+ return
+
+ iter = message.props.iter
+
+ if not iter:
+ iter = view.get_buffer().get_iter_at_mark(view.get_buffer().get_insert())
+
+ controller.parse_and_run_snippet(message.props.snippet, iter)
+
+ def find_snippet(self, snippets, tag):
+ result = []
+
+ for snippet in snippets:
+ if Snippet(snippet)['tag'] == tag:
+ result.append(snippet)
+
+ return result
+
+ def update_language(self, controller):
+ if not self.window:
+ return
+
+ if controller:
+ langid = controller.language_id
+ else:
+ langid = None
+
+ if langid != None:
+ accelgroup = Library().get_accel_group(langid)
+ else:
+ accelgroup = None
+
+ if accelgroup != self.current_language_accel_group:
+ if self.current_language_accel_group:
+ self.window.remove_accel_group(self.current_language_accel_group)
+
+ if accelgroup:
+ self.window.add_accel_group(accelgroup)
+
+ self.current_language_accel_group = accelgroup
+
+ def on_active_tab_changed(self, window, tab):
+ self.update_language(SharedData().get_controller(tab.get_view()))
+
+ def accelerator_activated(self, group, obj, keyval, mod):
+ if obj == self.window:
+ controller = SharedData().get_active_controller(self.window)
+
+ if controller:
+ return controller.accelerator_activate(keyval, mod)
+ else:
+ return False
+
+# ex:ts=4:et: