#!/usr/bin/env python # encoding: utf-8 """Base class for snippet sources.""" from collections import defaultdict from UltiSnips.snippet.source._snippet_dictionary import SnippetDictionary class SnippetSource(object): """See module docstring.""" def __init__(self): self._snippets = defaultdict(SnippetDictionary) self._extends = defaultdict(set) def ensure(self, filetypes, cached): """Update/reload the snippets in the source when needed. It makes sure that the snippets are not outdated. """ def loaded(self, filetypes): return len(self._snippets) > 0 def _get_existing_deep_extends(self, base_filetypes): """Helper for get all existing filetypes extended by base filetypes.""" deep_extends = self.get_deep_extends(base_filetypes) return [ft for ft in deep_extends if ft in self._snippets] def get_snippets(self, filetypes, before, possible, autotrigger_only): """Returns the snippets for all 'filetypes' (in order) and their parents matching the text 'before'. If 'possible' is true, a partial match is enough. Base classes can override this method to provide means of creating snippets on the fly. Returns a list of SnippetDefinition s. """ result = [] for ft in self._get_existing_deep_extends(filetypes): snips = self._snippets[ft] result.extend(snips.get_matching_snippets(before, possible, autotrigger_only)) return result def get_clear_priority(self, filetypes): """Get maximum clearsnippets priority without arguments for specified filetypes, if any. It returns None if there are no clearsnippets. """ pri = None for ft in self._get_existing_deep_extends(filetypes): snippets = self._snippets[ft] if pri is None or snippets._clear_priority > pri: pri = snippets._clear_priority return pri def get_cleared(self, filetypes): """Get a set of cleared snippets marked by clearsnippets with arguments for specified filetypes.""" cleared = {} for ft in self._get_existing_deep_extends(filetypes): snippets = self._snippets[ft] for key, value in snippets._cleared.items(): if key not in cleared or value > cleared[key]: cleared[key] = value return cleared def update_extends(self, child_ft, parent_fts): """Update the extending relation by given child filetype and its parent filetypes.""" self._extends[child_ft].update(parent_fts) def get_deep_extends(self, base_filetypes): """Get a list of filetypes that is either directed or indirected extended by given base filetypes. Note that the returned list include the root filetype itself. """ seen = set(base_filetypes) todo_fts = list(set(base_filetypes)) while todo_fts: todo_ft = todo_fts.pop() unseen_extends = set( ft for ft in self._extends[todo_ft] if ft not in seen) seen.update(unseen_extends) todo_fts.extend(unseen_extends) return seen