diff --git a/autoload/ale/pattern_options.vim b/autoload/ale/pattern_options.vim index a603c980..a55a27f6 100644 --- a/autoload/ale/pattern_options.vim +++ b/autoload/ale/pattern_options.vim @@ -1,22 +1,34 @@ " Author: w0rp " Description: Set options in files based on regex patterns. -function! ale#pattern_options#SetOptions() abort - let l:filename = expand('%:p') " no-custom-checks - let l:options = {} +function! s:CmpPatterns(left_item, right_item) abort + if a:left_item[0] < a:right_item[0] + return -1 + endif - for l:pattern in keys(g:ale_pattern_options) + if a:left_item[0] > a:right_item[0] + return 1 + endif + + return 0 +endfunction + +function! ale#pattern_options#SetOptions(buffer) abort + if !g:ale_pattern_options_enabled || empty(g:ale_pattern_options) + return + endif + + let l:filename = expand('#' . a:buffer . ':p') + + " The patterns are sorted, so they are applied consistently. + for [l:pattern, l:options] in sort( + \ items(g:ale_pattern_options), + \ function('s:CmpPatterns') + \) if match(l:filename, l:pattern) >= 0 - let l:options = g:ale_pattern_options[l:pattern] - break - endif - endfor - - for l:key in keys(l:options) - if l:key[:0] is# '&' - call setbufvar(bufnr(''), l:key, l:options[l:key]) - else - let b:[l:key] = l:options[l:key] + for [l:key, l:value] in items(l:options) + call setbufvar(a:buffer, l:key, l:value) + endfor endif endfor endfunction diff --git a/autoload/ale/toggle.vim b/autoload/ale/toggle.vim index 6809edd1..aa6d113b 100644 --- a/autoload/ale/toggle.vim +++ b/autoload/ale/toggle.vim @@ -4,9 +4,7 @@ function! ale#toggle#InitAuGroups() abort augroup ALEPatternOptionsGroup autocmd! - if g:ale_enabled && g:ale_pattern_options_enabled - autocmd BufEnter,BufRead * call ale#pattern_options#SetOptions() - endif + autocmd BufEnter,BufRead * call ale#pattern_options#SetOptions(str2nr(expand(''))) augroup END augroup ALERunOnTextChangedGroup @@ -71,7 +69,6 @@ function! ale#toggle#InitAuGroups() abort augroup END if !g:ale_enabled - augroup! ALEPatternOptionsGroup augroup! ALERunOnTextChangedGroup augroup! ALERunOnEnterGroup augroup! ALERunOnInsertLeave diff --git a/doc/ale.txt b/doc/ale.txt index 83646c57..4ad88914 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -1007,11 +1007,14 @@ g:ale_pattern_options *g:ale_pattern_options* only `eslint` for checking those files by setting `b:ale_linters`. Filenames are matched with |match()|, and patterns depend on the |magic| - setting, unless prefixed with the special escape sequences like `'\v'`, etc. - - The patterns can match any part of a filename. The absolute path of the + setting, unless prefixed with the special escape sequences like `'\v'`, + etc.The patterns can match any part of a filename. The absolute path of the filename will be used for matching, taken from `expand('%:p')`. + The options for every match for the filename will be applied, with the + pattern keys sorted in alphabetical order. Options for `'zebra'` will + override the options for `'alpha'` for a filename `alpha-zebra`. + g:ale_pattern_options_enabled *g:ale_pattern_options_enabled* @@ -1019,8 +1022,9 @@ g:ale_pattern_options_enabled *g:ale_pattern_options_enabled* Default: `!empty(g:ale_pattern_options)` This option can be used for turning the behaviour of setting - |g:ale_pattern_options| on or off. By default, setting a single key - for |g:ale_pattern_options| will turn this option on. + |g:ale_pattern_options| on or off. By default, setting a single key for + |g:ale_pattern_options| will turn this option on, as long as the setting is + configured before ALE is loaded. g:ale_set_balloons *g:ale_set_balloons* diff --git a/test/test_autocmd_commands.vader b/test/test_autocmd_commands.vader index 88504a9b..e7e9e86e 100644 --- a/test/test_autocmd_commands.vader +++ b/test/test_autocmd_commands.vader @@ -108,17 +108,28 @@ Execute (g:ale_lint_on_insert_leave = 0 should bind no events): AssertEqual [], CheckAutocmd('ALERunOnInsertLeave') -Execute (g:ale_pattern_options_enabled = 0 should bind no events): - let g:ale_pattern_options_enabled = 0 - - AssertEqual [], CheckAutocmd('ALEPatternOptionsGroup') - Execute (g:ale_pattern_options_enabled = 1 should bind BufReadPost and BufEnter): let g:ale_pattern_options_enabled = 1 AssertEqual [ - \ 'BufEnter * call ale#pattern_options#SetOptions()', - \ 'BufReadPost * call ale#pattern_options#SetOptions()', + \ 'BufEnter * call ale#pattern_options#SetOptions(str2nr(expand('''')))', + \ 'BufReadPost * call ale#pattern_options#SetOptions(str2nr(expand('''')))', + \], CheckAutocmd('ALEPatternOptionsGroup') + +Execute (g:ale_pattern_options_enabled = 0 should still bind events): + let g:ale_pattern_options_enabled = 0 + + AssertEqual [ + \ 'BufEnter * call ale#pattern_options#SetOptions(str2nr(expand('''')))', + \ 'BufReadPost * call ale#pattern_options#SetOptions(str2nr(expand('''')))', + \], CheckAutocmd('ALEPatternOptionsGroup') + +Execute (g:ale_enabled = 0 should still bind pattern events): + let g:ale_enabled = 0 + + AssertEqual [ + \ 'BufEnter * call ale#pattern_options#SetOptions(str2nr(expand('''')))', + \ 'BufReadPost * call ale#pattern_options#SetOptions(str2nr(expand('''')))', \], CheckAutocmd('ALEPatternOptionsGroup') Execute (g:ale_lint_on_enter = 0 should bind only the BufEnter event): diff --git a/test/test_pattern_options.vader b/test/test_pattern_options.vader index 164e5aa7..0ad4415f 100644 --- a/test/test_pattern_options.vader +++ b/test/test_pattern_options.vader @@ -3,30 +3,74 @@ Before: Save g:ale_pattern_options_enabled Save &filetype + let g:ale_pattern_options_enabled = 1 + let g:ale_pattern_options = {} + + let b:ale_enabled = 0 + let b:some_option = 0 + + call ale#test#SetDirectory('/testplugin/test') + After: Restore unlet! b:ale_enabled unlet! b:some_option + call ale#test#RestoreDirectory() + +Execute(The pattern options function should work when there are no patterns): + call ale#test#SetFilename('foobar.js') + call ale#pattern_options#SetOptions(bufnr('')) + Execute(Buffer variables should be set when filename patterns match): - let g:ale_pattern_options = {'baz.*\.js': { - \ 'ale_enabled': 1, - \ 'some_option': 347, - \ '&filetype': 'pattern_option_set_filetype', - \}} + let g:ale_pattern_options = { + \ 'baz.*\.js': { + \ 'ale_enabled': 1, + \ 'some_option': 347, + \ '&filetype': 'pattern_option_set_filetype', + \ }, + \} - silent! file foobar.js + call ale#test#SetFilename('foobar.js') + call ale#pattern_options#SetOptions(bufnr('')) - call ale#pattern_options#SetOptions() + AssertEqual 0, b:ale_enabled + AssertEqual 0, b:some_option - Assert !exists('b:ale_enabled') - Assert !exists('b:some_option') - - silent! file bazboz.js - - call ale#pattern_options#SetOptions() + call ale#test#SetFilename('bazboz.js') + call ale#pattern_options#SetOptions(bufnr('')) AssertEqual 1, b:ale_enabled AssertEqual 347, b:some_option AssertEqual 'pattern_option_set_filetype', &filetype + +Execute(Multiple pattern matches should be applied): + let g:ale_pattern_options = { + \ 'foo': { + \ 'some_option': 666, + \ }, + \ 'bar': { + \ 'ale_enabled': 1, + \ 'some_option': 123, + \ }, + \ 'notmatched': { + \ 'some_option': 489, + \ 'ale_enabled': 0, + \ }, + \} + + call ale#test#SetFilename('foobar.js') + call ale#pattern_options#SetOptions(bufnr('')) + + AssertEqual 1, b:ale_enabled + AssertEqual 666, b:some_option + +Execute(Patterns should not be applied when the setting is disabled): + let g:ale_pattern_options_enabled = 0 + let g:ale_pattern_options = {'foo': {'some_option': 666}} + + call ale#test#SetFilename('foobar.js') + call ale#pattern_options#SetOptions(bufnr('')) + + AssertEqual 0, b:some_option