diff --git a/ale_linters/javascript/eslint.vim b/ale_linters/javascript/eslint.vim index e93113d4..e9b7d959 100644 --- a/ale_linters/javascript/eslint.vim +++ b/ale_linters/javascript/eslint.vim @@ -4,6 +4,26 @@ let g:ale_javascript_eslint_executable = \ get(g:, 'ale_javascript_eslint_executable', 'eslint') +let g:ale_javascript_eslint_use_global = +\ get(g:, 'ale_javascript_eslint_use_global', 0) + +function! ale_linters#javascript#eslint#GetExecutable(buffer) abort + if g:ale_javascript_eslint_use_global + return g:ale_javascript_eslint_executable + endif + + return ale#util#ResolveLocalPath( + \ a:buffer, + \ 'node_modules/.bin/eslint', + \ g:ale_javascript_eslint_executable + \) +endfunction + +function! ale_linters#javascript#eslint#GetCommand(buffer) abort + return ale_linters#javascript#eslint#GetExecutable(a:buffer) + \ . ' -f unix --stdin --stdin-filename %s' +endfunction + function! ale_linters#javascript#eslint#Handle(buffer, lines) " Matches patterns line the following: " @@ -39,7 +59,7 @@ endfunction call ale#linter#Define('javascript', { \ 'name': 'eslint', -\ 'executable': g:ale_javascript_eslint_executable, -\ 'command': g:ale_javascript_eslint_executable . ' -f unix --stdin --stdin-filename %s', +\ 'executable_callback': 'ale_linters#javascript#eslint#GetExecutable', +\ 'command_callback': 'ale_linters#javascript#eslint#GetCommand', \ 'callback': 'ale_linters#javascript#eslint#Handle', \}) diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim index 82bed85a..969e1e30 100644 --- a/autoload/ale/util.vim +++ b/autoload/ale/util.vim @@ -44,6 +44,21 @@ function! ale#util#FindNearestFile(buffer, filename) abort return '' endfunction +" Given a buffer, a string to search for, an a global fallback for when +" the search fails, look for a file in parent paths, and if that fails, +" use the global fallback path instead. +function! ale#util#ResolveLocalPath(buffer, search_string, global_fallback) abort + " Search for a locally installed file first. + let l:path = ale#util#FindNearestFile(a:buffer, a:search_string) + + " If the serach fails, try the global executable instead. + if empty(l:path) + let l:path = a:global_fallback + endif + + return l:path +endfunction + function! ale#util#GetFunction(string_or_ref) abort if type(a:string_or_ref) == type('') return function(a:string_or_ref) diff --git a/doc/ale.txt b/doc/ale.txt index 42531598..c879a98b 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -370,8 +370,25 @@ g:ale_javascript_eslint_executable *g:ale_javascript_eslint_executable* Type: |String| Default: `'eslint'` - This variable can be changed to change the path to eslint. If you have - eslint_d installed, you can set this option to use eslint_d instead. + ALE will first discover the eslint path in an ancestor node_modules + directory. If no such path exists, this variable will be used instead. + + This variable can be set to change the path to eslint. If you have eslint_d + installed, you can set this option to use eslint_d instead. + + If you wish to use only a globally installed version of eslint, set + |g:ale_javascript_eslint_use_global| to `1`. + + +g:ale_javascript_eslint_use_global *g:ale_javascript_eslint_use_global* + + Type: |String| + Default: `0` + + This variable controls whether or not ALE will search for a local path for + eslint first. If this variable is set to `1`, then ALE will always use the + global version of eslint, in preference to locally installed versions of + eslint in node_modules. ------------------------------------------------------------------------------- diff --git a/test/test_resolve_local_path.vader b/test/test_resolve_local_path.vader new file mode 100644 index 00000000..bdbac01b --- /dev/null +++ b/test/test_resolve_local_path.vader @@ -0,0 +1,15 @@ +Execute(Open a file some directory down): + silent! cd /testplugin/test + :e! top/middle/bottom/dummy.txt + +Then(We should be able to to find the local version of a file): + AssertEqual + \ expand('%:p:h:h:h:h') . '/top/example.ini', + \ ale#util#ResolveLocalPath(bufnr('%'), 'example.ini', '/global/config.ini') + +Execute(Do nothing): + +Then(We shouldn't find anything for files which don't match): + AssertEqual + \ '/global/config.ini', + \ ale#util#ResolveLocalPath(bufnr('%'), 'missing.ini', '/global/config.ini')