From e3e4c4ab726bfd440fb2a53dba8cf1267c24d7b7 Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Tue, 21 Jun 2016 20:18:55 +0900 Subject: Use source/filter instead of sources/filters --- doc/deoplete.txt | 6 +- rplugin/python3/deoplete/deoplete.py | 24 +++--- rplugin/python3/deoplete/filter/base.py | 20 +++++ .../deoplete/filter/converter_auto_delimiter.py | 32 +++++++ .../deoplete/filter/converter_auto_paren.py | 27 ++++++ .../deoplete/filter/converter_remove_overlap.py | 38 +++++++++ .../deoplete/filter/converter_remove_paren.py | 23 +++++ .../deoplete/filter/converter_truncate_abbr.py | 28 +++++++ .../deoplete/filter/converter_truncate_menu.py | 29 +++++++ .../python3/deoplete/filter/matcher_full_fuzzy.py | 30 +++++++ rplugin/python3/deoplete/filter/matcher_fuzzy.py | 30 +++++++ rplugin/python3/deoplete/filter/matcher_head.py | 27 ++++++ rplugin/python3/deoplete/filter/matcher_length.py | 21 +++++ rplugin/python3/deoplete/filter/sorter_rank.py | 26 ++++++ rplugin/python3/deoplete/filter/sorter_word.py | 20 +++++ rplugin/python3/deoplete/filters/base.py | 20 ----- .../deoplete/filters/converter_auto_delimiter.py | 32 ------- .../deoplete/filters/converter_auto_paren.py | 27 ------ .../deoplete/filters/converter_remove_overlap.py | 38 --------- .../deoplete/filters/converter_remove_paren.py | 23 ----- .../deoplete/filters/converter_truncate_abbr.py | 28 ------- .../deoplete/filters/converter_truncate_menu.py | 29 ------- .../python3/deoplete/filters/matcher_full_fuzzy.py | 30 ------- rplugin/python3/deoplete/filters/matcher_fuzzy.py | 30 ------- rplugin/python3/deoplete/filters/matcher_head.py | 27 ------ rplugin/python3/deoplete/filters/matcher_length.py | 21 ----- rplugin/python3/deoplete/filters/sorter_rank.py | 26 ------ rplugin/python3/deoplete/filters/sorter_word.py | 20 ----- rplugin/python3/deoplete/source/base.py | 42 ++++++++++ rplugin/python3/deoplete/source/buffer.py | 61 ++++++++++++++ rplugin/python3/deoplete/source/dictionary.py | 50 +++++++++++ rplugin/python3/deoplete/source/file.py | 91 ++++++++++++++++++++ rplugin/python3/deoplete/source/member.py | 48 +++++++++++ rplugin/python3/deoplete/source/omni.py | 97 ++++++++++++++++++++++ rplugin/python3/deoplete/source/tag.py | 59 +++++++++++++ rplugin/python3/deoplete/sources/base.py | 42 ---------- rplugin/python3/deoplete/sources/buffer.py | 61 -------------- rplugin/python3/deoplete/sources/dictionary.py | 50 ----------- rplugin/python3/deoplete/sources/file.py | 91 -------------------- rplugin/python3/deoplete/sources/member.py | 48 ----------- rplugin/python3/deoplete/sources/omni.py | 97 ---------------------- rplugin/python3/deoplete/sources/tag.py | 59 ------------- rplugin/python3/deoplete/tests/test_filter.py | 2 +- 43 files changed, 817 insertions(+), 813 deletions(-) create mode 100644 rplugin/python3/deoplete/filter/base.py create mode 100644 rplugin/python3/deoplete/filter/converter_auto_delimiter.py create mode 100644 rplugin/python3/deoplete/filter/converter_auto_paren.py create mode 100644 rplugin/python3/deoplete/filter/converter_remove_overlap.py create mode 100644 rplugin/python3/deoplete/filter/converter_remove_paren.py create mode 100644 rplugin/python3/deoplete/filter/converter_truncate_abbr.py create mode 100644 rplugin/python3/deoplete/filter/converter_truncate_menu.py create mode 100644 rplugin/python3/deoplete/filter/matcher_full_fuzzy.py create mode 100644 rplugin/python3/deoplete/filter/matcher_fuzzy.py create mode 100644 rplugin/python3/deoplete/filter/matcher_head.py create mode 100644 rplugin/python3/deoplete/filter/matcher_length.py create mode 100644 rplugin/python3/deoplete/filter/sorter_rank.py create mode 100644 rplugin/python3/deoplete/filter/sorter_word.py delete mode 100644 rplugin/python3/deoplete/filters/base.py delete mode 100644 rplugin/python3/deoplete/filters/converter_auto_delimiter.py delete mode 100644 rplugin/python3/deoplete/filters/converter_auto_paren.py delete mode 100644 rplugin/python3/deoplete/filters/converter_remove_overlap.py delete mode 100644 rplugin/python3/deoplete/filters/converter_remove_paren.py delete mode 100644 rplugin/python3/deoplete/filters/converter_truncate_abbr.py delete mode 100644 rplugin/python3/deoplete/filters/converter_truncate_menu.py delete mode 100644 rplugin/python3/deoplete/filters/matcher_full_fuzzy.py delete mode 100644 rplugin/python3/deoplete/filters/matcher_fuzzy.py delete mode 100644 rplugin/python3/deoplete/filters/matcher_head.py delete mode 100644 rplugin/python3/deoplete/filters/matcher_length.py delete mode 100644 rplugin/python3/deoplete/filters/sorter_rank.py delete mode 100644 rplugin/python3/deoplete/filters/sorter_word.py create mode 100644 rplugin/python3/deoplete/source/base.py create mode 100644 rplugin/python3/deoplete/source/buffer.py create mode 100644 rplugin/python3/deoplete/source/dictionary.py create mode 100644 rplugin/python3/deoplete/source/file.py create mode 100644 rplugin/python3/deoplete/source/member.py create mode 100644 rplugin/python3/deoplete/source/omni.py create mode 100644 rplugin/python3/deoplete/source/tag.py delete mode 100644 rplugin/python3/deoplete/sources/base.py delete mode 100644 rplugin/python3/deoplete/sources/buffer.py delete mode 100644 rplugin/python3/deoplete/sources/dictionary.py delete mode 100644 rplugin/python3/deoplete/sources/file.py delete mode 100644 rplugin/python3/deoplete/sources/member.py delete mode 100644 rplugin/python3/deoplete/sources/omni.py delete mode 100644 rplugin/python3/deoplete/sources/tag.py diff --git a/doc/deoplete.txt b/doc/deoplete.txt index 8b91d75..d3585ee 100644 --- a/doc/deoplete.txt +++ b/doc/deoplete.txt @@ -583,10 +583,10 @@ converter_truncate_menu CREATE SOURCE *deoplete-create-source* To create source, you should read default sources implementation in -rplugin/python3/deoplete/sources/*.py. +rplugin/python3/deoplete/source/*.py. -The files in rplugin/python3/deoplete/sources/*.py are automatically loaded -and deoplete creates new Source class object. +The files are automatically loaded and deoplete creates new Source class +object. Source class must extend Base class in ".base". Note: The sources must be created by Python3 language. diff --git a/rplugin/python3/deoplete/deoplete.py b/rplugin/python3/deoplete/deoplete.py index fd27021..bbb730a 100644 --- a/rplugin/python3/deoplete/deoplete.py +++ b/rplugin/python3/deoplete/deoplete.py @@ -8,8 +8,8 @@ from deoplete.util import \ error, globruntime, charpos2bytepos, \ bytepos2charpos, get_custom, get_syn_name, get_buffer_config -import deoplete.sources -import deoplete.filters +import deoplete.source +import deoplete.filter import deoplete.util from deoplete import logger @@ -20,8 +20,8 @@ import copy import traceback import time -deoplete.sources # silence pyflakes -deoplete.filters # silence pyflakes +deoplete.source # silence pyflakes +deoplete.filter # silence pyflakes class Deoplete(logger.LoggingMixin): @@ -242,13 +242,17 @@ class Deoplete(logger.LoggingMixin): def load_sources(self, context): # Load sources from runtimepath for path in globruntime(context['runtimepath'], - 'rplugin/python3/deoplete/sources/base.py' + 'rplugin/python3/deoplete/source/base.py' ) + globruntime( context['runtimepath'], - 'rplugin/python3/deoplete/sources/*.py'): + 'rplugin/python3/deoplete/source/*.py' + ) + globruntime( + context['runtimepath'], + 'rplugin/python3/deoplete/sources/*.py' + ): filename = os.path.basename(path)[: -3] module = importlib.machinery.SourceFileLoader( - 'deoplete.sources.' + filename, path).load_module() + 'deoplete.source.' + filename, path).load_module() self.debug(path) if not hasattr(module, 'Source') or filename in self.__sources: continue @@ -277,13 +281,13 @@ class Deoplete(logger.LoggingMixin): def load_filters(self, context): # Load filters from runtimepath for path in globruntime(context['runtimepath'], - 'rplugin/python3/deoplete/filters/base.py' + 'rplugin/python3/deoplete/filter/base.py' ) + globruntime( context['runtimepath'], - 'rplugin/python3/deoplete/filters/*.py'): + 'rplugin/python3/deoplete/filter/*.py'): filename = os.path.basename(path)[: -3] module = importlib.machinery.SourceFileLoader( - 'deoplete.filters.' + filename, path).load_module() + 'deoplete.filter.' + filename, path).load_module() if hasattr(module, 'Filter') and filename not in self.__filters: filter = module.Filter(self.__vim) self.__filters[filter.name] = filter diff --git a/rplugin/python3/deoplete/filter/base.py b/rplugin/python3/deoplete/filter/base.py new file mode 100644 index 0000000..8de16bc --- /dev/null +++ b/rplugin/python3/deoplete/filter/base.py @@ -0,0 +1,20 @@ +# ============================================================================ +# FILE: base.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from abc import abstractmethod +from deoplete.logger import LoggingMixin + + +class Base(LoggingMixin): + + def __init__(self, vim): + self.vim = vim + self.name = 'base' + self.description = '' + + @abstractmethod + def filter(self, context): + pass diff --git a/rplugin/python3/deoplete/filter/converter_auto_delimiter.py b/rplugin/python3/deoplete/filter/converter_auto_delimiter.py new file mode 100644 index 0000000..200359e --- /dev/null +++ b/rplugin/python3/deoplete/filter/converter_auto_delimiter.py @@ -0,0 +1,32 @@ +# ============================================================================ +# FILE: converter_auto_delimiter.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from .base import Base + + +class Filter(Base): + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'converter_auto_delimiter' + self.description = 'auto delimiter converter' + + def filter(self, context): + delimiters = context['vars']['deoplete#delimiters'] + for candidate, delimiter in [ + [x, last_find(x['abbr'], delimiters)] + for x in context['candidates'] + if 'abbr' in x and x['abbr'] and + not last_find(x['word'], delimiters) and + last_find(x['abbr'], delimiters)]: + candidate['word'] += delimiter + return context['candidates'] + + +def last_find(s, needles): + for needle in needles: + if len(s) >= len(needle) and s[-len(needle):] == needle: + return needle diff --git a/rplugin/python3/deoplete/filter/converter_auto_paren.py b/rplugin/python3/deoplete/filter/converter_auto_paren.py new file mode 100644 index 0000000..cd14ceb --- /dev/null +++ b/rplugin/python3/deoplete/filter/converter_auto_paren.py @@ -0,0 +1,27 @@ +# ============================================================================ +# FILE: converter_auto_paren.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +import re +from .base import Base + + +class Filter(Base): + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'converter_auto_paren' + self.description = 'auto add parentheses converter' + + def filter(self, context): + p1 = re.compile('\(\)?$') + p2 = re.compile('\(.*\)') + for candidate in [ + x for x in context['candidates'] + if not p1.search(x['word']) and + (('abbr' in x and p2.search(x['abbr'])) or + ('info' in x and p2.search(x['info'])))]: + candidate['word'] += '(' + return context['candidates'] diff --git a/rplugin/python3/deoplete/filter/converter_remove_overlap.py b/rplugin/python3/deoplete/filter/converter_remove_overlap.py new file mode 100644 index 0000000..7d60015 --- /dev/null +++ b/rplugin/python3/deoplete/filter/converter_remove_overlap.py @@ -0,0 +1,38 @@ +# ============================================================================ +# FILE: converter_remove_overlap.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +import re +from .base import Base + + +class Filter(Base): + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'converter_remove_overlap' + self.description = 'remove overlap converter' + + def filter(self, context): + m = re.match('\S+', context['next_input']) + if not m: + return context['candidates'] + next = m.group(0) + for [overlap, candidate] in [ + [x, y] for x, y + in [[overlap_length(x['word'], next), x] + for x in context['candidates']] if x > 0]: + if 'abbr' not in candidate: + candidate['abbr'] = candidate['word'] + candidate['word'] = candidate['word'][: -overlap] + return [x for x in context['candidates'] + if x['word'] != context['complete_str']] + + +def overlap_length(left, right): + pos = len(right) + while pos > 0 and not left.endswith(right[: pos]): + pos -= 1 + return pos diff --git a/rplugin/python3/deoplete/filter/converter_remove_paren.py b/rplugin/python3/deoplete/filter/converter_remove_paren.py new file mode 100644 index 0000000..1e7a463 --- /dev/null +++ b/rplugin/python3/deoplete/filter/converter_remove_paren.py @@ -0,0 +1,23 @@ +# ============================================================================ +# FILE: converter_remove_paren.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +import re +from .base import Base + + +class Filter(Base): + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'converter_remove_paren' + self.description = 'remove parentheses converter' + + def filter(self, context): + p = re.compile('\(\)?$') + for candidate in [x for x in context['candidates'] + if p.search(x['word'])]: + candidate['word'] = re.sub('\(\)?$', '', candidate['word']) + return context['candidates'] diff --git a/rplugin/python3/deoplete/filter/converter_truncate_abbr.py b/rplugin/python3/deoplete/filter/converter_truncate_abbr.py new file mode 100644 index 0000000..bad8a34 --- /dev/null +++ b/rplugin/python3/deoplete/filter/converter_truncate_abbr.py @@ -0,0 +1,28 @@ +# ============================================================================ +# FILE: converter_truncate_abbr.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from .base import Base +from deoplete.util import truncate_skipping + + +class Filter(Base): + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'converter_truncate_abbr' + self.description = 'truncate abbr converter' + + def filter(self, context): + max_width = context['max_abbr_width'] + if max_width <= 0: + return context['candidates'] + + footer_width = max_width / 3 + for candidate in context['candidates']: + candidate['abbr'] = truncate_skipping( + candidate.get('abbr', candidate['word']), + max_width, '..', footer_width) + return context['candidates'] diff --git a/rplugin/python3/deoplete/filter/converter_truncate_menu.py b/rplugin/python3/deoplete/filter/converter_truncate_menu.py new file mode 100644 index 0000000..6ddddaa --- /dev/null +++ b/rplugin/python3/deoplete/filter/converter_truncate_menu.py @@ -0,0 +1,29 @@ +# ============================================================================ +# FILE: converter_truncate_menu.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from .base import Base +from deoplete.util import truncate_skipping + + +class Filter(Base): + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'converter_truncate_menu' + self.description = 'truncate menu converter' + + def filter(self, context): + max_width = context['max_menu_width'] + if not context['candidates'] or 'menu' not in context[ + 'candidates'][0] or max_width <= 0: + return context['candidates'] + + footer_width = max_width / 3 + for candidate in context['candidates']: + candidate['menu'] = truncate_skipping( + candidate.get('menu', ''), + max_width, '..', footer_width) + return context['candidates'] diff --git a/rplugin/python3/deoplete/filter/matcher_full_fuzzy.py b/rplugin/python3/deoplete/filter/matcher_full_fuzzy.py new file mode 100644 index 0000000..be296ce --- /dev/null +++ b/rplugin/python3/deoplete/filter/matcher_full_fuzzy.py @@ -0,0 +1,30 @@ +# ============================================================================ +# FILE: matcher_full_fuzzy.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +import re +from .base import Base +from deoplete.util import fuzzy_escape + + +class Filter(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'matcher_full_fuzzy' + self.description = 'full fuzzy matcher' + + def filter(self, context): + complete_str = context['complete_str'] + if context['ignorecase']: + complete_str = complete_str.lower() + p = re.compile(fuzzy_escape(complete_str, context['camelcase'])) + if context['ignorecase']: + return [x for x in context['candidates'] + if p.search(x['word'].lower())] + else: + return [x for x in context['candidates'] + if p.search(x['word'])] diff --git a/rplugin/python3/deoplete/filter/matcher_fuzzy.py b/rplugin/python3/deoplete/filter/matcher_fuzzy.py new file mode 100644 index 0000000..b88bb8c --- /dev/null +++ b/rplugin/python3/deoplete/filter/matcher_fuzzy.py @@ -0,0 +1,30 @@ +# ============================================================================ +# FILE: matcher_fuzzy.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +import re +from .base import Base +from deoplete.util import fuzzy_escape + + +class Filter(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'matcher_fuzzy' + self.description = 'fuzzy matcher' + + def filter(self, context): + complete_str = context['complete_str'] + if context['ignorecase']: + complete_str = complete_str.lower() + p = re.compile(fuzzy_escape(complete_str, context['camelcase'])) + if context['ignorecase']: + return [x for x in context['candidates'] + if p.match(x['word'].lower())] + else: + return [x for x in context['candidates'] + if p.match(x['word'])] diff --git a/rplugin/python3/deoplete/filter/matcher_head.py b/rplugin/python3/deoplete/filter/matcher_head.py new file mode 100644 index 0000000..a92443e --- /dev/null +++ b/rplugin/python3/deoplete/filter/matcher_head.py @@ -0,0 +1,27 @@ +# ============================================================================ +# FILE: matcher_head.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from .base import Base + + +class Filter(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'matcher_head' + self.description = 'head matcher' + + def filter(self, context): + complete_str = context['complete_str'] + if context['ignorecase']: + complete_str = complete_str.lower() + if context['ignorecase']: + return [x for x in context['candidates'] + if x['word'].lower().startswith(complete_str)] + else: + return [x for x in context['candidates'] + if x['word'].startswith(complete_str)] diff --git a/rplugin/python3/deoplete/filter/matcher_length.py b/rplugin/python3/deoplete/filter/matcher_length.py new file mode 100644 index 0000000..2a4ec17 --- /dev/null +++ b/rplugin/python3/deoplete/filter/matcher_length.py @@ -0,0 +1,21 @@ +# ============================================================================ +# FILE: matcher_length.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from .base import Base + + +class Filter(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'matcher_length' + self.description = 'length matcher' + + def filter(self, context): + input_len = len(context['complete_str']) + return [x for x in context['candidates'] + if len(x['word']) > input_len] diff --git a/rplugin/python3/deoplete/filter/sorter_rank.py b/rplugin/python3/deoplete/filter/sorter_rank.py new file mode 100644 index 0000000..32a72cc --- /dev/null +++ b/rplugin/python3/deoplete/filter/sorter_rank.py @@ -0,0 +1,26 @@ +# ============================================================================ +# FILE: sorter_rank.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from .base import Base + + +class Filter(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'sorter_rank' + self.description = 'rank sorter' + + def filter(self, context): + rank = context['vars']['deoplete#_rank'] + complete_str = context['complete_str'].lower() + input_len = len(complete_str) + return sorted(context['candidates'], + key=lambda x: -1 * rank[x['word']] + if x['word'] in rank + else abs(x['word'].lower().find( + complete_str, 0, input_len))) diff --git a/rplugin/python3/deoplete/filter/sorter_word.py b/rplugin/python3/deoplete/filter/sorter_word.py new file mode 100644 index 0000000..f4fc5a4 --- /dev/null +++ b/rplugin/python3/deoplete/filter/sorter_word.py @@ -0,0 +1,20 @@ +# ============================================================================ +# FILE: sorter_word.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from .base import Base + + +class Filter(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'sorter_word' + self.description = 'word sorter' + + def filter(self, context): + return sorted(context['candidates'], + key=lambda x: x['word']) diff --git a/rplugin/python3/deoplete/filters/base.py b/rplugin/python3/deoplete/filters/base.py deleted file mode 100644 index 8de16bc..0000000 --- a/rplugin/python3/deoplete/filters/base.py +++ /dev/null @@ -1,20 +0,0 @@ -# ============================================================================ -# FILE: base.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from abc import abstractmethod -from deoplete.logger import LoggingMixin - - -class Base(LoggingMixin): - - def __init__(self, vim): - self.vim = vim - self.name = 'base' - self.description = '' - - @abstractmethod - def filter(self, context): - pass diff --git a/rplugin/python3/deoplete/filters/converter_auto_delimiter.py b/rplugin/python3/deoplete/filters/converter_auto_delimiter.py deleted file mode 100644 index 200359e..0000000 --- a/rplugin/python3/deoplete/filters/converter_auto_delimiter.py +++ /dev/null @@ -1,32 +0,0 @@ -# ============================================================================ -# FILE: converter_auto_delimiter.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from .base import Base - - -class Filter(Base): - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'converter_auto_delimiter' - self.description = 'auto delimiter converter' - - def filter(self, context): - delimiters = context['vars']['deoplete#delimiters'] - for candidate, delimiter in [ - [x, last_find(x['abbr'], delimiters)] - for x in context['candidates'] - if 'abbr' in x and x['abbr'] and - not last_find(x['word'], delimiters) and - last_find(x['abbr'], delimiters)]: - candidate['word'] += delimiter - return context['candidates'] - - -def last_find(s, needles): - for needle in needles: - if len(s) >= len(needle) and s[-len(needle):] == needle: - return needle diff --git a/rplugin/python3/deoplete/filters/converter_auto_paren.py b/rplugin/python3/deoplete/filters/converter_auto_paren.py deleted file mode 100644 index cd14ceb..0000000 --- a/rplugin/python3/deoplete/filters/converter_auto_paren.py +++ /dev/null @@ -1,27 +0,0 @@ -# ============================================================================ -# FILE: converter_auto_paren.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -import re -from .base import Base - - -class Filter(Base): - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'converter_auto_paren' - self.description = 'auto add parentheses converter' - - def filter(self, context): - p1 = re.compile('\(\)?$') - p2 = re.compile('\(.*\)') - for candidate in [ - x for x in context['candidates'] - if not p1.search(x['word']) and - (('abbr' in x and p2.search(x['abbr'])) or - ('info' in x and p2.search(x['info'])))]: - candidate['word'] += '(' - return context['candidates'] diff --git a/rplugin/python3/deoplete/filters/converter_remove_overlap.py b/rplugin/python3/deoplete/filters/converter_remove_overlap.py deleted file mode 100644 index 7d60015..0000000 --- a/rplugin/python3/deoplete/filters/converter_remove_overlap.py +++ /dev/null @@ -1,38 +0,0 @@ -# ============================================================================ -# FILE: converter_remove_overlap.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -import re -from .base import Base - - -class Filter(Base): - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'converter_remove_overlap' - self.description = 'remove overlap converter' - - def filter(self, context): - m = re.match('\S+', context['next_input']) - if not m: - return context['candidates'] - next = m.group(0) - for [overlap, candidate] in [ - [x, y] for x, y - in [[overlap_length(x['word'], next), x] - for x in context['candidates']] if x > 0]: - if 'abbr' not in candidate: - candidate['abbr'] = candidate['word'] - candidate['word'] = candidate['word'][: -overlap] - return [x for x in context['candidates'] - if x['word'] != context['complete_str']] - - -def overlap_length(left, right): - pos = len(right) - while pos > 0 and not left.endswith(right[: pos]): - pos -= 1 - return pos diff --git a/rplugin/python3/deoplete/filters/converter_remove_paren.py b/rplugin/python3/deoplete/filters/converter_remove_paren.py deleted file mode 100644 index 1e7a463..0000000 --- a/rplugin/python3/deoplete/filters/converter_remove_paren.py +++ /dev/null @@ -1,23 +0,0 @@ -# ============================================================================ -# FILE: converter_remove_paren.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -import re -from .base import Base - - -class Filter(Base): - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'converter_remove_paren' - self.description = 'remove parentheses converter' - - def filter(self, context): - p = re.compile('\(\)?$') - for candidate in [x for x in context['candidates'] - if p.search(x['word'])]: - candidate['word'] = re.sub('\(\)?$', '', candidate['word']) - return context['candidates'] diff --git a/rplugin/python3/deoplete/filters/converter_truncate_abbr.py b/rplugin/python3/deoplete/filters/converter_truncate_abbr.py deleted file mode 100644 index bad8a34..0000000 --- a/rplugin/python3/deoplete/filters/converter_truncate_abbr.py +++ /dev/null @@ -1,28 +0,0 @@ -# ============================================================================ -# FILE: converter_truncate_abbr.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from .base import Base -from deoplete.util import truncate_skipping - - -class Filter(Base): - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'converter_truncate_abbr' - self.description = 'truncate abbr converter' - - def filter(self, context): - max_width = context['max_abbr_width'] - if max_width <= 0: - return context['candidates'] - - footer_width = max_width / 3 - for candidate in context['candidates']: - candidate['abbr'] = truncate_skipping( - candidate.get('abbr', candidate['word']), - max_width, '..', footer_width) - return context['candidates'] diff --git a/rplugin/python3/deoplete/filters/converter_truncate_menu.py b/rplugin/python3/deoplete/filters/converter_truncate_menu.py deleted file mode 100644 index 6ddddaa..0000000 --- a/rplugin/python3/deoplete/filters/converter_truncate_menu.py +++ /dev/null @@ -1,29 +0,0 @@ -# ============================================================================ -# FILE: converter_truncate_menu.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from .base import Base -from deoplete.util import truncate_skipping - - -class Filter(Base): - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'converter_truncate_menu' - self.description = 'truncate menu converter' - - def filter(self, context): - max_width = context['max_menu_width'] - if not context['candidates'] or 'menu' not in context[ - 'candidates'][0] or max_width <= 0: - return context['candidates'] - - footer_width = max_width / 3 - for candidate in context['candidates']: - candidate['menu'] = truncate_skipping( - candidate.get('menu', ''), - max_width, '..', footer_width) - return context['candidates'] diff --git a/rplugin/python3/deoplete/filters/matcher_full_fuzzy.py b/rplugin/python3/deoplete/filters/matcher_full_fuzzy.py deleted file mode 100644 index be296ce..0000000 --- a/rplugin/python3/deoplete/filters/matcher_full_fuzzy.py +++ /dev/null @@ -1,30 +0,0 @@ -# ============================================================================ -# FILE: matcher_full_fuzzy.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -import re -from .base import Base -from deoplete.util import fuzzy_escape - - -class Filter(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'matcher_full_fuzzy' - self.description = 'full fuzzy matcher' - - def filter(self, context): - complete_str = context['complete_str'] - if context['ignorecase']: - complete_str = complete_str.lower() - p = re.compile(fuzzy_escape(complete_str, context['camelcase'])) - if context['ignorecase']: - return [x for x in context['candidates'] - if p.search(x['word'].lower())] - else: - return [x for x in context['candidates'] - if p.search(x['word'])] diff --git a/rplugin/python3/deoplete/filters/matcher_fuzzy.py b/rplugin/python3/deoplete/filters/matcher_fuzzy.py deleted file mode 100644 index b88bb8c..0000000 --- a/rplugin/python3/deoplete/filters/matcher_fuzzy.py +++ /dev/null @@ -1,30 +0,0 @@ -# ============================================================================ -# FILE: matcher_fuzzy.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -import re -from .base import Base -from deoplete.util import fuzzy_escape - - -class Filter(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'matcher_fuzzy' - self.description = 'fuzzy matcher' - - def filter(self, context): - complete_str = context['complete_str'] - if context['ignorecase']: - complete_str = complete_str.lower() - p = re.compile(fuzzy_escape(complete_str, context['camelcase'])) - if context['ignorecase']: - return [x for x in context['candidates'] - if p.match(x['word'].lower())] - else: - return [x for x in context['candidates'] - if p.match(x['word'])] diff --git a/rplugin/python3/deoplete/filters/matcher_head.py b/rplugin/python3/deoplete/filters/matcher_head.py deleted file mode 100644 index a92443e..0000000 --- a/rplugin/python3/deoplete/filters/matcher_head.py +++ /dev/null @@ -1,27 +0,0 @@ -# ============================================================================ -# FILE: matcher_head.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from .base import Base - - -class Filter(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'matcher_head' - self.description = 'head matcher' - - def filter(self, context): - complete_str = context['complete_str'] - if context['ignorecase']: - complete_str = complete_str.lower() - if context['ignorecase']: - return [x for x in context['candidates'] - if x['word'].lower().startswith(complete_str)] - else: - return [x for x in context['candidates'] - if x['word'].startswith(complete_str)] diff --git a/rplugin/python3/deoplete/filters/matcher_length.py b/rplugin/python3/deoplete/filters/matcher_length.py deleted file mode 100644 index 2a4ec17..0000000 --- a/rplugin/python3/deoplete/filters/matcher_length.py +++ /dev/null @@ -1,21 +0,0 @@ -# ============================================================================ -# FILE: matcher_length.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from .base import Base - - -class Filter(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'matcher_length' - self.description = 'length matcher' - - def filter(self, context): - input_len = len(context['complete_str']) - return [x for x in context['candidates'] - if len(x['word']) > input_len] diff --git a/rplugin/python3/deoplete/filters/sorter_rank.py b/rplugin/python3/deoplete/filters/sorter_rank.py deleted file mode 100644 index 32a72cc..0000000 --- a/rplugin/python3/deoplete/filters/sorter_rank.py +++ /dev/null @@ -1,26 +0,0 @@ -# ============================================================================ -# FILE: sorter_rank.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from .base import Base - - -class Filter(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'sorter_rank' - self.description = 'rank sorter' - - def filter(self, context): - rank = context['vars']['deoplete#_rank'] - complete_str = context['complete_str'].lower() - input_len = len(complete_str) - return sorted(context['candidates'], - key=lambda x: -1 * rank[x['word']] - if x['word'] in rank - else abs(x['word'].lower().find( - complete_str, 0, input_len))) diff --git a/rplugin/python3/deoplete/filters/sorter_word.py b/rplugin/python3/deoplete/filters/sorter_word.py deleted file mode 100644 index f4fc5a4..0000000 --- a/rplugin/python3/deoplete/filters/sorter_word.py +++ /dev/null @@ -1,20 +0,0 @@ -# ============================================================================ -# FILE: sorter_word.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from .base import Base - - -class Filter(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'sorter_word' - self.description = 'word sorter' - - def filter(self, context): - return sorted(context['candidates'], - key=lambda x: x['word']) diff --git a/rplugin/python3/deoplete/source/base.py b/rplugin/python3/deoplete/source/base.py new file mode 100644 index 0000000..5e36030 --- /dev/null +++ b/rplugin/python3/deoplete/source/base.py @@ -0,0 +1,42 @@ +# ============================================================================ +# FILE: base.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +import re +from abc import abstractmethod +from deoplete.logger import LoggingMixin + + +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_length', 'matcher_fuzzy'] + self.sorters = ['sorter_rank'] + self.converters = [ + 'converter_remove_overlap', + 'converter_truncate_abbr', + 'converter_truncate_menu'] + self.filetypes = [] + self.is_bytepos = False + self.rank = 100 + self.disabled_syntaxes = [] + + def get_complete_position(self, context): + m = re.search('(?:' + context['keyword_patterns'] + ')$', + context['input']) + return m.start() if m else -1 + + @abstractmethod + def gather_candidate(self, context): + pass + + def on_event(self, context): + pass diff --git a/rplugin/python3/deoplete/source/buffer.py b/rplugin/python3/deoplete/source/buffer.py new file mode 100644 index 0000000..836bd06 --- /dev/null +++ b/rplugin/python3/deoplete/source/buffer.py @@ -0,0 +1,61 @@ +# ============================================================================ +# FILE: buffer.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from .base import Base + +import functools +import operator +from deoplete.util import parse_buffer_pattern + + +class Source(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'buffer' + self.mark = '[B]' + 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.__make_cache(context) + + buffers = [x['candidates'] for x in self.__buffers.values() + if x['filetype'] in context['filetypes']] + if not buffers: + return [] + + return [{'word': x} for x in + functools.reduce(operator.add, buffers)] + + def __make_cache(self, context): + try: + if (context['bufnr'] in self.__buffers and + context['event'] != 'BufWritePost' and + len(self.vim.current.buffer) > self.__max_lines): + line = context['position'][1] + buffer = self.__buffers[context['bufnr']] + buffer['candidates'] += parse_buffer_pattern( + self.vim.current.buffer[max([0, line-500]):line+500], + context['keyword_patterns'], + context['complete_str']) + buffer['candidates'] = list(set(buffer['candidates'])) + else: + self.__buffers[context['bufnr']] = { + 'filetype': context['filetype'], + 'candidates': parse_buffer_pattern( + self.vim.current.buffer, + context['keyword_patterns'], + context['complete_str']) + } + except UnicodeDecodeError: + return [] diff --git a/rplugin/python3/deoplete/source/dictionary.py b/rplugin/python3/deoplete/source/dictionary.py new file mode 100644 index 0000000..a8a79a6 --- /dev/null +++ b/rplugin/python3/deoplete/source/dictionary.py @@ -0,0 +1,50 @@ +# ============================================================================ +# FILE: dictionary.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from os.path import getmtime, exists +from collections import namedtuple +from deoplete.util import parse_file_pattern +from .base import Base + +DictCacheItem = namedtuple('DictCacheItem', 'mtime candidates') + + +class Source(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'dictionary' + self.mark = '[D]' + + 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 += self.__cache[filename].candidates + + return [{'word': x} for x in candidates] + + def __make_cache(self, context): + for filename in self.__get_dictionaries(context): + mtime = getmtime(filename) + if filename not in self.__cache or self.__cache[ + filename].mtime != mtime: + with open(filename, 'r', errors='replace') as f: + self.__cache[filename] = DictCacheItem( + mtime, parse_file_pattern( + f, context['keyword_patterns'])) + + def __get_dictionaries(self, context): + return [x for x in context['dict__dictionary'].split(',') + if exists(x)] diff --git a/rplugin/python3/deoplete/source/file.py b/rplugin/python3/deoplete/source/file.py new file mode 100644 index 0000000..02ba643 --- /dev/null +++ b/rplugin/python3/deoplete/source/file.py @@ -0,0 +1,91 @@ +# ============================================================================ +# FILE: file.py +# AUTHOR: Felipe Morales +# Shougo Matsushita +# License: MIT license +# ============================================================================ + +import os +import re +from os.path import exists, dirname +from .base import Base +from deoplete.util import \ + set_default, get_simple_buffer_config + + +class Source(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'file' + self.mark = '[F]' + self.min_pattern_length = 0 + self.rank = 150 + self.__isfname = '' + + set_default(self.vim, 'g: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): + 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): + data = [input_str] + m = re.search(self.__isfname, input_str) + if m and m.group(0) != '': + data = re.split(self.__isfname, input_str) + pos = [" ".join(data[i:]) for i in range(len(data))] + existing_paths = list(filter(lambda x: exists( + dirname(self.__substitute_path(context, x))), pos)) + if existing_paths and len(existing_paths) > 0: + return sorted(existing_paths)[-1] + return None + + def __substitute_path(self, context, path): + buffer_path = get_simple_buffer_config( + context, + 'deoplete_file_enable_buffer_path', + 'deoplete#file#enable_buffer_path') + m = re.match(r'(\.+)/', path) + if m: + h = self.vim.funcs.repeat(':h', len(m.group(1))) + return re.sub(r'^\.+', + self.vim.funcs.fnamemodify( + (context['bufname'] + if buffer_path + else context['cwd']), ':p' + h), + path) + m = re.match(r'~/', path) + if m and os.environ.get('HOME'): + return re.sub(r'^~', os.environ.get('HOME'), path) + m = re.match(r'\$([A-Z_]+)/', path) + if m and os.environ.get(m.group(1)): + return re.sub(r'^\$[A-Z_]+', os.environ.get(m.group(1)), path) + return path diff --git a/rplugin/python3/deoplete/source/member.py b/rplugin/python3/deoplete/source/member.py new file mode 100644 index 0000000..34a1f2b --- /dev/null +++ b/rplugin/python3/deoplete/source/member.py @@ -0,0 +1,48 @@ +# ============================================================================ +# FILE: member.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +from .base import Base + +import re +from deoplete.util import \ + get_buffer_config, convert2list, parse_buffer_pattern + + +class Source(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'member' + self.mark = '[M]' + self.min_pattern_length = 0 + + self.__object_pattern = r'[a-zA-Z_]\w*(?:\(\)?)?' + self.__prefix = '' + + 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', + 'deoplete#member#_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( + self.vim.current.buffer, + r'(?<=' + re.escape(self.__prefix) + r')\w+(?:\(\)?)?', + context['complete_str'] + ) + if x != context['complete_str']] diff --git a/rplugin/python3/deoplete/source/omni.py b/rplugin/python3/deoplete/source/omni.py new file mode 100644 index 0000000..5cb6fb6 --- /dev/null +++ b/rplugin/python3/deoplete/source/omni.py @@ -0,0 +1,97 @@ +# ============================================================================ +# FILE: omni.py +# AUTHOR: Shougo Matsushita +# License: MIT license +# ============================================================================ + +import re +from .base import Base +from deoplete.util import \ + get_buffer_config, error, convert2list + + +class Source(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'omni' + self.mark = '[O]' + self.rank = 500 + self.is_bytepos = True + self.min_pattern_length = 0 + + self.__prev_linenr = -1 + self.__prev_pos = -1 + self.__prev_input = '' + self.__prev_candidates = [] + + def get_complete_position(self, context): + if self.__use_previous_result(context): + return self.__prev_pos + + for filetype in context['filetypes']: + omnifunc = get_buffer_config(context, filetype, + 'deoplete_omni_functions', + 'deoplete#omni#functions', + 'deoplete#omni#_functions') + if omnifunc == '': + omnifunc = context['omni__omnifunc'] + if omnifunc == '' or [x for x in [ + 'ccomplete#Complete', 'htmlcomplete#CompleteTags'] + if x == omnifunc]: + continue + self.__omnifunc = omnifunc + for input_pattern in convert2list( + get_buffer_config(context, filetype, + 'deoplete_omni_input_patterns', + 'deoplete#omni#input_patterns', + 'deoplete#omni#_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 + + try: + complete_pos = self.vim.call(self.__omnifunc, 1, '') + except: + error(self.vim, + 'Error occurred calling omnifunction: ' + + self.__omnifunc) + return -1 + return complete_pos + return -1 + + def gather_candidates(self, context): + if self.__use_previous_result(context): + return self.__prev_candidates + + try: + candidates = self.vim.call( + self.__omnifunc, 0, context['complete_str']) + if candidates is dict: + candidates = candidates['words'] + elif candidates is int: + candidates = [] + except: + error(self.vim, + 'Error occurred calling omnifunction: ' + + self.__omnifunc) + candidates = [] + + self.__prev_linenr = context['position'][1] + self.__prev_pos = context['complete_position'] + self.__prev_input = context['input'] + self.__prev_candidates = candidates + + return candidates + + def __use_previous_result(self, context): + return (context['position'][1] == self.__prev_linenr and + re.sub(r'\w+$', '', context['input']) == re.sub( + r'\w+$', '', self.__prev_input) and + len(context['input']) > len(self.__prev_input) and + context['input'].find(self.__prev_input) == 0) diff --git a/rplugin/python3/deoplete/source/tag.py b/rplugin/python3/deoplete/source/tag.py new file mode 100644 index 0000000..41d6e5a --- /dev/null +++ b/rplugin/python3/deoplete/source/tag.py @@ -0,0 +1,59 @@ +# ============================================================================ +# FILE: tag.py +# AUTHOR: Felipe Morales +# Shougo Matsushita +# License: MIT license +# ============================================================================ + +from .base import Base + +import re +from collections import namedtuple +from os.path import exists, getmtime, getsize +from deoplete.util import parse_file_pattern + +TagsCacheItem = namedtuple('TagsCacheItem', 'mtime candidates') + + +class Source(Base): + + def __init__(self, vim): + Base.__init__(self, vim) + + self.name = 'tag' + self.mark = '[T]' + + self.__cache = {} + self.__tagfiles = {} + + def on_event(self, context): + self.__tagfiles[context['bufnr']] = self.__get_tagfiles(context) + + # Make cache + for filename in self.__tagfiles[context['bufnr']]: + mtime = getmtime(filename) + if filename not in self.__cache or self.__cache[ + filename].mtime != mtime: + with open(filename, 'r', errors='replace') as f: + self.__cache[filename] = TagsCacheItem( + mtime, parse_file_pattern(f, '^[^!][^\t]+')) + + def gather_candidates(self, context): + candidates = [] + for filename in [ + x for x in self.__tagfiles.get(context['bufnr'], []) + if x in self.__cache]: + candidates += self.__cache[filename].candidates + + p = re.compile('(?:{})$'.format(context['keyword_patterns'])) + return [{'word': x} for x in candidates if p.match(x)] + + def __get_tagfiles(self, context): + limit = context['vars']['deoplete#tag#cache_limit_size'] + 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) < limit] diff --git a/rplugin/python3/deoplete/sources/base.py b/rplugin/python3/deoplete/sources/base.py deleted file mode 100644 index 5e36030..0000000 --- a/rplugin/python3/deoplete/sources/base.py +++ /dev/null @@ -1,42 +0,0 @@ -# ============================================================================ -# FILE: base.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -import re -from abc import abstractmethod -from deoplete.logger import LoggingMixin - - -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_length', 'matcher_fuzzy'] - self.sorters = ['sorter_rank'] - self.converters = [ - 'converter_remove_overlap', - 'converter_truncate_abbr', - 'converter_truncate_menu'] - self.filetypes = [] - self.is_bytepos = False - self.rank = 100 - self.disabled_syntaxes = [] - - def get_complete_position(self, context): - m = re.search('(?:' + context['keyword_patterns'] + ')$', - context['input']) - return m.start() if m else -1 - - @abstractmethod - def gather_candidate(self, context): - pass - - def on_event(self, context): - pass diff --git a/rplugin/python3/deoplete/sources/buffer.py b/rplugin/python3/deoplete/sources/buffer.py deleted file mode 100644 index 836bd06..0000000 --- a/rplugin/python3/deoplete/sources/buffer.py +++ /dev/null @@ -1,61 +0,0 @@ -# ============================================================================ -# FILE: buffer.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from .base import Base - -import functools -import operator -from deoplete.util import parse_buffer_pattern - - -class Source(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'buffer' - self.mark = '[B]' - 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.__make_cache(context) - - buffers = [x['candidates'] for x in self.__buffers.values() - if x['filetype'] in context['filetypes']] - if not buffers: - return [] - - return [{'word': x} for x in - functools.reduce(operator.add, buffers)] - - def __make_cache(self, context): - try: - if (context['bufnr'] in self.__buffers and - context['event'] != 'BufWritePost' and - len(self.vim.current.buffer) > self.__max_lines): - line = context['position'][1] - buffer = self.__buffers[context['bufnr']] - buffer['candidates'] += parse_buffer_pattern( - self.vim.current.buffer[max([0, line-500]):line+500], - context['keyword_patterns'], - context['complete_str']) - buffer['candidates'] = list(set(buffer['candidates'])) - else: - self.__buffers[context['bufnr']] = { - 'filetype': context['filetype'], - 'candidates': parse_buffer_pattern( - self.vim.current.buffer, - context['keyword_patterns'], - context['complete_str']) - } - except UnicodeDecodeError: - return [] diff --git a/rplugin/python3/deoplete/sources/dictionary.py b/rplugin/python3/deoplete/sources/dictionary.py deleted file mode 100644 index a8a79a6..0000000 --- a/rplugin/python3/deoplete/sources/dictionary.py +++ /dev/null @@ -1,50 +0,0 @@ -# ============================================================================ -# FILE: dictionary.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from os.path import getmtime, exists -from collections import namedtuple -from deoplete.util import parse_file_pattern -from .base import Base - -DictCacheItem = namedtuple('DictCacheItem', 'mtime candidates') - - -class Source(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'dictionary' - self.mark = '[D]' - - 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 += self.__cache[filename].candidates - - return [{'word': x} for x in candidates] - - def __make_cache(self, context): - for filename in self.__get_dictionaries(context): - mtime = getmtime(filename) - if filename not in self.__cache or self.__cache[ - filename].mtime != mtime: - with open(filename, 'r', errors='replace') as f: - self.__cache[filename] = DictCacheItem( - mtime, parse_file_pattern( - f, context['keyword_patterns'])) - - def __get_dictionaries(self, context): - return [x for x in context['dict__dictionary'].split(',') - if exists(x)] diff --git a/rplugin/python3/deoplete/sources/file.py b/rplugin/python3/deoplete/sources/file.py deleted file mode 100644 index 02ba643..0000000 --- a/rplugin/python3/deoplete/sources/file.py +++ /dev/null @@ -1,91 +0,0 @@ -# ============================================================================ -# FILE: file.py -# AUTHOR: Felipe Morales -# Shougo Matsushita -# License: MIT license -# ============================================================================ - -import os -import re -from os.path import exists, dirname -from .base import Base -from deoplete.util import \ - set_default, get_simple_buffer_config - - -class Source(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'file' - self.mark = '[F]' - self.min_pattern_length = 0 - self.rank = 150 - self.__isfname = '' - - set_default(self.vim, 'g: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): - 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): - data = [input_str] - m = re.search(self.__isfname, input_str) - if m and m.group(0) != '': - data = re.split(self.__isfname, input_str) - pos = [" ".join(data[i:]) for i in range(len(data))] - existing_paths = list(filter(lambda x: exists( - dirname(self.__substitute_path(context, x))), pos)) - if existing_paths and len(existing_paths) > 0: - return sorted(existing_paths)[-1] - return None - - def __substitute_path(self, context, path): - buffer_path = get_simple_buffer_config( - context, - 'deoplete_file_enable_buffer_path', - 'deoplete#file#enable_buffer_path') - m = re.match(r'(\.+)/', path) - if m: - h = self.vim.funcs.repeat(':h', len(m.group(1))) - return re.sub(r'^\.+', - self.vim.funcs.fnamemodify( - (context['bufname'] - if buffer_path - else context['cwd']), ':p' + h), - path) - m = re.match(r'~/', path) - if m and os.environ.get('HOME'): - return re.sub(r'^~', os.environ.get('HOME'), path) - m = re.match(r'\$([A-Z_]+)/', path) - if m and os.environ.get(m.group(1)): - return re.sub(r'^\$[A-Z_]+', os.environ.get(m.group(1)), path) - return path diff --git a/rplugin/python3/deoplete/sources/member.py b/rplugin/python3/deoplete/sources/member.py deleted file mode 100644 index 34a1f2b..0000000 --- a/rplugin/python3/deoplete/sources/member.py +++ /dev/null @@ -1,48 +0,0 @@ -# ============================================================================ -# FILE: member.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -from .base import Base - -import re -from deoplete.util import \ - get_buffer_config, convert2list, parse_buffer_pattern - - -class Source(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'member' - self.mark = '[M]' - self.min_pattern_length = 0 - - self.__object_pattern = r'[a-zA-Z_]\w*(?:\(\)?)?' - self.__prefix = '' - - 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', - 'deoplete#member#_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( - self.vim.current.buffer, - r'(?<=' + re.escape(self.__prefix) + r')\w+(?:\(\)?)?', - context['complete_str'] - ) - if x != context['complete_str']] diff --git a/rplugin/python3/deoplete/sources/omni.py b/rplugin/python3/deoplete/sources/omni.py deleted file mode 100644 index 5cb6fb6..0000000 --- a/rplugin/python3/deoplete/sources/omni.py +++ /dev/null @@ -1,97 +0,0 @@ -# ============================================================================ -# FILE: omni.py -# AUTHOR: Shougo Matsushita -# License: MIT license -# ============================================================================ - -import re -from .base import Base -from deoplete.util import \ - get_buffer_config, error, convert2list - - -class Source(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'omni' - self.mark = '[O]' - self.rank = 500 - self.is_bytepos = True - self.min_pattern_length = 0 - - self.__prev_linenr = -1 - self.__prev_pos = -1 - self.__prev_input = '' - self.__prev_candidates = [] - - def get_complete_position(self, context): - if self.__use_previous_result(context): - return self.__prev_pos - - for filetype in context['filetypes']: - omnifunc = get_buffer_config(context, filetype, - 'deoplete_omni_functions', - 'deoplete#omni#functions', - 'deoplete#omni#_functions') - if omnifunc == '': - omnifunc = context['omni__omnifunc'] - if omnifunc == '' or [x for x in [ - 'ccomplete#Complete', 'htmlcomplete#CompleteTags'] - if x == omnifunc]: - continue - self.__omnifunc = omnifunc - for input_pattern in convert2list( - get_buffer_config(context, filetype, - 'deoplete_omni_input_patterns', - 'deoplete#omni#input_patterns', - 'deoplete#omni#_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 - - try: - complete_pos = self.vim.call(self.__omnifunc, 1, '') - except: - error(self.vim, - 'Error occurred calling omnifunction: ' + - self.__omnifunc) - return -1 - return complete_pos - return -1 - - def gather_candidates(self, context): - if self.__use_previous_result(context): - return self.__prev_candidates - - try: - candidates = self.vim.call( - self.__omnifunc, 0, context['complete_str']) - if candidates is dict: - candidates = candidates['words'] - elif candidates is int: - candidates = [] - except: - error(self.vim, - 'Error occurred calling omnifunction: ' + - self.__omnifunc) - candidates = [] - - self.__prev_linenr = context['position'][1] - self.__prev_pos = context['complete_position'] - self.__prev_input = context['input'] - self.__prev_candidates = candidates - - return candidates - - def __use_previous_result(self, context): - return (context['position'][1] == self.__prev_linenr and - re.sub(r'\w+$', '', context['input']) == re.sub( - r'\w+$', '', self.__prev_input) and - len(context['input']) > len(self.__prev_input) and - context['input'].find(self.__prev_input) == 0) diff --git a/rplugin/python3/deoplete/sources/tag.py b/rplugin/python3/deoplete/sources/tag.py deleted file mode 100644 index 41d6e5a..0000000 --- a/rplugin/python3/deoplete/sources/tag.py +++ /dev/null @@ -1,59 +0,0 @@ -# ============================================================================ -# FILE: tag.py -# AUTHOR: Felipe Morales -# Shougo Matsushita -# License: MIT license -# ============================================================================ - -from .base import Base - -import re -from collections import namedtuple -from os.path import exists, getmtime, getsize -from deoplete.util import parse_file_pattern - -TagsCacheItem = namedtuple('TagsCacheItem', 'mtime candidates') - - -class Source(Base): - - def __init__(self, vim): - Base.__init__(self, vim) - - self.name = 'tag' - self.mark = '[T]' - - self.__cache = {} - self.__tagfiles = {} - - def on_event(self, context): - self.__tagfiles[context['bufnr']] = self.__get_tagfiles(context) - - # Make cache - for filename in self.__tagfiles[context['bufnr']]: - mtime = getmtime(filename) - if filename not in self.__cache or self.__cache[ - filename].mtime != mtime: - with open(filename, 'r', errors='replace') as f: - self.__cache[filename] = TagsCacheItem( - mtime, parse_file_pattern(f, '^[^!][^\t]+')) - - def gather_candidates(self, context): - candidates = [] - for filename in [ - x for x in self.__tagfiles.get(context['bufnr'], []) - if x in self.__cache]: - candidates += self.__cache[filename].candidates - - p = re.compile('(?:{})$'.format(context['keyword_patterns'])) - return [{'word': x} for x in candidates if p.match(x)] - - def __get_tagfiles(self, context): - limit = context['vars']['deoplete#tag#cache_limit_size'] - 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) < limit] diff --git a/rplugin/python3/deoplete/tests/test_filter.py b/rplugin/python3/deoplete/tests/test_filter.py index 2effbb0..38c3dc2 100644 --- a/rplugin/python3/deoplete/tests/test_filter.py +++ b/rplugin/python3/deoplete/tests/test_filter.py @@ -2,7 +2,7 @@ from unittest import TestCase from nose.tools import eq_ from deoplete.util import ( fuzzy_escape, charwidth, strwidth, truncate, truncate_skipping) -from deoplete.filters.converter_remove_overlap import overlap_length +from deoplete.filter.converter_remove_overlap import overlap_length class FilterTestCase(TestCase): -- cgit v1.2.3 From c10169718ef9e9d59d93faab9ecd3802227c4f5d Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Tue, 21 Jun 2016 20:25:50 +0900 Subject: Rename handlers to handler --- autoload/deoplete/handler.vim | 155 +++++++++++++++++++++++++++++++++++++++++ autoload/deoplete/handlers.vim | 155 ----------------------------------------- autoload/deoplete/init.vim | 2 +- 3 files changed, 156 insertions(+), 156 deletions(-) create mode 100644 autoload/deoplete/handler.vim delete mode 100644 autoload/deoplete/handlers.vim diff --git a/autoload/deoplete/handler.vim b/autoload/deoplete/handler.vim new file mode 100644 index 0000000..45d9a6b --- /dev/null +++ b/autoload/deoplete/handler.vim @@ -0,0 +1,155 @@ +"============================================================================= +" FILE: handler.vim +" AUTHOR: Shougo Matsushita +" License: MIT license +"============================================================================= + +function! deoplete#handler#_init() abort "{{{ + augroup deoplete + autocmd! + autocmd InsertLeave * call s:on_insert_leave() + autocmd CompleteDone * call s:complete_done() + autocmd InsertCharPre * call s:on_insert_char_pre() + + autocmd TextChangedI * call s:completion_begin("TextChangedI") + autocmd InsertEnter * call s:completion_begin("InsertEnter") + augroup END + + for event in [ + \ 'BufNewFile', 'BufNew', 'BufRead', 'BufWritePost' + \ ] + execute 'autocmd deoplete' event '* call s:on_event('.string(event).')' + endfor + + call s:on_event('') +endfunction"}}} + +function! s:completion_begin(event) abort "{{{ + let context = deoplete#init#_context(a:event, []) + + if s:is_skip(a:event, context) + return + endif + + " Save the previous position + let g:deoplete#_context.position = context.position + + let g:deoplete#_context.refresh = 0 + + " Call omni completion + for filetype in context.filetypes + for pattern in deoplete#util#convert2list( + \ deoplete#util#get_buffer_config(filetype, + \ 'b:deoplete_omni_patterns', + \ 'g:deoplete#omni_patterns', + \ 'g:deoplete#_omni_patterns')) + if pattern != '' && &l:omnifunc != '' + \ && context.input =~# '\%('.pattern.'\)$' + call deoplete#mappings#_set_completeopt() + call feedkeys("\\", 'n') + return + endif + endfor + endfor + + call deoplete#mappings#_set_completeopt() + call rpcnotify(g:deoplete#_channel_id, + \ 'deoplete_auto_completion_begin', context) +endfunction"}}} +function! s:is_skip(event, context) abort "{{{ + if s:is_skip_textwidth(deoplete#util#get_input(a:event)) + return 1 + endif + + let disable_auto_complete = + \ deoplete#util#get_simple_buffer_config( + \ 'b:deoplete_disable_auto_complete', + \ 'g:deoplete#disable_auto_complete') + + if &paste + \ || (a:event !=# 'Manual' && disable_auto_complete) + \ || (&l:completefunc != '' && &l:buftype =~# 'nofile') + \ || (a:event ==# 'InsertEnter' + \ && has_key(g:deoplete#_context, 'position')) + return 1 + endif + + if !get(g:deoplete#_context, 'refresh', 0) + \ && a:context.position ==# get(g:deoplete#_context, 'position', []) + let word = get(v:completed_item, 'word', '') + let delimiters = filter(copy(g:deoplete#delimiters), + \ 'strridx(word, v:val) == (len(word) - len(v:val))') + if word == '' || empty(delimiters) + return 1 + endif + endif + + " Detect foldmethod. + if a:event !=# 'Manual' && a:event !=# 'InsertEnter' + \ && !exists('b:deoplete_detected_foldmethod') + \ && (&l:foldmethod ==# 'expr' || &l:foldmethod ==# 'syntax') + let b:deoplete_detected_foldmethod = 1 + call deoplete#util#print_error( + \ printf('foldmethod = "%s" is detected.', &foldmethod)) + let msg = substitute(deoplete#util#redir( + \ 'verbose setlocal foldmethod?'), '\t', '', 'g') + for msg in split(msg, "\n") + call deoplete#util#print_error(msg) + endfor + call deoplete#util#print_error( + \ 'You should disable it or install FastFold plugin.') + endif + + return 0 +endfunction"}}} +function! s:is_skip_textwidth(input) abort "{{{ + let displaywidth = strdisplaywidth(a:input) + 1 + + if &l:formatoptions =~# '[tca]' && &l:textwidth > 0 + \ && displaywidth >= &l:textwidth + if &l:formatoptions =~# '[ta]' + \ || deoplete#util#get_syn_name() ==# 'Comment' + return 1 + endif + endif + return !pumvisible() && virtcol('.') != displaywidth +endfunction"}}} + +function! s:on_event(event) abort "{{{ + let context = deoplete#init#_context(a:event, []) + call rpcnotify(g:deoplete#_channel_id, 'deoplete_on_event', context) +endfunction"}}} + +function! s:on_insert_leave() abort "{{{ + if exists('g:deoplete#_saved_completeopt') + let &completeopt = g:deoplete#_saved_completeopt + unlet g:deoplete#_saved_completeopt + endif + let g:deoplete#_context = {} +endfunction"}}} + +function! s:complete_done() abort "{{{ + if get(v:completed_item, 'word', '') != '' + let word = v:completed_item.word + if !has_key(g:deoplete#_rank, word) + let g:deoplete#_rank[word] = 1 + else + let g:deoplete#_rank[word] += 1 + endif + endif + + let g:deoplete#_context.position = getpos('.') +endfunction"}}} + +function! s:on_insert_char_pre() abort "{{{ + if !pumvisible() + \ || !g:deoplete#enable_refresh_always + \ || s:is_skip_textwidth(deoplete#util#get_input('InsertCharPre')) + return 1 + endif + + " Auto refresh + call feedkeys("\(deoplete_auto_refresh)") +endfunction"}}} + +" vim: foldmethod=marker diff --git a/autoload/deoplete/handlers.vim b/autoload/deoplete/handlers.vim deleted file mode 100644 index 3a714ee..0000000 --- a/autoload/deoplete/handlers.vim +++ /dev/null @@ -1,155 +0,0 @@ -"============================================================================= -" FILE: handlers.vim -" AUTHOR: Shougo Matsushita -" License: MIT license -"============================================================================= - -function! deoplete#handlers#_init() abort "{{{ - augroup deoplete - autocmd! - autocmd InsertLeave * call s:on_insert_leave() - autocmd CompleteDone * call s:complete_done() - autocmd InsertCharPre * call s:on_insert_char_pre() - - autocmd TextChangedI * call s:completion_begin("TextChangedI") - autocmd InsertEnter * call s:completion_begin("InsertEnter") - augroup END - - for event in [ - \ 'BufNewFile', 'BufNew', 'BufRead', 'BufWritePost' - \ ] - execute 'autocmd deoplete' event '* call s:on_event('.string(event).')' - endfor - - call s:on_event('') -endfunction"}}} - -function! s:completion_begin(event) abort "{{{ - let context = deoplete#init#_context(a:event, []) - - if s:is_skip(a:event, context) - return - endif - - " Save the previous position - let g:deoplete#_context.position = context.position - - let g:deoplete#_context.refresh = 0 - - " Call omni completion - for filetype in context.filetypes - for pattern in deoplete#util#convert2list( - \ deoplete#util#get_buffer_config(filetype, - \ 'b:deoplete_omni_patterns', - \ 'g:deoplete#omni_patterns', - \ 'g:deoplete#_omni_patterns')) - if pattern != '' && &l:omnifunc != '' - \ && context.input =~# '\%('.pattern.'\)$' - call deoplete#mappings#_set_completeopt() - call feedkeys("\\", 'n') - return - endif - endfor - endfor - - call deoplete#mappings#_set_completeopt() - call rpcnotify(g:deoplete#_channel_id, - \ 'deoplete_auto_completion_begin', context) -endfunction"}}} -function! s:is_skip(event, context) abort "{{{ - if s:is_skip_textwidth(deoplete#util#get_input(a:event)) - return 1 - endif - - let disable_auto_complete = - \ deoplete#util#get_simple_buffer_config( - \ 'b:deoplete_disable_auto_complete', - \ 'g:deoplete#disable_auto_complete') - - if &paste - \ || (a:event !=# 'Manual' && disable_auto_complete) - \ || (&l:completefunc != '' && &l:buftype =~# 'nofile') - \ || (a:event ==# 'InsertEnter' - \ && has_key(g:deoplete#_context, 'position')) - return 1 - endif - - if !get(g:deoplete#_context, 'refresh', 0) - \ && a:context.position ==# get(g:deoplete#_context, 'position', []) - let word = get(v:completed_item, 'word', '') - let delimiters = filter(copy(g:deoplete#delimiters), - \ 'strridx(word, v:val) == (len(word) - len(v:val))') - if word == '' || empty(delimiters) - return 1 - endif - endif - - " Detect foldmethod. - if a:event !=# 'Manual' && a:event !=# 'InsertEnter' - \ && !exists('b:deoplete_detected_foldmethod') - \ && (&l:foldmethod ==# 'expr' || &l:foldmethod ==# 'syntax') - let b:deoplete_detected_foldmethod = 1 - call deoplete#util#print_error( - \ printf('foldmethod = "%s" is detected.', &foldmethod)) - let msg = substitute(deoplete#util#redir( - \ 'verbose setlocal foldmethod?'), '\t', '', 'g') - for msg in split(msg, "\n") - call deoplete#util#print_error(msg) - endfor - call deoplete#util#print_error( - \ 'You should disable it or install FastFold plugin.') - endif - - return 0 -endfunction"}}} -function! s:is_skip_textwidth(input) abort "{{{ - let displaywidth = strdisplaywidth(a:input) + 1 - - if &l:formatoptions =~# '[tca]' && &l:textwidth > 0 - \ && displaywidth >= &l:textwidth - if &l:formatoptions =~# '[ta]' - \ || deoplete#util#get_syn_name() ==# 'Comment' - return 1 - endif - endif - return !pumvisible() && virtcol('.') != displaywidth -endfunction"}}} - -function! s:on_event(event) abort "{{{ - let context = deoplete#init#_context(a:event, []) - call rpcnotify(g:deoplete#_channel_id, 'deoplete_on_event', context) -endfunction"}}} - -function! s:on_insert_leave() abort "{{{ - if exists('g:deoplete#_saved_completeopt') - let &completeopt = g:deoplete#_saved_completeopt - unlet g:deoplete#_saved_completeopt - endif - let g:deoplete#_context = {} -endfunction"}}} - -function! s:complete_done() abort "{{{ - if get(v:completed_item, 'word', '') != '' - let word = v:completed_item.word - if !has_key(g:deoplete#_rank, word) - let g:deoplete#_rank[word] = 1 - else - let g:deoplete#_rank[word] += 1 - endif - endif - - let g:deoplete#_context.position = getpos('.') -endfunction"}}} - -function! s:on_insert_char_pre() abort "{{{ - if !pumvisible() - \ || !g:deoplete#enable_refresh_always - \ || s:is_skip_textwidth(deoplete#util#get_input('InsertCharPre')) - return 1 - endif - - " Auto refresh - call feedkeys("\(deoplete_auto_refresh)") -endfunction"}}} - -" vim: foldmethod=marker diff --git a/autoload/deoplete/init.vim b/autoload/deoplete/init.vim index 1ecaea4..c80cd4e 100644 --- a/autoload/deoplete/init.vim +++ b/autoload/deoplete/init.vim @@ -83,7 +83,7 @@ function! deoplete#init#_initialize() abort "{{{ endif endfunction"}}} function! deoplete#init#_enable() abort "{{{ - call deoplete#handlers#_init() + call deoplete#handler#_init() let s:is_enabled = 1 endfunction"}}} function! deoplete#init#_disable() abort "{{{ -- cgit v1.2.3 From 22b93aa532e6557e47deac76f7a755eb0a444ae7 Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Tue, 21 Jun 2016 20:35:27 +0900 Subject: Rename mappings to mapping --- autoload/deoplete.vim | 45 ++++++++++++++++++++++++++ autoload/deoplete/handler.vim | 4 +-- autoload/deoplete/init.vim | 2 +- autoload/deoplete/mapping.vim | 41 ++++++++++++++++++++++++ autoload/deoplete/mappings.vim | 71 +++++------------------------------------- doc/deoplete.txt | 41 ++++++++++++------------ 6 files changed, 116 insertions(+), 88 deletions(-) create mode 100644 autoload/deoplete/mapping.vim diff --git a/autoload/deoplete.vim b/autoload/deoplete.vim index c6d58d6..96975fd 100644 --- a/autoload/deoplete.vim +++ b/autoload/deoplete.vim @@ -31,4 +31,49 @@ function! deoplete#enable_logging(level, logfile) abort "{{{ \ 'deoplete_enable_logging', a:level, a:logfile) endfunction"}}} +function! deoplete#manual_complete(...) abort "{{{ + if deoplete#initialize() + return + endif + + " Start complete. + return (pumvisible() ? "\" : '') + \ . "\=deoplete#mapping#_rpcnotify_wrapper(" + \ . string(get(a:000, 0, [])) . ")\" +endfunction"}}} +function! deoplete#close_popup() abort "{{{ + let g:deoplete#_context.position = getpos('.') + return pumvisible() ? "\" : '' +endfunction"}}} +function! deoplete#smart_close_popup() abort "{{{ + let g:deoplete#_context.position = getpos('.') + return pumvisible() ? "\" : '' +endfunction"}}} +function! deoplete#cancel_popup() abort "{{{ + let g:deoplete#_context.position = getpos('.') + return pumvisible() ? "\" : '' +endfunction"}}} +function! deoplete#refresh() abort "{{{ + let g:deoplete#_context.refresh = 1 + if g:deoplete#_context.event ==# 'Manual' + let g:deoplete#_context.event = 'Refresh' + endif + return pumvisible() ? "\" : '' +endfunction"}}} + +function! deoplete#undo_completion() abort "{{{ + if !exists('v:completed_item') || empty(v:completed_item) + return '' + endif + + let input = deoplete#util#get_input('') + if strridx(input, v:completed_item.word) != + \ len(input) - len(v:completed_item.word) + return '' + endif + + return deoplete#mapping#smart_close_popup() . + \ repeat("\", strchars(v:completed_item.word)) +endfunction"}}} + " vim: foldmethod=marker diff --git a/autoload/deoplete/handler.vim b/autoload/deoplete/handler.vim index 45d9a6b..fb27120 100644 --- a/autoload/deoplete/handler.vim +++ b/autoload/deoplete/handler.vim @@ -45,14 +45,14 @@ function! s:completion_begin(event) abort "{{{ \ 'g:deoplete#_omni_patterns')) if pattern != '' && &l:omnifunc != '' \ && context.input =~# '\%('.pattern.'\)$' - call deoplete#mappings#_set_completeopt() + call deoplete#mapping#_set_completeopt() call feedkeys("\\", 'n') return endif endfor endfor - call deoplete#mappings#_set_completeopt() + call deoplete#mapping#_set_completeopt() call rpcnotify(g:deoplete#_channel_id, \ 'deoplete_auto_completion_begin', context) endfunction"}}} diff --git a/autoload/deoplete/init.vim b/autoload/deoplete/init.vim index c80cd4e..658bf2d 100644 --- a/autoload/deoplete/init.vim +++ b/autoload/deoplete/init.vim @@ -72,7 +72,7 @@ function! deoplete#init#_initialize() abort "{{{ return 1 endif - call deoplete#mappings#_init() + call deoplete#mapping#_init() call deoplete#init#_variables() let s:is_enabled = g:deoplete#enable_at_startup diff --git a/autoload/deoplete/mapping.vim b/autoload/deoplete/mapping.vim new file mode 100644 index 0000000..ad191c1 --- /dev/null +++ b/autoload/deoplete/mapping.vim @@ -0,0 +1,41 @@ +"============================================================================= +" FILE: mapping.vim +" AUTHOR: Shougo Matsushita +" License: MIT license +"============================================================================= + +function! deoplete#mapping#_init() abort "{{{ + inoremap (deoplete_start_complete) + \ =deoplete#mapping#_do_complete(g:deoplete#_context) + inoremap (deoplete_auto_refresh) + \ =deoplete#mapping#refresh() +endfunction"}}} + +function! deoplete#mapping#_do_complete(context) abort "{{{ + if b:changedtick == get(a:context, 'changedtick', -1) + \ && mode() ==# 'i' + call complete(a:context.complete_position + 1, a:context.candidates) + endif + + return '' +endfunction"}}} +function! deoplete#mapping#_set_completeopt() abort "{{{ + if exists('g:deoplete#_saved_completeopt') + return + endif + let g:deoplete#_saved_completeopt = &completeopt + set completeopt-=longest + set completeopt+=menuone + set completeopt-=menu + if &completeopt !~# 'noinsert\|noselect' + set completeopt+=noselect + endif +endfunction"}}} +function! deoplete#mapping#_rpcnotify_wrapper(sources) abort "{{{ + call rpcrequest(g:deoplete#_channel_id, + \ 'deoplete_manual_completion_begin', + \ deoplete#init#_context('Manual', a:sources)) + return '' +endfunction"}}} + +" vim: foldmethod=marker diff --git a/autoload/deoplete/mappings.vim b/autoload/deoplete/mappings.vim index c4fc223..30432a0 100644 --- a/autoload/deoplete/mappings.vim +++ b/autoload/deoplete/mappings.vim @@ -4,84 +4,27 @@ " License: MIT license "============================================================================= -function! deoplete#mappings#_init() abort "{{{ - inoremap (deoplete_start_complete) - \ =deoplete#mappings#_do_complete(g:deoplete#_context) - inoremap (deoplete_auto_refresh) - \ =deoplete#mappings#refresh() -endfunction"}}} - -function! deoplete#mappings#_do_complete(context) abort "{{{ - if b:changedtick == get(a:context, 'changedtick', -1) - \ && mode() ==# 'i' - call complete(a:context.complete_position + 1, a:context.candidates) - endif - - return '' -endfunction"}}} -function! deoplete#mappings#_set_completeopt() abort "{{{ - if exists('g:deoplete#_saved_completeopt') - return - endif - let g:deoplete#_saved_completeopt = &completeopt - set completeopt-=longest - set completeopt+=menuone - set completeopt-=menu - if &completeopt !~# 'noinsert\|noselect' - set completeopt+=noselect - endif -endfunction"}}} +" For compatibility. function! deoplete#mappings#manual_complete(...) abort "{{{ - if deoplete#initialize() - return - endif - - " Start complete. - return (pumvisible() ? "\" : '') - \ . "\=deoplete#mappings#_rpcnotify_wrapper(" - \ . string(get(a:000, 0, [])) . ")\" -endfunction"}}} -function! deoplete#mappings#_rpcnotify_wrapper(sources) abort "{{{ - call rpcrequest(g:deoplete#_channel_id, - \ 'deoplete_manual_completion_begin', - \ deoplete#init#_context('Manual', a:sources)) - return '' + return call('deoplete#manual_complete', a:000) endfunction"}}} function! deoplete#mappings#close_popup() abort "{{{ - let g:deoplete#_context.position = getpos('.') - return pumvisible() ? "\" : '' + return deoplete#close_popup() endfunction"}}} function! deoplete#mappings#smart_close_popup() abort "{{{ - let g:deoplete#_context.position = getpos('.') - return pumvisible() ? "\" : '' + return deoplete#smart_close_popup() endfunction"}}} function! deoplete#mappings#cancel_popup() abort "{{{ - let g:deoplete#_context.position = getpos('.') - return pumvisible() ? "\" : '' + return deoplete#cancel_popup() endfunction"}}} function! deoplete#mappings#refresh() abort "{{{ - let g:deoplete#_context.refresh = 1 - if g:deoplete#_context.event ==# 'Manual' - let g:deoplete#_context.event = 'Refresh' - endif - return pumvisible() ? "\" : '' + return deoplete#refresh() endfunction"}}} function! deoplete#mappings#undo_completion() abort "{{{ - if !exists('v:completed_item') || empty(v:completed_item) - return '' - endif - - let input = deoplete#util#get_input('') - if strridx(input, v:completed_item.word) != - \ len(input) - len(v:completed_item.word) - return '' - endif - - return deoplete#mappings#smart_close_popup() . - \ repeat("\", strchars(v:completed_item.word)) + return deoplete#undo_completion() endfunction"}}} " vim: foldmethod=marker diff --git a/doc/deoplete.txt b/doc/deoplete.txt index d3585ee..3afa5c0 100644 --- a/doc/deoplete.txt +++ b/doc/deoplete.txt @@ -131,7 +131,7 @@ g:deoplete#auto_complete_start_length g:deoplete#disable_auto_complete It controls whether you invalidate automatic completion. If it is 1, automatic completion becomes invalid, but can use the - manual completion by |deoplete#mappings#manual_complete()|. + manual completion by |deoplete#manual_complete()|. Default value: 0 @@ -420,8 +420,8 @@ deoplete#enable_logging({level}, {logfile}) ------------------------------------------------------------------------------ KEY MAPPINGS *deoplete-key-mappings* - *deoplete#mappings#manual_complete()* -deoplete#mappings#manual_complete([{sources}]) + *deoplete#manual_complete()* +deoplete#manual_complete([{sources}]) Use this function with |:inoremap| (|:map-expression|). It calls the completion of deoplete. You can use it with custom completion setups. @@ -434,38 +434,37 @@ deoplete#mappings#manual_complete([{sources}]) typically. > inoremap - \ pumvisible() ? "\" : - \ deoplete#mappings#manual_complete() + \ pumvisible() ? "\" : deoplete#manual_complete() < - *deoplete#mappings#smart_close_popup()* -deoplete#mappings#smart_close_popup() + *deoplete#smart_close_popup()* +deoplete#smart_close_popup() Insert candidate and re-generate popup menu for deoplete. > inoremap - \ deoplete#mappings#smart_close_popup()."\" + \ deoplete#smart_close_popup()."\" inoremap - \ deoplete#mappings#smart_close_popup()."\" + \ deoplete#smart_close_popup()."\" < Note: This mapping is conflicted with |SuperTab| or |endwise| plugins. Note: This key mapping is for or keymappings. - *deoplete#mappings#close_popup()* -deoplete#mappings#close_popup() + *deoplete#close_popup()* +deoplete#close_popup() Insert candidate and close popup menu for deoplete. - *deoplete#mappings#undo_completion()* -deoplete#mappings#undo_completion() + *deoplete#undo_completion()* +deoplete#undo_completion() Undo inputted candidate. > - inoremap deoplete#mappings#undo_completion() + inoremap deoplete#undo_completion() < - *deoplete#mappings#refresh()* -deoplete#mappings#refresh() + *deoplete#refresh()* +deoplete#refresh() Refresh the candidates. > - inoremap deoplete#mappings#refresh() + inoremap deoplete#refresh() < ============================================================================== EXAMPLES *deoplete-examples* @@ -476,13 +475,13 @@ EXAMPLES *deoplete-examples* let g:deoplete#enable_smart_case = 1 " , : close popup and delete backword char. - inoremap deoplete#mappings#smart_close_popup()."\" - inoremap deoplete#mappings#smart_close_popup()."\" + inoremap deoplete#smart_close_popup()."\" + inoremap deoplete#smart_close_popup()."\" " : close popup and save indent. inoremap =my_cr_function() function! s:my_cr_function() abort - return deoplete#mappings#close_popup() . "\" + return deoplete#close_popup() . "\" endfunction < ============================================================================== @@ -1027,7 +1026,7 @@ new line, you should map . > inoremap =my_cr_function() function! s:my_cr_function() abort - return deoplete#mappings#close_popup() . "\" + return deoplete#close_popup() . "\" endfunction Q: I want to use "vim-lua-ftplugin". -- cgit v1.2.3 From 9ea7b7a944aabdd5cde66b3cce515cd4bc9e47c3 Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Thu, 23 Jun 2016 08:35:11 +0900 Subject: Remove obsolete check --- autoload/deoplete/init.vim | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/autoload/deoplete/init.vim b/autoload/deoplete/init.vim index 658bf2d..6768e9c 100644 --- a/autoload/deoplete/init.vim +++ b/autoload/deoplete/init.vim @@ -32,21 +32,6 @@ function! deoplete#init#_initialize() abort "{{{ return 1 endif - if &completeopt !~# 'noinsert\|noselect' - let save_completeopt = &completeopt - try - set completeopt+=noselect - catch - call deoplete#util#print_error( - \ 'deoplete.nvim does not work with this version.') - call deoplete#util#print_error( - \ 'Please update neovim to latest version.') - return 1 - finally - let &completeopt = save_completeopt - endtry - endif - try if !exists('g:loaded_remote_plugins') runtime! plugin/rplugin.vim -- cgit v1.2.3 From 2af84d10e2c9d6c70bc0d8bd97c964e47b6a2b08 Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Sun, 26 Jun 2016 11:08:11 +0900 Subject: Fix PHP omni pattern --- doc/deoplete.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/deoplete.txt b/doc/deoplete.txt index 3afa5c0..39e9821 100644 --- a/doc/deoplete.txt +++ b/doc/deoplete.txt @@ -288,7 +288,7 @@ g:deoplete#omni#input_patterns \ ['[^. *\t]\.\w*', '[a-zA-Z_]\w*::'] let g:deoplete#omni#input_patterns.java = '[^. *\t]\.\w*' let g:deoplete#omni#input_patterns.php = - \ '\w+|[^. \t]->\w*\|\w+::\w*' + \ '\w+|[^. \t]->\w*|\w+::\w*' < Default value: in g:deoplete#omni#_input_patterns -- cgit v1.2.3