import re
from method import Method
from mode import Fundamental

_error_regexes = [
    r'at (?P<file>\S+) line (?P<line>\d+)\.?$', #perl
    r'File "(?P<file>.+?)", line (?P<line>\d+)(?:, in \S+)?$', #python
    r'^(?P<file>\S+?):(?P<line>\d+): ', #javac/gcc
    r'at \S+\((?P<file>.+?):(?P<line>\d+)\)$', #java
    r'^(?P<line>\d+):', #grep
]
error_regexes = [re.compile(s) for s in _error_regexes]

def find_next_error(w):
    b = w.buffer
    x, y = w.logical_cursor().xy()
    while y < len(b.lines):
        for regex in error_regexes:
            m = regex.search(b.lines[y], x)
            if m:
                return (m, y)
        x = 0
        y += 1
    return (None, None)

class ErrorGotoLine(Method):
    '''Goto the line of the file indicated'''
    def _execute(self, w, **vargs):
        a = w.application
        (m, y) = find_next_error(w)
        if m is None:
            w.set_error("nothing found")
            return
        errline = w.buffer.lines[y]

        d = m.groupdict()
        path = d.get('file')
        line = d.get('line')
        if line is None:
            return
        elif path is None or path == '-':
            path = w.buffer.orig_path
        b2 = a.open_path(path)
        a.switch_buffer(b2)
        a.methods['goto-line'].execute(b2.windows[0], lineno=int(line))
        w.set_error(errline)

class Error(Fundamental):
    name    = 'Error'
    actions = [ErrorGotoLine]
    def __init__(self, w):
        Fundamental.__init__(self, w)
        self.add_bindings('error-goto-line', ('RETURN', 'C-c M-g',))

install = Error.install