98 lines
3.3 KiB
Python
98 lines
3.3 KiB
Python
#!/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,
|
|
visual_content):
|
|
"""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,
|
|
visual_content))
|
|
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
|