"""ParenMatch -- An IDLE extension for parenthesis matching.

When you hit a right paren, the cursor should move briefly to the left
paren.  Paren here is used generically; the matching applies to
parentheses, square brackets, and curly braces.

WARNING: This extension will fight with the CallTips extension,
because they both are interested in the KeyRelease-parenright event.
We'll have to fix IDLE to do something reasonable when two or more
extensions what to capture the same event.
"""

import PyParse
from AutoIndent import AutoIndent, index2line
from IdleConf import idleconf

class ParenMatch:
    """Highlight matching parentheses

    There are three supported style of paren matching, based loosely
    on the Emacs options.  The style is select based on the
    HILITE_STYLE attribute; it can be changed used the set_style
    method.

    The supported styles are:

    default -- When a right paren is typed, highlight the matching
        left paren for 1/2 sec.

    expression -- When a right paren is typed, highlight the entire
        expression from the left paren to the right paren.

    TODO:
        - fix interaction with CallTips
        - extend IDLE with configuration dialog to change options
        - implement rest of Emacs highlight styles (see below)
        - print mismatch warning in IDLE status window

    Note: In Emacs, there are several styles of highlight where the
    matching paren is highlighted whenever the cursor is immediately
    to the right of a right paren.  I don't know how to do that in Tk,
    so I haven't bothered.
    """

    menudefs = []

    keydefs = {
        '<<flash-open-paren>>' : ('<KeyRelease-parenright>',
                                  '<KeyRelease-bracketright>',
                                  '<KeyRelease-braceright>'),
        '<<check-restore>>' : ('<KeyPress>',),
    }

    windows_keydefs = {}
    unix_keydefs = {}

    iconf = idleconf.getsection('ParenMatch')
    STYLE = iconf.getdef('style', 'default')
    FLASH_DELAY = iconf.getint('flash-delay')
    HILITE_CONFIG = iconf.getcolor('hilite')
    BELL = iconf.getboolean('bell')
    del iconf

    def __init__(self, editwin):
        self.editwin = editwin
        self.text = editwin.text
        self.finder = LastOpenBracketFinder(editwin)
        self.counter = 0
        self._restore = None
        self.set_style(self.STYLE)

    def set_style(self, style):
        self.STYLE = style
        if style == "default":
            self.create_tag = self.create_tag_default
            self.set_timeout = self.set_timeout_last
        elif style == "expression":
            self.create_tag = self.create_tag_expression
            self.set_timeout = self.set_timeout_none

    def flash_open_paren_event(self, event):
        index = self.finder.find(keysym_type(event.keysym))
        if index is None:
            self.warn_mismatched()
            return
        self._restore = 1
        self.create_tag(index)
        self.set_timeout()

    def check_restore_event(self, event=None):
        if self._restore:
            self.text.tag_delete("paren")
            self._restore = None

    def handle_restore_timer(self, timer_count):
        if timer_count + 1 == self.counter:
            self.check_restore_event()

    def warn_mismatched(self):
        if self.BELL:
            self.text.bell()

    # any one of the create_tag_XXX methods can be used depending on
    # the style

    def create_tag_default(self, index):
        """Highlight the single paren that matches"""
        self.text.tag_add("paren", index)
        self.text.tag_config("paren", self.HILITE_CONFIG)

    def create_tag_expression(self, index):
        """Highlight the entire expression"""
        self.text.tag_add("paren", index, "insert")
        self.text.tag_config("paren", self.HILITE_CONFIG)

    # any one of the set_timeout_XXX methods can be used depending on
    # the style

    def set_timeout_none(self):
        """Highlight will remain until user input turns it off"""
        pass

    def set_timeout_last(self):
        """The last highlight created will be removed after .5 sec"""
        # associate a counter with an event; only disable the "paren"
        # tag if the event is for the most recent timer.
        self.editwin.text_frame.after(self.FLASH_DELAY,
                                      lambda self=self, c=self.counter: \
                                      self.handle_restore_timer(c))
        self.counter = self.counter + 1

def keysym_type(ks):
    # Not all possible chars or keysyms are checked because of the
    # limited context in which the function is used.
    if ks == "parenright" or ks == "(":
        return "paren"
    if ks == "bracketright" or ks == "[":
        return "bracket"
    if ks == "braceright" or ks == "{":
        return "brace"

class LastOpenBracketFinder:
    num_context_lines = AutoIndent.num_context_lines
    indentwidth = AutoIndent.indentwidth
    tabwidth = AutoIndent.tabwidth
    context_use_ps1 = AutoIndent.context_use_ps1

    def __init__(self, editwin):
        self.editwin = editwin
        self.text = editwin.text

    def _find_offset_in_buf(self, lno):
        y = PyParse.Parser(self.indentwidth, self.tabwidth)
        for context in self.num_context_lines:
            startat = max(lno - context, 1)
            startatindex = `startat` + ".0"
            # rawtext needs to contain everything up to the last
            # character, which was the close paren.  the parser also
            # requires that the last line ends with "\n"
            rawtext = self.text.get(startatindex, "insert")[:-1] + "\n"
            y.set_str(rawtext)
            bod = y.find_good_parse_start(
                        self.context_use_ps1,
                        self._build_char_in_string_func(startatindex))
            if bod is not None or startat == 1:
                break
        y.set_lo(bod or 0)
        i = y.get_last_open_bracket_pos()
        return i, y.str

    def find(self, right_keysym_type):
        """Return the location of the last open paren"""
        lno = index2line(self.text.index("insert"))
        i, buf = self._find_offset_in_buf(lno)
        if i is None \
           or keysym_type(buf[i]) != right_keysym_type:
            return None
        lines_back = buf[i:].count("\n") - 1
        # subtract one for the "\n" added to please the parser
        upto_open = buf[:i]
        j = upto_open.rfind("\n") + 1 # offset of column 0 of line
        offset = i - j
        return "%d.%d" % (lno - lines_back, offset)

    def _build_char_in_string_func(self, startindex):
        def inner(offset, startindex=startindex,
                  icis=self.editwin.is_char_in_string):
            return icis(startindex + "%dc" % offset)
        return inner
