diff --git a/mode/scala.py b/mode/scala.py index 2bb355e..927bb03 100644 --- a/mode/scala.py +++ b/mode/scala.py @@ -184,12 +184,38 @@ class ScalaXRayBase(Method): return path else: raise Exception("classes.sxr not found") + + def get_pkg_tags(self, w, pkg, base): + return os.path.join(base, pkg.replace('.', '/') + '.scala.txt') def get_public_tags(self, w, base): return os.path.join(base, 'public-tags') + + def term_def_lookup(self, w): + pkg = self.find_pkg(w) + base = self.get_sxr_dir(w) + tags = self.get_public_tags + + def type_def_lookup(self, t, w): + base = self.get_sxr_dir(w) + tags = self.get_public_tags(w, base) + f = open(tags, 'r') + for line in f: + toks = line.split() + if toks[0] != 'type': continue + if toks[1] != t: continue + path = toks[2] + n = int(toks[4]) + return (path, n) + return (None, None) + def type_lookup(self, n, w): pkg = self.find_pkg(w) base = self.get_sxr_dir(w) - tags = os.path.join(base, pkg.replace('.', '/') + '.scala.txt') + path = w.buffer.path + + r = re.compile('^.*src/main/scala/(.+)$') + m = r.match(path) + tags = os.path.join(base, m.group(1) + '.txt') f = open(tags, 'r') for line in f: @@ -198,7 +224,6 @@ class ScalaXRayBase(Method): j = int(toks[1]) if i <= n and n <= j: return toks[2] - return None class ScalaGetType(ScalaXRayBase): @@ -212,20 +237,52 @@ class ScalaGetType(ScalaXRayBase): n = w.cursor_byte_offset() t = self.type_lookup(n, w) - if t: - if w.application.config['scala.type-abbrev']: - t = self.type_re.sub(lambda m: m.group(1), t) - #t = t.replace(')', ') => ') - t = self.ret_re.sub(') => ', t) - t = t.replace(': ', ':') - t = t.replace(',', ', ') - w.set_error(t) - else: + if not t: w.set_error('%s has unknown type' % word) + return + + if w.application.config['scala.type-abbrev']: + t = self.type_re.sub(lambda m: m.group(1), t) + #t = t.replace(')', ') => ') + t = self.ret_re.sub(') => ', t) + t = t.replace(': ', ':') + t = t.replace(',', ', ') + w.set_error(t) class ScalaGotoDefinition(ScalaXRayBase): + generic_re = re.compile('\[.+\]') def _execute(self, w, **vargs): - w.set_error('borken') + word = w.get_token().string + if word is None or word.strip() == "": + w.set_error('no word selected') + return + + n = w.cursor_byte_offset() + t = self.type_lookup(n, w) + if not t: + w.set_error('%s has unknown type' % word) + return + + # remove generics + t = self.generic_re.sub('', t) + + path, n = self.type_def_lookup(t, w) + if not path: + w.set_error('%s not found' % t) + return + + b = w.buffer + a = w.application + b2 = a.open_path(path) + a.switch_buffer(b2) + + if b == b2: + a.methods['goto-char'].execute(w, charno=n - 1) + a.methods['center-view'].execute(w) + else: + a.methods['goto-char'].execute(b2.windows[0], charno=n - 1) + a.methods['center-view'].execute(b2.windows[0]) + w.set_error('opening %s...' % path) # white is for delimiters, operators, numbers default = ('default', 'default') @@ -265,7 +322,7 @@ class Scala(Fundamental): tabbercls = ScalaTabber grammar = ScalaGrammar commentc = '//' - actions = [ScalaStart, ScalaDocBrowse, ScalaDocLookup, ScalaGetType] + actions = [ScalaStart, ScalaDocBrowse, ScalaDocLookup, ScalaGetType, ScalaGotoDefinition] opentokens = ('delimiter', 'sub.start', 'sub.sub.start', 'sub.sub.sub.start') opentags = {'(': ')', '[': ']', '{': '}'} closetokens = ('delimiter', 'sub.end', 'sub.sub.end', 'sub.sub.sub.end') @@ -303,6 +360,7 @@ class Scala(Fundamental): _bindings = { 'scala-get-type': ('M-,',), + 'scala-goto-definition': ('C-c ,',), 'close-paren': (')',), 'close-brace': ('}',), 'close-bracket': (']',),