Fixed vim and zsh

This commit is contained in:
2018-04-05 13:06:54 +02:00
parent f9db886bd3
commit 0331f6518a
2009 changed files with 256303 additions and 0 deletions

View File

@ -0,0 +1,52 @@
# ============================================================================
# FILE: around.py
# AUTHOR: Khalidov Oleg <brooth at gmail.com>
# License: MIT license
# ============================================================================
import re
from .base import Base
from deoplete.util import parse_buffer_pattern, getlines
LINES_ABOVE = 20
LINES_BELOW = 20
class Source(Base):
def __init__(self, vim):
super().__init__(vim)
self.name = 'around'
self.mark = '[~]'
self.rank = 300
def gather_candidates(self, context):
line = context['position'][1]
candidates = []
# lines above
words = parse_buffer_pattern(
reversed(getlines(self.vim, max([1, line - LINES_ABOVE]), line)),
context['keyword_patterns'])
candidates += [{'word': x, 'menu': 'A'} for x in words]
# grab ':changes' command output
p = re.compile(r'[\s\d]+')
lines = set()
for change_line in [x[p.search(x).span()[1]:] for x
in self.vim.call(
'execute', 'changes').split('\n')
if p.search(x)]:
if change_line and change_line != '-invalid-':
lines.add(change_line)
words = parse_buffer_pattern(lines, context['keyword_patterns'])
candidates += [{'word': x, 'menu': 'C'} for x in words]
# lines below
words = parse_buffer_pattern(
getlines(self.vim, line, line + LINES_BELOW),
context['keyword_patterns'])
candidates += [{'word': x, 'menu': 'B'} for x in words]
return candidates

View File

@ -0,0 +1,56 @@
# ============================================================================
# FILE: base.py
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
# License: MIT license
# ============================================================================
import re
from abc import abstractmethod
from deoplete.logger import LoggingMixin
from deoplete.util import debug, error_vim
class Base(LoggingMixin):
def __init__(self, vim):
self.vim = vim
self.description = ''
self.mark = ''
self.max_pattern_length = 80
self.input_pattern = ''
self.matchers = ['matcher_fuzzy']
self.sorters = ['sorter_rank']
self.converters = [
'converter_remove_overlap',
'converter_truncate_abbr',
'converter_truncate_kind',
'converter_truncate_menu']
self.filetypes = []
self.debug_enabled = False
self.is_bytepos = False
self.is_initialized = False
self.is_volatile = False
self.is_silent = False
self.rank = 100
self.disabled_syntaxes = []
self.events = None
def get_complete_position(self, context):
m = re.search('(?:' + context['keyword_patterns'] + ')$',
context['input'])
return m.start() if m else -1
def print(self, expr):
if not self.is_silent:
debug(self.vim, expr)
def print_error(self, expr):
if not self.is_silent:
error_vim(self.vim, expr)
@abstractmethod
def gather_candidates(self, context):
pass
def on_event(self, context):
pass

View File

@ -0,0 +1,63 @@
# ============================================================================
# FILE: buffer.py
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
# License: MIT license
# ============================================================================
from .base import Base
from deoplete.util import parse_buffer_pattern, getlines
class Source(Base):
def __init__(self, vim):
super().__init__(vim)
self.name = 'buffer'
self.mark = '[B]'
self.events = ['Init', 'InsertEnter', 'BufWritePost']
self._limit = 1000000
self._buffers = {}
self._max_lines = 5000
def on_event(self, context):
if (context['bufnr'] not in self._buffers
or context['event'] == 'BufWritePost'):
self._make_cache(context)
def gather_candidates(self, context):
self.on_event(context)
tab_bufnrs = self.vim.call('tabpagebuflist')
same_filetype = context['vars'].get(
'deoplete#buffer#require_same_filetype', True)
return {'sorted_candidates': [
x['candidates'] for x in self._buffers.values()
if not same_filetype or
x['filetype'] in context['filetypes'] or
x['filetype'] in context['same_filetypes'] or
x['bufnr'] in tab_bufnrs
]}
def _make_cache(self, context):
# Bufsize check
size = self.vim.call('line2byte',
self.vim.call('line', '$') + 1) - 1
if size > self._limit:
return
try:
self._buffers[context['bufnr']] = {
'bufnr': context['bufnr'],
'filetype': self.vim.eval('&l:filetype'),
'candidates': [
{'word': x} for x in
sorted(parse_buffer_pattern(getlines(self.vim),
context['keyword_patterns']),
key=str.lower)
]
}
except UnicodeDecodeError:
return []

View File

@ -0,0 +1,51 @@
# ============================================================================
# FILE: dictionary.py
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
# License: MIT license
# ============================================================================
from os.path import getmtime, exists
from collections import namedtuple
from .base import Base
DictCacheItem = namedtuple('DictCacheItem', 'mtime candidates')
class Source(Base):
def __init__(self, vim):
super().__init__(vim)
self.name = 'dictionary'
self.mark = '[D]'
self.events = ['Init', 'InsertEnter']
self._cache = {}
def on_event(self, context):
self._make_cache(context)
def gather_candidates(self, context):
self._make_cache(context)
candidates = []
for filename in [x for x in self._get_dictionaries(context)
if x in self._cache]:
candidates.append(self._cache[filename].candidates)
return {'sorted_candidates': candidates}
def _make_cache(self, context):
for filename in self._get_dictionaries(context):
mtime = getmtime(filename)
if filename in self._cache and self._cache[
filename].mtime == mtime:
continue
with open(filename, 'r', errors='replace') as f:
self._cache[filename] = DictCacheItem(
mtime, [{'word': x} for x in sorted(
[x.strip() for x in f], key=str.lower)]
)
def _get_dictionaries(self, context):
return [x for x in context['dict__dictionary'].split(',')
if exists(x)]

View File

@ -0,0 +1,86 @@
# ============================================================================
# FILE: file.py
# AUTHOR: Felipe Morales <hel.sheep at gmail.com>
# Shougo Matsushita <Shougo.Matsu at gmail.com>
# License: MIT license
# ============================================================================
import os
import re
from os.path import exists, dirname
from .base import Base
from deoplete.util import expand
class Source(Base):
def __init__(self, vim):
super().__init__(vim)
self.name = 'file'
self.mark = '[F]'
self.min_pattern_length = 0
self.rank = 150
self.events = ['Init', 'InsertEnter']
self._isfname = ''
def on_init(self, context):
self._buffer_path = context['vars'].get(
'deoplete#file#enable_buffer_path', 0)
def on_event(self, context):
self._isfname = self.vim.call(
'deoplete#util#vimoption2python_not',
self.vim.options['isfname'])
def get_complete_position(self, context):
pos = context['input'].rfind('/')
return pos if pos < 0 else pos + 1
def gather_candidates(self, context):
if not self._isfname:
self.on_event(context)
p = self._longest_path_that_exists(context, context['input'])
if p in (None, []) or p == '/' or re.search('//+$', p):
return []
complete_str = self._substitute_path(context, dirname(p) + '/')
if not os.path.isdir(complete_str):
return []
hidden = context['complete_str'].find('.') == 0
contents = [[], []]
try:
for item in sorted(os.listdir(complete_str), key=str.lower):
if not hidden and item[0] == '.':
continue
contents[not os.path.isdir(complete_str + item)].append(item)
except PermissionError:
pass
dirs, files = contents
return [{'word': x, 'abbr': x + '/'} for x in dirs
] + [{'word': x} for x in files]
def _longest_path_that_exists(self, context, input_str):
input_str = re.sub(r'[^/]*$', '', input_str)
data = re.split(r'((?:%s+|(?:(?<![\w\s/\.])(?:~|\.{1,2})?/)+))' %
self._isfname, input_str)
data = [''.join(data[i:]) for i in range(len(data))]
existing_paths = sorted(filter(lambda x: exists(
dirname(self._substitute_path(context, x))), data))
return existing_paths[-1] if existing_paths else None
def _substitute_path(self, context, path):
m = re.match(r'(\.{1,2})/+', path)
if m:
if self._buffer_path and context['bufpath']:
base = context['bufpath']
else:
base = os.path.join(context['cwd'], 'x')
for _ in m.group(1):
base = dirname(base)
return os.path.abspath(os.path.join(
base, path[len(m.group(0)):])) + '/'
return expand(path)

View File

@ -0,0 +1,62 @@
# ============================================================================
# FILE: member.py
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
# License: MIT license
# ============================================================================
from .base import Base
import re
from deoplete.util import (
get_buffer_config, convert2list,
parse_buffer_pattern, set_pattern, getlines)
class Source(Base):
def __init__(self, vim):
super().__init__(vim)
self.name = 'member'
self.mark = '[M]'
self.min_pattern_length = 0
self._object_pattern = r'[a-zA-Z_]\w*(?:\(\)?)?'
self._prefix = ''
self._prefix_patterns = {}
set_pattern(self._prefix_patterns,
'_', '\.')
set_pattern(self._prefix_patterns,
'c,objc', ['\.', '->'])
set_pattern(self._prefix_patterns,
'cpp,objcpp', ['\.', '->', '::'])
set_pattern(self._prefix_patterns,
'perl,php', ['->'])
set_pattern(self._prefix_patterns,
'ruby', ['\.', '::'])
set_pattern(self._prefix_patterns,
'lua', ['\.', ':'])
def get_complete_position(self, context):
# Check member prefix pattern.
for prefix_pattern in convert2list(
get_buffer_config(context, context['filetype'],
'deoplete_member_prefix_patterns',
'deoplete#member#prefix_patterns',
self._prefix_patterns)):
m = re.search(self._object_pattern + prefix_pattern + r'\w*$',
context['input'])
if m is None or prefix_pattern == '':
continue
self._prefix = re.sub(r'\w*$', '', m.group(0))
return re.search(r'\w*$', context['input']).start()
return -1
def gather_candidates(self, context):
return [{'word': x} for x in
parse_buffer_pattern(
getlines(self.vim),
r'(?<=' + re.escape(self._prefix) + r')\w+'
)
if x != context['complete_str']]

View File

@ -0,0 +1,98 @@
# ============================================================================
# FILE: omni.py
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
# License: MIT license
# ============================================================================
import re
from .base import Base
from deoplete.util import (
get_buffer_config, convert2list, set_pattern, convert2candidates)
class Source(Base):
def __init__(self, vim):
super().__init__(vim)
self.name = 'omni'
self.mark = '[O]'
self.rank = 500
self.is_bytepos = True
self.min_pattern_length = 0
self._input_patterns = {}
set_pattern(self._input_patterns, 'css,less,scss,sass',
[r'\w{2}', r'\w+[):;]?\s*\w*', r'[@!]'])
set_pattern(self._input_patterns, 'lua',
[r'\w+[.:]\w*', r'require\s*\(?["'']\w*'])
def get_complete_position(self, context):
current_ft = self.vim.eval('&filetype')
for filetype in list(set([context['filetype']] +
context['filetype'].split('.'))):
pos = self._get_complete_position(context, current_ft, filetype)
if pos >= 0:
return pos
return -1
def _get_complete_position(self, context, current_ft, filetype):
for omnifunc in convert2list(
get_buffer_config(context, filetype,
'deoplete_omni_functions',
'deoplete#omni#functions',
{'_': ''})):
if omnifunc == '' and (filetype == current_ft or
filetype in ['css', 'javascript']):
omnifunc = context['omni__omnifunc']
if omnifunc == '':
continue
self._omnifunc = omnifunc
for input_pattern in convert2list(
get_buffer_config(context, filetype,
'deoplete_omni_input_patterns',
'deoplete#omni#input_patterns',
self._input_patterns)):
m = re.search('(' + input_pattern + ')$', context['input'])
# self.debug(filetype)
# self.debug(input_pattern)
if input_pattern == '' or (context['event'] !=
'Manual' and m is None):
continue
if filetype == current_ft and self._omnifunc in [
'ccomplete#Complete',
'htmlcomplete#CompleteTags',
'LanguageClient#complete',
'phpcomplete#CompletePHP']:
# In the blacklist
return -1
try:
complete_pos = self.vim.call(self._omnifunc, 1, '')
except Exception as e:
self.print_error('Error occurred calling omnifunction: ' +
self._omnifunc)
return -1
return complete_pos
return -1
def gather_candidates(self, context):
try:
candidates = self.vim.call(self._omnifunc, 0, '')
if isinstance(candidates, dict):
candidates = candidates['words']
elif isinstance(candidates, int):
candidates = []
except Exception as e:
self.print_error('Error occurred calling omnifunction: ' +
self._omnifunc)
candidates = []
candidates = convert2candidates(candidates)
for candidate in candidates:
candidate['dup'] = 1
return candidates

View File

@ -0,0 +1,156 @@
# ============================================================================
# FILE: tag.py
# AUTHOR: Felipe Morales <hel.sheep at gmail.com>
# Shougo Matsushita <Shougo.Matsu at gmail.com>
# Roxma <roxma at qq.com>
# License: MIT license
# ============================================================================
from .base import Base
import re
import os
from os.path import exists, getsize
class Source(Base):
def __init__(self, vim):
super().__init__(vim)
self.name = 'tag'
self.mark = '[T]'
def on_init(self, context):
self._limit = context['vars'].get(
'deoplete#tag#cache_limit_size', 500000)
def gather_candidates(self, context):
candidates = []
for filename in self._get_tagfiles(context):
for line in binary_search_lines_by_prefix(
context['complete_str'], filename):
candidate = self._make_candidate(line)
if candidate:
candidates.append(candidate)
return candidates
def _make_candidate(self, line):
cols = line.strip().split('\t', 2)
if not cols or cols[0].startswith('!_'):
return {}
tagfield = {}
if ';"' in cols[-1]:
cols[-1], fields = cols[-1].split(';"', 1)
for pair in fields.split('\t'):
if ':' not in pair:
tagfield['kind'] = pair
else:
k, v = pair.split(':', 1)
tagfield[k] = v
kind = tagfield.get('kind', '')
if kind == 'f':
i = cols[2].find('(')
if i != -1 and cols[2].find(')', i+1) != -1:
m = re.search(r'(\w+\(.*\))', cols[2])
if m:
return {'word': cols[0], 'abbr': m.group(1), 'kind': kind}
return {'word': cols[0], 'kind': kind}
def _get_tagfiles(self, context):
include_files = self.vim.call(
'neoinclude#include#get_tag_files') if self.vim.call(
'exists', '*neoinclude#include#get_tag_files') else []
return [x for x in self.vim.call(
'map', self.vim.call('tagfiles') + include_files,
'fnamemodify(v:val, ":p")')
if exists(x) and getsize(x) < self._limit]
def binary_search_lines_by_prefix(prefix, filename):
with open(filename, 'r', errors='ignore') as f:
# to properly keep bounds of this loop it's important to understand
# *exactly* what our variables mean.
#
# to make sure we process only full lines, we are going to always seek
# to file position (x - 1), then skip partial or full line found there.
# except for position 0 which we know belongs to full 1st line.
# each line (except 1st one) will have multiple corresponding seeking
# positions.
#
# we are interested in finding such a seeking position for the first
# line in the file that matches our prefix. (let's call it target)
# begin - guaranteed not to exceed our target position
# e.g. (begin <= target) at any time.
begin = 0
# end - guaranteed to be higher then at least one seeking position for
# the target. e.g. (target < end) at any time.
# Note that this means it can be below the actual target line
f.seek(0, os.SEEK_END)
end = f.tell()
while end > begin + 1:
# pos - current seeking position
pos = int((begin + end) / 2) - 1
if pos == 0:
f.seek(0, os.SEEK_SET)
else:
f.seek(pos - 1, os.SEEK_SET)
f.readline() # skip partial line
line = f.readline()
l2 = f.tell() # start of next line (or end of file)
if l2 == 1:
# this is a corner case of a single empty first line.
# we mast advance here or we'll have an endless loop
begin = 1
next
if line:
key = line[:len(prefix)]
if key < prefix:
# we are strictly before the target line.
# so it starts at least from l2
begin = max(begin, l2)
elif key > prefix:
# we are strictly past the target line.
# our target seeking position is less than current pos
end = pos
else:
# current line is a possible target. it's reachable from
# current 'pos', so `target pos is <= current pos`, or
# `target post < current post + 1`
end = min(end, pos + 1)
else:
# we reached end of file. our current seeking position doesn't
# correspond to any line
end = min(end, pos)
# now we are at a *seeking position* for the target line. need to skip
# to the actual line
if begin == 0:
f.seek(0, os.SEEK_SET)
else:
f.seek(begin - 1, os.SEEK_SET)
f.readline()
while True:
line = f.readline()
if line.startswith(prefix):
yield line
else:
break
return