Skip to content

Commit 345a5a3

Browse files
committed
Use the correct buffer when running in an autocmd
In an autocmd (e.g., BufNew), `%` may not be the buffer being processed. Use `<afile>` and `<abuf>` in those cases instead.
1 parent daa5573 commit 345a5a3

1 file changed

Lines changed: 99 additions & 64 deletions

File tree

plugin/editorconfig.vim

Lines changed: 99 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -91,23 +91,24 @@ let s:initialized = 0
9191
" }}}1
9292

9393
" shellslash handling {{{1
94-
function! s:DisableShellSlash() " {{{2
94+
function! s:DisableShellSlash(bufnr) " {{{2
9595
" disable shellslash for proper escaping of Windows paths
9696

9797
" In Windows, 'shellslash' also changes the behavior of 'shellescape'.
9898
" It makes 'shellescape' behave like in UNIX environment. So ':setl
9999
" noshellslash' before evaluating 'shellescape' and restore the
100100
" settings afterwards when 'shell' does not contain 'sh' somewhere.
101-
if has('win32') && empty(matchstr(&shell, 'sh'))
102-
let s:old_shellslash = &l:shellslash
103-
setlocal noshellslash
101+
let l:shell = getbufvar(a:bufnr, '&shell')
102+
if has('win32') && empty(matchstr(l:shell, 'sh'))
103+
let s:old_shellslash = getbufvar(a:bufnr, '&shellslash')
104+
setbufvar(a:bufnr, '&shellslash', 0)
104105
endif
105106
endfunction " }}}2
106107

107-
function! s:ResetShellSlash() " {{{2
108+
function! s:ResetShellSlash(bufnr) " {{{2
108109
" reset shellslash to the user-set value, if any
109110
if exists('s:old_shellslash')
110-
let &l:shellslash = s:old_shellslash
111+
setbufvar(a:bufnr, '&shellslash', s:old_shellslash)
111112
unlet! s:old_shellslash
112113
endif
113114
endfunction " }}}2
@@ -204,9 +205,20 @@ function! s:GetFilenames(path, filename) " {{{1
204205
return l:path_list
205206
endfunction " }}}1
206207

207-
function! s:UseConfigFiles() abort " Apply config to the current buffer {{{1
208-
call setbufvar('%', 'editorconfig_tried', 1)
209-
let l:buffer_name = expand('%:p')
208+
function! s:UseConfigFiles(from_autocmd) abort " Apply config to the current buffer {{{1
209+
" from_autocmd is truthy if called from an autocmd, falsy otherwise.
210+
211+
" Get the properties of the buffer we are working on
212+
if a:from_autocmd
213+
let l:bufnr = str2nr(expand('<abuf>'))
214+
let l:buffer_name = expand('<afile>:p')
215+
let l:buffer_path = expand('<afile>:p:h')
216+
else
217+
let l:bufnr = bufnr('%')
218+
let l:buffer_name = expand('%:p')
219+
let l:buffer_path = expand('%:p:h')
220+
endif
221+
call setbufvar(l:bufnr, 'editorconfig_tried', 1)
210222

211223
" Only process normal buffers (do not treat help files as '.txt' files)
212224
" When starting Vim with a directory, the buftype might not yet be set:
@@ -226,7 +238,7 @@ function! s:UseConfigFiles() abort " Apply config to the current buffer {{{1
226238
endif
227239
endif
228240

229-
if getbufvar('%', 'EditorConfig_disable', 0)
241+
if getbufvar(l:bufnr, 'EditorConfig_disable', 0)
230242
if g:EditorConfig_verbose
231243
echo 'EditorConfig disabled --- skipping buffer "' . l:buffer_name . '"'
232244
endif
@@ -245,7 +257,7 @@ function! s:UseConfigFiles() abort " Apply config to the current buffer {{{1
245257
endfor
246258

247259
" Check if any .editorconfig does exist
248-
let l:conf_files = s:GetFilenames(expand('%:p:h'), '.editorconfig')
260+
let l:conf_files = s:GetFilenames(l:buffer_path, '.editorconfig')
249261
let l:conf_found = 0
250262
for conf_file in conf_files
251263
if filereadable(conf_file)
@@ -269,12 +281,12 @@ function! s:UseConfigFiles() abort " Apply config to the current buffer {{{1
269281
endif
270282

271283
if s:editorconfig_core_mode ==? 'vim_core'
272-
if s:UseConfigFiles_VimCore(l:buffer_name) == 0
273-
call setbufvar('%', 'editorconfig_applied', 1)
284+
if s:UseConfigFiles_VimCore(l:bufnr, l:buffer_name) == 0
285+
call setbufvar(l:bufnr, 'editorconfig_applied', 1)
274286
endif
275287
elseif s:editorconfig_core_mode ==? 'external_command'
276-
call s:UseConfigFiles_ExternalCommand(l:buffer_name)
277-
call setbufvar('%', 'editorconfig_applied', 1)
288+
call s:UseConfigFiles_ExternalCommand(l:bufnr, l:buffer_name)
289+
call setbufvar(l:bufnr, 'editorconfig_applied', 1)
278290
else
279291
echohl Error |
280292
\ echo "Unknown EditorConfig Core: " .
@@ -290,8 +302,8 @@ function! s:EditorConfigEnable(should_enable)
290302
augroup editorconfig
291303
autocmd!
292304
if a:should_enable
293-
autocmd BufNewFile,BufReadPost,BufFilePost * call s:UseConfigFiles()
294-
autocmd VimEnter,BufNew * call s:UseConfigFiles()
305+
autocmd BufNewFile,BufReadPost,BufFilePost * call s:UseConfigFiles(1)
306+
autocmd VimEnter,BufNew * call s:UseConfigFiles(1)
295307
endif
296308
augroup END
297309
endfunction
@@ -302,7 +314,7 @@ endfunction
302314
command! EditorConfigEnable call s:EditorConfigEnable(1)
303315
command! EditorConfigDisable call s:EditorConfigEnable(0)
304316

305-
command! EditorConfigReload call s:UseConfigFiles() " Reload EditorConfig files
317+
command! EditorConfigReload call s:UseConfigFiles(0) " Reload EditorConfig files
306318
" }}}2
307319

308320
" On startup, enable the autocommands
@@ -312,29 +324,29 @@ call s:EditorConfigEnable(1)
312324

313325
" UseConfigFiles function for different modes {{{1
314326

315-
function! s:UseConfigFiles_VimCore(target)
327+
function! s:UseConfigFiles_VimCore(bufnr, target)
316328
" Use the vimscript EditorConfig core
317329
try
318330
let l:config = editorconfig_core#handler#get_configurations(
319331
\ { 'target': a:target } )
320-
call s:ApplyConfig(l:config)
332+
call s:ApplyConfig(a:bufnr, l:config)
321333
return 0 " success
322334
catch
323335
return 1 " failure
324336
endtry
325337
endfunction
326338

327-
function! s:UseConfigFiles_ExternalCommand(target)
339+
function! s:UseConfigFiles_ExternalCommand(bufnr, target)
328340
" Use external EditorConfig core (e.g., the C core)
329341

330-
call s:DisableShellSlash()
342+
call s:DisableShellSlash(a:bufnr)
331343
let l:exec_path = shellescape(s:editorconfig_exec_path)
332-
call s:ResetShellSlash()
344+
call s:ResetShellSlash(a:bufnr)
333345

334-
call s:SpawnExternalParser(l:exec_path, a:target)
346+
call s:SpawnExternalParser(a:bufnr, l:exec_path, a:target)
335347
endfunction
336348

337-
function! s:SpawnExternalParser(cmd, target) " {{{2
349+
function! s:SpawnExternalParser(bufnr, cmd, target) " {{{2
338350
" Spawn external EditorConfig. Used by s:UseConfigFiles_ExternalCommand()
339351

340352
let l:cmd = a:cmd
@@ -345,9 +357,9 @@ function! s:SpawnExternalParser(cmd, target) " {{{2
345357

346358
let l:config = {}
347359

348-
call s:DisableShellSlash()
360+
call s:DisableShellSlash(a:bufnr)
349361
let l:cmd = l:cmd . ' ' . shellescape(a:target)
350-
call s:ResetShellSlash()
362+
call s:ResetShellSlash(a:bufnr)
351363

352364
let l:parsing_result = split(system(l:cmd), '\v[\r\n]+')
353365

@@ -386,96 +398,102 @@ function! s:SpawnExternalParser(cmd, target) " {{{2
386398
let l:config[l:eq_left] = l:eq_right
387399
endfor
388400

389-
call s:ApplyConfig(l:config)
401+
call s:ApplyConfig(a:bufnr, l:config)
390402
endfunction " }}}2
391403

392404
" }}}1
393405

394-
function! s:ApplyConfig(config) abort " Set the buffer options {{{1
406+
function! s:ApplyConfig(bufnr, config) abort " Set the buffer options {{{1
395407
if g:EditorConfig_verbose
396408
echo 'Options: ' . string(a:config)
397409
endif
398410

399411
if s:IsRuleActive('indent_style', a:config)
400412
if a:config["indent_style"] == "tab"
401-
setl noexpandtab
413+
call setbufvar(a:bufnr, '&expandtab', 0)
402414
elseif a:config["indent_style"] == "space"
403-
setl expandtab
415+
call setbufvar(a:bufnr, '&expandtab', 1)
404416
endif
405417
endif
406418

407419
if s:IsRuleActive('tab_width', a:config)
408-
let &l:tabstop = str2nr(a:config["tab_width"])
420+
let l:tabstop = str2nr(a:config["tab_width"])
421+
call setbufvar(a:bufnr, '&tabstop', l:tabstop)
422+
else
423+
" Grab the current ts so we can use it below
424+
let l:tabstop = getbufvar(a:bufnr, '&tabstop')
409425
endif
410426

411427
if s:IsRuleActive('indent_size', a:config)
412428
" if indent_size is 'tab', set shiftwidth to tabstop;
413429
" if indent_size is a positive integer, set shiftwidth to the integer
414430
" value
415431
if a:config["indent_size"] == "tab"
416-
let &l:shiftwidth = &l:tabstop
432+
call setbufvar(a:bufnr, '&shiftwidth', l:tabstop)
417433
if type(g:EditorConfig_softtabstop_tab) != type([])
418-
let &l:softtabstop = g:EditorConfig_softtabstop_tab > 0 ?
419-
\ &l:shiftwidth : g:EditorConfig_softtabstop_tab
434+
call setbufvar(a:bufnr, '&softtabstop',
435+
\ g:EditorConfig_softtabstop_tab > 0 ?
436+
\ l:tabstop : g:EditorConfig_softtabstop_tab)
420437
endif
421438
else
422439
let l:indent_size = str2nr(a:config["indent_size"])
423440
if l:indent_size > 0
424-
let &l:shiftwidth = l:indent_size
441+
call setbufvar(a:bufnr, '&shiftwidth', l:indent_size)
425442
if type(g:EditorConfig_softtabstop_space) != type([])
426-
let &l:softtabstop = g:EditorConfig_softtabstop_space > 0 ?
427-
\ &l:shiftwidth : g:EditorConfig_softtabstop_space
443+
call setbufvar(a:bufnr, '&softtabstop',
444+
\ g:EditorConfig_softtabstop_space > 0 ?
445+
\ l:indent_size : g:EditorConfig_softtabstop_space)
428446
endif
429447
endif
430448
endif
431449

432450
endif
433451

434452
if s:IsRuleActive('end_of_line', a:config) &&
435-
\ &l:modifiable
453+
\ getbufvar(a:bufnr, '&modifiable')
436454
if a:config["end_of_line"] == "lf"
437-
setl fileformat=unix
455+
call setbufvar(a:bufnr, '&fileformat', 'unix')
438456
elseif a:config["end_of_line"] == "crlf"
439-
setl fileformat=dos
457+
call setbufvar(a:bufnr, '&fileformat', 'dos')
440458
elseif a:config["end_of_line"] == "cr"
441-
setl fileformat=mac
459+
call setbufvar(a:bufnr, '&fileformat', 'mac')
442460
endif
443461
endif
444462

445463
if s:IsRuleActive('charset', a:config) &&
446-
\ &l:modifiable
464+
\ getbufvar(a:bufnr, '&modifiable')
447465
if a:config["charset"] == "utf-8"
448-
setl fileencoding=utf-8
449-
setl nobomb
466+
call setbufvar(a:bufnr, '&fileencoding', 'utf-8')
467+
call setbufvar(a:bufnr, '&bomb', 0)
450468
elseif a:config["charset"] == "utf-8-bom"
451-
setl fileencoding=utf-8
452-
setl bomb
469+
call setbufvar(a:bufnr, '&fileencoding', 'utf-8')
470+
call setbufvar(a:bufnr, '&bomb', 1)
453471
elseif a:config["charset"] == "latin1"
454-
setl fileencoding=latin1
455-
setl nobomb
472+
call setbufvar(a:bufnr, '&fileencoding', 'latin1')
473+
call setbufvar(a:bufnr, '&bomb', 0)
456474
elseif a:config["charset"] == "utf-16be"
457-
setl fileencoding=utf-16be
458-
setl bomb
475+
call setbufvar(a:bufnr, '&fileencoding', 'utf-16be')
476+
call setbufvar(a:bufnr, '&bomb', 1)
459477
elseif a:config["charset"] == "utf-16le"
460-
setl fileencoding=utf-16le
461-
setl bomb
478+
call setbufvar(a:bufnr, '&fileencoding', 'utf-16le')
479+
call setbufvar(a:bufnr, '&bomb', 1)
462480
endif
463481
endif
464482

465483
augroup editorconfig_trim_trailing_whitespace
466484
autocmd! BufWritePre <buffer>
467485
if s:IsRuleActive('trim_trailing_whitespace', a:config) &&
468486
\ get(a:config, 'trim_trailing_whitespace', 'false') ==# 'true'
469-
autocmd BufWritePre <buffer> call s:TrimTrailingWhitespace()
487+
execute 'autocmd BufWritePre <buffer=' . a:bufnr . '> call s:TrimTrailingWhitespace()'
470488
endif
471489
augroup END
472490

473491
if s:IsRuleActive('insert_final_newline', a:config)
474492
if exists('+fixendofline')
475493
if a:config["insert_final_newline"] == "false"
476-
setl nofixendofline
494+
call setbufvar(a:bufnr, '&fixendofline', 0)
477495
else
478-
setl fixendofline
496+
call setbufvar(a:bufnr, '&fixendofline', 1)
479497
endif
480498
elseif exists(':SetNoEOL') == 2
481499
if a:config["insert_final_newline"] == "false"
@@ -490,23 +508,39 @@ function! s:ApplyConfig(config) abort " Set the buffer options {{{1
490508
let l:max_line_length = str2nr(a:config['max_line_length'])
491509

492510
if l:max_line_length >= 0
493-
let &l:textwidth = l:max_line_length
511+
call setbufvar(a:bufnr, '&textwidth', l:max_line_length)
494512
if g:EditorConfig_preserve_formatoptions == 0
495-
setlocal formatoptions+=tc
513+
" setlocal formatoptions+=tc
514+
let l:fo = getbufvar(a:bufnr, '&formatoptions')
515+
if l:fo !~# 't'
516+
let l:fo .= 't'
517+
endif
518+
if l:fo !~# 'c'
519+
let l:fo .= 'c'
520+
endif
521+
call setbufvar(a:bufnr, '&formatoptions', l:fo)
496522
endif
497523
endif
498524

499525
if exists('+colorcolumn')
500526
if l:max_line_length > 0
501527
if g:EditorConfig_max_line_indicator == 'line'
502-
setlocal colorcolumn+=+1
528+
" setlocal colorcolumn+=+1
529+
let l:cocol = getbufvar(a:bufnr, '&colorcolumn')
530+
if !empty(l:cocol)
531+
let l:cocol .= ','
532+
endif
533+
let l:cocol .= '+1'
534+
call setbufvar(a:bufnr, '&colorcolumn', l:cocol)
503535
elseif g:EditorConfig_max_line_indicator == 'fill' &&
504-
\ l:max_line_length < &l:columns
536+
\ l:max_line_length < getbufvar(a:bufnr, '&columns')
505537
" Fill only if the columns of screen is large enough
506-
let &l:colorcolumn = join(
507-
\ range(l:max_line_length+1,&l:columns),',')
538+
call setbufvar(a:bufnr, '&colorcolumn',
539+
\ join(range(l:max_line_length+1,
540+
\ getbufvar(a:bufnr, '&columns')),
541+
\ ','))
508542
elseif g:EditorConfig_max_line_indicator == 'exceeding'
509-
let &l:colorcolumn = ''
543+
call setbufvar(a:bufnr, '&colorcolumn', '')
510544
for l:match in getmatches()
511545
if get(l:match, 'group', '') == 'ColorColumn'
512546
call matchdelete(get(l:match, 'id'))
@@ -534,7 +568,8 @@ endfunction
534568
" }}}1
535569

536570
function! s:TrimTrailingWhitespace() " {{{1
537-
if &l:modifiable
571+
" Called from within a buffer-specific autocmd, so we can use '%'
572+
if getbufvar('%', '&modifiable')
538573
" don't lose user position when trimming trailing whitespace
539574
let s:view = winsaveview()
540575
try

0 commit comments

Comments
 (0)