diff --git a/method/introspect.py b/method/introspect.py index 4ad1455..92e44ca 100644 --- a/method/introspect.py +++ b/method/introspect.py @@ -53,7 +53,7 @@ class DumpTokens(Method): if modename in w.buffer.highlights: tokens = w.buffer.highlights[modename].tokens for i in range(0, len(tokens)): - lines.append("LINE %d" % i + 1) + lines.append("LINE %d" % (i + 1)) group = tokens[i] for token in group: fqname = token.fqname() diff --git a/mode/erlang.py b/mode/erlang.py index acd1fbc..c7a9b29 100644 --- a/mode/erlang.py +++ b/mode/erlang.py @@ -10,6 +10,7 @@ class StringGrammar(Grammar): class ErlangGrammar(Grammar): rules = [ + PatternRule(r'eol', r'\n'), PatternRule(r'comment', r'%.*$'), PatternRule(r'erl_attribute', r'-[a-z][a-zA-Z0-9_@]+'), PatternRule(r'erl_reserved', r"(?:xor|when|try|rem|receive|query|orelse|or|of|not|let|if|fun|end|div|cond|catch|case|bxor|bsr|bsl|bor|bnot|begin|band|andalso|and|after)(?![a-zA-Z0-9_'])"), @@ -21,16 +22,60 @@ class ErlangGrammar(Grammar): RegionRule(r'erl_atom', r"'", StringGrammar, r"'"), PatternRule(r'erl_atom', r"[a-z][a-zA-Z0-9_@]*"), PatternRule(r'erl_variable', r"[A-Z_][a-zA-Z0-9_@]*"), - PatternRule(r'operator', r'\+\+|--|==|/=|=<|<|>=|>|=:=|=/=>|-|\+|\*|/|:|#|!]'), PatternRule(r'delimiter', r'->|<<|>>|\(|\)|{|}|\[|\]|\.|;|,|\|'), + PatternRule(r'operator', r'\+\+|--|==|/=|=<|<|>=|>|=:=|=/=>|-|\+|\*|/|:|#|!]'), NocasePatternRule(r'number', r'\$.|[+-]?\d+#[a-z0-9]+|[+-]?\d+\.\d+|[+-]?\.\d+|[+-]?\d+'), ] +class ErlangTabber(tab.StackTabber): + enterlvl = ('after', 'begin', 'case', 'catch', 'fun', 'if', 'query', 'receive', + 'try', 'when') + def _handle_other_token(self, currlvl, y, i): + token = self.get_token(y, i) + rtoken = self.get_next_right_token(y, i) + ltoken = self.get_next_left_token(y, i) + if token.name == 'eol': + if ltoken is not None and ltoken.name == 'comment': + ltoken = self.get_next_left_token(y, i - 1) + + if ltoken is None: + pass + elif ltoken.name == 'erl_reserved' and ltoken.string in self.enterlvl: + pass + elif ltoken.name == 'delimiter' and ltoken.string in ('.', ';', ',', '->'): + pass + else: + self._pop_while('->') + if not self._empty() and self._peek_name() != '->': + self._pop() + elif token.name == 'delimiter': + if token.string == '->': + if rtoken is None or rtoken.name == 'comment': + level = self.get_curr_level() + self.mode.tabwidth + else: + level = rtoken.x + self._append(token.string, level) + elif token.string == '.': + self.markers = [] + elif token.string == ';': + self._pop() + elif token.name == 'erl_reserved': + if token.string in self.enterlvl: + if rtoken is None or rtoken.name == 'comment': + level = self.get_curr_level() + self.mode.tabwidth + else: + level = rtoken.x + self._append(token.string, level) + elif token.string == 'end': + self._opt_pop('->') + self._pop_unless('->') + return currlvl + class Erlang(mode.Fundamental): modename = 'Erlang' extensions = ['.erl'] tabwidth = 4 - #tabbercls = ErlangTabber + tabbercls = ErlangTabber grammar = ErlangGrammar opentokens = ('delimiter',) opentags = {'(': ')', '[': ']', '{': '}'} diff --git a/tab.py b/tab.py index eed2d23..f97e46f 100644 --- a/tab.py +++ b/tab.py @@ -183,13 +183,28 @@ class StackTabber(Tabber): def _append(self, name, level): self.markers.append(Marker(name, level)) def _peek(self): - return self.markers[-1] + if self.markers: + return self.markers[-1] + else: + return None def _peek_name(self): - return self.markers[-1].name + if self.markers: + return self.markers[-1].name + else: + return None def _peek_level(self): - return self.markers[-1].level + if self.markers: + return self.markers[-1].level + else: + return None def _pop(self): self.markers.pop(-1) + def _pop_while(self, *names): + while self.markers and self.markers[-1].name in names: + self.markers.pop(-1) + def _pop_unless(self, *names): + if self.markers and self.markers[-1].name not in names: + self.markers.pop(-1) def _pop_until(self, *names): while self.markers: if self.markers[-1].name in names: