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 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'[^\\\']+'), ] 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'[^\\\"]+'), ] 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'[^/\\]+'), ] chr1 = '[a-zA-Z_]' chr2 = '[a-zA-Z_0-9]' word = chr1 + chr2 + '*' class JavascriptGrammar(Grammar): rules = [ PatternRule('comment', '//.*$'), RegionRule('comment', '/\*', Grammar, '\*/'), PatternRule('continuation', r'\\(?= *$)'), PatternMatchRule('x', '(function)( +)(' + word + ')', 'js.reserved', 'spaces', 'js.function'), PatternMatchRule('x', '(class|new)( +)(' + word + ')', 'js.reserved', 'spaces', 'js.class'), 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 + ')'), 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]+"), PatternRule('eol', r'\n'), PatternRule('spaces', ' +'), PatternRule('delimiter', r'%=|&&=|&=|\(|\)|\*=|\+=|,|-=|\.{3}|\.|/=(?= |$)|::|:|;|<<=|>>=|>>>=|\?|\[|\]|^=|^^=|\{|\}|\|=|\|\|='), # 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'!==|!=|!|%|&&|&|\*|\+\+|\+|--|-|/|<<=|<<|<=|<|===|==|=|>>>=|>>>|>>=|>>|>=|>|\\|\|\|'), RegionRule('string', "'", StringGrammar1, "'"), RegionRule('string', '"', StringGrammar2, '"'), ] class JavascriptTabber2(tab.StackTabber2): 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'} 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 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') class RhinoStart(Interact): args = [] reuse = True 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 = [] reuse = True 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 Javascript(Fundamental): name = 'Javascript' extensions = ['.js'] grammar = JavascriptGrammar tabbercls = JavascriptTabber2 commentc = '//' opentokens = ('delimiter',) opentags = {'(': ')', '[': ']', '{': '}'} closetokens = ('delimiter',) closetags = {')': '(', ']': '[', '}': '{'} 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'), } config = {'rhino.cmd': 'rhino'} actions = [RhinoStart, RhinoLoadFile] _bindings = { 'close-paren': (')',), 'close-brace': ('}',), 'close-bracket': (']',), } install = Javascript.install