parent
b99a73988e
commit
0806e467fe
|
@ -0,0 +1,127 @@
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from stat import ST_MTIME
|
||||||
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
|
class CtagsRunError(Exception): pass
|
||||||
|
class CtagsParseError(Exception): pass
|
||||||
|
|
||||||
|
# ctags --languages=... -R -excmd=number
|
||||||
|
|
||||||
|
class TagManager(object):
|
||||||
|
lang = None
|
||||||
|
prune = set(['SCCS', 'RCS', 'CVS', '.svn', '.hg', '.git', '.bzr'])
|
||||||
|
exts = set()
|
||||||
|
|
||||||
|
def __init__(self, base='.'):
|
||||||
|
self.db = None
|
||||||
|
self.base = base
|
||||||
|
self.path = os.path.join(self.base, 'tags')
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def has(self, name):
|
||||||
|
return name in self.db.tags
|
||||||
|
|
||||||
|
def get(self, name):
|
||||||
|
return self.db.tags.get(name, [])
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if self.is_outdated():
|
||||||
|
self.generate()
|
||||||
|
self.db = Ctags(self.path)
|
||||||
|
self.db.parse()
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
args = ['ctags', '-f', self.path, '-L-', '--excmd=number']
|
||||||
|
if self.lang:
|
||||||
|
args.append('--language-force=%s' % self.lang)
|
||||||
|
|
||||||
|
pipe = Popen(args, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
|
||||||
|
indata = '\n'.join(self.get_paths()) + '\n'
|
||||||
|
outdata = pipe.communicate(indata)
|
||||||
|
if pipe.returncode != 0:
|
||||||
|
raise CtagsRunError("%r: %r" % (args, outdata))
|
||||||
|
|
||||||
|
def get_paths(self):
|
||||||
|
return list(self._walk())
|
||||||
|
|
||||||
|
def is_outdated(self):
|
||||||
|
if not os.path.exists(self.path):
|
||||||
|
return True
|
||||||
|
mtime = os.stat(self.path)[ST_MTIME]
|
||||||
|
itr = self._walk(mtime)
|
||||||
|
try:
|
||||||
|
itr.next()
|
||||||
|
return True
|
||||||
|
except StopIteration:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _walk(self, mtime=0):
|
||||||
|
paths = []
|
||||||
|
for root, dirs, files in os.walk(self.base):
|
||||||
|
for d in dirs:
|
||||||
|
if d in self.prune:
|
||||||
|
dirs.remove(d)
|
||||||
|
for f in files:
|
||||||
|
path = os.path.join(root, f)
|
||||||
|
if not self._match(path):
|
||||||
|
continue
|
||||||
|
elif os.stat(path)[ST_MTIME] < mtime:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
yield os.path.join(root, f)
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
def _match(self, path):
|
||||||
|
return os.path.splitext(path)[1] in self.exts
|
||||||
|
|
||||||
|
class Ctags(object):
|
||||||
|
line_re = re.compile(r'^(.+?)\t(.+?)\t(.+?);"(.+)$')
|
||||||
|
|
||||||
|
def __init__(self, path):
|
||||||
|
self.path = path
|
||||||
|
self.records = []
|
||||||
|
self.tags = {}
|
||||||
|
|
||||||
|
def get(self, tag):
|
||||||
|
return self.tags.get(tag, [])
|
||||||
|
|
||||||
|
def parse(self):
|
||||||
|
for line in open(self.path, 'r'):
|
||||||
|
if line.startswith('!'): continue
|
||||||
|
|
||||||
|
m = self.line_re.match(line)
|
||||||
|
if not m: raise CtagsParseError("%r" % line)
|
||||||
|
|
||||||
|
name, path, ex, _ = m.groups()
|
||||||
|
self.add(CtagRecord(name, path, ex))
|
||||||
|
|
||||||
|
def add(self, r):
|
||||||
|
self.records.append(r)
|
||||||
|
self.tags.setdefault(r.name, [])
|
||||||
|
self.tags[r.name].append(r)
|
||||||
|
|
||||||
|
class CtagRecord(object):
|
||||||
|
def __init__(self, name, path, ex):
|
||||||
|
if not ex.isdigit():
|
||||||
|
raise Exception("excmd %r unsupported; use --excmd=number" % ex)
|
||||||
|
self.name = name
|
||||||
|
self.path = path
|
||||||
|
self.line = int(ex)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "CtagRecord(%r, %r, %d)" % (self.name, self.path, self.line)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
ctags = Ctags(sys.argv[1])
|
||||||
|
ctags.parse()
|
||||||
|
|
||||||
|
if len(sys.argv) > 2:
|
||||||
|
print "records for %r:" % sys.argv[2]
|
||||||
|
for r in ctags.get(sys.argv[2]):
|
||||||
|
print r
|
||||||
|
else:
|
||||||
|
pprint(ctags.records)
|
40
etags.py
40
etags.py
|
@ -9,35 +9,33 @@ import re
|
||||||
from stat import ST_MTIME
|
from stat import ST_MTIME
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
|
|
||||||
class EtagsRunError(Exception): pass
|
class EtagsRunError(Exception): pass
|
||||||
|
|
||||||
|
|
||||||
class TagManager(object):
|
class TagManager(object):
|
||||||
lang = None
|
lang = None
|
||||||
prune = set(['SCCS', 'RCS', 'CVS', '.svn', '.hg', '.git', '.bzr'])
|
prune = set(['SCCS', 'RCS', 'CVS', '.svn', '.hg', '.git', '.bzr'])
|
||||||
exts = set()
|
exts = set()
|
||||||
|
|
||||||
def __init__(self, base='.'):
|
def __init__(self, base='.'):
|
||||||
self.etags = None
|
self.db = None
|
||||||
self.base = base
|
self.base = base
|
||||||
self.path = os.path.join(self.base, 'TAGS')
|
self.path = os.path.join(self.base, 'TAGS')
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def has(self, name):
|
def has(self, name):
|
||||||
return name in self.etags.tag_map
|
return name in self.db.tags
|
||||||
|
|
||||||
def get(self, name):
|
def get(self, name):
|
||||||
return self.etags.tag_map.get(name, [])
|
return self.db.get(name, [])
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
return self.etags.record_list
|
return self.db.records
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
if self.is_outdated():
|
if self.is_outdated():
|
||||||
self.run()
|
self.run()
|
||||||
self.etags = Etags(self.path)
|
self.db = Etags(self.path)
|
||||||
self.etags.parse()
|
self.db.parse()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
lf = '--language-force=%s' % self.lang
|
lf = '--language-force=%s' % self.lang
|
||||||
|
@ -86,19 +84,16 @@ class Etags(object):
|
||||||
def __init__(self, fname=None):
|
def __init__(self, fname=None):
|
||||||
self.fname = fname
|
self.fname = fname
|
||||||
self.rawdata = None
|
self.rawdata = None
|
||||||
self.record_list = []
|
self.records = []
|
||||||
self.tag_map = {}
|
self.tags = {}
|
||||||
|
|
||||||
def _load(self):
|
def _load(self):
|
||||||
fd = file(self.fname, 'r')
|
fd = file(self.fname, 'r')
|
||||||
self.rawdata = fd.read()
|
self.rawdata = fd.read()
|
||||||
fd.close()
|
fd.close()
|
||||||
|
|
||||||
def lookup(self, tag):
|
def get(self, name):
|
||||||
return self.tag_map[tag]
|
return self.tags.get(name, [])
|
||||||
|
|
||||||
def __getitem__(self, tag):
|
|
||||||
return self.lookup(tag)
|
|
||||||
|
|
||||||
def parse(self, fname=None):
|
def parse(self, fname=None):
|
||||||
"""
|
"""
|
||||||
|
@ -116,21 +111,20 @@ class Etags(object):
|
||||||
i = self._parse_block(data, i+2)
|
i = self._parse_block(data, i+2)
|
||||||
|
|
||||||
def _add_record(self, record):
|
def _add_record(self, record):
|
||||||
self.record_list.append(record)
|
self.records.append(record)
|
||||||
name = record.name
|
name = record.name
|
||||||
if name is None:
|
if name is None:
|
||||||
return
|
return
|
||||||
self.tag_map.setdefault(name, [])
|
self.tags.setdefault(name, [])
|
||||||
self.tag_map[name].append(record)
|
self.tags[name].append(record)
|
||||||
|
|
||||||
def _parse_block(self, data, i):
|
def _parse_block(self, data, i):
|
||||||
n = data[i:].find('\n') + i
|
n = data[i:].find('\n') + i
|
||||||
l = data[i:n]
|
l = data[i:n]
|
||||||
try:
|
try:
|
||||||
filename, size = l.split(',')
|
filename, size = l.split(',')
|
||||||
except ValueError:
|
except ValueError, e:
|
||||||
print i
|
raise Exception("parse failed(%s): %r %r %r" % (i, l, e, data))
|
||||||
raise
|
|
||||||
size = int(size)
|
size = int(size)
|
||||||
subblock = data[n+1:n+size+1]
|
subblock = data[n+1:n+size+1]
|
||||||
|
|
||||||
|
@ -185,6 +179,6 @@ if __name__ == '__main__':
|
||||||
etags.parse()
|
etags.parse()
|
||||||
|
|
||||||
if len(sys.argv) > 2:
|
if len(sys.argv) > 2:
|
||||||
print etags[sys.argv[2]]
|
print etags.get(sys.argv[2])
|
||||||
else:
|
else:
|
||||||
pprint(etags.record_list)
|
pprint(etags.records)
|
||||||
|
|
|
@ -177,7 +177,7 @@ class GitBlame(VcBlame):
|
||||||
# rev, user, date, [time], [timezone], [date-str], content
|
# rev, user, date, [time], [timezone], [date-str], content
|
||||||
num_fields = 3
|
num_fields = 3
|
||||||
#line_re = re.compile(r'^\^*([0-9a-f]+) \(([a-zA-Z0-9_ ]+|Not Committed Yet) +([-0-9]+) [:0-9]+ +[-\+]\d{4} +\d+\) (.*)\n$')
|
#line_re = re.compile(r'^\^*([0-9a-f]+) \(([a-zA-Z0-9_ ]+|Not Committed Yet) +([-0-9]+) [:0-9]+ +[-\+]\d{4} +\d+\) (.*)\n$')
|
||||||
line_re = re.compile(r'^\^*([0-9a-f]+) +(.+) +\(([a-zA-Z0-9_ ]+|Not Committed Yet) +([-0-9]+) [:0-9]+ +[-\+]\d{4} +\d+\) (.*)\n$')
|
line_re = re.compile(r'^\^*([0-9a-f]+) +(.*)\((.+) +([-0-9]+) [:0-9]+ +[-\+]\d{4} +\d+\) (.*)\n$')
|
||||||
prefix_fmt = '[g:d:*]%*s [c:d:*]%-*s [b:d:*]%*s[d:d:*]'
|
prefix_fmt = '[g:d:*]%*s [c:d:*]%-*s [b:d:*]%*s[d:d:*]'
|
||||||
pretest_err_msg = 'Git is not installed'
|
pretest_err_msg = 'Git is not installed'
|
||||||
_is_method = True
|
_is_method = True
|
||||||
|
|
|
@ -31,7 +31,7 @@ class TagBase(Method):
|
||||||
if not cwd.endswith('/'):
|
if not cwd.endswith('/'):
|
||||||
cwd += '/'
|
cwd += '/'
|
||||||
|
|
||||||
tpls = [(r.path.replace(cwd, ''), r.line, r.defn) for r in records]
|
tpls = [(r.path.replace(cwd, ''), r.line, r.name) for r in records]
|
||||||
data = '\n'.join(['%s:%d:%s' % tpl for tpl in tpls]) + '\n'
|
data = '\n'.join(['%s:%d:%s' % tpl for tpl in tpls]) + '\n'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class SearchTags(TagBase):
|
||||||
if base is None:
|
if base is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
records = [r for r in m.etags.record_list if query in r.name]
|
records = [r for r in m.etags.records if query in r.name]
|
||||||
|
|
||||||
if len(records) == 0:
|
if len(records) == 0:
|
||||||
w.set_error('no records matched query %r' % query)
|
w.set_error('no records matched query %r' % query)
|
||||||
|
@ -94,7 +94,7 @@ class InitTags(Method):
|
||||||
m = w.mode.tagcls(base)
|
m = w.mode.tagcls(base)
|
||||||
w.application.state['tags'][base] = m
|
w.application.state['tags'][base] = m
|
||||||
w.buffer.settings[w.mode.name]['tag-base'] = base
|
w.buffer.settings[w.mode.name]['tag-base'] = base
|
||||||
ntag, nrec = len(m.etags.tag_map), len(m.etags.record_list)
|
ntag, nrec = len(m.db.tags), len(m.db.records)
|
||||||
w.set_error('%s: loaded %d names (%d records)' % (m.path, ntag, nrec))
|
w.set_error('%s: loaded %d names (%d records)' % (m.path, ntag, nrec))
|
||||||
|
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
|
@ -112,7 +112,7 @@ class InitTags(Method):
|
||||||
m = a.state['tags'][t]
|
m = a.state['tags'][t]
|
||||||
if m.is_outdated():
|
if m.is_outdated():
|
||||||
m.update()
|
m.update()
|
||||||
ntag, nrec = len(m.etags.tag_map), len(m.etags.record_list)
|
ntag, nrec = len(m.db.tags), len(m.db.records)
|
||||||
fmt = '%s: updated %d names (%d records)'
|
fmt = '%s: updated %d names (%d records)'
|
||||||
w.set_error(fmt % (m.path, ntag, nrec))
|
w.set_error(fmt % (m.path, ntag, nrec))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -58,6 +58,7 @@ MarkdownGrammar.rules = [
|
||||||
RegionRule('md.bold', r'\*', MarkdownGrammar, r'\*'),
|
RegionRule('md.bold', r'\*', MarkdownGrammar, r'\*'),
|
||||||
RegionRule('md.tt', r'`', MarkdownGrammar, r'`'),
|
RegionRule('md.tt', r'`', MarkdownGrammar, r'`'),
|
||||||
|
|
||||||
|
PatternRule('md.escaped', r'\\.'),
|
||||||
PatternRule('md.word', r'[a-zA-Z\'"\-]+'),
|
PatternRule('md.word', r'[a-zA-Z\'"\-]+'),
|
||||||
|
|
||||||
PatternRule('spaces', '\s+'),
|
PatternRule('spaces', '\s+'),
|
||||||
|
|
|
@ -11,6 +11,8 @@ import urllib2
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
#from etags import TagManager
|
||||||
|
from ctags import TagManager
|
||||||
|
|
||||||
chr1 = '[a-zA-Z_]'
|
chr1 = '[a-zA-Z_]'
|
||||||
chr2 = '[a-zA-Z_0-9]'
|
chr2 = '[a-zA-Z_0-9]'
|
||||||
|
@ -22,12 +24,32 @@ NestedCommentGrammar.rules = [
|
||||||
PatternRule('data', r'(?:[^\*]|\*(?!/))+'),
|
PatternRule('data', r'(?:[^\*]|\*(?!/))+'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
class String3Grammar(Grammar):
|
||||||
|
rules = [
|
||||||
|
PatternRule('data', r'[^"]+'),
|
||||||
|
]
|
||||||
|
|
||||||
class StringGrammar(Grammar):
|
class StringGrammar(Grammar):
|
||||||
rules = [
|
rules = [
|
||||||
PatternRule('escaped', r"\\u[0-9A-Fa-f]{4}|\\[0-7]{1,3}|\\[btnfr\"'\\]"),
|
PatternRule('escaped', r"\\u[0-9A-Fa-f]{4}|\\[0-7]{1,3}|\\[btnfr\"'\\]"),
|
||||||
PatternRule('data', r'[^\\"]+'),
|
PatternRule('data', r'[^\\"]+'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
class IString3Grammar(Grammar):
|
||||||
|
rules = [
|
||||||
|
PatternRule('interp', r'\$[a-zA-Z0-9_]+'),
|
||||||
|
PatternRule('escaped', r'\$\$'),
|
||||||
|
PatternRule('data', r'[^$"]+'),
|
||||||
|
]
|
||||||
|
|
||||||
|
class IStringGrammar(Grammar):
|
||||||
|
rules = [
|
||||||
|
PatternRule('interp', r'\$[a-zA-Z0-9_]+'),
|
||||||
|
PatternRule('escaped', r'\$\$'),
|
||||||
|
PatternRule('escaped', r"\\u[0-9A-Fa-f]{4}|\\[0-7]{1,3}|\\[btnfr\"'\\]"),
|
||||||
|
PatternRule('data', r'[^\\$"]+'),
|
||||||
|
]
|
||||||
|
|
||||||
class SubTypeGrammar(Grammar): pass
|
class SubTypeGrammar(Grammar): pass
|
||||||
SubTypeGrammar.rules = [
|
SubTypeGrammar.rules = [
|
||||||
RegionRule('sub', r'\[', SubTypeGrammar, r'\]'),
|
RegionRule('sub', r'\[', SubTypeGrammar, r'\]'),
|
||||||
|
@ -49,7 +71,7 @@ class ScalaGrammar(Grammar):
|
||||||
'delimiter', 'scala.type'),
|
'delimiter', 'scala.type'),
|
||||||
PatternMatchRule('x', r'(?<=[a-zA-Z0-9_ ])(:)( +)([a-zA-Z0-9_]+)',
|
PatternMatchRule('x', r'(?<=[a-zA-Z0-9_ ])(:)( +)([a-zA-Z0-9_]+)',
|
||||||
'delimiter', 'spaces', 'scala.type'),
|
'delimiter', 'spaces', 'scala.type'),
|
||||||
PatternMatchRule('x', r'(?<=[^a-zA-Z0-9_])(new|extends|with)( +)([^{}0-9:\[\(\n\t ][^:\[\(\n\t ]*)',
|
PatternMatchRule('x', r'(?<=[^a-zA-Z0-9_])(new|extends|with)( +)([^{}()0-9:\[\n\t ][^:\[\]{}()\n\t ]*)',
|
||||||
'scala.reserved', 'spaces', 'scala.type'),
|
'scala.reserved', 'spaces', 'scala.type'),
|
||||||
|
|
||||||
# class, object, and trait
|
# class, object, and trait
|
||||||
|
@ -58,7 +80,9 @@ class ScalaGrammar(Grammar):
|
||||||
PatternRule('scala.trait', '(?<=(?<![a-zA-Z0-9_])trait )[^0-9:\[\](){}\n\t ][^:\[\]{}()\n\t ]*'),
|
PatternRule('scala.trait', '(?<=(?<![a-zA-Z0-9_])trait )[^0-9:\[\](){}\n\t ][^:\[\]{}()\n\t ]*'),
|
||||||
|
|
||||||
# method names
|
# method names
|
||||||
PatternRule('scala.def', '(?<=(?<![a-zA-Z0-9_])def )[^0-9:\[\](){}\n\t ][^:\[\]{}()\n\t ]*'),
|
###PatternRule('scala.def', '(?<=(?<![a-zA-Z0-9_])def )[^0-9\[\](){}\n\t ][^\[\]{}()\n\t ]*(?=[:\[\{\( \t\n])'),
|
||||||
|
PatternRule('scala.def', '(?<=(?<![a-zA-Z0-9_])def )[a-zA-Z_][a-zA-Z0-9_]*[^a-zA-Z0-9_\[\]{}()\n\t ]*(?=[:\[{( \t\n])'),
|
||||||
|
PatternRule('scala.def', '(?<=(?<![a-zA-Z0-9_])def )[^a-zA-Z0-9_\[\]{}()\n\t ]+(?=[:\[{( \t\n])'),
|
||||||
|
|
||||||
# package names
|
# package names
|
||||||
PatternRule('scala.package', '(?<=(?<![a-zA-Z0-9_])package )[a-zA-Z0-9_.]+'),
|
PatternRule('scala.package', '(?<=(?<![a-zA-Z0-9_])package )[a-zA-Z0-9_.]+'),
|
||||||
|
@ -75,18 +99,20 @@ class ScalaGrammar(Grammar):
|
||||||
PatternRule('eol', r'\n'),
|
PatternRule('eol', r'\n'),
|
||||||
|
|
||||||
# these are some constants that show up a lot
|
# these are some constants that show up a lot
|
||||||
PatternRule('scala.pseudo', '(?:true|null|false)(?!%s)' % word),
|
PatternRule('scala.pseudo', '(?:true|null|false)(?!%s)' % chr2),
|
||||||
|
|
||||||
PatternRule('scala.reserved', '(?:yield|with|while|var|val|type|true|try|trait|throw|this|super|sealed|return|protected|private|package|override|object|null|new|match|macro|lazy|import|implicit|if|forSome|for|finally|final|false|extends|else|do|def|class|catch|case object|case class|case|abstract)(?!%s)' % word),
|
PatternRule('scala.reserved', '(?:yield|with|while|var|val|type|true|try|trait|throw|this|super|sealed|return|protected|private|package|override|object|null|new|match|macro|lazy|import|implicit|if|forSome|for|finally|final|false|extends|else|do|def|class|catch|case object|case class|case|abstract)(?!%s)' % chr2),
|
||||||
|
|
||||||
PatternRule('scala.float', r'[0-9]+\.[0-9]*[Ff]?'), # FIXME
|
PatternRule('scala.float', r'[0-9]+\.[0-9]*(?:[eE][0-9]+)?[FfDd]?'), # FIXME
|
||||||
|
|
||||||
PatternRule('scala.integer', '(?:0|[1-9])[0-9]*[Ll]?'),
|
PatternRule('scala.integer', '(?:0|[1-9])[0-9]*[Ll]?'),
|
||||||
PatternRule('scala.integer', '0x[0-9A-Fa-f]+[Ll]?'),
|
PatternRule('scala.integer', '0x[0-9A-Fa-f]+[Ll]?'),
|
||||||
PatternRule('scala.integer', '0[0-7]+[Ll]?'),
|
PatternRule('scala.integer', '0[0-7]+[Ll]?'),
|
||||||
|
|
||||||
PatternRule('scala.char', r"'(?:[^'\\]|\\u[0-9A-Fa-f]{4}|\\[0-7]{1,3}|\\[btnfr\"'\\])'"),
|
PatternRule('scala.char', r"'(?:[^'\\]|\\u[0-9A-Fa-f]{4}|\\[0-7]{1,3}|\\[btnfr\"'\\])'"),
|
||||||
RegionRule('scala.string', '"""', Grammar, '"""+'),
|
RegionRule('scala.string', '[a-zA-Z_][a-zA-Z0-9_]*"""', IString3Grammar, '"""+'),
|
||||||
|
RegionRule('scala.string', '[a-zA-Z_][a-zA-Z0-9_]*"', IStringGrammar, '"'),
|
||||||
|
RegionRule('scala.string', '"""', String3Grammar, '"""+'),
|
||||||
RegionRule('scala.string', '"', StringGrammar, '"'),
|
RegionRule('scala.string', '"', StringGrammar, '"'),
|
||||||
PatternRule('scala.symbol', "'[a-zA-Z_][a-zA-Z0-9_]*"),
|
PatternRule('scala.symbol', "'[a-zA-Z_][a-zA-Z0-9_]*"),
|
||||||
|
|
||||||
|
@ -332,6 +358,10 @@ class ScalaShowClasspath(ScalaSetClasspath):
|
||||||
w.set_error(w.application.config.get('scala.cp'))
|
w.set_error(w.application.config.get('scala.cp'))
|
||||||
w.application.config['scala.cp'].extend(vargs['lib'].split(':'))
|
w.application.config['scala.cp'].extend(vargs['lib'].split(':'))
|
||||||
|
|
||||||
|
class ScalaTagManager(TagManager):
|
||||||
|
lang = 'scala'
|
||||||
|
exts = set(['.scala', '.sbt'])
|
||||||
|
|
||||||
# white is for delimiters, operators, numbers
|
# white is for delimiters, operators, numbers
|
||||||
default = ('default', 'default')
|
default = ('default', 'default')
|
||||||
|
|
||||||
|
@ -365,9 +395,10 @@ hi_blue = ('blue225', 'default')
|
||||||
|
|
||||||
class Scala(Fundamental):
|
class Scala(Fundamental):
|
||||||
name = 'Scala'
|
name = 'Scala'
|
||||||
extensions = ['.scala']
|
extensions = ['.scala', '.sbt']
|
||||||
tabwidth = 2
|
tabwidth = 2
|
||||||
tabbercls = ScalaTabber
|
tabbercls = ScalaTabber
|
||||||
|
tagcls = ScalaTagManager
|
||||||
grammar = ScalaGrammar
|
grammar = ScalaGrammar
|
||||||
commentc = '//'
|
commentc = '//'
|
||||||
|
|
||||||
|
@ -405,6 +436,7 @@ class Scala(Fundamental):
|
||||||
'scala.def': hi_blue,
|
'scala.def': hi_blue,
|
||||||
'scala.type': hi_magenta,
|
'scala.type': hi_magenta,
|
||||||
|
|
||||||
|
'scala.string.interp': hi_yellow,
|
||||||
}
|
}
|
||||||
|
|
||||||
_bindings = {
|
_bindings = {
|
||||||
|
|
11
tab.py
11
tab.py
|
@ -413,9 +413,11 @@ class StackTabber2(Tabber):
|
||||||
if all_closed:
|
if all_closed:
|
||||||
self._save_curr_level()
|
self._save_curr_level()
|
||||||
|
|
||||||
|
at_eol = i + start == end
|
||||||
|
|
||||||
# if we need to end at eof and we're at the EOF and we have a control
|
# 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.
|
# token, then we need to pop it.
|
||||||
if self.end_at_eof and i == end - start and self._match('control'):
|
if self.end_at_eof and at_eol and self._match('control'):
|
||||||
self.stack.pop()
|
self.stack.pop()
|
||||||
|
|
||||||
# if we are in a control test and this closes the test, then we need to
|
# if we are in a control test and this closes the test, then we need to
|
||||||
|
@ -424,6 +426,11 @@ class StackTabber2(Tabber):
|
||||||
t.string in self.close_test_tokens.get(t.name, empty):
|
t.string in self.close_test_tokens.get(t.name, empty):
|
||||||
self.stack[-1].name = 'control'
|
self.stack[-1].name = 'control'
|
||||||
|
|
||||||
|
# FIXME: we shouldn't be getting the type from the language
|
||||||
|
if (self.end_at_eof and at_eol and self.stack and
|
||||||
|
self.stack[-1].type_ == 'else'):
|
||||||
|
self._pop_while('continue', 'control', 'pre-control')
|
||||||
|
|
||||||
# if we don't want implicit continuation, return.
|
# if we don't want implicit continuation, return.
|
||||||
if self.end_at_eof:
|
if self.end_at_eof:
|
||||||
return
|
return
|
||||||
|
@ -531,7 +538,7 @@ class StackTabber2(Tabber):
|
||||||
if i == start:
|
if i == start:
|
||||||
self._save_curr_level()
|
self._save_curr_level()
|
||||||
self._pop_while('continue');
|
self._pop_while('continue');
|
||||||
self._append_unless('pre-control', name, self._get_next_level(), y)
|
self._append_unless('pre-control', s, self._get_next_level(), y)
|
||||||
elif s in self.case_tokens.get(name, empty):
|
elif s in self.case_tokens.get(name, empty):
|
||||||
if top is not None and top.name in ['case', 'case-eol']:
|
if top is not None and top.name in ['case', 'case-eol']:
|
||||||
self._pop('case', 'case-eol')
|
self._pop('case', 'case-eol')
|
||||||
|
|
Loading…
Reference in New Issue