pmacs3/mode/javascript.py

151 lines
6.0 KiB
Python
Raw Permalink Normal View History

2009-04-01 15:07:28 -04:00
import os.path
import time
import tab
from mode import Fundamental
from method.shell import Interact
from lex import Grammar, PatternRule, RegionRule, PatternMatchRule
from point import Point
from etags import TagManager
2008-09-30 18:05:42 -04:00
class StringGrammar1(Grammar):
rules = [
PatternRule('octal', r'\\[0-7]{3}'),
PatternRule('hex', r'\\x[0-9a-fA-F]{2}'),
PatternRule('escaped', r'\\.'),
PatternRule('data', r'[^\\\']+'),
2008-09-30 18:05:42 -04:00
]
class StringGrammar2(Grammar):
rules = [
PatternRule('octal', r'\\[0-7]{3}'),
PatternRule('hex', r'\\x[0-9a-fA-F]{2}'),
PatternRule('escaped', r'\\.'),
PatternRule('data', r'[^\\\"]+'),
2008-09-30 18:05:42 -04:00
]
class RegexGrammar(Grammar):
rules = [
PatternRule('octal', r'\\[0-7]{3}'),
PatternRule('hex', r'\\x[0-9a-fA-F]{2}'),
PatternRule('escaped', r'\\.'),
PatternRule('data', r'[^/\\]+'),
2008-09-30 18:05:42 -04:00
]
2007-07-21 11:40:53 -04:00
chr1 = '[a-zA-Z_]'
chr2 = '[a-zA-Z_0-9]'
word = chr1 + chr2 + '*'
2007-07-21 11:40:53 -04:00
class JavascriptGrammar(Grammar):
rules = [
PatternRule('comment', '//.*$'),
RegionRule('comment', r'/\*', Grammar, '\*/'),
RegionRule('comment', r'<!--', Grammar, '-->'),
PatternRule('continuation', r'\\(?= *$)'),
2008-09-30 18:05:42 -04:00
PatternMatchRule('x', '(function)( +)(' + word + ')',
'js.reserved', 'spaces', 'js.function'),
PatternMatchRule('x', '(class|new)( +)(' + word + ')',
'js.reserved', 'spaces', 'js.class'),
2007-07-21 11:40:53 -04:00
PatternRule('js.reserved', '(?:abstract|as|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|goto|if|import|implements|include|instanceof|interface|in|is|namespace|native|new|null|package|private|protected|public|return|set|super|switch|synchronized|this|throws|throw|transient|true|try|typeof|use|var|void|volatile|while|with)(?!' + chr2 + ')'),
2007-07-21 11:40:53 -04:00
PatternRule('js.identifier', word),
PatternRule('js.integer', "(?:0|[1-9][0-9]*|0[0-7]+|0[xX][0-9a-fA-F]+)[lL]?"),
PatternRule('js.float', r"[0-9]+\.[0-9]*|\.[0-9]+|(?:[0-9]|[0-9]+\.[0-9]*|\.[0-9]+)[eE][\+-]?[0-9]+"),
2007-07-21 11:40:53 -04:00
PatternRule('eol', r'\n'),
PatternRule('spaces', ' +'),
PatternRule('delimiter', r'%=|&&=|&=|\(|\)|\*=|\+=|,|-=|\.{3}|\.|/=(?= |$)|::|:|;|<<=|>>=|>>>=|\?|\[|\]|^=|^^=|\{|\}|\|=|\|\|='),
2007-07-21 11:40:53 -04:00
# fucking javascript!
# their lexer grammar requires one-token look-behind in order to know
# whether a "/" starts a literal regex, or is part of a mathematical
# expression/assignment.
RegionRule('js.regex', r"(?<=[\(=:,]) */", RegexGrammar, "/[a-z]*"),
PatternRule('js.operator', r'!==|!=|!|%|&&|&|\*|\+\+|\+|--|-|/|<<=|<<|<=|<|===|==|=|>>>=|>>>|>>=|>>|>=|>|\\|\|\|'),
2008-09-30 18:05:42 -04:00
RegionRule('string', "'", StringGrammar1, "'"),
RegionRule('string', '"', StringGrammar2, '"'),
2007-07-21 11:40:53 -04:00
]
class JavascriptTabber2(tab.StackTabber2):
fixed_indent = True
open_tokens = {'delimiter': {'{': '}', '(': ')', '[': ']'}}
close_tokens = {'delimiter': {'}': '{', ')': '(', ']': '['}}
control_tokens = {'js.keyword': {'if': 1, 'else': 1, 'while': 1,
'do': 1, 'for': 1}}
end_at_eof = False
end_at_tokens = {'delimiter': {';': 1}}
nocontinue_tokens = {'delimiter': {';': 1, ',': 1},
'comment': 1,
'comment.start': 1,
'comment.data': 1,
'comment.end': 1}
start_free_tokens = {'string.start': 'string.end'}
end_free_tokens = {'string.end': 'string.start'}
2007-07-21 11:40:53 -04:00
def is_base(self, y):
if y == 0: return True
highlighter = self.mode.window.buffer.highlights[self.mode.name]
if not highlighter.tokens[y]: return False
2007-07-21 11:40:53 -04:00
t = highlighter.tokens[y][0]
return t.name == 'js.reserved' and t.string == 'function'
def _is_indent(self, t):
return t.name == 'spaces'
def _is_ignored(self, t):
return t.fqname() in ('spaces', 'eol', 'comment', 'comment.start',
'comment.data', 'comment.null', 'comment.end')
2007-07-21 11:40:53 -04:00
2009-04-01 15:07:28 -04:00
class RhinoStart(Interact):
args = []
2009-04-07 00:34:26 -04:00
reuse = True
2009-04-01 15:07:28 -04:00
def _execute(self, w, **vargs):
cmd = w.application.config.get('rhino.cmd', 'rhino')
Interact._execute(self, w, bname='*Rhino*', cmd=cmd)
class RhinoLoadFile(RhinoStart):
args = []
2009-04-07 00:34:26 -04:00
reuse = True
2009-04-01 15:07:28 -04:00
def _execute(self, w, **vargs):
RhinoStart._execute(self, w, **vargs)
b = w.application.get_buffer_by_name('*Rhino*')
path = os.path.realpath(w.buffer.path)
time.sleep(0.5)
b.pipe_write('load("env.js");\n')
time.sleep(0.5)
b.pipe_write('load("%s");\n' % path)
class JavascriptTagManager(TagManager):
lang = 'Javascript'
exts = set(('.js', '.json'))
2009-04-01 15:07:28 -04:00
class Javascript(Fundamental):
name = 'Javascript'
extensions = ['.js', '.json']
tabwidth = 2
2007-07-21 11:40:53 -04:00
grammar = JavascriptGrammar
tabbercls = JavascriptTabber2
tagcls = JavascriptTagManager
2009-02-15 12:06:35 -05:00
commentc = '//'
2007-07-21 11:40:53 -04:00
opentokens = ('delimiter',)
opentags = {'(': ')', '[': ']', '{': '}'}
closetokens = ('delimiter',)
closetags = {')': '(', ']': '[', '}': '{'}
2007-10-18 17:07:35 -04:00
colors = {
'js.function': ('blue', 'default', 'bold'),
'js.class': ('magenta', 'default', 'bold'),
'js.reserved': ('cyan', 'default', 'bold'),
'js.regex.start': ('cyan', 'default', 'bold'),
'js.regex.data': ('cyan', 'default', 'bold'),
'js.regex.null': ('cyan', 'default', 'bold'),
'js.regex.octal': ('magenta', 'default', 'bold'),
'js.regex.escaped': ('magenta', 'default', 'bold'),
'js.regex.end': ('cyan', 'default', 'bold'),
2007-07-21 11:40:53 -04:00
}
2009-04-01 15:07:28 -04:00
config = {'rhino.cmd': 'rhino'}
actions = [RhinoStart, RhinoLoadFile]
2009-02-15 12:06:35 -05:00
_bindings = {
'close-paren': (')',),
'close-brace': ('}',),
'close-bracket': (']',),
}
2007-10-19 02:41:33 -04:00
install = Javascript.install