pmacs3/mode/erlang.py

105 lines
5.8 KiB
Python

import commands, os.path, sets, string, sys, traceback
import color, completer, default, mode, method, regex, tab
from point import Point
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule, NocasePatternRule
class StringGrammar(Grammar):
rules = [
NocasePatternRule(r'escaped', r'\\(?:[bdefnrstv\\"\']|\^[a-z]|\d{1,3})'),
]
class ErlangGrammar(Grammar):
rules = [
PatternRule(r'eol', r'\n'),
PatternRule(r'comment', r'%.*$'),
PatternRule(r'erl_attribute', r'-[a-z][a-zA-Z0-9_@]+'),
PatternRule(r'erl_reserved', r"(?:xor|when|try|rem|receive|query|orelse|or|of|not|let|if|fun|end|div|cond|catch|case|bxor|bsr|bsl|bor|bnot|begin|band|andalso|and|after)(?![a-zA-Z0-9_'])"),
PatternRule(r'erl_arity', r'[a-z][a-zA-Z0-9_@]*/[1-9][0-9]*'),
PatternRule(r'erl_function', r'[a-z][a-zA-Z0-9_@]*(?= *\()'),
PatternRule(r'erl_namespace', r'[a-z][a-zA-Z0-9_@]*(?=:)'),
PatternRule(r'erl_builtin', r"whereis|unregister|unlink|tuple_to_list|tuple_size|trunc|tl|time|throw|term_to_binary|term_to_binary|statistics|split_binary|spawn_opt|spawn_opt|spawn_opt|spawn_opt|spawn_monitor|spawn_monitor|spawn_link|spawn_link|spawn_link|spawn_link|spawn|spawn|spawn|spawn|size|setelement|self|round|registered|register|put|purge_module|process_info|process_info|process_flag|process_flag|processes|pre_loaded|port_control|port_connect|port_command|port_close|pid_to_list|open_port|now|nodes|nodes|node|node|monitor_node|module_loaded|make_ref|load_module|list_to_tuple|list_to_pid|list_to_integer|list_to_float|list_to_existing_atom|list_to_bitstring|list_to_binary|list_to_atom|link|length|is_tuple|is_reference|is_record|is_record|is_process_alive|is_port|is_pid|is_number|is_list|is_integer|is_function|is_function|is_float|is_boolean|is_bitstring|is_binary|is_atom|is_alive|iolist_to_binary|iolist_size|iolist|iodata|integer_to_list|hd|halt|halt|group_leader|group_leader|get_keys|get|get|garbage_collect|garbage_collect|float_to_list|float|ext_binary|exit|exit|erase|erase|ence|element|disconnect_node|delete_module|date|concat_binary|check_process_code|byte_size|bitstring_to_list|bit_size|binary_to_term|binary_to_list|binary_to_list|atom_to_list|atom_to_list|apply|apply|apply|abs"),
RegionRule(r'string', r'"', StringGrammar, r'"'),
RegionRule(r'erl_atom', r"'", StringGrammar, r"'"),
PatternRule(r'erl_atom', r"[a-z][a-zA-Z0-9_@]*"),
PatternRule(r'erl_variable', r"[A-Z_][a-zA-Z0-9_@]*"),
PatternRule(r'delimiter', r'->|<<|>>|\(|\)|{|}|\[|\]|\.|;|,|\|'),
PatternRule(r'operator', r'\+\+|--|==|/=|=<|<|>=|>|=:=|=/=>|-|\+|\*|/|:|#|!]'),
NocasePatternRule(r'number', r'\$.|[+-]?\d+#[a-z0-9]+|[+-]?\d+\.\d+|[+-]?\.\d+|[+-]?\d+'),
]
class ErlangTabber(tab.StackTabber):
enterlvl = ('after', 'begin', 'case', 'catch', 'fun', 'if', 'query', 'receive',
'try', 'when')
def _handle_other_token(self, currlvl, y, i):
token = self.get_token(y, i)
rtoken = self.get_next_right_token(y, i)
ltoken = self.get_next_left_token(y, i)
if token.name == 'eol':
if ltoken is not None and ltoken.name == 'comment':
ltoken = self.get_next_left_token(y, i - 1)
if ltoken is None:
pass
elif ltoken.name == 'erl_reserved' and ltoken.string in self.enterlvl:
pass
elif ltoken.name == 'delimiter' and ltoken.string in ('.', ';', ',', '->'):
pass
else:
self._pop_while('->')
if not self._empty() and self._peek_name() != '->':
self._pop()
elif token.name == 'delimiter':
if token.string == '->':
if rtoken is None or rtoken.name == 'comment':
level = self.get_curr_level() + self.mode.tabwidth
else:
level = rtoken.x
self._append(token.string, level)
elif token.string == '.':
self.markers = []
elif token.string == ';':
self._pop()
elif token.name == 'erl_reserved':
if token.string in self.enterlvl:
if rtoken is None or rtoken.name == 'comment':
level = self.get_curr_level() + self.mode.tabwidth
else:
level = rtoken.x
self._append(token.string, level)
elif token.string == 'end':
self._opt_pop('->')
self._pop_unless('->')
return currlvl
class Erlang(mode.Fundamental):
modename = 'Erlang'
extensions = ['.erl']
tabwidth = 4
tabbercls = ErlangTabber
grammar = ErlangGrammar
opentokens = ('delimiter',)
opentags = {'(': ')', '[': ']', '{': '}'}
closetokens = ('delimiter',)
closetags = {')': '(', ']': '[', '}': '{'}
colors = {
'erl_attribute': ('cyan', 'default', 'bold'),
'erl_reserved': ('cyan', 'default', 'bold'),
'erl_arity': ('magenta', 'default', 'bold'),
'erl_namespace': ('magenta', 'default', 'bold'),
'erl_function': ('blue', 'default', 'bold'),
'erl_builtin': ('magenta', 'default', 'bold'),
'erl_variable': ('yellow', 'default', 'bold'),
'erl_operator': ('default', 'default', 'bold'),
'erl_atom': ('magenta', 'default', 'bold'),
'erl_atom.start': ('magenta', 'default', 'bold'),
'erl_atom.null': ('magenta', 'default', 'bold'),
'erl_atom.end': ('magenta', 'default', 'bold'),
}
def __init__(self, w):
mode.Fundamental.__init__(self, w)
self.add_bindings('close-paren', (')',))
self.add_bindings('close-brace', ('}',))
self.add_bindings('close-bracket', (']',))
install = Erlang.install