wordfuzzycompletion.vim 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. " -*- coding: utf-8 -*-"
  2. " authors: jonatan alexis anauati (barakawins@gmail.com) "
  3. " Bence DOMONKOS (c89@protonmail.com) "
  4. " version: 0.8. "
  5. if !has('python3')
  6. finish
  7. endif
  8. function! PythonWordFuzzyCompletion(base)
  9. python3 << EOF
  10. import string
  11. import sys
  12. import vim
  13. MAX_RESULTS = int(vim.eval('g:fuzzywordcompletion_maxresults'))
  14. transtable = vim.eval('g:fuzzywordcompletion_completiontable')
  15. if not transtable:
  16. nosplitchars = string.ascii_letters + '_'
  17. deletechars = ''.join((chr(c) for c in range(256) if chr(c) not in nosplitchars))
  18. transtable = string.maketrans(deletechars, ' ' * len(deletechars))
  19. def levenshtein(a, b):
  20. #from http://hetland.org/coding/python/levenshtein.py
  21. "Calculates the Levenshtein distance between a and b."
  22. n, m = len(a), len(b)
  23. if n > m:
  24. # Make sure n <= m, to use O(min(n,m)) space
  25. a, b = b, a
  26. n, m = m, n
  27. current = range(n + 1)
  28. for i in range(1, m + 1):
  29. previous, current = current, [i] + [0] * n
  30. for j in range(1, n + 1):
  31. add, delete = previous[j] + 1, current[j - 1] + 1
  32. change = previous[j - 1]
  33. if a[j - 1] != b[i - 1]:
  34. change = change + 1
  35. current[j] = min(add, delete, change)
  36. return current[n]
  37. def completion(word):
  38. results = []
  39. distances = None
  40. distances_1 = {}
  41. distances_2 = {}
  42. try:
  43. first_char = word[0].lower()
  44. except:
  45. first_char = ''
  46. word_len = len(word)
  47. word_lower = word.lower()
  48. endwalk = False
  49. for line in vim.current.buffer:
  50. for w in line.translate(transtable).split():
  51. wl = w.lower()
  52. if wl.startswith(word_lower[0:len(word_lower)]):
  53. results.append(w)
  54. if len(results) > MAX_RESULTS:
  55. endwalk = True
  56. break
  57. else:
  58. if wl.startswith(first_char):
  59. distances = distances_1
  60. distances_2 = {}
  61. elif not distances_1:
  62. distances = distances_2
  63. if distances != None:
  64. w_len = len(w)
  65. if word_len < w_len:
  66. w_len = word_len
  67. d = levenshtein(w[0:w_len], word)
  68. try:
  69. distancesList = distances[d]
  70. except:
  71. distancesList = []
  72. distances[d ]= distancesList
  73. distancesList.append(w)
  74. distances = None
  75. if endwalk:
  76. break
  77. if distances_1:
  78. distances = distances_1
  79. else:
  80. distances = distances_2
  81. results.sort(key = lambda e: len(e))
  82. keys = list(distances.keys())
  83. keys.sort()
  84. fuzzylen = int(MAX_RESULTS) - len(results)
  85. if fuzzylen >= 0:
  86. for k in keys:
  87. distancesList = distances[k]
  88. results.extend(distancesList)
  89. del distances[k]
  90. if len(results) >= MAX_RESULTS:
  91. results = results[0:MAX_RESULTS]
  92. break
  93. return results
  94. base=vim.eval('a:base')
  95. vim.command('let g:fuzzyret='+str(completion(base)))
  96. EOF
  97. return g:fuzzyret
  98. endfunction
  99. function! FuzzyWordCompletion(findstart, base)
  100. if a:findstart
  101. let line = getline('.')
  102. let start = col('.') - 1
  103. while start > 0 && line[start - 1] =~ '\a\|_'
  104. let start -= 1
  105. endwhile
  106. return start
  107. else
  108. return PythonWordFuzzyCompletion(a:base)
  109. endif
  110. endfunction
  111. if !exists("g:fuzzywordcompletion_maxresults")
  112. let g:fuzzywordcompletion_maxresults=10
  113. endif
  114. if !exists("g:fuzzywordcompletion_completiontable")
  115. let g:fuzzywordcompletion_completiontable=''
  116. endif
  117. set completefunc=FuzzyWordCompletion
  118. if !exists("g:fuzzywordcompletion_disable_keybinding")
  119. let g:fuzzywordcompletion_disable_keybinding=0
  120. endif
  121. if !g:fuzzywordcompletion_disable_keybinding
  122. imap <C-k> <C-x><C-u>
  123. endif