123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- " -*- coding: utf-8 -*-"
- " authors: jonatan alexis anauati (barakawins@gmail.com) "
- " Bence DOMONKOS (c89@protonmail.com) "
- " version: 0.8. "
- if !has('python3')
- finish
- endif
- function! PythonWordFuzzyCompletion(base)
- python3 << EOF
- import string
- import sys
- import vim
- MAX_RESULTS = int(vim.eval('g:fuzzywordcompletion_maxresults'))
- transtable = vim.eval('g:fuzzywordcompletion_completiontable')
- if not transtable:
- nosplitchars = string.ascii_letters + '_'
- deletechars = ''.join((chr(c) for c in range(256) if chr(c) not in nosplitchars))
- transtable = string.maketrans(deletechars, ' ' * len(deletechars))
- def levenshtein(a, b):
- #from http://hetland.org/coding/python/levenshtein.py
- "Calculates the Levenshtein distance between a and b."
- n, m = len(a), len(b)
- if n > m:
- # Make sure n <= m, to use O(min(n,m)) space
- a, b = b, a
- n, m = m, n
- current = range(n + 1)
- for i in range(1, m + 1):
- previous, current = current, [i] + [0] * n
- for j in range(1, n + 1):
- add, delete = previous[j] + 1, current[j - 1] + 1
- change = previous[j - 1]
- if a[j - 1] != b[i - 1]:
- change = change + 1
- current[j] = min(add, delete, change)
- return current[n]
- def completion(word):
- results = []
- distances = None
- distances_1 = {}
- distances_2 = {}
- try:
- first_char = word[0].lower()
- except:
- first_char = ''
- word_len = len(word)
- word_lower = word.lower()
- endwalk = False
- for line in vim.current.buffer:
- for w in line.translate(transtable).split():
- wl = w.lower()
- if wl.startswith(word_lower[0:len(word_lower)]):
- results.append(w)
- if len(results) > MAX_RESULTS:
- endwalk = True
- break
- else:
- if wl.startswith(first_char):
- distances = distances_1
- distances_2 = {}
- elif not distances_1:
- distances = distances_2
- if distances != None:
- w_len = len(w)
- if word_len < w_len:
- w_len = word_len
- d = levenshtein(w[0:w_len], word)
- try:
- distancesList = distances[d]
- except:
- distancesList = []
- distances[d ]= distancesList
- distancesList.append(w)
- distances = None
- if endwalk:
- break
- if distances_1:
- distances = distances_1
- else:
- distances = distances_2
- results.sort(key = lambda e: len(e))
- keys = list(distances.keys())
- keys.sort()
- fuzzylen = int(MAX_RESULTS) - len(results)
- if fuzzylen >= 0:
- for k in keys:
- distancesList = distances[k]
- results.extend(distancesList)
- del distances[k]
- if len(results) >= MAX_RESULTS:
- results = results[0:MAX_RESULTS]
- break
- return results
- base=vim.eval('a:base')
- vim.command('let g:fuzzyret='+str(completion(base)))
- EOF
- return g:fuzzyret
- endfunction
- function! FuzzyWordCompletion(findstart, base)
- if a:findstart
- let line = getline('.')
- let start = col('.') - 1
- while start > 0 && line[start - 1] =~ '\a\|_'
- let start -= 1
- endwhile
- return start
- else
- return PythonWordFuzzyCompletion(a:base)
- endif
- endfunction
- if !exists("g:fuzzywordcompletion_maxresults")
- let g:fuzzywordcompletion_maxresults=10
- endif
- if !exists("g:fuzzywordcompletion_completiontable")
- let g:fuzzywordcompletion_completiontable=''
- endif
- set completefunc=FuzzyWordCompletion
- if !exists("g:fuzzywordcompletion_disable_keybinding")
- let g:fuzzywordcompletion_disable_keybinding=0
- endif
- if !g:fuzzywordcompletion_disable_keybinding
- imap <C-k> <C-x><C-u>
- endif
|