Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(utils): add neomake#utils#find_nearest_file_upwards #2528

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 38 additions & 1 deletion autoload/neomake/utils.vim
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ function! neomake#utils#path_sep() abort
return neomake#utils#IsRunningWindows() ? ';' : ':'
endfunction

" Find a file matching `a:glob` (using `globpath()`) by going up the
" Find a file/dir matching `a:glob` (using `globpath()`) by going up the
" directories from the start directory (a:1, defaults to `expand('%:p:h')`,
" i.e. the directory of the current buffer's file).)
function! neomake#utils#FindGlobFile(glob, ...) abort
Expand All @@ -552,6 +552,43 @@ function! neomake#utils#FindGlobFile(glob, ...) abort
return ''
endfunction

" Find the nearest file of the given filenames (upwards).
" (provides better performance than `neomake#utils#FindGlobFile`).
" a:1: optional start dir, defaulting to "current buffer" (".").
function! neomake#utils#find_nearest_file_upwards(fnames, ...) abort
if !empty(&suffixesadd)
let saved_suffixesadd = &suffixesadd
let &suffixesadd = ''
endif
" NOTE: findfile requires an absolute path, except for special '.'.
let path = (a:0 ? fnamemodify(a:1, ':p') : '.') . ';'
let found = ''
let found_parts_count = 0
for fname in a:fnames
let ffname = findfile(fname, path)
if empty(ffname)
continue
endif

let abs_ffname = fnamemodify(ffname, ':p')
if isdirectory(abs_ffname)
" Remove trailing slash.
let abs_ffname = fnamemodify(ffname, ':h')
endif
let abs_dir = fnamemodify(abs_ffname, ':h')
let part_count = len(split(abs_dir, neomake#utils#Slash()))
if part_count > found_parts_count
let found = abs_ffname
let found_parts_count = part_count
let path = fnamemodify(found, ':h') . '.'
endif
endfor
if exists('l:saved_suffixesadd')
let &suffixesadd = saved_suffixesadd
endif
return found
endfunction

function! neomake#utils#JSONdecode(json) abort
return neomake#compat#json_decode(a:json)
endfunction
Expand Down
62 changes: 61 additions & 1 deletion tests/utils.vader
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ Execute (neomake#utils#fnamemodify handles empty bufname):
AssertEqual neomake#utils#fnamemodify(bufnr('%'), ':p'), ''
bwipe

Execute (neomake#utils#FindGlobFile):
Execute (neomake#utils#FindGlobFile / neomake#utils#find_nearest_file_upwards):
let tempdir = tempname()
let slash = neomake#utils#Slash()
let subdir = tempdir . slash . 'sub'
Expand All @@ -778,13 +778,32 @@ Execute (neomake#utils#FindGlobFile):
let anotherfile_in_subdir = subdir.slash.'common-file-2'
call writefile([], anotherfile_in_subdir)

" tree:
" ├── common-file
" ├── sub
" │   ├── common-file
" │   ├── common-file-2
" │   └── sub-file
" └── temp-file

new
exe 'lcd' subdir
AssertEqual neomake#utils#FindGlobFile('doesnotexist'), ''
AssertEqual neomake#utils#FindGlobFile('sub-file'), subfile
AssertEqual neomake#utils#FindGlobFile('sub-file', subdir), subfile
AssertEqual neomake#utils#FindGlobFile('sub-file', tempdir), ''
AssertEqual neomake#utils#FindGlobFile('common-file'), file_in_subdir
AssertEqual neomake#utils#FindGlobFile('common-file', tempdir), file_in_tempdir
" Behaves the same.
AssertEqual neomake#utils#find_nearest_file_upwards(['doesnotexist']), ''
AssertEqual neomake#utils#find_nearest_file_upwards(['sub-file']), subfile
AssertEqual neomake#utils#find_nearest_file_upwards(['sub-file'], subdir), subfile
AssertEqual neomake#utils#find_nearest_file_upwards(['sub-file'], tempdir), ''
AssertEqual neomake#utils#find_nearest_file_upwards(['common-file']), file_in_subdir
AssertEqual neomake#utils#find_nearest_file_upwards(['common-file'], tempdir), file_in_tempdir

AssertEqual neomake#utils#find_nearest_file_upwards(['sub-file', 'temp-file']), subfile
AssertEqual neomake#utils#find_nearest_file_upwards(['common-file', 'temp-file']), file_in_subdir

exe 'lcd' tempdir
AssertEqual neomake#utils#FindGlobFile('sub-file'), ''
Expand All @@ -794,10 +813,51 @@ Execute (neomake#utils#FindGlobFile):
AssertEqual neomake#utils#FindGlobFile('common-file'), file_in_tempdir
AssertEqual neomake#utils#FindGlobFile('common-file'), file_in_tempdir
AssertEqual neomake#utils#FindGlobFile('common-file', subdir), file_in_subdir
" Behaves the same.
AssertEqual neomake#utils#find_nearest_file_upwards(['sub-file']), ''
AssertEqual neomake#utils#find_nearest_file_upwards(['sub-file'], subdir), subfile
AssertEqual neomake#utils#find_nearest_file_upwards(['sub-file'], tempdir), ''
AssertEqual neomake#utils#find_nearest_file_upwards(['sub-file'], tempname()), ''
AssertEqual neomake#utils#find_nearest_file_upwards(['common-file']), file_in_tempdir
AssertEqual neomake#utils#find_nearest_file_upwards(['common-file']), file_in_tempdir
AssertEqual neomake#utils#find_nearest_file_upwards(['common-file'], subdir), file_in_subdir

" Handles relative path/startdir.
AssertEqual neomake#utils#FindGlobFile('sub-file', 'sub'), 'sub'.slash.'sub-file'
AssertEqual neomake#utils#find_nearest_file_upwards(['sub-file'], 'sub'), subfile

" FindGlobFile handles directories.
AssertEqual neomake#utils#FindGlobFile('sub'), subdir
" find_nearest_file_upwards does not handle directories.
AssertEqual neomake#utils#find_nearest_file_upwards(['sub']), ''

" Only the first found file gets returned.
AssertEqual neomake#utils#FindGlobFile('common-file{,-2}', subdir), file_in_subdir
AssertEqual neomake#utils#FindGlobFile('common-file{-2,}', subdir), anotherfile_in_subdir
" Behaves the same.
AssertEqual neomake#utils#find_nearest_file_upwards(['common-file', 'common-file-2'], subdir), file_in_subdir
AssertEqual neomake#utils#find_nearest_file_upwards(['common-file-2', 'common-file'], subdir), anotherfile_in_subdir
bwipe

Execute (neomake#utils#find_nearest_file_upwards handles &suffixesadd):
let tempdir = tempname()
let slash = neomake#utils#Slash()
call mkdir(tempdir, 'p', 0700)
let file_with_ext = tempdir.slash.'file_with_ext.txt'
call writefile([], file_with_ext)

new
exe 'lcd' tempdir
setlocal suffixesadd=.txt

" Test behavior with used findfile.
AssertEqual findfile('file_with_ext', fnameescape(tempdir).';'), 'file_with_ext.txt'

AssertEqual neomake#utils#find_nearest_file_upwards(['file_with_ext']), ''
AssertEqual neomake#utils#find_nearest_file_upwards(['file_with_ext.txt']), file_with_ext

" Gets reset.
AssertEqual findfile('file_with_ext', '.;'), 'file_with_ext.txt'
bwipe

Execute (neomake#utils#shellescape):
Expand Down