From c494da8b4492ee9bd05d6bb39877c8a3d65276ab Mon Sep 17 00:00:00 2001 From: Erik Osheim Date: Thu, 12 Aug 2010 00:01:47 -0400 Subject: [PATCH] adding more powerful support for single-statement control structures to support scala's lack of semicolons --HG-- branch : pmacs2 --- mode/scala.py | 16 +++++++++++++++- tab.py | 29 ++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/mode/scala.py b/mode/scala.py index 6519c22..d8a4ad3 100644 --- a/mode/scala.py +++ b/mode/scala.py @@ -64,7 +64,21 @@ class ScalaTabber(StackTabber2): is_ignored_tokens = set(('spaces', 'eol', 'comment', 'comment.start', 'comment.data', 'comment.null', 'comment.end')) is_indent_tokens = set(('spaces',)) - def is_base(self, y): return y == 0 + def _is_base(self, y): + # the first line is always safe + if y == 0: return True + + # if there are no tokens we don't really have any info + tokens = self._get_tokens(y) + if not tokens: return False + + # if it looks like a top-level class, object or function, then say ok + t = tokens[0] + if t.fqmatchs('scala.reserved', ('class', 'object', 'def')): + return True + + # the default is to assume no + return False class Scala(Fundamental): name = 'Scala' diff --git a/tab.py b/tab.py index a77470f..175be0b 100644 --- a/tab.py +++ b/tab.py @@ -247,6 +247,8 @@ class StackTabber2(Tabber): close_tokens = {'delimiter': set(['}', ')', ']'])} open_scope_tokens = {'delimiter': set(['{'])} close_scope_tokens = {'delimiter': set(['}'])} + open_test_tokens = {'delimiter': set(['('])} + close_test_tokens = {'delimiter': set([')'])} control_tokens = {'keyword': set(['if', 'else', 'while', 'do', 'for'])} end_at_eof = True end_at_tokens = {} @@ -383,6 +385,17 @@ class StackTabber2(Tabber): if i == 0: self._save_curr_level() + # if we need to end at eof and we're at the EOF and we have a control + # token, then we need to pop it. + if self.end_at_eof and i == end - start and self._match('control'): + self.stack.pop() + + # if we are in a control test and this closes the test, then we need to + # mark that we're out of the control test. + if self._match('in-control') and \ + t.string in self.close_test_tokens.get(t.name, set()): + self.stack[-1].name = 'control' + # if we don't want implicit continuation, return. if self.end_at_eof: return @@ -408,9 +421,18 @@ class StackTabber2(Tabber): def _is_open_token(self, t): return t.string in self.open_tokens.get(t.name, set()) + def _handle_open_token(self, y, tokens, start, end, i, t): - if i == 0 and self.stack and self.stack[-1].name == 'continue': - self.stack.pop() + if self.stack: + if i == 0 and self._match('continue'): + self.stack.pop() + + # if we have seen a control token, and we are starting a test, then + # need to note that we've entered the test stanza. + if self._match('pre-control') and \ + t.string in self.open_test_tokens.get(t.name, set()): + self.stack[-1].name = 'in-control' + if t.string in self.open_scope_tokens.get(t.name, set()): self._pop('continue', 'control') if i == 0 and t.string in self.open_scope_tokens.get(t.name, set()): @@ -472,4 +494,5 @@ class StackTabber2(Tabber): if i == start: self._save_curr_level() self._pop_while('continue'); - self._append_unless('control', name, self._get_next_level(), y) + #self._append_unless('control', name, self._get_next_level(), y) + self._append_unless('pre-control', name, self._get_next_level(), y)