Skip to content

Commit

Permalink
Update python file_in_path completion
Browse files Browse the repository at this point in the history
  • Loading branch information
jityao committed Apr 23, 2022
1 parent 3cf8e52 commit 777b163
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 40 deletions.
21 changes: 21 additions & 0 deletions autoload/wilder/cmdline.vim
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ function! wilder#cmdline#prepare_file_completion(ctx, res, fuzzy)
let l:res = copy(a:res)
let l:arg = l:res.arg

if l:res.expand ==# 'file_in_path'
let l:res.fuzzy_char = ''
let l:res.expand_arg = l:arg
let l:res.match_arg = l:arg

return l:res
endif

" Remove backslash preceding spaces.
let l:arg = substitute(l:arg, '\\ ', ' ', 'g')

Expand Down Expand Up @@ -1123,6 +1131,10 @@ function! wilder#cmdline#getcompletion_pipeline(opts) abort
\ wilder#subpipeline({ctx, res -> [
\ {ctx, res -> s:getcompletion(ctx, res, l:fuzzy, l:use_python)},
\ wilder#result({
\ 'value': {ctx, xs, data -> l:fuzzy == 0 ?
\ s:filter_file_in_path(ctx, xs, data) : xs},
\ }),
\ wilder#result({
\ 'value': {ctx, xs -> get(res, 'relative_to_home_dir', 0) ?
\ map(xs, {i, x -> fnamemodify(x, ':~')}) : xs},
\ }),
Expand Down Expand Up @@ -1190,6 +1202,15 @@ function! wilder#cmdline#getcompletion_pipeline(opts) abort
\ ]
endfunction

function! s:filter_file_in_path(ctx, xs, data) abort
if get(a:data, 'cmdline.expand', '') !=# 'file_in_path'
return a:xs
endif

let l:arg = get(a:data, 'cmdline.arg', '')
return filter(a:xs, {_, x -> stridx(x, l:arg) != -1})
endfunction

function! s:get_lua_completion(ctx, res, fuzzy) abort
let l:last_char = a:res.arg[-1 :]
if !empty(l:last_char) &&
Expand Down
89 changes: 49 additions & 40 deletions rplugin/python3/wilder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,26 +344,13 @@ def _get_file_completion(self, args):

cwd = self.nvim.eval('getcwd()')
wildignore_opt = self.nvim.eval('&wildignore')
current_file_dir = self.nvim.eval('expand("%:p:h")')

add_dot = False

if expand_type == 'file_in_path':
directories = []
if expand_arg:
if expand_arg[0:2] == './':
directories = [cwd]
else:
relpath = os.path.relpath(expand_arg, cwd)
if relpath[0:2] == '..':
add_dot = True
directories = [cwd]

if not directories:
path_opt = self.nvim.eval('&path')
directories = path_opt.split(',')

directories = list(map(lambda d: self.nvim.eval('expand("%:p:h")') if d == '.' else d, directories))
directories = list(map(lambda d: cwd if d == '' else d, directories))
path_opt = self.nvim.eval('&path')
directories = path_opt.split(',')
elif expand_type == 'shellcmd':
directories = []
if expand_arg:
Expand All @@ -382,7 +369,7 @@ def _get_file_completion(self, args):
else:
directories = [cwd]

self.run_in_background(self.get_file_completion_handler, args + [wildignore_opt, directories, add_dot, cwd])
self.run_in_background(self.get_file_completion_handler, args + [wildignore_opt, directories, add_dot, cwd, current_file_dir])

def get_file_completion_handler(self,
event,
Expand All @@ -394,22 +381,30 @@ def get_file_completion_handler(self,
wildignore_opt,
directories,
add_dot,
cwd):
cwd,
current_file_dir):
if event.is_set():
return

try:
res = set()
original_has_wildcard = has_wildcard
res = list()
seen_files = set()
wildignore_list = wildignore_opt.split(',')
is_file_in_path = expand_type == 'file_in_path'
if is_file_in_path:
seen_file_names = set()
visited_directories = set()

checker = EventChecker(event)
for directory in directories:
if checker.check():
return

if is_file_in_path:
if not directory:
directory = cwd
elif directory == '.':
directory = current_file_dir

if not directory:
continue

Expand All @@ -418,13 +413,16 @@ def get_file_completion_handler(self,

visited_directories.add(directory)

has_wildcard = has_wildcard or '*' in directory
has_wildcard = original_has_wildcard or '*' in directory
if has_wildcard:
tail = os.path.basename(expand_arg)
show_hidden = tail.startswith('.')
pattern = ''
if is_file_in_path and directory == '**':
wildcard = os.path.join(cwd, '**')
if is_file_in_path:
if directory == '**':
wildcard = os.path.join(cwd, '**')
else:
wildcard = directory
elif expand_arg:
wildcard = os.path.join(directory, expand_arg)
else:
Expand All @@ -439,7 +437,10 @@ def get_file_completion_handler(self,
path = os.path.join(directory, expand_arg)
head, tail = os.path.split(path)
show_hidden = tail.startswith('.')
pattern = tail + '*'
if is_file_in_path:
pattern = ''
else:
pattern = tail + '*'

try:
it = os.scandir(head)
Expand Down Expand Up @@ -482,26 +483,25 @@ def get_file_completion_handler(self,
if is_file_in_path and directory == '**' and Path(entry) == Path(cwd):
continue

# iglob and scandir return different types
entry_name = str(entry) if has_wildcard else entry.name

if is_file_in_path:
file_name = os.path.basename(entry_name)
# add the base file name if not added already, otherwise add the full path
if file_name in seen_file_names:
entry_name = str(entry) if has_wildcard else entry.path
else:
entry_name = file_name
seen_file_names.add(file_name)
# iglob and scandir return different types
entry_name = str(entry) if has_wildcard else entry.path
entry_name = self.get_path_relative_to_cwd(entry_name, cwd)
else:
entry_name = str(entry) if has_wildcard else entry.name

if entry.is_dir():
entry_name += os.sep
res.add(entry_name)
if entry_name in seen_files:
continue
seen_files.add(entry_name)

res.append(entry_name)
except OSError:
pass
res = sorted(res)

if not has_wildcard:
if not original_has_wildcard and not is_file_in_path:
head = os.path.dirname(expand_arg)
res = list(map(lambda f: os.path.join(head, f) if head else f, res))

Expand All @@ -519,11 +519,20 @@ def get_file_completion_handler(self,
def is_descendant_path(self, p1, p2):
return os.path.relpath(p2, p1)[0:2] != '..'

def get_basename(self, f):
if f.endswith(os.sep) or f.endswith('/'):
return os.path.basename(f[:-1])
def get_basename(self, f, is_dir):
if is_dir:
return os.path.basename(f[:-1]) + os.sep
return os.path.basename(f)

def get_path_relative_to_cwd(self, p, cwd):
if not self.is_descendant_path(cwd, p):
return p

p = os.path.relpath(p, cwd)
if not p.startswith('/'):
p = os.path.join('.', p)
return p

@neovim.function('_wilder_python_get_help_tags', sync=False, allow_nested=True)
def _get_help_tags(self, args):
self.run_in_background(self.get_help_tags_handler, args)
Expand Down

0 comments on commit 777b163

Please sign in to comment.