pmacs3/mode/erlang.py

134 lines
6.4 KiB
Python

import commands, os.path, string, sys, traceback
import color, completer, default, mode, regex, tab
from point import Point
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
from lex import NocasePatternRule, PatternMatchRule
from method.shell import Interact
from etags import TagManager
class AtomGrammar(Grammar):
rules = [
NocasePatternRule(r'escaped', r'\\(?:[bdefnrstv\\"\']|\^[a-z]|\d{1,3})'),
NocasePatternRule(r'data', r"[^\\']+"),
]
class StringGrammar(Grammar):
rules = [
NocasePatternRule(r'escaped', r'\\(?:[bdefnrstv\\"\']|\^[a-z]|\d{1,3})'),
NocasePatternRule(r'data', r'[^\\"]+'),
]
chr1 = '[a-z]'
chr2 = '[a-zA-Z0-9_@]'
atom = chr1 + chr2 + '*'
class ErlangGrammar(Grammar):
rules = [
PatternRule('eol', r'\n'),
PatternRule('comment', '%.*$'),
PatternRule('erl_attribute', '-' + atom),
RegionRule('erl_attribute', "-'", AtomGrammar ,"'"),
PatternRule('erl_reserved', "(?: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)(?!" + chr2 + ")"),
PatternRule('erl_arity', atom + '/(?:0|[1-9][0-9]*)'),
PatternMatchRule('x', '('+atom+')( *)(\()', 'erl_function', 'spaces', 'delimiter'),
PatternMatchRule('x', '('+atom+')(:)', 'erl_namespace', 'delimiter'),
PatternRule('erl_builtin', "(?: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)(?!" + chr2 + ")"),
RegionRule('erl_atom', "'", AtomGrammar, "'"),
RegionRule('string', '"', StringGrammar, '"'),
PatternRule('erl_atom', atom),
PatternRule('erl_variable', r"[A-Z_]" + chr2 + "*"),
PatternRule('delimiter', r'->|<<|>>|\(|\)|{|}|\[|\]|\.|;|,|\|'),
PatternRule('operator', r'\+\+|--|==|/=|=<|<|>=|>|=:=|=/=>|-|\+|\*|/|:|#|!]'),
NocasePatternRule('number', r'\$.|[+-]?\d+#[a-z0-9]+|[+-]?\d+\.\d+|[+-]?\.\d+|[+-]?\d+'),
]
class ErlangTabber(tab.StackTabber):
enterlvl = ('after', 'begin', 'case', 'catch', 'fun', 'if', 'query', 'receive')
def _handle_close_token(self, currlvl, y, i):
self._opt_pop(*self.enterlvl)
return tab.StackTabber._handle_close_token(self, currlvl, y, i)
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':
pass
elif token.name == 'string.start':
self._append('string', None)
elif token.name == 'string.end':
self._opt_pop('string')
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 == 'of':
self._opt_pop('case')
elif token.string == 'end':
self._opt_pop('->')
self._pop_unless('->')
currlvl = self.get_curr_level()
return currlvl
class ErlStart(Interact):
args = []
reuse = True
def _execute(self, w, **vargs):
Interact._execute(self, w, bname='*Erl*', cmd='erl')
class ErlangTagManager(TagManager):
lang = 'Erlang'
exts = set(('.erl',))
class Erlang(mode.Fundamental):
name = 'Erlang'
extensions = ['.erl']
tabwidth = 4
tabbercls = ErlangTabber
tagcls = ErlangTagManager
grammar = ErlangGrammar
commentc = '%'
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.data': ('magenta', 'default', 'bold'),
'erl_atom.end': ('magenta', 'default', 'bold'),
}
actions = [
ErlStart,
]
_bindings = {
'close-paren': (')',),
'close-brace': ('}',),
'close-bracket': (']',),
}
install = Erlang.install