parent
c3e1f583a4
commit
87e96d3ed1
|
@ -170,7 +170,7 @@ class Application(object):
|
|||
mode.install(self)
|
||||
names = (
|
||||
'blame', 'c', 'console', 'consolemini', 'css', 'diff', 'dir',
|
||||
'elisp', 'hex', 'html', 'java', 'javascript', 'lisp', 'make',
|
||||
'elisp', 'hex', 'html', 'java', 'javap', 'javascript', 'lisp', 'make',
|
||||
'mini', 'mutt', 'nasm', 'ocaml', 'perl', 'python', 'replace', 'rst',
|
||||
'scheme', 'search', 'sh', 'sql', 'tt', 'text', 'text2', 'which',
|
||||
'xml', 'cheetah', 'colortext', 'latex', 'insertmini', 'conf',
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
from mode import Fundamental
|
||||
from lex import Grammar, PatternRule, RegionRule, PatternMatchRule
|
||||
|
||||
name = '[a-zA-Z0-9_$.]+'
|
||||
|
||||
class JavapGrammar(Grammar):
|
||||
rules = [
|
||||
#PatternMatchRule('x', r'^( )(\d+:)([ \t]+)([a-z0-9_]+)',
|
||||
# 'spaces', 'javap.linenum', 'spaces', 'javap.ins'),
|
||||
#PatternMatchRule('x', r'^( )(\d+:)([ \t]+)([a-z0-9_]+)',
|
||||
# 'spaces', 'javap.linenum', 'spaces', 'javap.ins'),
|
||||
#PatternMatchRule('x', r'^( )(\d+:)([ \t]+)([a-z0-9_]+)',
|
||||
# 'spaces', 'javap.linenum', 'spaces', 'javap.ins'),
|
||||
|
||||
PatternMatchRule('x', '^(package)( )(.+)$',
|
||||
'javap.keyword', 'spaces', 'javap.package'),
|
||||
|
||||
PatternRule('javap.keyword', '(?:static|public|protected|private|final|abstract)'),
|
||||
PatternMatchRule('x', '(--class)( +)([^ ]+)',
|
||||
'javap.pseudo', 'spaces', 'javap.type'),
|
||||
PatternMatchRule('x', '(--field)( +)([^ ]+)( +)([^ ]+)',
|
||||
'javap.pseudo', 'spaces', 'javap.type', 'spaces', 'javap.type'),
|
||||
PatternRule('javap.pseudo', '--(?:method|iface|string|field)'),
|
||||
|
||||
PatternMatchRule('x', '([^ ]+)( +)(\()',
|
||||
'javap.type', 'spaces', 'javap.delim'),
|
||||
|
||||
PatternMatchRule('x', '(class|extends|implements)( )([^ ]+)',
|
||||
'javap.keyword', 'spaces', 'javap.type'),
|
||||
|
||||
PatternMatchRule('x', '([^ ]+)( )([^ ]+)( )(\()',
|
||||
'javap.type', 'spaces', 'javap.method', 'spaces', 'javap.delim'),
|
||||
PatternMatchRule('x', '([^ ]+)( )([^ ]+)( )({)(})',
|
||||
'javap.type', 'spaces', 'javap.method', 'spaces', 'javap.delim', 'javap.delim'),
|
||||
PatternMatchRule('x', '([^ ]+)(,)( )',
|
||||
'javap.type', 'javap.delim', 'spaces'),
|
||||
PatternMatchRule('x', '([^ ]+)(\))',
|
||||
'javap.type', 'javap.delim'),
|
||||
|
||||
#PatternMatchRule('x', '(//class )(.+)', 'javap.zcomment', 'javap.class'),
|
||||
#PatternMatchRule('x', '(//InterfaceMethod )([^:]+)(:)(.+)',
|
||||
# 'javap.zcomment', 'javap.method', 'javap.zcomment', 'javap.sig'),
|
||||
#PatternMatchRule('x', '(//Method )([^:]+)(:)(.+)',
|
||||
# 'javap.zcomment', 'javap.method', 'javap.zcomment', 'javap.sig'),
|
||||
|
||||
PatternMatchRule('x', '^( +)(\d+)( +)([^ ]+)',
|
||||
'spaces', 'javap.byte', 'spaces', 'javap.ins'),
|
||||
PatternRule('javap.const', r'#\d+'),
|
||||
PatternRule('javap.int', r'\d+'),
|
||||
|
||||
#PatternRule('javap.zcomment', r'^Compiled from .*$'),
|
||||
#PatternRule('javap.zcomment', r'Code:'),
|
||||
|
||||
#PatternMatchRule('x', r'(class)( )(' + name + ')', 'javap.zkeyword', 'spaces', 'javap.class'),
|
||||
#PatternMatchRule('x', r'(extends)( )(' + name + ')', 'javap.zkeyword', 'spaces', 'javap.class'),
|
||||
#PatternMatchRule('x', r'(public)( )(static)( )(' + name + ')( )(' + name + ')',
|
||||
# 'javap.zkeyword', 'spaces', 'javap.zkeyword', 'spaces',
|
||||
# 'javap.class', 'spaces', 'javap.method'),
|
||||
|
||||
#PatternRule(r'javap.zkeyword', r'(?:static|public|protected|private|extends|class|abstract)'),
|
||||
#PatternRule(r'javap.cls', r'L[^;]+'),
|
||||
#PatternRule(r'javap.cls2', r'B|C|D|F|I|J|S|Z|\['),
|
||||
#PatternRule(r'javap.ins', r'(?<= )\d+:'),
|
||||
#PatternRule(r'javap.class', name),
|
||||
|
||||
PatternRule('spaces', r' +'),
|
||||
PatternRule('eol', r'\n'),
|
||||
]
|
||||
|
||||
|
||||
# white is for delimiters, operators, numbers
|
||||
c_default = ('default', 'default')
|
||||
|
||||
# magenta is for keywords/builtins, translation, globs
|
||||
lo_magenta = ('magenta202', 'default')
|
||||
hi_magenta = ('magenta505', 'default')
|
||||
|
||||
# red is for comments, pods, endblocks
|
||||
lo_red = ('red300', 'default')
|
||||
hi_red = ('red511', 'default')
|
||||
|
||||
# orange are for arrays and hashes
|
||||
hi_orange = ('yellow531', 'default')
|
||||
lo_orange = ('yellow520', 'default')
|
||||
|
||||
# yellow is for scalars and prototypes
|
||||
hi_yellow = ('yellow551', 'default')
|
||||
lo_yellow = ('yellow330', 'default')
|
||||
|
||||
# green is for strings and hash keys
|
||||
lo_green = ('green030', 'default')
|
||||
hi_green = ('green050', 'default')
|
||||
|
||||
# cyan is for quotes, evals, regexes, subs
|
||||
lo_cyan = ('cyan033', 'default')
|
||||
hi_cyan = ('cyan155', 'default')
|
||||
|
||||
# blue is unused
|
||||
lo_blue = ('blue113', 'default')
|
||||
hi_blue = ('blue225', 'default')
|
||||
|
||||
class Javap(Fundamental):
|
||||
name = 'Javap'
|
||||
grammar = JavapGrammar()
|
||||
colors = {
|
||||
###'javap.string': ('green', 'default'),
|
||||
##'javap.label': ('blue', 'default', 'bold'),
|
||||
#'javap.class': ('cyan', 'default', 'bold'),
|
||||
'javap.package': hi_yellow,
|
||||
'javap.type': hi_cyan,
|
||||
'javap.method': hi_blue,
|
||||
##'javap.abbrev': ('green', 'default', 'bold'),
|
||||
#'javap.name': ('yellow', 'default', 'bold'),
|
||||
#'javap.linenum': ('green', 'default', 'bold'),
|
||||
'javap.byte': lo_orange,
|
||||
'javap.ins': hi_orange,
|
||||
#'javap.cls': ('cyan', 'default', 'bold'),
|
||||
#'javap.int': ('green', 'default', 'bold'),
|
||||
'javap.const': hi_yellow,
|
||||
'javap.keyword': hi_magenta,
|
||||
'javap.pseudo': hi_magenta,
|
||||
}
|
||||
_bindings = {
|
||||
'ipython-start': ('M-e',),
|
||||
}
|
||||
|
||||
install = Javap.install
|
304
mode/scala.py
304
mode/scala.py
|
@ -10,6 +10,7 @@ import default
|
|||
import urllib2
|
||||
import os
|
||||
import re
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
|
||||
chr1 = '[a-zA-Z_]'
|
||||
chr2 = '[a-zA-Z_0-9]'
|
||||
|
@ -131,164 +132,172 @@ class ScalaStart(Interact):
|
|||
def _execute(self, w, **vargs):
|
||||
Interact._execute(self, w, bname='*Scala*', cmd='scala')
|
||||
|
||||
class ScalaDocBrowse(Method):
|
||||
def _execute(self, w, **vargs):
|
||||
a = w.application
|
||||
url = a.config['scala.api']
|
||||
Interact().execute(w, bname='*Scala-Doc*', cmd='links "%s"' % url)
|
||||
class ScalaDecompile(Method):
|
||||
args = [arg('classname', t='string', p='Class: ', h='The class to decompile')]
|
||||
|
||||
class ScalaDocLookup(Method):
|
||||
args = [arg('name', t='string', p='Name: ', dv=default.current_word,
|
||||
ld=True, h='The Scala name to get help on')]
|
||||
def _get_path(self, w, name):
|
||||
return w.application.getpath('cache', 'scala', name)
|
||||
def _get_url(self, w, name, url):
|
||||
path = self._get_path(w, name)
|
||||
w.application.mkdirs('cache', 'scala')
|
||||
ins_re = re.compile(r'^(\d+):')
|
||||
|
||||
if not os.path.exists(path):
|
||||
open(path, 'w').write(urllib2.urlopen(url).read())
|
||||
def _abbrev(self, s):
|
||||
s = s.replace('/', '.')
|
||||
s = s.replace('java.lang.', '')
|
||||
s = s.replace('scala.', '')
|
||||
if self.pkg is not None:
|
||||
s = s.replace(self.pkg, '')
|
||||
return s
|
||||
|
||||
html = open(path, 'r').read()
|
||||
return html
|
||||
pkg = None
|
||||
obj_re = re.compile(r'^.+ (?:class|interface) ([^ ]+) ')
|
||||
def _parse_obj(self, line):
|
||||
s = self._abbrev(line[:-1])
|
||||
m = self.obj_re.match(line)
|
||||
obj = m.group(1)
|
||||
toks = obj.split('.')
|
||||
|
||||
def _execute(self, w, **vargs):
|
||||
try:
|
||||
from BeautifulSoup import BeautifulSoup
|
||||
except ImportError:
|
||||
w.set_error('BeautifulSoup is not installed...')
|
||||
return
|
||||
|
||||
a = w.application
|
||||
name = vargs.get('name')
|
||||
html = self._get_url(w, 'api.html', a.config['scala.api'])
|
||||
soup = BeautifulSoup(html)
|
||||
|
||||
tags = soup.findAll('li')
|
||||
for li in tags:
|
||||
if li['title'].endswith(name):
|
||||
frag = li.contents[0]['href']
|
||||
url2 = a.config['scala.api-base'] + '/' + frag
|
||||
a.run_external('links', url2)
|
||||
return
|
||||
|
||||
w.set_error('error looking up %s...' % name)
|
||||
|
||||
class ScalaXRayBase(Method):
|
||||
_is_method = False
|
||||
pkg_re = re.compile('^package (.+)$')
|
||||
def find_pkg(self, w):
|
||||
for line in w.buffer.lines:
|
||||
m = self.pkg_re.match(line)
|
||||
if m:
|
||||
return m.group(1)
|
||||
raise Exception("no package found")
|
||||
def get_sxr_dir(self, w):
|
||||
# TODO: fixme fixme
|
||||
path = 'target/scala_2.8.0/classes.sxr'
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
if len(toks) > 1:
|
||||
self.pkg = '.'.join(toks[:-1]) + '.'
|
||||
else:
|
||||
raise Exception("classes.sxr not found")
|
||||
self.pkg = None
|
||||
|
||||
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')
|
||||
return self._abbrev(line[:-1])
|
||||
|
||||
def term_def_lookup(self, w):
|
||||
pkg = self.find_pkg(w)
|
||||
base = self.get_sxr_dir(w)
|
||||
tags = self.get_public_tags
|
||||
def _parse_method(self, line):
|
||||
return self._abbrev(line[:-1]).replace("(", " (")
|
||||
|
||||
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)
|
||||
prims = {
|
||||
'B': 'byte',
|
||||
'C': 'char',
|
||||
'D': 'double',
|
||||
'F': 'float',
|
||||
'I': 'int',
|
||||
'J': 'long',
|
||||
'S': 'short',
|
||||
'V': 'void',
|
||||
'Z': 'bool',
|
||||
}
|
||||
def _parse_args(self, line):
|
||||
args = []
|
||||
i = 0
|
||||
arr = ""
|
||||
while i < len(line):
|
||||
if line[i] in self.prims:
|
||||
args.append(self.prims[line[i]] + arr)
|
||||
arr = ""
|
||||
elif line[i] == "[":
|
||||
arr += "[]"
|
||||
elif line[i] == "L":
|
||||
j = i + 1
|
||||
while line[j] != ';': j += 1
|
||||
args.append(self._abbrev(line[i + 1:j]) + arr)
|
||||
arr = ""
|
||||
i = j
|
||||
else:
|
||||
raise Exception("huh? saw %r (%r)" % (line[i:], line))
|
||||
i += 1
|
||||
return args
|
||||
|
||||
def type_lookup(self, n, w):
|
||||
pkg = self.find_pkg(w)
|
||||
base = self.get_sxr_dir(w)
|
||||
path = w.buffer.path
|
||||
typs = {
|
||||
'InterfaceMethod': 'iface ',
|
||||
'Method': 'method',
|
||||
}
|
||||
|
||||
r = re.compile('^.*src/main/scala/(.+)$')
|
||||
m = r.match(path)
|
||||
tags = os.path.join(base, m.group(1) + '.txt')
|
||||
field_re = re.compile('^Field\s+([^:]+):(.+)$')
|
||||
sig_re = re.compile('^(\w+)\s+([^:]+):\(([^)]*)\)(.+)$')
|
||||
def _parse_sig(self, line):
|
||||
if line.startswith('class'):
|
||||
_, name = line.split()
|
||||
return "class " + self._abbrev(name)
|
||||
|
||||
f = open(tags, 'r')
|
||||
for line in f:
|
||||
toks = line.split('\t')
|
||||
i = int(toks[0])
|
||||
j = int(toks[1])
|
||||
if i <= n and n <= j:
|
||||
return toks[2]
|
||||
return None
|
||||
elif line.startswith('String'):
|
||||
return 'string'
|
||||
|
||||
class ScalaGetType(ScalaXRayBase):
|
||||
type_re = re.compile('(?:[^ \[\]{}()\.,;:]+\.)*([^ \[\]{}()\.,;:]+)')
|
||||
ret_re = re.compile('\)(?=[a-zA-Z0-9_])')
|
||||
def _execute(self, w, **vargs):
|
||||
word = w.get_token().string
|
||||
if word is None or word.strip() == "":
|
||||
w.set_error('no word selected')
|
||||
return
|
||||
elif line.startswith('Field'):
|
||||
m = self.field_re.match(line)
|
||||
if not m: raise Exception("failed to match %r" % line)
|
||||
name = self._abbrev(m.group(1))
|
||||
result = self._parse_args(m.group(2))[0]
|
||||
#return "field %s -> %s" % (name, result)
|
||||
return "field %s %s" % (result, name)
|
||||
|
||||
n = w.cursor_byte_offset()
|
||||
t = self.type_lookup(n, w)
|
||||
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):
|
||||
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)
|
||||
m = self.sig_re.match(line)
|
||||
if not m: raise Exception("failed to match %r" % line)
|
||||
typ = self.typs[m.group(1)]
|
||||
name = self._abbrev(m.group(2))
|
||||
|
||||
args = self._parse_args(m.group(3))
|
||||
result = self._parse_args(m.group(4))[0]
|
||||
|
||||
#return "%s %s (%s) -> %s" % (typ, name, ', '.join(args), result)
|
||||
return "%s %s %s (%s)" % (typ, result, name, ', '.join(args))
|
||||
|
||||
def _parse_instruction(self, line):
|
||||
if '//' in line:
|
||||
real, x = line.split('//')
|
||||
sig = self._parse_sig(x)
|
||||
else:
|
||||
real, sig = line, None
|
||||
|
||||
toks = real.split()
|
||||
n = toks[0][:-1]
|
||||
ins = toks[1]
|
||||
rest = [t[:-1] for t in toks[2:]]
|
||||
args = " ".join(rest)
|
||||
|
||||
if sig:
|
||||
#return "%4s %-22s -- %s" % (n, ins + " " + args, sig)
|
||||
return "%4s %-22s --%s" % (n, ins + " " + args, sig)
|
||||
else:
|
||||
return "%4s %-22s" % (n, ins + " " + args)
|
||||
|
||||
def _execute(self, w, **vargs):
|
||||
cp = 'target/scala-2.9.1.final/classes' #FIXME
|
||||
argv = ['javap', '-classpath', cp, '-c', vargs['classname']]
|
||||
|
||||
p = Popen(argv, stdout=PIPE, stderr=STDOUT)
|
||||
lines = p.stdout.readlines()
|
||||
|
||||
obj = None
|
||||
methods = []
|
||||
curr = None
|
||||
instructions = []
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
line = line.strip()
|
||||
if i == 0:
|
||||
continue
|
||||
elif i == 1:
|
||||
obj = self._parse_obj(line)
|
||||
elif line == "Code:":
|
||||
continue
|
||||
elif line == "":
|
||||
if curr:
|
||||
methods.append((curr, instructions))
|
||||
curr = None
|
||||
instructions = []
|
||||
elif self.ins_re.match(line):
|
||||
instructions.append(self._parse_instruction(line))
|
||||
else:
|
||||
curr = self._parse_method(line)
|
||||
|
||||
outlines = []
|
||||
if self.pkg:
|
||||
outlines.append('package ' + self.pkg[:-1])
|
||||
outlines.append('')
|
||||
outlines.append(obj + " {")
|
||||
for method, instructions in methods:
|
||||
if instructions:
|
||||
outlines.append(" " + method + " {")
|
||||
for ins in instructions:
|
||||
outlines.append(" " + ins)
|
||||
outlines.append(" }")
|
||||
else:
|
||||
outlines.append(" " + method + " {}")
|
||||
outlines.append("}")
|
||||
|
||||
output = "\n".join(outlines)
|
||||
|
||||
#w.application.data_buffer("*Javap*", output, switch_to=True)
|
||||
w.application.data_buffer("*Javap*", output, modename='javap', switch_to=True)
|
||||
|
||||
# white is for delimiters, operators, numbers
|
||||
default = ('default', 'default')
|
||||
|
@ -328,7 +337,8 @@ class Scala(Fundamental):
|
|||
tabbercls = ScalaTabber
|
||||
grammar = ScalaGrammar
|
||||
commentc = '//'
|
||||
actions = [ScalaStart, ScalaDocBrowse, ScalaDocLookup, ScalaGetType, ScalaGotoDefinition]
|
||||
#actions = [ScalaStart, ScalaDocBrowse, ScalaDocLookup, ScalaGetType, ScalaGotoDefinition]
|
||||
actions = [ScalaStart, ScalaDecompile]
|
||||
opentokens = ('delimiter', 'sub.start', 'sub.sub.start', 'sub.sub.sub.start')
|
||||
opentags = {'(': ')', '[': ']', '{': '}'}
|
||||
closetokens = ('delimiter', 'sub.end', 'sub.sub.end', 'sub.sub.sub.end')
|
||||
|
@ -365,8 +375,8 @@ class Scala(Fundamental):
|
|||
}
|
||||
|
||||
_bindings = {
|
||||
'scala-get-type': ('M-,',),
|
||||
'scala-goto-definition': ('C-c ,',),
|
||||
#'scala-get-type': ('M-,',),
|
||||
#'scala-goto-definition': ('C-c ,',),
|
||||
'close-paren': (')',),
|
||||
'close-brace': ('}',),
|
||||
'close-bracket': (']',),
|
||||
|
|
Loading…
Reference in New Issue