# Initial version from https://gist.github.com/skuroda/5105635
# Posted on SO: http://stackoverflow.com/questions/15260843

# Things still to do:
#   complete more
#   only complete unique (maybe make this an option? could be annoying with complete more)

import sublime
import sublime_plugin


last_initial_pos = None
last_word_at_ipos = None

last_search_pos = None

REGION_KEY = 'VimCompletion'
DRAW_FLAGS = sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_SOLID_UNDERLINE

def complete_word(view, edit, do_previous):
    global last_initial_pos, last_word_at_ipos, last_search_pos

    view.erase_regions(REGION_KEY)

    # Compute the region from the beginning of the word containing the cursor
    # through the cursor.
    initial_word_region = view.word(view.sel()[0])
    initial_word_region = sublime.Region(initial_word_region.a, view.sel()[0].a)
    word = view.substr(initial_word_region)

    if (initial_word_region.a == last_initial_pos and last_word_at_ipos is not None and
            word.startswith(last_word_at_ipos) and last_search_pos is not None):
        position = last_search_pos
        word = last_word_at_ipos
    else:
        if do_previous:
            position = initial_word_region.begin()
        else:
            position = initial_word_region.end()
        last_initial_pos = initial_word_region.a
        last_word_at_ipos = word

    if (do_previous and position > 0) or (not do_previous and position < view.size()):
        position += -1 if do_previous else 1

    # sublime.status_message("word: %s; position: %d" % (word, position))

    size_checked = 0
    match_found = False
    while (size_checked < 5000 and not match_found and position >= 0 and
           position <= view.size()):
        compare_word_region = view.word(position)
        compare_word = view.substr(compare_word_region)

        # If we find a word that starts with the proper prefix, it's a match!
        # But don't count it if we have just found our starting place.
        if compare_word.startswith(word) and compare_word_region.a != view.word(view.sel()[0]).a:
            # replace word
            view.replace(edit, initial_word_region, compare_word)
            view.add_regions(REGION_KEY, [compare_word_region], "error", "", DRAW_FLAGS)

            match_found = True

        if do_previous:
            position = compare_word_region.begin() - 1
        else:
            position = compare_word_region.end() + 1

        size_checked += compare_word_region.size()

    if match_found:
        sublime.status_message(
            "Completion line: %s" %
            view.substr(view.line(sublime.Region(compare_word_region.a, compare_word_region.a))))
    else:
        sublime.status_message("No completion found")

    last_search_pos = position


#
class CompletePreviousWordCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        complete_word(self.view, edit, True)


class CompleteNextWordCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        complete_word(self.view, edit, False)

@@ -252,112 +252,513 @@
 re)%0A
-%0Aimport sublime%0Aimport sublime_plugin%0A%0A%0Alast_initial_pos = None%0Alast_word_at_ipos = None%0A%0Alast_search_po
+#   complete from other open buffers, MRU first%0A%0Aimport sublime%0Aimport sublime_plugin%0A%0A# The view that we searched in last%0Alast_view = None%0A%0A# The location of the beginning of the prefix that was last searched for%0Alast_initial_pos = None%0A%0A# The prefix that was at last_initial_pos last time we searched%0Alast_word_at_ipos = None%0A%0A# The place to begin searching for words on next complete_word%0Alast_search_pos = None%0A%0A# True iff the most recent search was in the 'previous' direction%0Alast_search_was_previou
 s = 
@@ -991,16 +991,53 @@
 arch_pos
+, last_view, last_search_was_previous
 %0A%0A    vi
@@ -1355,16 +1355,38 @@
     if (
+last_view == view and 
 initial_
@@ -1418,24 +1418,36 @@
 tial_pos and
+%0A           
  last_word_a
@@ -1550,16 +1550,91 @@
  None):%0A
+        # Continue at previous search position with previous search prefix%0A
         
@@ -1693,25 +1693,311 @@
 at_ipos%0A
+%0A
     
-else:
+    if do_previous != last_search_was_previous:%0A            r = view.word(position + (1 if last_search_was_previous else -1))%0A            if do_previous:%0A                position = r.begin() - 1%0A            else:%0A                position = r.end() + 1%0A    else:%0A        # Start a new search
 %0A       
@@ -2208,16 +2208,41 @@
 s = word
+%0A        last_view = view
 %0A%0A    if
@@ -2447,29 +2447,8 @@
 ))%0A%0A
-    size_checked = 0%0A
     
@@ -2481,33 +2481,8 @@
 ile 
-(size_checked %3C 5000 and 
 not 
@@ -2514,27 +2514,16 @@
 %3E= 0 and
-%0A          
  positio
@@ -2530,33 +2530,32 @@
 n %3C= view.size()
-)
 :%0A        compar
@@ -3260,60 +3260,8 @@
  1%0A%0A
-        size_checked += compare_word_region.size()%0A%0A
     
@@ -3538,19 +3538,60 @@
 osition%0A
+    last_search_was_previous = do_previous
 %0A%0A
-#
 %0Aclass C
@@ -3848,8 +3848,103 @@
  False)%0A
+%0A%0Aclass CompleteMoreCommand(sublime_plugin.TextCommand):%0A    def run(self, edit):%0A        pass%0A

Remove search size limit, switch directions more smoothly