summaryrefslogtreecommitdiffstats
path: root/plugins/snippets/snippets/library.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--plugins/snippets/snippets/library.py989
1 files changed, 989 insertions, 0 deletions
diff --git a/plugins/snippets/snippets/library.py b/plugins/snippets/snippets/library.py
new file mode 100644
index 0000000..7ce163b
--- /dev/null
+++ b/plugins/snippets/snippets/library.py
@@ -0,0 +1,989 @@
+# Gedit snippets plugin
+# Copyright (C) 2005-2006 Jesse van den Kieboom <jesse@icecrew.nl>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import os
+import weakref
+import sys
+import re
+
+from gi.repository import Gdk, Gtk
+
+import xml.etree.ElementTree as et
+from . import helper
+
+class NamespacedId:
+ def __init__(self, namespace, id):
+ if not id:
+ self.id = None
+ else:
+ if namespace:
+ self.id = namespace + '-'
+ else:
+ self.id = 'global-'
+
+ self.id += id
+
+class SnippetData:
+ PROPS = {'tag': '', 'text': '', 'description': 'New snippet',
+ 'accelerator': '', 'drop-targets': ''}
+
+ def __init__(self, node, library):
+ self.priv_id = node.attrib.get('id')
+
+ self.set_library(library)
+ self.valid = False
+ self.set_node(node)
+
+ def can_modify(self):
+ return (self.library and (isinstance(self.library(), SnippetsUserFile)))
+
+ def set_library(self, library):
+ if library:
+ self.library = weakref.ref(library)
+ else:
+ self.library = None
+
+ self.id = NamespacedId(self.language(), self.priv_id).id
+
+ def set_node(self, node):
+ if self.can_modify():
+ self.node = node
+ else:
+ self.node = None
+
+ self.init_snippet_data(node)
+
+ def init_snippet_data(self, node):
+ if node is None:
+ return
+
+ self.override = node.attrib.get('override')
+
+ self.properties = {}
+ props = SnippetData.PROPS.copy()
+
+ # Store all properties present
+ for child in node:
+ if child.tag in props:
+ del props[child.tag]
+
+ # Normalize accelerator
+ if child.tag == 'accelerator' and child.text != None:
+ keyval, mod = Gtk.accelerator_parse(child.text)
+
+ if Gtk.accelerator_valid(keyval, mod):
+ child.text = Gtk.accelerator_name(keyval, mod)
+ else:
+ child.text = ''
+
+ if self.can_modify():
+ self.properties[child.tag] = child
+ else:
+ self.properties[child.tag] = child.text or ''
+
+ # Create all the props that were not found so we stay consistent
+ for prop in props:
+ if self.can_modify():
+ child = et.SubElement(node, prop)
+
+ child.text = props[prop]
+ self.properties[prop] = child
+ else:
+ self.properties[prop] = props[prop]
+
+ self.check_validation()
+
+ def check_validation(self):
+ if not self['tag'] and not self['accelerator'] and not self['drop-targets']:
+ return False
+
+ library = Library()
+ keyval, mod = Gtk.accelerator_parse(self['accelerator'])
+
+ self.valid = library.valid_tab_trigger(self['tag']) and \
+ (not self['accelerator'] or library.valid_accelerator(keyval, mod))
+
+ def _format_prop(self, prop, value):
+ if prop == 'drop-targets' and value != '':
+ return re.split('\\s*[,;]\\s*', value)
+ else:
+ return value
+
+ def __getitem__(self, prop):
+ if prop in self.properties:
+ if self.can_modify():
+ return self._format_prop(prop, self.properties[prop].text or '')
+ else:
+ return self._format_prop(prop, self.properties[prop] or '')
+
+ return self._format_prop(prop, '')
+
+ def __setitem__(self, prop, value):
+ if not prop in self.properties:
+ return
+
+ if isinstance(value, list):
+ value = ','.join(value)
+
+ if not self.can_modify() and self.properties[prop] != value:
+ # ohoh, this is not can_modify, but it needs to be changed...
+ # make sure it is transfered to the changes file and set all the
+ # fields.
+ # This snippet data container will effectively become the container
+ # for the newly created node, but transparently to whoever uses
+ # it
+ self._override()
+
+ if self.can_modify() and self.properties[prop].text != value:
+ if self.library():
+ self.library().tainted = True
+
+ oldvalue = self.properties[prop].text
+ self.properties[prop].text = value
+
+ if prop == 'tag' or prop == 'accelerator' or prop == 'drop-targets':
+ container = Library().container(self.language())
+ container.prop_changed(self, prop, oldvalue)
+
+ self.check_validation()
+
+ def language(self):
+ if self.library and self.library():
+ return self.library().language
+ else:
+ return None
+
+ def is_override(self):
+ return self.override and Library().overridden[self.override]
+
+ def to_xml(self):
+ return self._create_xml()
+
+ def _create_xml(self, parent=None, update=False, attrib={}):
+ # Create a new node
+ if parent != None:
+ element = et.SubElement(parent, 'snippet', attrib)
+ else:
+ element = et.Element('snippet')
+
+ # Create all the properties
+ for p in self.properties:
+ prop = et.SubElement(element, p)
+ prop.text = self[p]
+
+ if update:
+ self.properties[p] = prop
+
+ return element
+
+ def _override(self):
+ # Find the user file
+ target = Library().get_user_library(self.language())
+
+ # Create a new node there with override
+ element = self._create_xml(target.root, True, {'override': self.id})
+
+ # Create an override snippet data, feed it element so that it stores
+ # all the values and then set the node to None so that it only contains
+ # the values in .properties
+ override = SnippetData(element, self.library())
+ override.set_node(None)
+ override.id = self.id
+
+ # Set our node to the new element
+ self.node = element
+
+ # Set the override to our id
+ self.override = self.id
+ self.id = None
+
+ # Set the new library
+ self.set_library(target)
+
+ # The library is tainted because we added this snippet
+ target.tainted = True
+
+ # Add the override
+ Library().overridden[self.override] = override
+
+ def revert(self, snippet):
+ userlib = self.library()
+ self.set_library(snippet.library())
+
+ userlib.remove(self.node)
+
+ self.set_node(None)
+
+ # Copy the properties
+ self.properties = snippet.properties
+
+ # Set the id
+ self.id = snippet.id
+
+ # Reset the override flag
+ self.override = None
+
+class SnippetsTreeBuilder(et.TreeBuilder):
+ def __init__(self, start=None, end=None):
+ et.TreeBuilder.__init__(self)
+ self.set_start(start)
+ self.set_end(end)
+
+ def set_start(self, start):
+ self._start_cb = start
+
+ def set_end(self, end):
+ self._end_cb = end
+
+ def start(self, tag, attrs):
+ result = et.TreeBuilder.start(self, tag, attrs)
+
+ if self._start_cb:
+ self._start_cb(result)
+
+ return result
+
+ def end(self, tag):
+ result = et.TreeBuilder.end(self, tag)
+
+ if self._end_cb:
+ self._end_cb(result)
+
+ return result
+
+class LanguageContainer:
+ def __init__(self, language):
+ self.language = language
+ self.snippets = []
+ self.snippets_by_prop = {'tag': {}, 'accelerator': {}, 'drop-targets': {}}
+ self.accel_group = Gtk.AccelGroup()
+ self._refs = 0
+
+ def _add_prop(self, snippet, prop, value=0):
+ if value == 0:
+ value = snippet[prop]
+
+ if not value or value == '':
+ return
+
+ helper.snippets_debug('Added ', prop ,' ', value, ' to ', str(self.language))
+
+ if prop == 'accelerator':
+ keyval, mod = Gtk.accelerator_parse(value)
+ self.accel_group.connect(keyval, mod, 0, \
+ Library().accelerator_activated)
+
+ snippets = self.snippets_by_prop[prop]
+
+ if not isinstance(value, list):
+ value = [value]
+
+ for val in value:
+ if val in snippets:
+ snippets[val].append(snippet)
+ else:
+ snippets[val] = [snippet]
+
+ def _remove_prop(self, snippet, prop, value=0):
+ if value == 0:
+ value = snippet[prop]
+
+ if not value or value == '':
+ return
+
+ helper.snippets_debug('Removed ', prop, ' ', value, ' from ', str(self.language))
+
+ if prop == 'accelerator':
+ keyval, mod = Gtk.accelerator_parse(value)
+ self.accel_group.disconnect_key(keyval, mod)
+
+ snippets = self.snippets_by_prop[prop]
+
+ if not isinstance(value, list):
+ value = [value]
+
+ for val in value:
+ try:
+ snippets[val].remove(snippet)
+ except:
+ True
+
+ def append(self, snippet):
+ self.snippets.append(snippet)
+
+ self._add_prop(snippet, 'tag')
+ self._add_prop(snippet, 'accelerator')
+ self._add_prop(snippet, 'drop-targets')
+
+ return snippet
+
+ def remove(self, snippet):
+ try:
+ self.snippets.remove(snippet)
+ except:
+ True
+
+ self._remove_prop(snippet, 'tag')
+ self._remove_prop(snippet, 'accelerator')
+ self._remove_prop(snippet, 'drop-targets')
+
+ def prop_changed(self, snippet, prop, oldvalue):
+ helper.snippets_debug('PROP CHANGED (', prop, ')', oldvalue)
+
+ self._remove_prop(snippet, prop, oldvalue)
+ self._add_prop(snippet, prop)
+
+ def from_prop(self, prop, value):
+ snippets = self.snippets_by_prop[prop]
+
+ if prop == 'drop-targets':
+ s = []
+
+ # FIXME: change this to use
+ # gnomevfs.mime_type_get_equivalence when it comes
+ # available
+ for key, val in snippets.items():
+ if not value.startswith(key):
+ continue
+
+ for snippet in snippets[key]:
+ if not snippet in s:
+ s.append(snippet)
+
+ return s
+ else:
+ if value in snippets:
+ return snippets[value]
+ else:
+ return []
+
+ def ref(self):
+ self._refs += 1
+
+ return True
+
+ def unref(self):
+ if self._refs > 0:
+ self._refs -= 1
+
+ return self._refs != 0
+
+class SnippetsSystemFile:
+ def __init__(self, path=None):
+ self.path = path
+ self.loaded = False
+ self.language = None
+ self.ok = True
+ self.need_id = True
+
+ def load_error(self, message):
+ sys.stderr.write("An error occurred loading " + self.path + ":\n")
+ sys.stderr.write(message + "\nSnippets in this file will not be " \
+ "available, please correct or remove the file.\n")
+
+ def _add_snippet(self, element):
+ if not self.need_id or element.attrib.get('id'):
+ self.loading_elements.append(element)
+
+ def set_language(self, element):
+ self.language = element.attrib.get('language')
+
+ if self.language:
+ self.language = self.language.lower()
+
+ def _set_root(self, element):
+ self.set_language(element)
+
+ def _preprocess_element(self, element):
+ if not self.loaded:
+ if not element.tag == "snippets":
+ self.load_error("Root element should be `snippets' instead " \
+ "of `%s'" % element.tag)
+ return False
+ else:
+ self._set_root(element)
+ self.loaded = True
+ elif element.tag != 'snippet' and not self.insnippet:
+ self.load_error("Element should be `snippet' instead of `%s'" \
+ % element.tag)
+ return False
+ else:
+ self.insnippet = True
+
+ return True
+
+ def _process_element(self, element):
+ if element.tag == 'snippet':
+ self._add_snippet(element)
+ self.insnippet = False
+
+ return True
+
+ def ensure(self):
+ if not self.ok or self.loaded:
+ return
+
+ self.load()
+
+ def parse_xml(self, readsize=16384):
+ if not self.path:
+ return
+
+ elements = []
+
+ builder = SnippetsTreeBuilder( \
+ lambda node: elements.append((node, True)), \
+ lambda node: elements.append((node, False)))
+
+ parser = et.XMLParser(target=builder)
+ self.insnippet = False
+
+ try:
+ f = open(self.path, "r", encoding='utf-8')
+ except IOError:
+ self.ok = False
+ return
+
+ while True:
+ try:
+ data = f.read(readsize)
+ except IOError:
+ self.ok = False
+ break
+
+ if not data:
+ break
+
+ try:
+ parser.feed(data)
+ except Exception:
+ self.ok = False
+ break
+
+ for element in elements:
+ yield element
+
+ del elements[:]
+
+ f.close()
+
+ def load(self):
+ if not self.ok:
+ return
+
+ helper.snippets_debug("Loading library (" + str(self.language) + "): " + \
+ self.path)
+
+ self.loaded = False
+ self.ok = False
+ self.loading_elements = []
+
+ for element in self.parse_xml():
+ if element[1]:
+ if not self._preprocess_element(element[0]):
+ del self.loading_elements[:]
+ return
+ else:
+ if not self._process_element(element[0]):
+ del self.loading_elements[:]
+ return
+
+ for element in self.loading_elements:
+ Library().add_snippet(self, element)
+
+ del self.loading_elements[:]
+ self.ok = True
+
+ # This function will get the language for a file by just inspecting the
+ # root element of the file. This is provided so that a cache can be built
+ # for which file contains which language.
+ # It returns the name of the language
+ def ensure_language(self):
+ if not self.loaded:
+ self.ok = False
+
+ for element in self.parse_xml(256):
+ if element[1]:
+ if element[0].tag == 'snippets':
+ self.set_language(element[0])
+ self.ok = True
+
+ break
+
+ def unload(self):
+ helper.snippets_debug("Unloading library (" + str(self.language) + "): " + \
+ self.path)
+ self.language = None
+ self.loaded = False
+ self.ok = True
+
+class SnippetsUserFile(SnippetsSystemFile):
+ def __init__(self, path=None):
+ SnippetsSystemFile.__init__(self, path)
+ self.tainted = False
+ self.need_id = False
+
+ def _set_root(self, element):
+ SnippetsSystemFile._set_root(self, element)
+ self.root = element
+
+ def add_prop(self, node, tag, data):
+ if data[tag]:
+ prop = et.SubElement(node, tag)
+ prop.text = data[tag]
+
+ return prop
+ else:
+ return None
+
+ def new_snippet(self, properties=None):
+ if (not self.ok) or self.root is None:
+ return None
+
+ element = et.SubElement(self.root, 'snippet')
+
+ if properties:
+ for prop in properties:
+ sub = et.SubElement(element, prop)
+ sub.text = properties[prop]
+
+ self.tainted = True
+
+ return Library().add_snippet(self, element)
+
+ def set_language(self, element):
+ SnippetsSystemFile.set_language(self, element)
+
+ filename = os.path.basename(self.path).lower()
+
+ if not self.language and filename == "global.xml":
+ self.modifier = True
+ elif self.language and filename == self.language + ".xml":
+ self.modifier = True
+ else:
+ self.modifier = False
+
+ def create_root(self, language):
+ if self.loaded:
+ helper.snippets_debug('Not creating root, already loaded')
+ return
+
+ if language:
+ root = et.Element('snippets', {'language': language})
+ self.path = os.path.join(Library().userdir, language.lower() + '.xml')
+ else:
+ root = et.Element('snippets')
+ self.path = os.path.join(Library().userdir, 'global.xml')
+
+ self._set_root(root)
+ self.loaded = True
+ self.ok = True
+ self.tainted = True
+ self.save()
+
+ def remove(self, element):
+ try:
+ self.root.remove(element)
+ self.tainted = True
+ except:
+ return
+
+ try:
+ self.root[0]
+ except:
+ # No more elements, this library is useless now
+ Library().remove_library(self)
+
+ def save(self):
+ if not self.ok or self.root is None or not self.tainted:
+ return
+
+ path = os.path.dirname(self.path)
+
+ try:
+ if not os.path.isdir(path):
+ os.makedirs(path, 0o755)
+ except OSError:
+ # TODO: this is bad...
+ sys.stderr.write("Error in making dirs\n")
+
+ try:
+ helper.write_xml(self.root, self.path, ('text', 'accelerator'))
+ self.tainted = False
+ except IOError:
+ # Couldn't save, what to do
+ sys.stderr.write("Could not save user snippets file to " + \
+ self.path + "\n")
+
+ def unload(self):
+ SnippetsSystemFile.unload(self)
+ self.root = None
+
+class Singleton(object):
+ _instance = None
+
+ def __new__(cls, *args, **kwargs):
+ if not cls._instance:
+ cls._instance = super(Singleton, cls).__new__(
+ cls, *args, **kwargs)
+ cls._instance.__init_once__()
+
+ return cls._instance
+
+class Library(Singleton):
+ def __init_once__(self):
+ self._accelerator_activated_cb = []
+ self.loaded = False
+ self.check_buffer = Gtk.TextBuffer()
+
+ def set_dirs(self, userdir, systemdirs):
+ self.userdir = userdir
+ self.systemdirs = systemdirs
+
+ self.libraries = {}
+ self.containers = {}
+ self.overridden = {}
+ self.loaded_ids = []
+
+ self.loaded = False
+
+ def add_accelerator_callback(self, cb):
+ self._accelerator_activated_cb.append(cb)
+
+ def remove_accelerator_callback(self, cb):
+ self._accelerator_activated_cb.remove(cb)
+
+ def accelerator_activated(self, group, obj, keyval, mod):
+ ret = False
+
+ for cb in self._accelerator_activated_cb:
+ ret = cb(group, obj, keyval, mod)
+
+ if ret:
+ break
+
+ return ret
+
+ def add_snippet(self, library, element):
+ container = self.container(library.language)
+ overrided = self.overrided(library, element)
+
+ if overrided:
+ overrided.set_library(library)
+ helper.snippets_debug('Snippet is overriden: ' + overrided['description'])
+ return None
+
+ snippet = SnippetData(element, library)
+
+ if snippet.id in self.loaded_ids:
+ helper.snippets_debug('Not added snippet ' + str(library.language) + \
+ '::' + snippet['description'] + ' (duplicate)')
+ return None
+
+ snippet = container.append(snippet)
+ helper.snippets_debug('Added snippet ' + str(library.language) + '::' + \
+ snippet['description'])
+
+ if snippet and snippet.override:
+ self.add_override(snippet)
+
+ if snippet.id:
+ self.loaded_ids.append(snippet.id)
+
+ return snippet
+
+ def container(self, language):
+ language = self.normalize_language(language)
+
+ if not language in self.containers:
+ self.containers[language] = LanguageContainer(language)
+
+ return self.containers[language]
+
+ def get_user_library(self, language):
+ target = None
+
+ if language in self.libraries:
+ for library in self.libraries[language]:
+ if isinstance(library, SnippetsUserFile) and library.modifier:
+ target = library
+ elif not isinstance(library, SnippetsUserFile):
+ break
+
+ if not target:
+ # Create a new user file then
+ helper.snippets_debug('Creating a new user file for language ' + \
+ str(language))
+ target = SnippetsUserFile()
+ target.create_root(language)
+ self.add_library(target)
+
+ return target
+
+ def new_snippet(self, language, properties=None):
+ language = self.normalize_language(language)
+ library = self.get_user_library(language)
+
+ return library.new_snippet(properties)
+
+ def revert_snippet(self, snippet):
+ # This will revert the snippet to the one it overrides
+ if not snippet.can_modify() or not snippet.override in self.overridden:
+ # It can't be reverted, shouldn't happen, but oh..
+ return
+
+ # The snippet in self.overriden only contains the property contents and
+ # the library it belongs to
+ revertto = self.overridden[snippet.override]
+ del self.overridden[snippet.override]
+
+ if revertto:
+ snippet.revert(revertto)
+
+ if revertto.id:
+ self.loaded_ids.append(revertto.id)
+
+ def remove_snippet(self, snippet):
+ if not snippet.can_modify() or snippet.is_override():
+ return
+
+ # Remove from the library
+ userlib = snippet.library()
+ userlib.remove(snippet.node)
+
+ # Remove from the container
+ container = self.containers[userlib.language]
+ container.remove(snippet)
+
+ def overrided(self, library, element):
+ id = NamespacedId(library.language, element.attrib.get('id')).id
+
+ if id in self.overridden:
+ snippet = SnippetData(element, None)
+ snippet.set_node(None)
+
+ self.overridden[id] = snippet
+ return snippet
+ else:
+ return None
+
+ def add_override(self, snippet):
+ helper.snippets_debug('Add override:', snippet.override)
+ if not snippet.override in self.overridden:
+ self.overridden[snippet.override] = None
+
+ def add_library(self, library):
+ library.ensure_language()
+
+ if not library.ok:
+ helper.snippets_debug('Library in wrong format, ignoring')
+ return False
+
+ helper.snippets_debug('Adding library (' + str(library.language) + '): ' + \
+ library.path)
+
+ if library.language in self.libraries:
+ # Make sure all the user files are before the system files
+ if isinstance(library, SnippetsUserFile):
+ self.libraries[library.language].insert(0, library)
+ else:
+ self.libraries[library.language].append(library)
+ else:
+ self.libraries[library.language] = [library]
+
+ return True
+
+ def remove_library(self, library):
+ if not library.ok:
+ return
+
+ if library.path and os.path.isfile(library.path):
+ os.unlink(library.path)
+
+ try:
+ self.libraries[library.language].remove(library)
+ except KeyError:
+ True
+
+ container = self.containers[library.language]
+
+ for snippet in list(container.snippets):
+ if snippet.library() == library:
+ container.remove(snippet)
+
+ def add_user_library(self, path):
+ library = SnippetsUserFile(path)
+ return self.add_library(library)
+
+ def add_system_library(self, path):
+ library = SnippetsSystemFile(path)
+ return self.add_library(library)
+
+ def find_libraries(self, path, searched, addcb):
+ helper.snippets_debug("Finding in: " + path)
+
+ if not os.path.isdir(path):
+ return searched
+
+ files = os.listdir(path)
+ searched.append(path)
+
+ for f in files:
+ f = os.path.realpath(os.path.join(path, f))
+
+ # Determine what language this file provides snippets for
+ if os.path.isfile(f):
+ addcb(f)
+
+ return searched
+
+ def normalize_language(self, language):
+ if language:
+ return language.lower()
+
+ return language
+
+ def remove_container(self, language):
+ for snippet in self.containers[language].snippets:
+ if snippet.id in self.loaded_ids:
+ self.loaded_ids.remove(snippet.id)
+
+ if snippet.override in self.overridden:
+ del self.overridden[snippet.override]
+
+ del self.containers[language]
+
+ def get_accel_group(self, language):
+ language = self.normalize_language(language)
+ container = self.container(language)
+
+ self.ensure(language)
+ return container.accel_group
+
+ def save(self, language):
+ language = self.normalize_language(language)
+
+ if language in self.libraries:
+ for library in self.libraries[language]:
+ if isinstance(library, SnippetsUserFile):
+ library.save()
+ else:
+ break
+
+ def ref(self, language):
+ language = self.normalize_language(language)
+
+ helper.snippets_debug('Ref:', language)
+ self.container(language).ref()
+
+ def unref(self, language):
+ language = self.normalize_language(language)
+
+ helper.snippets_debug('Unref:', language)
+
+ if language in self.containers:
+ if not self.containers[language].unref() and \
+ language in self.libraries:
+
+ for library in self.libraries[language]:
+ library.unload()
+
+ self.remove_container(language)
+
+ def ensure(self, language):
+ self.ensure_files()
+ language = self.normalize_language(language)
+
+ # Ensure language as well as the global snippets (None)
+ for lang in (None, language):
+ if lang in self.libraries:
+ # Ensure the container exists
+ self.container(lang)
+
+ for library in self.libraries[lang]:
+ library.ensure()
+
+ def ensure_files(self):
+ if self.loaded:
+ return
+
+ searched = []
+ searched = self.find_libraries(self.userdir, searched, \
+ self.add_user_library)
+
+ for d in self.systemdirs:
+ searched = self.find_libraries(d, searched, \
+ self.add_system_library)
+
+ self.loaded = True
+
+ def valid_accelerator(self, keyval, mod):
+ mod &= Gtk.accelerator_get_default_mod_mask()
+
+ return (mod and (Gdk.keyval_to_unicode(keyval) or \
+ keyval in range(Gdk.KEY_F1, Gdk.KEY_F12 + 1)))
+
+ def valid_tab_trigger(self, trigger):
+ if not trigger:
+ return True
+
+ return helper.is_tab_trigger(trigger)
+
+ # Snippet getters
+ # ===============
+ def _from_prop(self, prop, value, language=None):
+ self.ensure_files()
+
+ result = []
+ language = self.normalize_language(language)
+
+ if not language in self.containers:
+ return []
+
+ self.ensure(language)
+ result = self.containers[language].from_prop(prop, value)
+
+ if len(result) == 0 and language and None in self.containers:
+ result = self.containers[None].from_prop(prop, value)
+
+ return result
+
+ # Get snippets for a given language
+ def get_snippets(self, language=None):
+ self.ensure_files()
+ language = self.normalize_language(language)
+
+ if not language in self.libraries:
+ return []
+
+ self.ensure(language)
+
+ return list(self.containers[language].snippets)
+
+ # Get snippets for a given accelerator
+ def from_accelerator(self, accelerator, language=None):
+ return self._from_prop('accelerator', accelerator, language)
+
+ # Get snippets for a given tag
+ def from_tag(self, tag, language=None):
+ return self._from_prop('tag', tag, language)
+
+ # Get snippets for a given drop target
+ def from_drop_target(self, drop_target, language=None):
+ return self._from_prop('drop-targets', drop_target, language)
+
+# ex:ts=4:et: