""" keywords scraped from cadabra.science/man.html """ properties = [ "Accent", "AntiCommuting", "AntiSymmetric", "Commuting", "CommutingAsProduct", "CommutingAsSum", "Coordinate", "DAntiSymmetric", "Depends", "Derivative", "Determinant", "Diagonal", "DiracBar", "EpsilonTensor", "FilledTableau", "GammaMatrix", "ImplicitIndex", "IndexInherit", "Indices", "Integer", "InverseMetric", "KroneckerDelta", "LaTeXForm", "Metric", "NonCommuting", "PartialDerivative", "RiemannTensor", "SatisfiesBianchi", "SelfAntiCommuting", "SelfCommuting", "SelfNonCommuting", "SortOrder", "Spinor", "Symbol", "Symmetric", "Tableau", "TableauSymmetry", "WeightInherit", ] import re import string class CodeCompleter: def __init__(self, kernel): self._kernel = kernel self.code = "" @property def triggers(self): return string.ascii_letters + ":;." def get_last_word(self): return re.compile(r"[\W\s]").split(self.code)[-1] def cursor_on_property(self, last): search_query = re.compile(".*::{}$".format(last), re.MULTILINE) return re.search(search_query, self.code) def match(self, last, options): opts = list(filter(lambda i: re.match("^{}.*".format(last), i), options)) # return options and length of the last matched word return opts, len(last) def match_member(self, last, klass): """ matches last word in the namespace of the currently selected class """ instance = self._kernel._sandbox_context._sandbox[klass] #  filter out hidden namespace, unless typing hidden namespace return self.match(last, (i for i in dir(instance) if "__" not in i)) def get_class(self): """ get class currently behind cursor """ return re.findall(r"(\w+)\.\w*$", self.code) def __call__(self, code, cursor_pos, namespace): # only choose up until current cursor position self.code = code[:cursor_pos] last = self.get_last_word() matched_klass = self.get_class() if self.cursor_on_property(last): # cursor on cadabra property if last: return self.match(last, properties) else: return properties, 0 elif matched_klass and matched_klass[-1] in namespace: # cursor on member function return self.match_member(last, matched_klass[-1]) else: return self.match(last, namespace)