diff options
author | Perberos <[email protected]> | 2011-11-07 16:46:58 -0300 |
---|---|---|
committer | Perberos <[email protected]> | 2011-11-07 16:46:58 -0300 |
commit | 528c1e5ff51e213936e800fc5a9a25da99c0bdf2 (patch) | |
tree | 77f8aa456b09367ba81f04d4562fc935f898a951 /plugins/snippets | |
download | pluma-528c1e5ff51e213936e800fc5a9a25da99c0bdf2.tar.bz2 pluma-528c1e5ff51e213936e800fc5a9a25da99c0bdf2.tar.xz |
initial
Diffstat (limited to 'plugins/snippets')
44 files changed, 9734 insertions, 0 deletions
diff --git a/plugins/snippets/Makefile.am b/plugins/snippets/Makefile.am new file mode 100755 index 00000000..06f0009b --- /dev/null +++ b/plugins/snippets/Makefile.am @@ -0,0 +1,15 @@ +# Python snippets plugin +SUBDIRS = snippets data +plugindir = $(GEDIT_PLUGINS_LIBS_DIR) + +plugin_in_files = snippets.gedit-plugin.desktop.in +%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache + +plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin) + +EXTRA_DIST = $(plugin_in_files) + +CLEANFILES = $(plugin_DATA) +DISTCLEANFILES = $(plugin_DATA) + +-include $(top_srcdir)/git.mk diff --git a/plugins/snippets/data/Makefile.am b/plugins/snippets/data/Makefile.am new file mode 100755 index 00000000..8ec40419 --- /dev/null +++ b/plugins/snippets/data/Makefile.am @@ -0,0 +1,33 @@ +# Python snippets plugin +SUBDIRS = lang + +snippets_DATA = \ + css.xml \ + c.xml \ + cpp.xml \ + chdr.xml \ + docbook.xml \ + fortran.xml \ + global.xml \ + haskell.xml \ + html.xml \ + idl.xml \ + javascript.xml \ + java.xml \ + latex.xml \ + mallard.xml \ + perl.xml \ + php.xml \ + python.xml \ + ruby.xml \ + sh.xml \ + snippets.xml \ + tcl.xml \ + xml.xml \ + xslt.xml + +snippetsdir = $(GEDIT_PLUGINS_DATA_DIR)/snippets + +EXTRA_DIST = $(snippets_DATA) + +-include $(top_srcdir)/git.mk diff --git a/plugins/snippets/data/c.xml b/plugins/snippets/data/c.xml new file mode 100755 index 00000000..61171cb8 --- /dev/null +++ b/plugins/snippets/data/c.xml @@ -0,0 +1,283 @@ +<?xml version="1.0" encoding="UTF-8"?> +<snippets language="C"> + <snippet id="gpl"> + <text><![CDATA[/* + * ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]} + * This file is part of ${2:<program name>} + * + * Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4: +import pwd, os +try: + return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0] +except KeyError: + return '<author\>' > + * + * ${2} is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ${2} is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ${2}; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +$0]]></text> + <tag>gpl</tag> + <description>GPL License</description> + </snippet> + <snippet id="lgpl"> + <text><![CDATA[/* + * ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]} + * This file is part of ${2:<library name>} + * + * Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4: +import pwd, os +try: + return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0] +except KeyError: + return '<author\>' > + * + * ${2} is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * ${2} is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +$0]]></text> + <tag>lgpl</tag> + <description>LGPL License</description> + </snippet> + <snippet id="do"> + <text><![CDATA[do +{ + $0 +} while ($1);]]></text> + <tag>do</tag> + <description>do .. while</description> + </snippet> + <snippet id="for"> + <text><![CDATA[for (${1:i} = ${2:0}; ${1:i} < ${3:count}; ${1:i} += ${4:1}) +{ + $0 +}]]></text> + <tag>for</tag> + <description>for loop</description> + </snippet> + <snippet id="while"> + <text><![CDATA[while (${1:condition}) +{ + $0 +}]]></text> + <tag>while</tag> + <description>while loop</description> + </snippet> + <snippet id="if"> + <text><![CDATA[if (${1:condition}) +{ + $0 +}]]></text> + <tag>if</tag> + <description>if</description> + </snippet> + <snippet id="elif"> + <text><![CDATA[else if (${1:condition}) +{ + $0 +}]]></text> + <tag>elif</tag> + <description>else if</description> + </snippet> + <snippet id="else"> + <text><![CDATA[else +{ + $0 +}]]></text> + <tag>else</tag> + <description>else</description> + </snippet> + <snippet id="Inc"> + <text><![CDATA[#include <${1:file}.h> +$0]]></text> + <tag>Inc</tag> + <description>#include <..></description> + </snippet> + <snippet id="inc"> + <text><![CDATA[#include "${1:file}.h" +$0]]></text> + <tag>inc</tag> + <description>#include ".."</description> + </snippet> + <snippet id="main"> + <text><![CDATA[int +main (int argc, char *argv[]) +{ + $0 + return 0; +}]]></text> + <tag>main</tag> + <description>main</description> + </snippet> + <snippet id="struct"> + <text><![CDATA[struct ${1:name} +{ + ${0:/* data */} +};]]></text> + <tag>struct</tag> + <description>struct</description> + </snippet> + <snippet id="endif"> + <text><![CDATA[#endif +$0]]></text> + <description>#endif</description> + <accelerator><![CDATA[<Control><Alt>period]]></accelerator> + </snippet> + <snippet id="td"> + <text><![CDATA[typedef ${1:newtype} ${2:type}; +$0]]></text> + <tag>td</tag> + <description>typedef</description> + </snippet> + <snippet id="gobject"> + <text><![CDATA[#include "$1.h" +$< +global camel_str,low_str, type_str, is_str, up_str +components = $1.split('-') +low_str = '_'.join(components).lower() +up_str = '_'.join(components).upper() +type_str = '_'.join([components[0], 'TYPE'] + components[1:]).upper() +is_str = '_'.join([components[0], 'IS'] + components[1:]).upper() +camel_str = '' + +for t in components: + camel_str += t.capitalize() +> + +#define $<[1]: return up_str >_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), $<[1]: return type_str >, $<[1]: return camel_str >Private)) + +struct _$<[1]: return camel_str >Private +{ +}; + +G_DEFINE_TYPE ($<[1]: return camel_str >, $<[1]: return low_str >, ${2:G_TYPE_OBJECT}) + +static void +$<[1]: return low_str>_finalize (GObject *object) +{ + G_OBJECT_CLASS ($<[1]: return low_str >_parent_class)->finalize (object); +} + +static void +$<[1]: return low_str >_class_init ($<[1]: return camel_str >Class *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = $<[1]: return low_str >_finalize; + + g_type_class_add_private (object_class, sizeof ($<[1]: return camel_str >Private)); +} + +static void +$<[1]: return low_str >_init ($<[1]: return camel_str> *self) +{ + self->priv = $<[1]: return up_str >_GET_PRIVATE (self); +} + +$<[1]: return camel_str > * +$<[1]: return low_str >_new () +{ + return g_object_new ($<[1]: return type_str >, NULL); +}]]></text> + <tag>gobject</tag> + <description>GObject template</description> + </snippet> + <snippet id="ginterface"> + <text><![CDATA[#include "$1.h" +$< +global camel_str,low_str,up_str +components = $1.split('-') +low_str = '_'.join(components).lower() +up_str = '_'.join(components).upper() +camel_str = '' + +for t in components: + camel_str += t.capitalize() +> +/* Default implementation */ +static const gchar * +$<[1]: return low_str>_example_method_default ($<[1]: return camel_str > *self) +{ + g_return_val_if_reached (NULL); +} + +static void +$<[1]: return low_str>_init ($<[1]: return camel_str >Iface *iface) +{ + static gboolean initialized = FALSE; + + iface->example_method = $<[1]: return low_str>_example_method_default; + + if (!initialized) + { + initialized = TRUE; + } +} + +/* + * This is an method example for an interface + */ +const gchar * +$<[1]: return low_str>_example_method ($<[1]: return camel_str > *self) +{ + g_return_val_if_fail ($<[1]: return up_str> (self), NULL); + return $<[1]: return up_str>_GET_INTERFACE (self)->example_method (self); +} + +GType +$<[1]: return low_str>_get_type () +{ + static GType $<[1]: return low_str>_type_id = 0; + + if (!$<[1]: return low_str>_type_id) + { + static const GTypeInfo g_define_type_info = + { + sizeof ($<[1]: return camel_str >Iface), + (GBaseInitFunc) $<[1]: return low_str>_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL + }; + + $<[1]: return low_str>_type_id = + g_type_register_static (G_TYPE_INTERFACE, + "$<[1]: return camel_str>", + &g_define_type_info, + 0); + } + + return $<[1]: return low_str>_type_id; +}]]></text> + <tag>ginterface</tag> + <description>GObject interface</description> + </snippet> +</snippets> diff --git a/plugins/snippets/data/chdr.xml b/plugins/snippets/data/chdr.xml new file mode 100755 index 00000000..f71ea901 --- /dev/null +++ b/plugins/snippets/data/chdr.xml @@ -0,0 +1,241 @@ +<?xml version="1.0" encoding="UTF-8"?> +<snippets language="chdr"> + <snippet id="once"> + <text><![CDATA[#ifndef __${1:NAME}_H__ +#define __$1_H__ + +$0 + +#endif /* __$1_H__ */ +]]></text> + <description>Header Include-Guard</description> + <tag>once</tag> + </snippet> + <snippet id="inc"> + <text><![CDATA[#include "${1:file}" +$0]]></text> + <description>#include ".."</description> + <tag>inc</tag> + </snippet> + <snippet id="Inc"> + <text><![CDATA[#include <${1:file}> +$0]]></text> + <description>#include <..></description> + <tag>Inc</tag> + </snippet> + <snippet id="namespace"> + <text><![CDATA[namespace ${1:ns} +{ + $0 +}; +]]></text> + <description>namespace ..</description> + <tag>namespace</tag> + </snippet> + <snippet id="gpl"> + <text><![CDATA[/* + * ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]} + * This file is part of ${2:<program name>} + * + * Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4: +import pwd, os +try: + return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0] +except KeyError: + return '<author\>' > + * + * ${2} is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ${2} is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ${2}; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +$0]]></text> + <tag>gpl</tag> + <description>GPL License</description> + </snippet> + <snippet id="lgpl"> + <text><![CDATA[/* + * ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]} + * This file is part of ${2:<library name>} + * + * Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4: +import pwd, os +try: + return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0] +except KeyError: + return '<author\>' > + * + * ${2} is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * ${2} is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +$0]]></text> + <tag>lgpl</tag> + <description>LGPL License</description> + </snippet> + <snippet id="td"> + <text><![CDATA[typedef ${1:newtype} ${2:type}; +$0]]></text> + <tag>td</tag> + <description>typedef</description> + </snippet> + <snippet id="class"> + <text><![CDATA[class ${1:name} +{ + public: + ${1:name} (${2:arguments}); + virtual ~${1:name} (); + + private: + ${0:/* data */} +};]]></text> + <description>class ..</description> + <tag>class</tag> + </snippet> + <snippet id="struct"> + <text><![CDATA[struct ${1:name} +{ + ${0:/* data */} +};]]></text> + <tag>struct</tag> + <description>struct</description> + </snippet> + <snippet id="template"> + <text><![CDATA[template <typename ${1:_InputIter}>]]></text> + <description>template <typename ..></description> + <tag>template</tag> + </snippet> + <snippet id="gobject"> + <text><![CDATA[#ifndef __${1:NAME}_H__ +#define __$1_H__ + +#include <${2:glib-object.h}> + +G_BEGIN_DECLS + +$< +global camel_str +components = $1.split('_') +type_str = '_'.join([components[0], 'TYPE'] + components[1:]) +is_str = '_'.join([components[0], 'IS'] + components[1:]) +camel_str = '' + +for t in components: + camel_str += t.capitalize() + +items = [ \ +['#define ' + type_str, '(' + $1.lower() + '_get_type ())'], \ +['#define ' + $1 + '(obj)', '(G_TYPE_CHECK_INSTANCE_CAST ((obj), ' + type_str + ', ' + camel_str + '))'], \ +['#define ' + $1 + '_CONST(obj)', '(G_TYPE_CHECK_INSTANCE_CAST ((obj), ' + type_str + ', ' + camel_str + ' const))'], \ +['#define ' + $1 + '_CLASS(klass)', '(G_TYPE_CHECK_CLASS_CAST ((klass), ' + type_str + ', ' + camel_str + 'Class))'], \ +['#define ' + is_str + '(obj)', '(G_TYPE_CHECK_INSTANCE_TYPE ((obj), ' + type_str + '))'], \ +['#define ' + is_str + '_CLASS(klass)', '(G_TYPE_CHECK_CLASS_TYPE ((klass), ' + type_str + '))'], \ +['#define ' + $1 + '_GET_CLASS(obj)', '(G_TYPE_INSTANCE_GET_CLASS ((obj), ' + type_str + ', ' + camel_str + 'Class))'] +] + +return align(items) > + +$<[1]: +items = [ \ +['typedef struct _' + camel_str, camel_str + ';'], \ +['typedef struct _' + camel_str + 'Class', camel_str + 'Class;'], \ +['typedef struct _' + camel_str + 'Private', camel_str + 'Private;'] \ +] + +return align(items) > + +struct _$<[1]: return camel_str > { + ${7:GObject} parent; + + $<[1]: return camel_str >Private *priv; +}; + +struct _$<[1]: return camel_str >Class { + $7Class parent_class; +}; + +GType $< return $1.lower() + '_get_type' > (void) G_GNUC_CONST; +$<[1]: return camel_str > *$< return $1.lower()>_new (void); + +$0 +G_END_DECLS + +#endif /* __$1_H__ */]]></text> + <tag>gobject</tag> + <description>GObject template</description> + </snippet> + <snippet id="ginterface"> + <text><![CDATA[#ifndef __${1:NAME}_H__ +#define __$1_H__ + +#include <${2:glib-object.h}> + +G_BEGIN_DECLS + +$< +global camel_str +components = $1.split('_') +type_str = '_'.join([components[0], 'TYPE'] + components[1:]) +is_str = '_'.join([components[0], 'IS'] + components[1:]) +camel_str = '' + +for t in components: + camel_str += t.capitalize() + +items = [ \ +['#define ' + type_str, '(' + $1.lower() + '_get_type ())'], \ +['#define ' + $1 + '(obj)', '(G_TYPE_CHECK_INSTANCE_CAST ((obj), ' + type_str + ', ' + camel_str + '))'], \ +['#define ' + is_str + '(obj)', '(G_TYPE_CHECK_INSTANCE_TYPE ((obj), ' + type_str + '))'], \ +['#define ' + $1 + '_GET_INTERFACE(obj)', '(G_TYPE_INSTANCE_GET_INTERFACE ((obj), ' + type_str + ', ' + camel_str + 'Iface))'] +] + +return align(items) > + +$<[1]: +items = [ \ +['typedef struct _' + camel_str, camel_str + ';'], \ +['typedef struct _' + camel_str + 'Iface', camel_str + 'Iface;'], \ +] + +return align(items) > + +struct _$<[1]: return camel_str >Iface +{ + ${7:GTypeInterface} parent; + + const gchar * (*example_method) ($<[1]: return camel_str > *self); +}; + +GType $< return $1.lower() + '_get_type' > (void) G_GNUC_CONST; + +const gchar *$< return $1.lower()>_example_method ($<[1]: return camel_str > *self); +$0 +G_END_DECLS + +#endif /* __$1_H__ */]]></text> + <tag>ginterface</tag> + <description>GObject interface</description> + </snippet> +</snippets> diff --git a/plugins/snippets/data/cpp.xml b/plugins/snippets/data/cpp.xml new file mode 100755 index 00000000..7c7ccabd --- /dev/null +++ b/plugins/snippets/data/cpp.xml @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="UTF-8"?> +<snippets language="cpp"> + <snippet id="main"> + <text><![CDATA[int main (int argc, char const* argv[]) +{ + $0 + return 0; +}]]></text> + <description>main</description> + <tag>main</tag> + </snippet> + <snippet id="for"> + <text><![CDATA[for (${1:unsigned int} ${2:i} = ${3:0}; ${2:i} < ${4:count}; ${2:i} += ${5:1}) +{ + $0 +}]]></text> + <description>for loop</description> + <tag>for</tag> + </snippet> + <snippet id="beginend"> + <text><![CDATA[${1:v}.begin(), ${1:v}.end()]]></text> + <description>$1.begin</description> + <tag>beginend</tag> + </snippet> + <snippet id="do"> + <text><![CDATA[do +{ + $0 +} while ($1 );]]></text> + <description>do .. while</description> + <tag>do</tag> + </snippet> + <snippet id="endif"> + <text><![CDATA[#endif +$0]]></text> + <accelerator><![CDATA[<Control><Alt>period]]></accelerator> + <description>#endif</description> + </snippet> + <snippet id="if"> + <text><![CDATA[if (${1:condition}) +{ + $0 +}]]></text> + <description>if ..</description> + <tag>if</tag> + </snippet> + <snippet id="inc"> + <text><![CDATA[#include "${1:file}" +$0]]></text> + <description>#include ".."</description> + <tag>inc</tag> + </snippet> + <snippet id="Inc"> + <text><![CDATA[#include <${1:file}> +$0]]></text> + <description>#include <..></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 <typename ..></description> + <tag>template</tag> + </snippet> + <snippet id="gpl"> + <text><![CDATA[/* + * ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]} + * This file is part of ${2:<program name>} + * + * Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4: +import pwd, os +try: + return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0] +except KeyError: + return '<author\>' > + * + * ${2} is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ${2} is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ${2}; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + + $0]]></text> + <tag>gpl</tag> + <description>GPL License</description> + </snippet> + <snippet id="lgpl"> + <text><![CDATA[/* + * ${1:[$GEDIT_CURRENT_DOCUMENT_NAME,<filename>]} + * This file is part of ${2:<library name>} + * + * Copyright (C) $<3: import datetime; return str(datetime.date.today().year)> - $<4: +import pwd, os +try: + return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0] +except KeyError: + return '<author\>' > + * + * ${2} is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * ${2} is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + $0]]></text> + <tag>lgpl</tag> + <description>LGPL License</description> + </snippet> + <snippet id="td"> + <text><![CDATA[typedef ${1:newtype} ${2:type}; +$0]]></text> + <tag>td</tag> + <description>typedef</description> + </snippet> + <snippet id="while"> + <text><![CDATA[while ($1) +{ + $0 +}]]></text> + <tag>while</tag> + <description>while</description> + </snippet> +</snippets> diff --git a/plugins/snippets/data/css.xml b/plugins/snippets/data/css.xml new file mode 100755 index 00000000..babca912 --- /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 100755 index 00000000..3159b603 --- /dev/null +++ b/plugins/snippets/data/docbook.xml @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8"?> +<snippets language="docbook"> + <!-- useful snippets from xml set --> + <snippet id="<"> + <text><![CDATA[<${1}>$0</${1}>]]></text> + <description>XML tag</description> + <tag><</tag> + </snippet> + <snippet id="menuchoice"> + <text><![CDATA[<menuchoice><guimenu>$1</guimenu><guimenuitem>$2</guimenuitem></menuchoice> +]]></text> + <tag>menu</tag> + <description>menuchoice</description> + <accelerator /> + </snippet> + <snippet id="keycombo"> + <text><![CDATA[<keycombo><keycap>${1:Ctrl}</keycap><keycap>${2}</keycap></keycombo>]]></text> + <tag>key</tag> + <description>keycombo</description> + <accelerator/> + </snippet> + <snippet id="sect"> + <text><![CDATA[<sect${1} id="${2}"> + <title>${3}</title> +</sect${1}>]]></text> + <tag>sect</tag> + <description>sect*</description> + <accelerator/> + </snippet> + <snippet id="app"> + <text><![CDATA[<application>&app;</application>]]></text> + <tag>app</tag> + <description>app entity</description> + <accelerator/> + </snippet> + <snippet id="appwrap"> + <text><![CDATA[<application>$GEDIT_SELECTED_TEXT</application>]]></text> + <tag>application</tag> + <description>application tag</description> + <accelerator/> + </snippet> + <snippet id="enclose"> + <text><![CDATA[<${1}>$GEDIT_SELECTED_TEXT</${1}>]]></text> + <tag>enclose</tag> + <description>enclose selected text</description> + <accelerator/> + </snippet> + <snippet id="itemizedlist"> + <text><![CDATA[<itemizedlist> + <listitem> + <para>${1}</para> + </listitem> +</itemizedlist>]]></text> + <tag>ul</tag> + <description>itemized list</description> + <accelerator/> + </snippet> + <snippet id="orderedlist"> + <text><![CDATA[<orderedlist> + <listitem> + <para>${1}</para> + </listitem> +</orderedlist>]]></text> + <tag>ol</tag> + <description>ordered list</description> + <accelerator/> + </snippet> + <snippet id="listitem"> + <text><![CDATA[<listitem> + <para>${1}</para> +</listitem>]]></text> + <tag>li</tag> + <description>list item</description> + <accelerator/> + </snippet> + <snippet id="variablelist"> + <text><![CDATA[<variablelist> + $1 +</variablelist>]]></text> + <tag>vl</tag> + <description>variablelist</description> + <accelerator/> + </snippet> + <snippet id="varlistentry"> + <text><![CDATA[<varlistentry><term>${1}</term> + <listitem> + <para>${2}</para> + </listitem> +</varlistentry>]]></text> + <tag>vli</tag> + <description>variablelist entry</description> + <accelerator/> + </snippet> + <snippet id="closepara"> + <text><![CDATA[</para>]]></text> + <tag>/</tag> + <description>para close</description> + <accelerator/> + </snippet> + <snippet id="openpara"> + <text><![CDATA[<para>]]></text> + <tag>p</tag> + <description>para open</description> + <accelerator/> + </snippet> + <snippet id="http"> + <text><![CDATA[<ulink type="http" url="$1">$2</ulink>]]></text> + <tag>http</tag> + <description>ulink http</description> + <accelerator/> + </snippet> + <snippet id="yelp"> + <text><![CDATA[<ulink type="help" url="$1">$2</ulink>]]></text> + <tag>help</tag> + <description>ulink mate help</description> + <accelerator/> + </snippet> +</snippets> diff --git a/plugins/snippets/data/fortran.xml b/plugins/snippets/data/fortran.xml new file mode 100755 index 00000000..c64d6461 --- /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 100755 index 00000000..afe3c0b7 --- /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 100755 index 00000000..54a8e7d6 --- /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 -> t</description> + <tag>\</tag> + </snippet> +</snippets> diff --git a/plugins/snippets/data/html.xml b/plugins/snippets/data/html.xml new file mode 100755 index 00000000..d294f934 --- /dev/null +++ b/plugins/snippets/data/html.xml @@ -0,0 +1,246 @@ +<?xml version="1.0" encoding="UTF-8"?> +<snippets language="HTML"> + <snippet id="doctype"> + <text><![CDATA[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +]]></text> + <description>HTML — 4.01 Strict</description> + <tag>doctype</tag> + </snippet> + <snippet id="doctype-1"> + <text><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> +]]></text> + <description>XHTML — 1.0 Frameset</description> + <tag>doctype</tag> + </snippet> + <snippet id="doctype-2"> + <text><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +]]></text> + <description>XHTML — 1.0 Strict</description> + <tag>doctype</tag> + </snippet> + <snippet id="doctype-3"> + <text><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +]]></text> + <description>XHTML — 1.0 Transitional</description> + <tag>doctype</tag> + </snippet> + <snippet id="doctype-4"> + <text><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +]]></text> + <description>XHTML — 1.1</description> + <tag>doctype</tag> + </snippet> + <snippet id="doctype-5"> + <text><![CDATA[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +]]></text> + <description>HTML — 4.0 Transitional</description> + <tag>doctype</tag> + </snippet> + <snippet id="author"> + <text><![CDATA[<meta name="author" content="${1:author}" /> +$0]]></text> + <tag>author</tag> + <description>Author</description> + </snippet> + <snippet id="date"> + <text><![CDATA[<meta name="date" content="$<1: import time; return time.strftime("%Y-%m-%d") >" /> +$0]]></text> + <tag>date</tag> + <description>Date</description> + </snippet> + <snippet id="ref"> + <text><![CDATA[<a href="${1:http://somesite.com/}">${2:$GEDIT_SELECTED_TEXT}</a> +]]></text> + <accelerator><![CDATA[<Shift><Alt>l]]></accelerator> + <description>Wrap Selection as Link</description> + <tag>ref</tag> + </snippet> + <snippet id="open/close"> + <text><![CDATA[<${1:p}>$GEDIT_SELECTED_TEXT</${1}>]]></text> + <accelerator><![CDATA[<Shift><Alt>w]]></accelerator> + <description>Wrap Selection in Open/Close Tag</description> + </snippet> + <snippet id="mailto"> + <text><![CDATA[<a href="mailto:${1:[email protected]}?subject=${2:feedback}">${3:email me}</a> $0]]></text> + <description>Mail Anchor</description> + <tag>mailto</tag> + </snippet> + <snippet id="base"> + <text><![CDATA[<base href="$1" ${2}/>$0]]></text> + <description>Base</description> + <tag>base</tag> + </snippet> + <snippet id="body"> + <text><![CDATA[<body id="${1:ID} " onload="$2"}> + $0 +</body>]]></text> + <description>Body</description> + <tag>body</tag> + </snippet> + <snippet id="br"> + <text><![CDATA[<br /> +$0]]></text> + <accelerator><![CDATA[<Shift><Control>space]]></accelerator> + <description>Br</description> + </snippet> + <snippet id="button"> + <text><![CDATA[<button type="button" name="${1:name}" value="${2:caption}" onclick="$3" />$4 +]]></text> + <tag>button</tag> + <description>Button</description> + </snippet> + <snippet id="div"> + <text><![CDATA[<div ${1}> + ${0:$GEDIT_SELECTED_TEXT} +</div>]]></text> + <description>Div</description> + <tag>div</tag> + </snippet> + <snippet id="file"> + <text><![CDATA[<input type="file" name="${1:name}" size="$2" accept="$3" />$0 +]]></text> + <tag>file</tag> + <description>File</description> + </snippet> + <snippet id="form"> + <text><![CDATA[<form action="${1}" method="${2:get}"> + $0 + + <p><input type="submit" value="${3:Continue →}" /></p> +</form>]]></text> + <description>Form</description> + <tag>form</tag> + </snippet> + <snippet id="h"> + <text><![CDATA[<h${1:1} id="${2}">${3:$GEDIT_SELECTED_TEXT}</h${1}> +$0]]></text> + <description>Heading</description> + <tag>h</tag> + </snippet> + <snippet id="head"> + <text><![CDATA[<head> + <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> + <title>${1:Page Title}</title> + $0 +</head>]]></text> + <description>Head</description> + <tag>head</tag> + </snippet> + <snippet id="image"> + <text><![CDATA[<img src="${1:path/to/file}" alt="${2:description}" title="${3:description}" width="$4" height="$5" />$0]]></text> + <tag>img</tag> + <description>Image</description> + </snippet> + <snippet id="input"> + <text><![CDATA[<input type="${1:[button,checkbox,file,hidden,image,password,radio,reset,submit,text]}" name="${2:some_name}" value="$3" id="${5}" />]]></text> + <description>Input</description> + <tag>input</tag> + </snippet> + <snippet id="li"> + <text><![CDATA[<li>$1</li>$0]]></text> + <tag>li</tag> + <description>List Element</description> + </snippet> + <snippet id="link"> + <text><![CDATA[<link rel="${1:stylesheet}" href="${2:/css/master.css}" type="text/css" media="${3:screen}" title="${4:no title}" charset="${5:utf-8}" />]]></text> + <description>Link</description> + <tag>link</tag> + </snippet> + <snippet id="meta"> + <text><![CDATA[<meta name="${1:name}" content="${2:content}" />]]></text> + <description>Meta</description> + <tag>meta</tag> + </snippet> + <snippet id="nbsp"> + <text><![CDATA[ ]]></text> + <accelerator><![CDATA[<Control><Alt>space]]></accelerator> + <description>Non-Breaking Space</description> + </snippet> + <snippet id="noscript"> + <text><![CDATA[<noscript>$1</noscript>$0]]></text> + <tag>noscript</tag> + <description>Noscript</description> + </snippet> + <snippet id="option"> + <text><![CDATA[<option value="${1:value}">$2</option>$0]]></text> + <tag>option</tag> + <description>Option</description> + </snippet> + <snippet id="script"> + <text><![CDATA[<script type="text/javascript" language="javascript" charset="utf-8"> +// <![CDATA[ + $0 +// ]]]]><![CDATA[> +</script>]]></text> + <description>Script</description> + <tag>script</tag> + </snippet> + <snippet id="scriptsrc"> + <text><![CDATA[<script src="$1" type="text/javascript" language="${2:javascript}" charset="${3:utf-8}" />]]></text> + <description>Script With External Source</description> + <tag>scriptsrc</tag> + </snippet> + <snippet id="select"> + <text><![CDATA[<select name="${1:name}"> + <option value="${2:value}">$3</option> + $4 +</select>$0 +]]></text> + <tag>select</tag> + <description>Select</description> + </snippet> + <snippet id="span"> + <text><![CDATA[<span ${1}>$2</span>$0]]></text> + <tag>span</tag> + <description>Span</description> + </snippet> + <snippet id="style"> + <text><![CDATA[<style type="text/css" media="screen"> +/* <![CDATA[ */ + $0 +/* ]]]]><![CDATA[> */ +</style> +]]></text> + <description>Style</description> + <tag>style</tag> + </snippet> + <snippet id="table"> + <text><![CDATA[<table border="${1:0}" cellspacing="${2:0}" cellpadding="${3:0}"> + <tr><th>${4:Header}</th></tr> + <tr><td>${5:Data}</td></tr> + $0 +</table>]]></text> + <description>Table</description> + <tag>table</tag> + </snippet> + <snippet id="textarea"> + <text><![CDATA[<textarea name="${1:Name}" rows="${2:8}" cols="${3:40}">$0</textarea>]]></text> + <description>Text Area</description> + <tag>textarea</tag> + </snippet> + <snippet id="title"> + <text><![CDATA[<title>${1:Page Title}</title>]]></text> + <description>Title</description> + <tag>title</tag> + </snippet> + <snippet id="tr"> + <text><![CDATA[<tr><td>$1</td></tr> +$0]]></text> + <tag>tr</tag> + <description>Table Row</description> + </snippet> + <snippet id="ul"> + <text><![CDATA[<ul> + <li>$1</li> + $2 +</ul> +$0]]></text> + <tag>ul</tag> + <description>Unordered List</description> + </snippet> +</snippets> diff --git a/plugins/snippets/data/idl.xml b/plugins/snippets/data/idl.xml new file mode 100755 index 00000000..2b6ef30d --- /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 100755 index 00000000..043a5dd3 --- /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 100755 index 00000000..c1d498a6 --- /dev/null +++ b/plugins/snippets/data/javascript.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<snippets language="JavaScript"> + <snippet id="fun"> + <text><![CDATA[function ${1:function_name} (${2:first_argument}) +{ + ${0:# body...} +}]]></text> + <description>function</description> + <tag>fun</tag> + </snippet> +</snippets> diff --git a/plugins/snippets/data/lang/Makefile.am b/plugins/snippets/data/lang/Makefile.am new file mode 100755 index 00000000..8a497c12 --- /dev/null +++ b/plugins/snippets/data/lang/Makefile.am @@ -0,0 +1,9 @@ +# Python snippets plugin +lang_DATA = \ + snippets.lang + +langdir = $(GEDIT_PLUGINS_DATA_DIR)/snippets/lang + +EXTRA_DIST = $(lang_DATA) + +-include $(top_srcdir)/git.mk diff --git a/plugins/snippets/data/lang/snippets.lang b/plugins/snippets/data/lang/snippets.lang new file mode 100755 index 00000000..81e57394 --- /dev/null +++ b/plugins/snippets/data/lang/snippets.lang @@ -0,0 +1,162 @@ +<?xml version="1.0"?> +<!-- + + Author: Jesse van den Kieboom <[email protected]> + Copyright (C) 2007-2008 Jesse van den Kieboom <[email protected]> + + 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, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +--> +<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>\$<\%{tabstop}?\%{number-list}?</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 sub-pattern="5" where="start" style-ref="tabstop"/> + <context sub-pattern="7" where="start" style-ref="seperator"/> + <context> + <match>\\></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 100755 index 00000000..71672ec8 --- /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 100755 index 00000000..ffa418d7 --- /dev/null +++ b/plugins/snippets/data/mallard.xml @@ -0,0 +1,207 @@ +<?xml version='1.0' encoding='utf-8'?> +<snippets language="mallard"> + <snippet> + <text><![CDATA[<app>${1:Application's name}</app>$0]]></text> + <tag>app</tag> + <description>app</description> + </snippet> + <snippet> + <text><![CDATA[<![CDATA[$0]]]]><![CDATA[>]]></text> + <tag>cdata</tag> + <description>cdata</description> + </snippet> + <snippet> + <text><![CDATA[<cite>${1:Joe Example}</cite>]]></text> + <tag>cite</tag> + <description>cite</description> + </snippet> + <snippet> + <text><![CDATA[<cite date="$1">${2:Joe Example}</cite>]]></text> + <tag>cited</tag> + <description>cite</description> + </snippet> + <snippet> + <text><![CDATA[<desc>${1:Description}</desc>]]></text> + <tag>desc</tag> + <description>desc</description> + </snippet> + <snippet> + <text><![CDATA[<em>$1</em>]]></text> + <tag>em</tag> + <description>em</description> + </snippet> + <snippet> + <text><![CDATA[<figure> + <title>${1:Title}</title> + <desc>${2:Short description}</desc> + <media type="${3:image}" mime="${5:image/png}" src="${4:figures/image.png}" > + </media> +</figure>]]></text> + <tag>figure</tag> + <description>figure</description> + </snippet> + <snippet> + <text><![CDATA[<file>${0:filename}</file>]]></text> + <tag>file</tag> + <description>file</description> + </snippet> + <snippet> + <text><![CDATA[<gui>$1</gui>$2]]></text> + <tag>g</tag> + <description>gui</description> + </snippet> + <snippet> + <text><![CDATA[<guiseq><gui>$1</gui><gui>$2</gui></guiseq>]]></text> + <tag>q</tag> + <description>guiseq</description> + </snippet> + <snippet> + <text><![CDATA[<link href="http://$1/"<$2></link>]]></text> + <tag>http</tag> + <description>http</description> + </snippet> + <snippet> + <text><![CDATA[<item><p>$0</p></item>]]></text> + <tag>item</tag> + <description>item</description> + </snippet> + <snippet> + <text><![CDATA[<key>$1</key>]]></text> + <tag>key</tag> + <description>key</description> + </snippet> + <snippet> + <text><![CDATA[<keyseq><key>$1</key><key>$2</key></keyseq>]]></text> + <tag>keys</tag> + <description>keystroke</description> + </snippet> + <snippet> + <text><![CDATA[<link type="${1:guide}" xref="${2:index}"/>]]></text> + <tag>link</tag> + <description>link</description> + </snippet> + <snippet> + <text><![CDATA[<list> + <title>${2:Title}</title> + <item><p>${3}</p></item> + <item><p>${4}</p></item> +</list>]]></text> + <tag>list</tag> + <description>list</description> + </snippet> + <snippet> + <text><![CDATA[<listing> + <title>${1:Title}</title> + <desc>${2:Short description}</desc> + <code><![CDATA[ +$0 +]]]]><![CDATA[></code> +</listing>]]></text> + <tag>listing</tag> + <description>listing</description> + </snippet> + <snippet> + <text><![CDATA[<note style="${1:advanced|bug|important|tip|warning}"> + <p> + $0 + </p> +</note>]]></text> + <tag>note</tag> + <description>note</description> + </snippet> + <snippet> + <text><![CDATA[<list type="numbered"> + <item><p>$1</p></item> + <item><p>$2</p></item> + <item><p>$3</p></item> +</list> ]]></text> + <tag>num</tag> + <description>numbered list</description> + </snippet> + <snippet> + <text><![CDATA[<page xmlns="http://projectmallard.org/1.0/" + type="${1:topic}" style="${2:task}" + id="${3:id}"> + +<info> + <desc>${4:Short description}</desc> + <revision pkgversion="${5:program_version}" version="${6:document_version}" date="$<7: import datetime as d; return d.date.isoformat(d.date.today())>" status="${8:incomplete}"/> + <credit type="author"> + <name>$<9: +import pwd, os +try: + return pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0] +except KeyError: + return 'Joe Example' ></name> + <email>$<10: +import os +return os.getenv('EMAIL', '[email protected]') ></email> + </credit> +</info> + +$0 + +</page>]]></text> + <tag>page</tag> + <description>page</description> + </snippet> + <snippet> + <text><![CDATA[</p>]]></text> + <tag>/</tag> + <description>p close</description> + </snippet> + <snippet> + <text><![CDATA[<p>]]></text> + <tag>p</tag> + <description>p open</description> + </snippet> + <snippet> + <text><![CDATA[<quote> + <p>$0</p> +</quote>]]></text> + <tag>quote</tag> + <description>quote</description> + </snippet> + <snippet> + <text><![CDATA[<section id="${1}"> + <title>${2:Section Title}</title> + <p>$0</p> +</section>]]></text> + <tag>section</tag> + <description>section</description> + </snippet> + <snippet> + <text><![CDATA[<steps> + <item><p>$0</p></item> +</steps>]]></text> + <tag>steps</tag> + <description>steps</description> + </snippet> + <snippet> + <text><![CDATA[<terms> + <title>$1</title> + <item><p>$2</p></item> +</terms>]]></text> + <tag>terms</tag> + <description>terms</description> + </snippet> + <snippet> + <text><![CDATA[<note style="tip"> + <p>$1</p> +</note> ]]></text> + <tag>tip</tag> + <description>tip note</description> + </snippet> + <snippet> + <text><![CDATA[<title>$1</title>]]></text> + <tag>title</tag> + <description>title</description> + </snippet> + <snippet> + <text><![CDATA[<note style="warning> + <p>$1</p> +</note> ]]></text> + <tag>warn</tag> + <description>warning note</description> + </snippet> +</snippets> diff --git a/plugins/snippets/data/perl.xml b/plugins/snippets/data/perl.xml new file mode 100755 index 00000000..add148fa --- /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 100755 index 00000000..7d03f97d --- /dev/null +++ b/plugins/snippets/data/php.xml @@ -0,0 +1,224 @@ +<?xml version="1.0" encoding="UTF-8"?> +<snippets language="PHP"> + <snippet id="class"> + <text><![CDATA[#doc +# classname: ${1:ClassName} +# scope: ${2:PUBLIC} +# +#/doc + +class ${1:ClassName} ${3:extends AnotherClass} +{ + # internal variables + + # Constructor + function __construct (${4:argument}) + { + # code... + $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 +{ + # code... + $0 +} while (${1:$a <= 10});]]></text> + <description>do .. while ..</description> + <tag>do</tag> + </snippet> + <snippet id="elseif"> + <text><![CDATA[elseif (${1:condition}) +{ + # code... + $0 +}]]></text> + <description>elseif ..</description> + <tag>elseif</tag> + </snippet> + <snippet id="else"> + <text><![CDATA[else +{ + # code... + $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}) +{ + # code... + $0: +}]]></text> + <description>foreach ..</description> + <tag>foreach</tag> + </snippet> + <snippet id="for"> + <text><![CDATA[for ($${1:i} = ${2:0}; $${1:i} < $3; $${1:i}++) +{ + # code... + $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:# code...} +} +else +{ + ${3:# code...} +} +$0]]></text> + <description>if .. else ..</description> + <tag>ifelse</tag> + </snippet> + <snippet id="if"> + <text><![CDATA[if (${1:condition}) +{ + # code... + $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><?php .. ?></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}': + # code... + $0 +break;]]></text> + <description>case ..</description> + <tag>case</tag> + </snippet> + <snippet id="switch"> + <text><![CDATA[switch (${1:variable}) +{ + case '${2:value}': + ${3:# code...} + break; + + $0 + + default: + ${4:# code...} + break; +}]]></text> + <description>switch ..</description> + <tag>switch</tag> + </snippet> + <snippet id="while"> + <text><![CDATA[while (${1:$a <= 10}) +{ + # code... + $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 100755 index 00000000..a25617b8 --- /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/ruby.xml b/plugins/snippets/data/ruby.xml new file mode 100755 index 00000000..e68602f3 --- /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 100755 index 00000000..b8fc0a62 --- /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 100755 index 00000000..ee405e6d --- /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 100755 index 00000000..73a50c0a --- /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 100755 index 00000000..a53d565b --- /dev/null +++ b/plugins/snippets/data/xml.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<snippets language="XML"> + <snippet id="""> + <text><![CDATA[<${1:name} ${2:attr}="${3:value}">$0</${1}>]]></text> + <description>Long Attribute Tag</description> + <tag>"</tag> + </snippet> + <snippet id="<"> + <text><![CDATA[<${1:name}>$0</${1}> + +]]></text> + <description>Long Tag</description> + <tag><</tag> + </snippet> + <snippet id=">"> + <text><![CDATA[<${1:name} />]]></text> + <description>Short Tag</description> + <tag>></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 100755 index 00000000..0ff5cc15 --- /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/snippets.gedit-plugin.desktop.in b/plugins/snippets/snippets.gedit-plugin.desktop.in new file mode 100755 index 00000000..dc3c8281 --- /dev/null +++ b/plugins/snippets/snippets.gedit-plugin.desktop.in @@ -0,0 +1,9 @@ +[Gedit Plugin] +Loader=python +Module=snippets +IAge=2 +_Name=Snippets +_Description=Insert often-used pieces of text in a fast way +Authors=Jesse van den Kieboom <[email protected]> +Copyright=Copyright © 2005 Jesse van den Kieboom +Website=http://www.gedit.org diff --git a/plugins/snippets/snippets/Completion.py b/plugins/snippets/snippets/Completion.py new file mode 100755 index 00000000..d83915a5 --- /dev/null +++ b/plugins/snippets/snippets/Completion.py @@ -0,0 +1,165 @@ +import gtksourceview2 as gsv +import gobject +import gedit +import gtk + +from Library import Library +from LanguageManager import get_language_manager +from Snippet import Snippet + +class Proposal(gobject.GObject, gsv.CompletionProposal): + def __init__(self, snippet): + gobject.GObject.__init__(self) + 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.GObject, gsv.CompletionProvider): + def __init__(self, name, language_id, handler): + gobject.GObject.__init__(self) + + 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.icon_theme_get_default() + w, h = gtk.icon_size_lookup(gtk.ICON_SIZE_MENU) + + self.icon = theme.load_icon(gtk.STOCK_JUSTIFY_LEFT, w, 0) + + 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): + it = context.get_iter() + + 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 None + + return 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 = filter(lambda x: x['tag'].startswith(word), proposals) + + return map(lambda x: Proposal(x), 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(gedit.Document()) + manager = get_language_manager() + + lang = manager.get_language('snippets') + view.get_buffer().set_language(lang) + + sw = gtk.ScrolledWindow() + sw.add(view) + + 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(), False) + + info.set_sizing(-1, -1, False, False) + info.process_resize() + + def do_get_icon(self): + return self.icon + + def do_get_activation(self): + return gsv.COMPLETION_ACTIVATION_USER_REQUESTED + +class Defaults(gobject.GObject, gsv.CompletionProvider): + def __init__(self, handler): + gobject.GObject.__init__(self) + + self.handler = handler + self.proposals = [] + + def set_defaults(self, defaults): + self.proposals = [] + + for d in defaults: + self.proposals.append(gsv.CompletionItem(d)) + + 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 gsv.COMPLETION_ACTIVATION_NONE + +gobject.type_register(Proposal) +gobject.type_register(Provider) +gobject.type_register(Defaults) + +# ex:ts=8:et: diff --git a/plugins/snippets/snippets/Document.py b/plugins/snippets/snippets/Document.py new file mode 100755 index 00000000..da166668 --- /dev/null +++ b/plugins/snippets/snippets/Document.py @@ -0,0 +1,1089 @@ +# Gedit snippets plugin +# Copyright (C) 2005-2006 Jesse van den Kieboom <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import re + +import gtk +from gtk import gdk +import gio +import gedit +import gtksourceview2 as gsv +import gobject + +from Library import Library +from Snippet import Snippet +from Placeholder import * +import Completion + +class DynamicSnippet(dict): + def __init__(self, text): + self['text'] = text + self.valid = True + +class Document: + TAB_KEY_VAL = (gtk.keysyms.Tab, \ + gtk.keysyms.ISO_Left_Tab) + SPACE_KEY_VAL = (gtk.keysyms.space,) + + def __init__(self, instance, view): + self.view = None + self.instance = instance + + self.placeholders = [] + self.active_snippets = [] + self.active_placeholder = None + self.signal_ids = {} + + 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) + self.defaults_provider = Completion.Defaults(self.on_default_activated) + + # Always have a reference to the global snippets + Library().ref(None) + self.set_view(view) + + # Stop controlling the view. Remove all active snippets, remove references + # to the view and the plugin instance, disconnect all signal handlers + def stop(self): + if self.timeout_update_id != 0: + gobject.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.set_view(None) + self.instance = None + self.active_placeholder = None + + def disconnect_signal(self, obj, signal): + if (obj, signal) in self.signal_ids: + obj.disconnect(self.signal_ids[(obj, signal)]) + del self.signal_ids[(obj, signal)] + + def connect_signal(self, obj, signal, cb): + self.disconnect_signal(obj, signal) + self.signal_ids[(obj, signal)] = obj.connect(signal, cb) + + def connect_signal_after(self, obj, signal, cb): + self.disconnect_signal(obj, signal) + self.signal_ids[(obj, signal)] = obj.connect_after(signal, cb) + + # Set the view to be controlled. Installs signal handlers and sets current + # language. If there is already a view set this function will first remove + # all currently active snippets and disconnect all current signals. So + # self.set_view(None) will effectively remove all the control from the + # current view + def _set_view(self, view): + if self.view: + buf = self.view.get_buffer() + + # Remove signals + signals = {self.view: ('key-press-event', 'destroy', + 'notify::editable', 'drag-data-received', 'expose-event'), + buf: ('notify::language', 'changed', 'cursor-moved', 'insert-text'), + self.view.get_completion(): ('hide',)} + + for obj, sig in signals.items(): + for s in sig: + self.disconnect_signal(obj, s) + + # Remove all active snippets + for snippet in list(self.active_snippets): + self.deactivate_snippet(snippet, True) + + completion = self.view.get_completion() + completion.remove_provider(self.provider) + completion.remove_provider(self.defaults_provider) + + self.view = view + + if view != None: + buf = view.get_buffer() + + self.connect_signal(view, 'destroy', self.on_view_destroy) + + if view.get_editable(): + self.connect_signal(view, 'key-press-event', self.on_view_key_press) + + self.connect_signal(buf, 'notify::language', self.on_notify_language) + self.connect_signal(view, 'notify::editable', self.on_notify_editable) + self.connect_signal(view, 'drag-data-received', self.on_drag_data_received) + self.connect_signal_after(view, 'expose-event', self.on_expose_event) + + self.update_language() + + completion = view.get_completion() + completion.add_provider(self.provider) + + completion.add_provider(self.defaults_provider) + + self.connect_signal(completion, 'hide', self.on_completion_hide) + elif self.language_id != 0: + langid = self.language_id + + self.language_id = None; + self.provider.language_id = self.language_id + + if self.instance: + self.instance.language_changed(self) + + Library().unref(langid) + + def set_view(self, view): + if view == self.view: + return + + self._set_view(view) + + # 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 == None and self.language_id == 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 self.instance: + self.instance.language_changed(self) + + if langid != 0: + Library().unref(langid) + + Library().ref(self.language_id) + self.provider.language_id = self.language_id + + 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) + + snippets_debug('Accel!') + + if len(snippets) == 0: + return False + elif len(snippets) == 1: + self.apply_snippet(snippets[0]) + else: + # Do the fancy completion dialog + self.provider.set_proposals(snippets) + self.view.show_completion((self,)) + + 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): + foundIndex = index + found = placeholder + + # Find the current placeholder + if piter.compare(begin) >= 0 and \ + piter.compare(end) <= 0 and \ + current == 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: + self.defaults_provider.set_defaults(next.defaults) + + cm = self.view.get_completion() + cm.show([self.defaults_provider], cm.create_context()) + + 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 env_get_selected_text(self, buf): + bounds = buf.get_selection_bounds() + + if bounds: + return buf.get_text(bounds[0], bounds[1]) + else: + return '' + + def env_get_current_word(self, buf): + start, end = buffer_word_boundary(buf) + + return buf.get_text(start, end) + + def env_get_current_line(self, buf): + start, end = buffer_line_boundary(buf) + + return buf.get_text(start, end) + + def env_get_current_line_number(self, buf): + start, end = buffer_line_boundary(buf) + + return str(start.get_line() + 1) + + def env_get_document_uri(self, buf): + location = buf.get_location() + + if location: + return location.get_uri() + else: + return '' + + def env_get_document_name(self, buf): + location = buf.get_location() + + if location: + return location.get_basename() + else: + return '' + + def env_get_document_scheme(self, buf): + location = buf.get_location() + + if location: + return location.get_uri_scheme() + else: + return '' + + def env_get_document_path(self, buf): + location = buf.get_location() + + if location: + return location.get_path() + else: + return '' + + def env_get_document_dir(self, buf): + location = buf.get_location() + + if location: + return location.get_parent().get_path() or '' + else: + return '' + + 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() + + if isinstance(toplevel, gedit.Window): + documents_uri = [doc.get_location().get_uri() + for doc in toplevel.get_documents() + if doc.get_location() is not None] + else: + documents_uri = [] + + return ' '.join(documents_uri) + + def env_get_documents_path(self, buf): + toplevel = self.view.get_toplevel() + + if isinstance(toplevel, gedit.Window): + documents_location = [doc.get_location() + for doc in toplevel.get_documents() + if doc.get_location() is not None] + + documents_path = [location.get_path() + for location in documents_location + if gedit.utils.uri_has_file_scheme(location.get_uri())] + else: + documents_path = [] + + return ' '.join(documents_path) + + def update_environment(self): + buf = self.view.get_buffer() + + 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_URI': self.env_get_document_uri, + 'GEDIT_CURRENT_DOCUMENT_NAME': self.env_get_document_name, + 'GEDIT_CURRENT_DOCUMENT_SCHEME': self.env_get_document_scheme, + 'GEDIT_CURRENT_DOCUMENT_PATH': self.env_get_document_path, + 'GEDIT_CURRENT_DOCUMENT_DIR': self.env_get_document_dir, + '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: + os.environ[var] = variables[var](buf) + + 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): + if not snippet.valid: + return False + + buf = self.view.get_buffer() + s = Snippet(snippet) + + 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 = 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 = buffer_line_boundary(buf) + + # Set environmental variables + self.update_environment() + + # 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) + + buf.begin_user_action() + + # Remove the tag, selection or current word + buf.delete(start, end) + + # Insert the snippet + holders = len(self.placeholders) + + if len(self.active_snippets) == 0: + self.first_snippet_inserted() + + sn = s.insert_into(self, start) + self.active_snippets.append(sn) + + # Put cursor at first tab placeholder + keys = filter(lambda x: x > 0, sn.placeholders.keys()) + + 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]]) + + 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 + + if start.backward_word_start(): + # Check if we were at a word start ourselves + tmp = start.copy() + tmp.forward_word_end() + + if tmp.equal(end): + word = buf.get_text(start, end) + else: + start = end.copy() + else: + start = end.copy() + + if not word or word == '': + if start.backward_char(): + word = start.get_char() + + if word.isalnum() or word.isspace(): + return (None, None, None) + else: + return (None, None, None) + + return (word, start, end) + + def parse_and_run_snippet(self, data, iter): + self.apply_snippet(DynamicSnippet(data), iter, iter) + + def run_snippet_trigger(self, trigger, bounds): + if not self.view: + return False + + snippets = Library().from_tag(trigger, self.language_id) + buf = self.view.get_buffer() + + if snippets: + if len(snippets) == 1: + return self.apply_snippet(snippets[0], bounds[0], bounds[1]) + else: + # Do the fancy completion dialog + self.provider.set_proposals(snippets) + cm = self.view.get_completion() + + cm.show([self.provider], cm.create_context()) + return True + + return False + + def run_snippet(self): + if not self.view: + 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): + buf = self.view.get_buffer() + 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 + + # Callbacks + def on_view_destroy(self, view): + self.stop() + return + + 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 = gobject.timeout_add(0, + self.update_snippet_contents) + + def on_buffer_changed(self, buf): + 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 = gobject.timeout_add(0, \ + self.update_snippet_contents) + + def on_buffer_insert_text(self, buf, piter, text, length): + ctx = 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_notify_editable(self, view, spec): + self._set_view(view) + + def on_view_key_press(self, view, event): + library = Library() + + if not (event.state & gdk.CONTROL_MASK) and \ + not (event.state & gdk.MOD1_MASK) and \ + event.keyval in self.TAB_KEY_VAL: + if not event.state & gdk.SHIFT_MASK: + return self.run_snippet() + else: + return self.skip_to_previous_placeholder() + elif not library.loaded and \ + library.valid_accelerator(event.keyval, event.state): + library.ensure_files() + library.ensure(self.language_id) + self.accelerator_activate(event.keyval, \ + event.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 relative_path(self, first, second, mime): + prot1 = re.match('(^[a-z]+:\/\/|\/)(.*)', first) + prot2 = re.match('(^[a-z]+:\/\/|\/)(.*)', second) + + if not prot1 or not prot2: + return second + + # Different protocols + if prot1.group(1) != prot2.group(1): + return second + + # Split on backslash + path1 = self.path_split(prot1.group(2)) + path2 = self.path_split(prot2.group(2)) + + # Remove as long as common + while path1 and path2 and path1[0] == path2[0]: + path1.pop(0) + path2.pop(0) + + # If we need to ../ more than 3 times, then just return + # the absolute path + if len(path1) - 1 > 3: + return second + + if mime.startswith('x-directory'): + # directory, special case + if not path2: + result = './' + else: + result = '../' * (len(path1) - 1) + else: + # Insert ../ + result = '../' * (len(path1) - 1) + + if not path2: + result = os.path.basename(second) + + if path2: + result += os.path.join(*path2) + + return result + + def apply_uri_snippet(self, snippet, mime, uri): + # Remove file scheme + gfile = gio.File(uri) + pathname = '' + dirname = '' + ruri = '' + + if gedit.utils.uri_has_file_scheme(uri): + pathname = gfile.get_path() + dirname = gfile.get_parent().get_path() + + name = os.path.basename(uri) + scheme = gfile.get_uri_scheme() + + os.environ['GEDIT_DROP_DOCUMENT_URI'] = uri + os.environ['GEDIT_DROP_DOCUMENT_NAME'] = name + os.environ['GEDIT_DROP_DOCUMENT_SCHEME'] = scheme + os.environ['GEDIT_DROP_DOCUMENT_PATH'] = pathname + os.environ['GEDIT_DROP_DOCUMENT_DIR'] = dirname + os.environ['GEDIT_DROP_DOCUMENT_TYPE'] = mime + + buf = self.view.get_buffer() + location = buf.get_location() + if location: + ruri = location.get_uri() + + relpath = self.relative_path(ruri, uri, mime) + + os.environ['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) + + def in_bounds(self, x, y): + rect = self.view.get_visible_rect() + rect.x, rect.y = self.view.buffer_to_window_coords(gtk.TEXT_WINDOW_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 (gtk.targets_include_uri(context.targets) and data.data and self.in_bounds(x, y)): + return + + uris = drop_get_uris(data) + 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_completion_hide(self, completion): + self.provider.set_proposals(None) + + def on_proposal_activated(self, proposal, piter): + 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.TEXT_WINDOW_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, col): + 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.TEXT_WINDOW_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.TEXT_WINDOW_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, col): + 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 from_color(self, col): + return [col.red / 0x10000, col.green / 0x10000, col.blue / 0x10000] + + def draw_placeholder(self, ctx, placeholder): + if isinstance(placeholder, PlaceholderEnd): + return + + buf = self.view.get_buffer() + + col = self.from_color(self.view.get_style().text[gtk.STATE_INSENSITIVE]) + ctx.set_source_rgba(col[0], col[1], col[2], 0.5) + + 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, col) + else: + self.draw_placeholder_rect(ctx, placeholder, col) + + def on_expose_event(self, view, event): + if event.window != view.get_window(gtk.TEXT_WINDOW_TEXT): + return False + + # Draw something + ctx = event.window.cairo_create() + ctx.rectangle(event.area) + ctx.clip() + + ctx.set_line_width(1.0) + + for placeholder in self.ordered_placeholders: + if not self.placeholder_in_area(placeholder, event.area): + continue + + ctx.save() + self.draw_placeholder(ctx, placeholder) + ctx.restore() + + return False + +# ex:ts=8:et: diff --git a/plugins/snippets/snippets/Exporter.py b/plugins/snippets/snippets/Exporter.py new file mode 100755 index 00000000..51d49104 --- /dev/null +++ b/plugins/snippets/snippets/Exporter.py @@ -0,0 +1,98 @@ +import os +import tempfile +import sys +import shutil + +from snippets.Library import * +import xml.etree.ElementTree as et +from Helper import * + +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 + 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=8:et: diff --git a/plugins/snippets/snippets/Helper.py b/plugins/snippets/snippets/Helper.py new file mode 100755 index 00000000..de363360 --- /dev/null +++ b/plugins/snippets/snippets/Helper.py @@ -0,0 +1,182 @@ +# Gedit snippets plugin +# Copyright (C) 2005-2006 Jesse van den Kieboom <[email protected]> +# +# 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 string +from xml.sax import saxutils +from xml.etree.ElementTree import * +import re + +import gtk +from gtk import gdk + +def message_dialog(par, typ, msg): + d = gtk.MessageDialog(par, gtk.DIALOG_MODAL, typ, gtk.BUTTONS_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') + + view.get_buffer().set_data('GeditSnippetsPluginContext', 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' + + view.get_buffer().insert(piter, text[:-1]) + + view.get_buffer().set_data('GeditSnippetsPluginContext', None) + +def get_buffer_context(buf): + return buf.get_data('GeditSnippetsPluginContext') + +def snippets_debug(*s): + return + +def write_xml(node, f, cdata_nodes=()): + assert node is not None + + if not hasattr(f, "write"): + f = open(f, "wb") + + # 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 Comment: + _write_indent(file, "<!-- %s -->\n" % saxutils.escape(node.text.encode('utf-8')), indent) + elif node is ProcessingInstruction: + _write_indent(file, "<?%s?>\n" % saxutils.escape(node.text.encode('utf-8')), indent) + else: + items = node.items() + + if items or node.text or len(node): + _write_indent(file, "<" + tag.encode('utf-8'), indent) + + if items: + items.sort() # lexical order + for k, v in items: + file.write(" %s=%s" % (k.encode('utf-8'), saxutils.quoteattr(v.encode('utf-8')))) + 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.encode('utf-8'))) + else: + file.write("\n") + + for n in node: + _write_node(n, file, cdata_nodes, indent + 1) + + if not len(node): + file.write("</" + tag.encode('utf-8') + ">\n") + else: + _write_indent(file, "</" + tag.encode('utf-8') + ">\n", \ + indent) + else: + file.write(" />\n") + + if node.tail and node.tail.strip() != "": + file.write(saxutils.escape(node.tail.encode('utf-8'))) + +def _cdata(text, replace=string.replace): + text = text.encode('utf-8') + return '<![CDATA[' + replace(text, ']]>', ']]]]><![CDATA[>') + ']]>' + +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): + lines = re.split('\\s*[\\n\\r]+\\s*', selection.data.strip()) + result = [] + + for line in lines: + if not line.startswith('#'): + result.append(line) + + return result + +# ex:ts=8:et: diff --git a/plugins/snippets/snippets/Importer.py b/plugins/snippets/snippets/Importer.py new file mode 100755 index 00000000..6151027d --- /dev/null +++ b/plugins/snippets/snippets/Importer.py @@ -0,0 +1,100 @@ +import os +import tempfile +import sys +import shutil + +from snippets.Library import * + +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 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 + dest = self.import_destination(filename) + + # 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=8:et: diff --git a/plugins/snippets/snippets/LanguageManager.py b/plugins/snippets/snippets/LanguageManager.py new file mode 100755 index 00000000..9646ef17 --- /dev/null +++ b/plugins/snippets/snippets/LanguageManager.py @@ -0,0 +1,21 @@ +import gtksourceview2 as gsv +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 = gsv.LanguageManager() + manager.set_search_path(dirs + manager.get_search_path()) + + return manager diff --git a/plugins/snippets/snippets/Library.py b/plugins/snippets/snippets/Library.py new file mode 100755 index 00000000..4717280c --- /dev/null +++ b/plugins/snippets/snippets/Library.py @@ -0,0 +1,993 @@ +# Gedit snippets plugin +# Copyright (C) 2005-2006 Jesse van den Kieboom <[email protected]> +# +# 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 tempfile +import re + +import gtk + +import xml.etree.ElementTree as et +from Helper import * + +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 == 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 + + snippets_debug('Added ', prop ,' ', value, ' to ', str(self.language)) + + if prop == 'accelerator': + keyval, mod = gtk.accelerator_parse(value) + self.accel_group.connect_group(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 + + 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): + tag = snippet['tag'] + accelerator = snippet['accelerator'] + + 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): + 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 + # matevfs.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.XMLTreeBuilder(target=builder) + self.insnippet = False + + try: + f = open(self.path, "r") + + while True: + data = f.read(readsize) + + if not data: + break + + parser.feed(data) + + for element in elements: + yield element + + del elements[:] + + f.close() + except IOError: + self.ok = False + + def load(self): + if not self.ok: + return + + 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: + snippet = 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): + 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 == 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: + 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: + first = 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 == None or not self.tainted: + return + + path = os.path.dirname(self.path) + + try: + if not os.path.isdir(path): + os.makedirs(path, 0755) + except OSError: + # TODO: this is bad... + sys.stderr.write("Error in making dirs\n") + + try: + 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 = None + 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 set_accelerator_callback(self, cb): + self._accelerator_activated_cb = cb + + def accelerator_activated(self, group, obj, keyval, mod): + ret = False + + if self._accelerator_activated_cb: + ret = self._accelerator_activated_cb(group, obj, keyval, mod) + + return ret + + def add_snippet(self, library, element): + container = self.container(library.language) + overrided = self.overrided(library, element) + + if overrided: + overrided.set_library(library) + snippets_debug('Snippet is overriden: ' + overrided['description']) + return None + + snippet = SnippetData(element, library) + + if snippet.id in self.loaded_ids: + snippets_debug('Not added snippet ' + str(library.language) + \ + '::' + snippet['description'] + ' (duplicate)') + return None + + snippet = container.append(snippet) + 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 + 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): + 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: + snippets_debug('Library in wrong format, ignoring') + return False + + 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): + 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) + + snippets_debug('Ref:', language) + self.container(language).ref() + + def unref(self, language): + language = self.normalize_language(language) + + 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(gtk.keysyms.F1, gtk.keysyms.F12 + 1))) + + def valid_tab_trigger(self, trigger): + if not trigger: + return True + + if trigger.isdigit(): + return False + + self.check_buffer.set_text(trigger) + + start, end = self.check_buffer.get_bounds() + text = self.check_buffer.get_text(start, end) + + s = start.copy() + e = end.copy() + + end.backward_word_start() + start.forward_word_end() + + return (s.equal(end) and e.equal(start)) or (len(text) == 1 and not (text.isalnum() or text.isspace())) + + # 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 [] + + snippets = [] + 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=8:et: diff --git a/plugins/snippets/snippets/Makefile.am b/plugins/snippets/snippets/Makefile.am new file mode 100755 index 00000000..7a05b562 --- /dev/null +++ b/plugins/snippets/snippets/Makefile.am @@ -0,0 +1,28 @@ +# Python snippets plugin +plugindir = $(GEDIT_PLUGINS_LIBS_DIR)/snippets + +plugin_PYTHON = \ + __init__.py \ + WindowHelper.py \ + Document.py \ + Library.py \ + Snippet.py \ + Parser.py \ + Placeholder.py \ + Manager.py \ + Helper.py \ + SubstitutionParser.py \ + Importer.py \ + Exporter.py \ + LanguageManager.py \ + Completion.py + +uidir = $(GEDIT_PLUGINS_DATA_DIR)/snippets/ui +ui_DATA = snippets.ui + +EXTRA_DIST = $(ui_DATA) + +CLEANFILES = *.bak *.gladep *.pyc +DISTCLEANFILES = *.bak *.gladep *.pyc + +-include $(top_srcdir)/git.mk diff --git a/plugins/snippets/snippets/Manager.py b/plugins/snippets/snippets/Manager.py new file mode 100755 index 00000000..16acbdb4 --- /dev/null +++ b/plugins/snippets/snippets/Manager.py @@ -0,0 +1,1157 @@ +# Gedit snippets plugin +# Copyright (C) 2005-2006 Jesse van den Kieboom <[email protected]> +# +# 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 gobject +import gtk +from gtk import gdk +import gtksourceview2 as gsv +import pango +import gedit +import gio + +from Snippet import Snippet +from Helper import * +from Library import * +from Importer import * +from Exporter import * +from Document import Document +from LanguageManager import get_language_manager + +class Manager: + NAME_COLUMN = 0 + SORT_COLUMN = 1 + OBJ_COLUMN = 2 + TARGET_URI = 105 + + model = None + drag_icons = ('mate-mime-application-x-tarz', 'mate-package', 'package') + default_export_name = _('Snippets archive') + '.tar.gz' + dragging = False + dnd_target_list = [('text/uri-list', 0, TARGET_URI)] + + def __init__(self, datadir): + self.datadir = datadir + self.snippet = None + self.dlg = None + self._temp_export = None + self.snippets_doc = None + self.manager = None + self.default_size = None + + self.key_press_id = 0 + self.run() + + 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)) + + 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 = gedit.app_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() + source_view = self['source_view_snippet'] + + 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, object) + self.model.set_sort_column_id(self.SORT_COLUMN, gtk.SORT_ASCENDING) + manager = get_language_manager() + langs = gedit.language_manager_list_languages_sorted(manager, True) + + piter = self.model.append(None, (_('Global'), '', None)) + # Add dummy node + self.model.append(piter, ('', '', 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)) + + # Add dummy node + self.model.append(parent, ('', '', 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_root() + + 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): + s = model.get_value(iter, self.OBJ_COLUMN) + + snippet = isinstance(s, SnippetData) + + if snippet and not s.valid: + cell.set_property('stock-id', gtk.STOCK_DIALOG_ERROR) + else: + cell.set_property('stock-id', None) + + cell.set_property('xalign', 1.0) + + def get_cell_data_cb(self, column, cell, model, iter): + s = model.get_value(iter, self.OBJ_COLUMN) + + snippet = isinstance(s, SnippetData) + + cell.set_property('editable', snippet) + 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(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: + context.set_icon_name(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() + + self.import_snippets(uris) + + 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.ACTION_COPY: + action = gdk.ACTION_COPY + else: + for act in context.actions: + if act == gdk.ACTION_COPY: + action = gdk.ACTION_COPY + break + + if action == gdk.ACTION_COPY: + context.drag_status(gdk.ACTION_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.BUTTON1_MASK, self.dnd_target_list, gdk.ACTION_DEFAULT | gdk.ACTION_COPY) + + # Set it as a drag destination for importing snippets + tv.drag_dest_set(gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP, + self.dnd_target_list, gdk.ACTION_DEFAULT | gdk.ACTION_COPY) + + 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.icon_theme_get_for_screen(tv.get_screen()) + + self.dnd_name = None + for name in self.drag_icons: + icon = theme.lookup_icon(name, gtk.ICON_SIZE_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) + + renderer = gtk.CellRendererPixbuf() + self.column.pack_start(renderer, True) + self.column.set_cell_data_func(renderer, self.get_cell_data_pixbuf_cb) + + 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.SELECTION_MULTIPLE) + selection.connect('changed', self.on_tree_view_selection_changed) + + self.build_dnd() + + def build(self): + self.builder = gtk.Builder() + self.builder.add_from_file(os.path.join(self.datadir, 'ui', 'snippets.ui')) + + handlers_dic = { + 'on_dialog_snippets_response': self.on_dialog_snippets_response, + 'on_dialog_snippets_destroy': self.on_dialog_snippets_destroy, + 'on_button_new_snippet_clicked': self.on_button_new_snippet_clicked, + 'on_button_import_snippets_clicked': self.on_button_import_snippets_clicked, + 'on_button_export_snippets_clicked': self.on_button_export_snippets_clicked, + 'on_button_remove_snippet_clicked': self.on_button_remove_snippet_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() + + image = self['image_remove'] + image.set_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_SMALL_TOOLBAR) + + 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) + self.snippets_doc = Document(None, source_view) + + combo = self['combo_drop_targets'] + combo.set_text_column(0) + + entry = combo.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 = gtk.target_list_add_uri_targets(entry.drag_dest_get_target_list(), self.TARGET_URI) + entry.drag_dest_set_target_list(lst) + + self.dlg = self['dialog_snippets'] + + if self.default_size: + self.dlg.set_default_size(*self.default_size) + + 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) + obj = self.model.get_value(child, self.OBJ_COLUMN) + + return (obj 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): + node = self.model.get_value(piter, self.OBJ_COLUMN) + + if node == 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_buttons(self): + button_remove = self['button_remove_snippet'] + button_new = self['button_new_snippet'] + image_remove = self['image_remove'] + + button_new.set_sensitive(self.language_path != None) + override, remove, system = self.selected_snippets_state() + + if not (override ^ remove) or system: + button_remove.set_sensitive(False) + image_remove.set_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_BUTTON) + else: + button_remove.set_sensitive(True) + + if override: + image_remove.set_from_stock(gtk.STOCK_UNDO, gtk.ICON_SIZE_BUTTON) + tooltip = _('Revert selected snippet') + else: + image_remove.set_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_BUTTON) + 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.OBJ_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(piter, self.NAME_COLUMN, nm, self.SORT_COLUMN, nm) + self.update_buttons() + self.entry_tab_trigger_update_valid() + + return piter + + def add_snippet(self, parent, snippet): + piter = self.model.append(parent, ('', '', snippet)) + + return self.snippet_changed(piter) + + def run(self): + if not self.dlg: + self.build() + self.dlg.show() + else: + self.build_model() + self.dlg.present() + + + def snippet_from_iter(self, model, piter): + parent = model.iter_parent(piter) + + if parent: + return model.get_value(piter, self.OBJ_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'].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'].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_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[0] == 0: + return None + else: + return self.model.get_value(self.model.get_iter( \ + (path[0],)), self.OBJ_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.OBJ_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 on_dialog_snippets_destroy(self, dlg): + # Remove temporary drag export + if self._temp_export: + shutil.rmtree(os.path.dirname(self._temp_export)) + self._temp_export = None + + if self.snippets_doc: + self.snippets_doc.stop() + + self.default_size = [dlg.allocation.width, dlg.allocation.height] + self.manager = None + + self.unref_languages() + self.snippet = None + self.model = None + self.dlg = None + + def on_dialog_snippets_response(self, dlg, resp): + if resp == gtk.RESPONSE_HELP: + gedit.help_display(self.dlg, 'gedit', 'gedit-snippets-plugin') + return + + self.dlg.destroy() + + 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.OBJ_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(piter, self.OBJ_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_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_BUTTON) + img.show() + + #self['hbox_tab_trigger'].set_spacing(3) + tip = _('This is not a valid Tab trigger. Triggers can either contain letters 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()) + + self.snippet['text'] = text + self.snippet_changed() + + def on_button_new_snippet_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, filenames): + success = True + + for filename in filenames: + if not gedit.utils.uri_has_file_scheme(filename): + continue + + # Remove file:// + gfile = gio.File(filename) + filename = gfile.get_path() + + importer = Importer(filename) + error = importer.run() + + if error: + message = _('The following error occurred while importing: %s') % error + success = False + message_dialog(self.dlg, gtk.MESSAGE_ERROR, message) + + self.build_model(True) + + if success: + message = _('Import successfully completed') + message_dialog(self.dlg, gtk.MESSAGE_INFO, message) + + def on_import_response(self, dialog, response): + if response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_CLOSE: + dialog.destroy() + return + + f = dialog.get_uris() + dialog.destroy() + + self.import_snippets(f) + + def on_button_import_snippets_clicked(self, button): + dlg = gtk.FileChooserDialog(parent=self.dlg, title=_("Import snippets"), + action=gtk.FILE_CHOOSER_ACTION_OPEN, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_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.MESSAGE_ERROR + retval = False + else: + message = _('Export successfully completed') + msgtype = gtk.MESSAGE_INFO + retval = True + + if show_dialogs: + message_dialog(self.dlg, msgtype, message) + + return retval + + def on_export_response(self, dialog, response): + filename = dialog.get_filename() + snippets = dialog._export_snippets + + dialog.destroy() + + if response != gtk.RESPONSE_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.DIALOG_MODAL, + type=gtk.MESSAGE_QUESTION, + buttons=gtk.BUTTONS_YES_NO, + message_format=message) + mes.set_property('use-markup', True) + resp = mes.run() + mes.destroy() + + if resp == gtk.RESPONSE_NO: + export_snippets = usersnippets + elif resp != gtk.RESPONSE_YES: + return False + + if len(export_snippets) == 0 and show_dialogs: + message = _('There are no snippets selected to be exported') + message_dialog(self.dlg, gtk.MESSAGE_INFORMATION, message) + return False + + if not filename: + dlg = gtk.FileChooserDialog(parent=self.dlg, title=_('Export snippets'), + action=gtk.FILE_CHOOSER_ACTION_SAVE, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_SAVE, gtk.RESPONSE_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_button_export_snippets_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.dlg, title=_('Export snippets'), + action=gtk.FILE_CHOOSER_ACTION_SAVE, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_SAVE, gtk.RESPONSE_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.DIALOG_MODAL, + type=gtk.MESSAGE_QUESTION, + buttons=gtk.BUTTONS_YES_NO, + message_format=message) + mes.set_property('use-markup', True) + resp = mes.run() + mes.destroy() + + if resp == gtk.RESPONSE_NO: + dlg._export_snippets = usersnippets + elif resp != gtk.RESPONSE_YES: + dlg.destroy() + return + + if len(dlg._export_snippets) == 0: + dlg.destroy() + + message = _('There are no snippets selected to be exported') + message_dialog(self.dlg, gtk.MESSAGE_INFORMATION, 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) + + if self.model.remove(piter): + return piter + elif path[-1] != 0: + self.select_iter(self.model.get_iter((path[0], path[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_button_remove_snippet_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: + references.append(gtk.TreeRowReference(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): + source_view = self['source_view_snippet'] + + 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.state): + # New accelerator + self.set_accelerator(event.keyval, \ + event.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'].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_button_remove_snippet_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): + if not gtk.targets_include_uri(context.targets): + return + + uris = drop_get_uris(selection_data) + + if not uris: + return + + if entry.get_text(): + mimes = [entry.get_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=8:et: diff --git a/plugins/snippets/snippets/Parser.py b/plugins/snippets/snippets/Parser.py new file mode 100755 index 00000000..3bbaf6e7 --- /dev/null +++ b/plugins/snippets/snippets/Parser.py @@ -0,0 +1,259 @@ +# Gedit snippets plugin +# Copyright (C) 2006-2007 Jesse van den Kieboom <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import re +import sys +from SubstitutionParser import SubstitutionParser + +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=8:et: diff --git a/plugins/snippets/snippets/Placeholder.py b/plugins/snippets/snippets/Placeholder.py new file mode 100755 index 00000000..c43eecac --- /dev/null +++ b/plugins/snippets/snippets/Placeholder.py @@ -0,0 +1,700 @@ +# Gedit snippets plugin +# Copyright (C) 2005-2006 Jesse van den Kieboom <[email protected]> +# +# 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 os +import sys +import signal +import select +import locale +import subprocess +from SubstitutionParser import SubstitutionParser +import gobject + +from Helper import * + +# These are places in a view where the cursor can go and do things +class Placeholder: + def __init__(self, view, tabstop, 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.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 __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): + if m.group(1) or not m.group(2) in os.environ: + return '$' + m.group(2) + else: + return self.format_environment(os.environ[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: + 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()) + 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 + 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, begin): + Placeholder.__init__(self, view, -1, 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, begin, default): + Placeholder.__init__(self, view, 0, 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, begin, s): + Placeholder.__init__(self, view, tabstop, 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): + text = None + + 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] == 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, begin, s): + PlaceholderExpand.__init__(self, view, tabstop, begin, s) + + self.shell = None + self.remove_me = False + + 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) + + message_dialog(None, gtk.MESSAGE_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 == 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 = unicode(line, 'utf-8') + except: + line = unicode(line, locale.getdefaultlocale()[1], + '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' : os.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, refs, begin, s, namespace): + PlaceholderExpand.__init__(self, view, tabstop, 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 in 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() + + message_dialog(None, gtk.MESSAGE_ERROR, \ + _('Execution of the Python command (%s) exceeds the maximum ' \ + 'time, execution aborted.') % self.command) + + return False + except Exception, detail: + self.remove_timeout() + + message_dialog(None, gtk.MESSAGE_ERROR, + _('Execution of the Python command (%s) failed: %s') % + (self.command, detail)) + + return False + + if result == 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, begin, inp, pattern, substitution, modifiers): + PlaceholderExpand.__init__(self, view, tabstop, 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): + if isinstance(self.inp, int): + return self.mirror_text[self.inp] + elif self.inp in os.environ: + return os.environ[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, 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=8:et: diff --git a/plugins/snippets/snippets/Snippet.py b/plugins/snippets/snippets/Snippet.py new file mode 100755 index 00000000..d7baead5 --- /dev/null +++ b/plugins/snippets/snippets/Snippet.py @@ -0,0 +1,355 @@ +# Gedit snippets plugin +# Copyright (C) 2005-2006 Jesse van den Kieboom <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import gio + +from Placeholder import * +from Parser import Parser, Token +from Helper import * + +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(filename) + + return gfile.get_uri() + + def util_readfile(self, filename): + stream = gio.File(filename).read() + + if not stream: + return '' + + res = stream.read() + stream.close() + + return res + + def util_filesize(self, filename): + gfile = gio.File(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" * ((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): + self.data = data + + 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 = 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>' + markup_escape(str.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 = unicode.join('\n' + unicode(self._indent), 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): + val = ((data in os.environ) and os.environ[data]) or '' + + # Get all the current indentation + all_indent = compute_indentation(self._view, self._insert_iter()) + + # Substract initial indentation to get the snippet indentation + indent = all_indent[len(self._indent):] + + # Keep indentation + return unicode.join('\n' + unicode(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, begin, data['default']) + elif tabstop in self.placeholders: + # Mirror placeholder + return PlaceholderMirror(self._view, tabstop, begin) + else: + # Default placeholder + return Placeholder(self._view, tabstop, data['default'], begin) + + def _create_shell(self, data): + begin = self._insert_iter() + return PlaceholderShell(self._view, data['tabstop'], begin, data['contents']) + + def _create_eval(self, data): + begin = self._insert_iter() + return PlaceholderEval(self._view, data['tabstop'], data['dependencies'], begin, data['contents'], self._utils.namespace) + + def _create_regex(self, data): + begin = self._insert_iter() + return PlaceholderRegex(self._view, data['tabstop'], 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 = 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: + sys.stderr.write('Token class not supported: %s\n' % token.klass) + continue + + if isinstance(val, basestring): + # 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.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 = self.placeholders.keys() + k.sort(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=8:et: diff --git a/plugins/snippets/snippets/SubstitutionParser.py b/plugins/snippets/snippets/SubstitutionParser.py new file mode 100755 index 00000000..6522222b --- /dev/null +++ b/plugins/snippets/snippets/SubstitutionParser.py @@ -0,0 +1,202 @@ +# Gedit snippets plugin +# Copyright (C) 2006-2007 Jesse van den Kieboom <[email protected]> +# +# 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 = '\\\\|\\(\\?|,|\\)' + + def __init__(self, pattern, groups = {}, modifiers = {}): + self.pattern = pattern + self.groups = groups + + self.REG_GROUP = '(?:(%s)|<(%s|%s)(?:,(%s))?>)' % (self.REG_ID, self.REG_ID, self.REG_NAME, self.REG_MOD) + 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 == None or self._peek(tokens) != ',': + raise ParseError + + truepart, tokens = self._parse(self._remains(tokens), ',') + + if truepart == None: + raise ParseError + + falsepart, tokens = self._parse(tokens, ')') + + if falsepart == None: + raise ParseError + + if condition: + return truepart, tokens + else: + return falsepart, tokens + + def escape_substitution(substitution): + return re.sub('(%s|%s)' % (self.REG_GROUP, self.REG_ESCAPE), '\\\\\\1', substitution) + + escapesubstitution = staticmethod(escape_substitution) +# ex:ts=8:et: diff --git a/plugins/snippets/snippets/WindowHelper.py b/plugins/snippets/snippets/WindowHelper.py new file mode 100755 index 00000000..29bf3a58 --- /dev/null +++ b/plugins/snippets/snippets/WindowHelper.py @@ -0,0 +1,209 @@ +# Gedit snippets plugin +# Copyright (C) 2005-2006 Jesse van den Kieboom <[email protected]> +# +# 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 +import os +import gettext + +import gtk +from gtk import gdk +import gedit + +from Document import Document +from Library import Library + +class WindowHelper: + def __init__(self, plugin): + self.plugin = plugin + self.current_controller = None + self.current_language = None + self.signal_ids = {} + + def run(self, window): + self.window = window + + self.insert_menu() + self.register_messages() + + self.accel_group = Library().get_accel_group(None) + + window.add_accel_group(self.accel_group) + window.connect('tab-added', self.on_tab_added) + + # Add controllers to all the current views + for view in self.window.get_views(): + if isinstance(view, gedit.View) and not self.has_controller(view): + view._snippet_controller = Document(self, view) + + self.update() + + def stop(self): + self.window.remove_accel_group(self.accel_group) + self.accel_group = None + + #self.window.remove_accel_group(accel) + self.remove_menu() + self.unregister_messages() + + # Iterate over all the tabs and remove every controller + for view in self.window.get_views(): + if isinstance(view, gedit.View) and self.has_controller(view): + view._snippet_controller.stop() + view._snippet_controller = None + + self.window = None + self.plugin = None + + def register_messages(self): + bus = self.window.get_message_bus() + + self.messages = { + 'activate': bus.register('/plugins/snippets', 'activate', ('view', 'iter'), trigger=str, view=gedit.View, iter=gtk.TextIter), + 'parse-and-activate': bus.register('/plugins/snippets', 'parse-and-activate', ('view', 'iter'), snippet=str, view=gedit.View, iter=gtk.TextIter) + } + + bus.connect('/plugins/snippets', 'activate', self.on_message_activate) + bus.connect('/plugins/snippets', 'parse-and-activate', self.on_message_parse_and_activate) + + def unregister_messages(self): + bus = self.window.get_message_bus() + + for name in self.messages: + bus.unregister(self.messages[name]) + + self.messages = {} + + def on_message_activate(self, bus, message): + if message.has_key('view'): + view = message.view + else: + view = self.window.get_active_view() + + if not self.has_controller(view): + return + + if message.has_key('iter'): + iter = message.iter + else: + iter = view.get_buffer().get_iter_at_mark(view.get_buffer().get_insert()) + + controller = view._snippet_controller + controller.run_snippet_trigger(message.trigger, (iter, iter)) + + def on_message_parse_and_activate(self, bus, message): + if message.has_key('view'): + view = message.view + else: + view = self.window.get_active_view() + + if not self.has_controller(view): + return + + if message.has_key('iter'): + iter = message.iter + else: + iter = view.get_buffer().get_iter_at_mark(view.get_buffer().get_insert()) + + controller = view._snippet_controller + controller.parse_and_run_snippet(message.snippet, iter) + + def insert_menu(self): + manager = self.window.get_ui_manager() + + self.action_group = gtk.ActionGroup("GeditSnippetPluginActions") + self.action_group.set_translation_domain('gedit') + self.action_group.add_actions([('ManageSnippets', None, + _('Manage _Snippets...'), \ + None, _('Manage snippets'), \ + self.on_action_snippets_activate)]) + + self.merge_id = manager.new_merge_id() + manager.insert_action_group(self.action_group, -1) + manager.add_ui(self.merge_id, '/MenuBar/ToolsMenu/ToolsOps_5', \ + 'ManageSnippets', 'ManageSnippets', gtk.UI_MANAGER_MENUITEM, False) + + def remove_menu(self): + manager = self.window.get_ui_manager() + manager.remove_ui(self.merge_id) + manager.remove_action_group(self.action_group) + self.action_group = None + + def find_snippet(self, snippets, tag): + result = [] + + for snippet in snippets: + if Snippet(snippet)['tag'] == tag: + result.append(snippet) + + return result + + def has_controller(self, view): + return hasattr(view, '_snippet_controller') and view._snippet_controller + + def update_language(self): + if not self.window: + return + + if self.current_language: + accel_group = Library().get_accel_group( \ + self.current_language) + self.window.remove_accel_group(accel_group) + + if self.current_controller: + self.current_language = self.current_controller.language_id + + if self.current_language != None: + accel_group = Library().get_accel_group( \ + self.current_language) + self.window.add_accel_group(accel_group) + else: + self.current_language = None + + def language_changed(self, controller): + if controller == self.current_controller: + self.update_language() + + def update(self): + view = self.window.get_active_view() + + if not view or not self.has_controller(view): + return + + controller = view._snippet_controller + + if controller != self.current_controller: + self.current_controller = controller + self.update_language() + + # Callbacks + + def on_tab_added(self, window, tab): + # Create a new controller for this tab if it has a standard gedit view + view = tab.get_view() + + if isinstance(view, gedit.View) and not self.has_controller(view): + view._snippet_controller = Document(self, view) + + self.update() + + def on_action_snippets_activate(self, item): + self.plugin.create_configure_dialog() + + def accelerator_activated(self, keyval, mod): + return self.current_controller.accelerator_activate(keyval, mod) + +# ex:ts=8:et: diff --git a/plugins/snippets/snippets/__init__.py b/plugins/snippets/snippets/__init__.py new file mode 100755 index 00000000..b21da508 --- /dev/null +++ b/plugins/snippets/snippets/__init__.py @@ -0,0 +1,101 @@ +# Gedit snippets plugin +# Copyright (C) 2005-2006 Jesse van den Kieboom <[email protected]> +# +# 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 sys +import os +import shutil + +import gtk +from gtk import gdk +import gedit +import platform + +from WindowHelper import WindowHelper +from Library import Library +from Manager import Manager +from Snippet import Snippet + +class SnippetsPlugin(gedit.Plugin): + def __init__(self): + gedit.Plugin.__init__(self) + + self.dlg = None + + library = Library() + library.set_accelerator_callback(self.accelerator_activated) + + if platform.platform() == 'Windows': + snippetsdir = os.path.expanduser('~/gedit/snippets') + else: + userdir = os.getenv('MATE22_USER_DIR') + if userdir: + snippetsdir = os.path.join(userdir, 'gedit/snippets') + else: + snippetsdir = os.path.expanduser('~/.mate2/gedit/snippets') + + library.set_dirs(snippetsdir, self.system_dirs()) + + def system_dirs(self): + if platform.platform() != 'Windows': + if 'XDG_DATA_DIRS' in os.environ: + datadirs = os.environ['XDG_DATA_DIRS'] + else: + datadirs = '/usr/local/share' + os.pathsep + '/usr/share' + + dirs = [] + + for d in datadirs.split(os.pathsep): + d = os.path.join(d, 'gedit-2', 'plugins', 'snippets') + + if os.path.isdir(d): + dirs.append(d) + + dirs.append(self.get_data_dir()) + return dirs + + def activate(self, window): + data = WindowHelper(self) + window._snippets_plugin_data = data + data.run(window) + + def deactivate(self, window): + window._snippets_plugin_data.stop() + window._snippets_plugin_data = None + + def update_ui(self, window): + window._snippets_plugin_data.update() + + def create_configure_dialog(self): + if not self.dlg: + self.dlg = Manager(self.get_data_dir()) + else: + self.dlg.run() + + window = gedit.app_get_default().get_active_window() + + if window: + self.dlg.dlg.set_transient_for(window) + + return self.dlg.dlg + + def accelerator_activated(self, group, obj, keyval, mod): + ret = False + + if hasattr(obj, '_snippets_plugin_data'): + ret = obj._snippets_plugin_data.accelerator_activated(keyval, mod) + + return ret diff --git a/plugins/snippets/snippets/snippets.ui b/plugins/snippets/snippets/snippets.ui new file mode 100755 index 00000000..426df886 --- /dev/null +++ b/plugins/snippets/snippets/snippets.ui @@ -0,0 +1,647 @@ +<?xml version="1.0"?> +<!--*- mode: xml -*--> +<interface> + <object class="GtkListStore" id="model1"> + <columns> + <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"> + <property name="highlight-matching-brackets">True</property> + </object> + <object class="GtkDialog" id="dialog_snippets"> + <property name="title" translatable="yes">Snippets Manager</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">750</property> + <property name="default_height">500</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">True</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">True</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">False</property> + <signal handler="on_dialog_snippets_response" last_modification_time="Mon, 19 Dec 2005 11:20:00 GMT" name="response"/> + <signal handler="on_dialog_snippets_destroy" last_modification_time="Sun, 22 Jun 2008 13:22:00 GMT" name="destroy"/> + <child internal-child="vbox"> + <object class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + <child internal-child="action_area"> + <object class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <object class="GtkButton" id="closebutton1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-close</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </object> + </child> + <child> + <object class="GtkButton" id="button1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-help</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </object> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + <child> + <object class="GtkHPaned" id="hpaned_paned"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="position">275</property> + <child> + <object class="GtkVBox" id="vbox_selection"> + <property name="width_request">230</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Snippets:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">tree_view_snippets</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="scrolled_window_snippets"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + <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> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + <signal handler="on_tree_view_snippets_row_expanded" last_modification_time="Tue, 03 Jan 2006 22:06:02 GMT" name="row_expanded"/> + <signal handler="on_tree_view_snippets_key_press" last_modification_time="Tue, 03 Jan 2006 22:07:00 GMT" name="key_press_event"/> + </object> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox_buttons"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkButton" id="button_new_snippet"> + <property name="visible">True</property> + <property name="tooltip-text" translatable="yes">Create new snippet</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal handler="on_button_new_snippet_clicked" last_modification_time="Tue, 20 Dec 2005 19:50:58 GMT" name="clicked"/> + <child> + <object class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-new</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </object> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button_import_snippets"> + <property name="visible">True</property> + <property name="tooltip-text" translatable="yes">Import snippets</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal handler="on_button_import_snippets_clicked" last_modification_time="Tue, 10 Jul 2007 18:37:11 GMT" name="clicked"/> + <child> + <object class="GtkImage" id="image5"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </object> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button_export_snippets"> + <property name="visible">True</property> + <property name="tooltip-text" translatable="yes">Export selected snippets</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal handler="on_button_export_snippets_clicked" last_modification_time="Tue, 10 Jul 2007 18:37:25 GMT" name="clicked"/> + <child> + <object class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-save</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </object> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button_remove_snippet"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="tooltip-text" translatable="yes">Delete selected snippet</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal handler="on_button_remove_snippet_clicked" last_modification_time="Mon, 19 Dec 2005 13:15:14 GMT" name="clicked"/> + <child> + <object class="GtkImage" id="image_remove"> + <property name="visible">True</property> + <property name="stock">gtk-delete</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </object> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </object> + <packing> + <property name="shrink">False</property> + <property name="resize">False</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="vbox_snippet"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + <child> + <object class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Edit:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="scrolled_window_snippet"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + <child> + <object class="GeditView" id="source_view_snippet"> + <property name="buffer">source_buffer</property> + <property name="visible">True</property> + <property name="auto-indent">True</property> + <property name="insert-spaces-instead-of-tabs">False</property> + <property name="smart-home-end">GTK_SOURCE_SMART_HOME_END_AFTER</property> + <property name="tab-width">2</property> + <property name="highlight-current-line">True</property> + <property name="show-right-margin">False</property> + <property name="show-line-numbers">False</property> + + <signal handler="on_source_view_snippet_focus_out" last_modification_time="Sat, 07 Jan 2006 17:13:24 GMT" name="focus_out_event"/> + </object> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">Activation</property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + <attributes> + <attribute name="weight" value="PANGO_WEIGHT_BOLD"/> + </attributes> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + <child> + <object class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes"> </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <object class="GtkTable" id="table1"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">2</property> + <property name="homogeneous">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 comments=""tab" here means the tab key, not the notebook tab!" name="label" translatable="yes">_Tab trigger:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">entry_tab_trigger</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"/> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox_tab_trigger"> + <property name="visible">True</property> + <child> + <object class="GtkEntry" id="entry_tab_trigger"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="tooltip-text" translatable="yes">Single word the snippet is activated with after pressing Tab</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"/> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + <signal handler="on_entry_tab_trigger_focus_out" last_modification_time="Wed, 04 Jan 2006 14:07:29 GMT" name="focus_out_event"/> + <signal handler="on_entry_tab_trigger_changed" last_modification_time="Fri, 28 Apr 2006 16:50:34 GMT" name="changed"/> + </object> + <packing> + <property name="expand">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkImage" id="image_tab_trigger"> + <property name="visible">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + <property name="padding">3</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options"/> + </packing> + </child> + <child> + <object class="GtkEntry" id="entry_accelerator"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="tooltip-text" translatable="yes">Shortcut key with which the snippet is activated</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"/> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + <signal handler="on_entry_accelerator_focus_out" last_modification_time="Wed, 04 Jan 2006 14:07:20 GMT" name="focus_out_event"/> + <signal handler="on_entry_accelerator_key_press" last_modification_time="Wed, 04 Jan 2006 14:07:23 GMT" name="key_press_event"/> + <signal handler="on_entry_accelerator_focus_in" last_modification_time="Wed, 04 Jan 2006 14:09:06 GMT" name="focus_in_event"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"/> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_accelerator"> + <property name="visible">True</property> + <property name="label" translatable="yes">S_hortcut key:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">entry_accelerator</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"/> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_drop_targets"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Drop targets:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">entry_accelerator</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"/> + </packing> + </child> + <child> + <object class="GtkComboBoxEntry" id="combo_drop_targets"> + <property name="visible">True</property> + <property name="add_tearoffs">False</property> + <property name="has_frame">True</property> + <property name="focus_on_click">True</property> + <property name="model">model1</property> + <child> + <object class="GtkCellRendererText" id="renderer1"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </object> + <packing> + <property name="shrink">True</property> + <property name="resize">True</property> + </packing> + </child> + </object> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="-7">closebutton1</action-widget> + <action-widget response="-11">button1</action-widget> + </action-widgets> + </object> +</interface> |