diff --git a/autoload/ale/command.vim b/autoload/ale/command.vim new file mode 100644 index 0000000..f8d04ff --- /dev/null +++ b/autoload/ale/command.vim @@ -0,0 +1,57 @@ +" Author: w0rp +" Description: Special command formatting for creating temporary files and +" passing buffer filenames easily. + +function! s:TemporaryFilename(buffer) abort + let l:filename = fnamemodify(bufname(a:buffer), ':t') + + if empty(l:filename) + " If the buffer's filename is empty, create a dummy filename. + let l:ft = getbufvar(a:buffer, '&filetype') + let l:filename = 'file' . ale#filetypes#GuessExtension(l:ft) + endif + + " Create a temporary filename, / + " The file itself will not be created by this function. + return tempname() . (has('win32') ? '\' : '/') . l:filename +endfunction + +" Given a command string, replace every... +" %s -> with the current filename +" %t -> with the name of an unused file in a temporary directory +" %% -> with a literal % +function! ale#command#FormatCommand(buffer, command, pipe_file_if_needed) abort + let l:temporary_file = '' + let l:command = a:command + + " First replace all uses of %%, used for literal percent characters, + " with an ugly string. + let l:command = substitute(l:command, '%%', '<>', 'g') + + " Replace all %s occurences in the string with the name of the current + " file. + if l:command =~# '%s' + let l:filename = fnamemodify(bufname(a:buffer), ':p') + let l:command = substitute(l:command, '%s', '\=ale#Escape(l:filename)', 'g') + endif + + if l:command =~# '%t' + " Create a temporary filename, / + " The file itself will not be created by this function. + let l:temporary_file = s:TemporaryFilename(a:buffer) + let l:command = substitute(l:command, '%t', '\=ale#Escape(l:temporary_file)', 'g') + endif + + " Finish formatting so %% becomes %. + let l:command = substitute(l:command, '<>', '%', 'g') + + if a:pipe_file_if_needed && empty(l:temporary_file) + " If we are to send the Vim buffer to a command, we'll do it + " in the shell. We'll write out the file to a temporary file, + " and then read it back in, in the shell. + let l:temporary_file = s:TemporaryFilename(a:buffer) + let l:command = l:command . ' < ' . ale#Escape(l:temporary_file) + endif + + return [l:temporary_file, l:command] +endfunction diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index 49cc2a9..af074c0 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -313,52 +313,6 @@ function! ale#engine#EscapeCommandPart(command_part) abort return substitute(a:command_part, '%', '%%', 'g') endfunction -function! s:TemporaryFilename(buffer) abort - let l:filename = fnamemodify(bufname(a:buffer), ':t') - - if empty(l:filename) - " If the buffer's filename is empty, create a dummy filename. - let l:ft = getbufvar(a:buffer, '&filetype') - let l:filename = 'file' . ale#filetypes#GuessExtension(l:ft) - endif - - " Create a temporary filename, / - " The file itself will not be created by this function. - return tempname() . (has('win32') ? '\' : '/') . l:filename -endfunction - -" Given a command string, replace every... -" %s -> with the current filename -" %t -> with the name of an unused file in a temporary directory -" %% -> with a literal % -function! ale#engine#FormatCommand(buffer, command) abort - let l:temporary_file = '' - let l:command = a:command - - " First replace all uses of %%, used for literal percent characters, - " with an ugly string. - let l:command = substitute(l:command, '%%', '<>', 'g') - - " Replace all %s occurences in the string with the name of the current - " file. - if l:command =~# '%s' - let l:filename = fnamemodify(bufname(a:buffer), ':p') - let l:command = substitute(l:command, '%s', '\=ale#Escape(l:filename)', 'g') - endif - - if l:command =~# '%t' - " Create a temporary filename, / - " The file itself will not be created by this function. - let l:temporary_file = s:TemporaryFilename(a:buffer) - let l:command = substitute(l:command, '%t', '\=ale#Escape(l:temporary_file)', 'g') - endif - - " Finish formatting so %% becomes %. - let l:command = substitute(l:command, '<>', '%', 'g') - - return [l:temporary_file, l:command] -endfunction - function! s:CreateTemporaryFileForJob(buffer, temporary_file) abort if empty(a:temporary_file) " There is no file, so we didn't create anything. @@ -385,15 +339,7 @@ function! s:RunJob(options) abort let l:next_chain_index = a:options.next_chain_index let l:read_buffer = a:options.read_buffer - let [l:temporary_file, l:command] = ale#engine#FormatCommand(l:buffer, l:command) - - if l:read_buffer && empty(l:temporary_file) - " If we are to send the Vim buffer to a command, we'll do it - " in the shell. We'll write out the file to a temporary file, - " and then read it back in, in the shell. - let l:temporary_file = s:TemporaryFilename(l:buffer) - let l:command = l:command . ' < ' . ale#Escape(l:temporary_file) - endif + let [l:temporary_file, l:command] = ale#command#FormatCommand(l:buffer, l:command, l:read_buffer) if s:CreateTemporaryFileForJob(l:buffer, l:temporary_file) " If a temporary filename has been formatted in to the command, then diff --git a/test/test_format_command.vader b/test/test_format_command.vader index 08496c1..156ced9 100644 --- a/test/test_format_command.vader +++ b/test/test_format_command.vader @@ -7,16 +7,16 @@ After: unlet! g:match Execute(FormatCommand should do nothing to basic command strings): - AssertEqual ['', 'awesome-linter do something'], ale#engine#FormatCommand(bufnr('%'), 'awesome-linter do something') + AssertEqual ['', 'awesome-linter do something'], ale#command#FormatCommand(bufnr('%'), 'awesome-linter do something', 0) Execute(FormatCommand should handle %%, and ignore other percents): - AssertEqual ['', '% %%d %%f %x %'], ale#engine#FormatCommand(bufnr('%'), '%% %%%d %%%f %x %') + AssertEqual ['', '% %%d %%f %x %'], ale#command#FormatCommand(bufnr('%'), '%% %%%d %%%f %x %', 0) Execute(FormatCommand should convert %s to the current filename): - AssertEqual ['', 'foo ' . shellescape(expand('%:p')) . ' bar ' . shellescape(expand('%:p'))], ale#engine#FormatCommand(bufnr('%'), 'foo %s bar %s') + AssertEqual ['', 'foo ' . shellescape(expand('%:p')) . ' bar ' . shellescape(expand('%:p'))], ale#command#FormatCommand(bufnr('%'), 'foo %s bar %s', 0) Execute(FormatCommand should convert %t to a new temporary filename): - let g:result = ale#engine#FormatCommand(bufnr('%'), 'foo %t bar %t') + let g:result = ale#command#FormatCommand(bufnr('%'), 'foo %t bar %t', 0) let g:match = matchlist(g:result[1], '\v^foo (''/tmp/[^'']*/dummy.txt'') bar (''/tmp/[^'']*/dummy.txt'')$') Assert !empty(g:match), 'No match found! Result was: ' . g:result[1] @@ -27,7 +27,7 @@ Execute(FormatCommand should convert %t to a new temporary filename): AssertEqual g:match[1], g:match[2] Execute(FormatCommand should let you combine %s and %t): - let g:result = ale#engine#FormatCommand(bufnr('%'), 'foo %t bar %s') + let g:result = ale#command#FormatCommand(bufnr('%'), 'foo %t bar %s', 0) let g:match = matchlist(g:result[1], '\v^foo (''/tmp/.*/dummy.txt'') bar (''.*/dummy.txt'')$') Assert !empty(g:match), 'No match found! Result was: ' . g:result[1] @@ -39,3 +39,14 @@ Execute(FormatCommand should let you combine %s and %t): Execute(EscapeCommandPart should escape all percent signs): AssertEqual '%%s %%t %%%% %%s %%t %%%%', ale#engine#EscapeCommandPart('%s %t %% %s %t %%') + +Execute(EscapeCommandPart should pipe in temporary files appropriately): + let g:result = ale#command#FormatCommand(bufnr('%'), 'foo bar', 1) + let g:match = matchlist(g:result[1], '\v^foo bar \< (''/tmp/[^'']*/dummy.txt'')$') + Assert !empty(g:match), 'No match found! Result was: ' . g:result[1] + AssertEqual shellescape(g:result[0]), g:match[1] + + let g:result = ale#command#FormatCommand(bufnr('%'), 'foo bar %t', 1) + let g:match = matchlist(g:result[1], '\v^foo bar (''/tmp/[^'']*/dummy.txt'')$') + Assert !empty(g:match), 'No match found! Result was: ' . g:result[1] + AssertEqual shellescape(g:result[0]), g:match[1]