import collections
import re

import porcupine
from porcupine import tabs, utils

setup_before = ['tabs2spaces']      # see tabs2spaces.py


class AutoCompleter:

    def __init__(self, textwidget):
        self.textwidget = textwidget
        self._startpos = None
        self._suffixes = None
        self._completing = False    # avoid recursion

    def _find_suffixes(self):
        before_cursor = self.textwidget.get('insert linestart', 'insert')
        after_cursor = self.textwidget.get('insert', 'insert lineend')

        match = re.search('\w+$', before_cursor)
        if match is None:
            # can't autocomplete based on this
            return None
        prefix = match.group(0)

        # Tcl's regexes don't support \b or a sane way of grouping so
        # they are kind of useless for this. I guess I should implement
        # this with Tcl regexes too and check which is faster :)
        result = set()
        for chunk in self.textwidget.iter_chunks():
            for match in re.finditer(r'\b' + prefix + r'(\w+)', chunk):
                result.add(match.group(1))

        # if the cursor is in the middle of a word, that word must not
        # be completed, e.g. if the user types abcdef and moves the
        # cursor between c and d, we must not autocomplete to abcdefdef
        result.discard(re.search('^\w*', after_cursor).group(0))

        return collections.deque(sorted(result, key=str.casefold))

    def _complete(self, rotation):
        self._completing = True

        if self._suffixes is None:
            self._startpos = self.textwidget.index('insert')
            self._suffixes = self._find_suffixes()
            if self._suffixes is None:
                # no completable characters before the cursor, just give
                # up and allow doing something else on this tab press
                return None
            self._suffixes.appendleft('')  # end of completions

        self._suffixes.rotate(rotation)
        self.textwidget.delete(self._startpos, 'insert')
        self.textwidget.mark_set('insert', self._startpos)
        self.textwidget.insert(self._startpos, self._suffixes[0])

        self._completing = False
        return 'break'

    def on_tab(self, event, shifted):
        if event.widget.tag_ranges('sel'):
            # something's selected, autocompleting is probably not the
            # right thing to do
            return None

        if shifted:       # display the previous completion
            return self._complete(1)
        else:
            return self._complete(-1)

    def reset(self, *junk):
        # deleting and inserting from _complete() runs this, so this
        # must do nothing if we're currently completing
        if not self._completing:
            self._suffixes = None


def on_new_tab(event):
    # TODO: autocomplete in other kinds of tabs too?
    tab = event.widget.tabs[-1]
    if isinstance(tab, tabs.FileTab):
        completer = AutoCompleter(tab.textwidget)
        utils.bind_tab_key(tab.textwidget, completer.on_tab, add=True)
        tab.textwidget.bind('<<CursorMoved>>', completer.reset, add=True)


def setup():
    porcupine.get_tab_manager().bind('<<NewTab>>', on_new_tab, add=True)

@@ -23,16 +23,29 @@
 ort re%0A%0A
+import jedi%0A%0A
 import p
@@ -146,16 +146,87 @@
 ces.py%0A%0A
+# Some jedi settings.%0Ajedi.settings.add_bracket_after_function = True%0A%0A
 %0Aclass A
@@ -616,766 +616,608 @@
     
-match = re.search('%5Cw+$', before_cursor)%0A        if match is None:%0A            # can't autocomplete based on this%0A            return None%0A        prefix = match.group(0)%0A%0A        # Tcl's regexes don't support %5Cb or a sane way of grouping so%0A        # they are kind of useless for this. I guess I should implement%0A        # this with Tcl regexes too and check which is faster :)%0A        result = set()%0A        for chunk in self.textwidget.iter_chunks():%0A            for match in re.finditer(r'%5Cb' + prefix + r'(%5Cw+)', chunk):%0A                result.add(match.group(1))%0A%0A        # if the cursor is in the middle of a word, that word must not%0A        # be completed, e.g. if the user types abcdef and moves the%0A        # cursor between c and d, we must not au
+if re.match(r%22%5E%5Cs*$%22, before_cursor) is not None:%0A            # If the line is just whitespace, or empty, we want to indent.%0A            return None%0A        elif re.match(r%22%5Cw+%22, after_cursor) is None:%0A            line, col = map(int, self.textwidget.index(%22insert%22).split(%22.%22))%0A            source = self.textwidget.get(%221.0%22, %22end - 1 char%22)%0A%0A            script = jedi.Script(source, line, col)%0A            completions = (c.complete for c in script.completions())%0A%0A            # Jedi automatically sorts its completions.%0A            return collections.deque(completions)%0A%0A        # We don't want 
 to
+ 
 comp
@@ -1225,86 +1225,32 @@
 ete 
-to abcdefdef%0A        result.discard(re.search('%5E%5Cw*', after_cursor).group(0))%0A
+in the middle of a word.
 %0A   
@@ -1283,40 +1283,8 @@
 que(
-sorted(result, key=str.casefold)
 )%0A%0A 
@@ -2777,16 +2777,50 @@
 FileTab)
+ and tab.filetype.name == %22Python%22
 :%0A      

Use Jedi for auto-completion.