87 lines
2.9 KiB
Python
87 lines
2.9 KiB
Python
|
# ============================================================================
|
||
|
# 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)
|