Skip to content

Commit d144ada

Browse files
committed
ale: add FindNearestFileOrDirectory function
Some anchor paths can be files or directories (e.g., `.git` is a directory normally, but a file for worktrees). Add a function that finds either type of path and returns the nearest.
1 parent cd3d667 commit d144ada

File tree

8 files changed

+53
-0
lines changed

8 files changed

+53
-0
lines changed

autoload/ale/path.vim

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,37 @@ function! ale#path#FindNearestDirectory(buffer, directory_name) abort
6262
return ''
6363
endfunction
6464

65+
" Given a buffer and a filename, find the nearest file or directory by
66+
" searching upwards through the paths relative to the given buffer.
67+
function! ale#path#FindNearestFileOrDirectory(buffer, filename) abort
68+
let l:buffer_filename = fnamemodify(bufname(a:buffer), ':p')
69+
let l:buffer_filename = fnameescape(l:buffer_filename)
70+
71+
let l:relative_path_file = findfile(a:filename, l:buffer_filename . ';')
72+
let l:relative_path_dir = finddir(a:filename, l:buffer_filename . ';')
73+
74+
" If we find both a file and directory, choose the longer response by
75+
" making the longer one empty instead. We choose the shorter because the
76+
" longer one has more `../` components.
77+
if !empty(l:relative_path_file) && !empty(l:relative_path_dir)
78+
if strlen(l:relative_path_file) < strlen(l:relative_path_dir)
79+
let l:relative_path_dir = ''
80+
else
81+
let l:relative_path_file = ''
82+
endif
83+
endif
84+
85+
if !empty(l:relative_path_file)
86+
return fnamemodify(l:relative_path_file, ':p')
87+
endif
88+
89+
if !empty(l:relative_path_dir)
90+
return fnamemodify(l:relative_path_dir, ':p')
91+
endif
92+
93+
return ''
94+
endfunction
95+
6596
" Given a buffer, a string to search for, and a global fallback for when
6697
" the search fails, look for a file in parent paths, and if that fails,
6798
" use the global fallback path instead.

test/test-files/top/needle_dir/needle

Whitespace-only changes.

test/test-files/top/needle_dir/target/needle/.gitkeep

Whitespace-only changes.

test/test-files/top/needle_dir/target/query/buffer.txt

Whitespace-only changes.

test/test-files/top/needle_file/needle/.gitkeep

Whitespace-only changes.

test/test-files/top/needle_file/target/needle

Whitespace-only changes.

test/test-files/top/needle_file/target/query/buffer.txt

Whitespace-only changes.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Before:
2+
call ale#test#SetDirectory('/testplugin/test')
3+
4+
After:
5+
call ale#test#RestoreDirectory()
6+
7+
Execute(We should find a directory when searching and it is closer):
8+
call ale#test#SetFilename('test-files/top/needle_dir/target/query/buffer.txt')
9+
10+
AssertEqual
11+
\ ale#path#Simplify(expand('%:p:h:h:h:h:h:h') . '/test-files/top/needle_dir/target/needle'),
12+
\ ale#path#FindNearestFileOrDirectory(bufnr('%'), 'needle')
13+
14+
Execute(We should find a file when searching and it is closer):
15+
call ale#test#SetFilename('test-files/top/needle_file/target/query/buffer.txt')
16+
17+
AssertEqual
18+
\ ale#path#Simplify(expand('%:p:h:h:h:h:h:h') . '/test-files/top/needle_file/target/needle'),
19+
\ ale#path#FindNearestFileOrDirectory(bufnr('%'), 'needle')
20+
21+
Execute(We shouldn't find anything for files which don't match):
22+
AssertEqual '', ale#path#FindNearestFileOrDirectory(bufnr('%'), 'cantfindthis')

0 commit comments

Comments
 (0)