2015-05-23 04:02:05 -04:00
|
|
|
" TODO:
|
|
|
|
" - Make :Autoformat accept ranges
|
|
|
|
|
|
|
|
|
2015-05-18 13:27:00 -04:00
|
|
|
" Function for finding the formatters for this filetype
|
2015-05-23 04:02:05 -04:00
|
|
|
" Result is stored in b:formatters
|
2015-05-18 13:27:00 -04:00
|
|
|
function! s:find_formatters(...)
|
|
|
|
" Detect verbosity
|
2015-05-23 04:02:05 -04:00
|
|
|
let verbose = &verbose || exists("g:autoformat_verbosemode")
|
2015-05-18 13:27:00 -04:00
|
|
|
|
|
|
|
" Extract filetype to be used
|
2014-06-29 15:30:05 -04:00
|
|
|
let type = a:0 ? a:1 : &filetype
|
2015-04-09 04:59:54 -04:00
|
|
|
" Support composite filetypes by replacing dots with underscores
|
2015-01-12 08:17:27 -05:00
|
|
|
let type = substitute(type, "[.]", "_", "g")
|
2014-06-29 15:30:05 -04:00
|
|
|
|
2015-05-23 04:02:05 -04:00
|
|
|
let formatters_var = "g:formatters_".type
|
2015-05-18 13:27:00 -04:00
|
|
|
let b:formatters = []
|
2013-03-10 14:51:39 -04:00
|
|
|
|
2015-05-23 04:02:05 -04:00
|
|
|
if !exists(formatters_var)
|
2015-05-18 13:27:00 -04:00
|
|
|
" No formatters defined
|
2015-05-23 04:02:05 -04:00
|
|
|
if verbose
|
2015-05-18 13:27:00 -04:00
|
|
|
echoerr "No formatters defined for filetype '".type."'."
|
2013-03-16 05:36:16 -04:00
|
|
|
endif
|
2013-03-15 18:12:09 -04:00
|
|
|
return 0
|
2013-03-14 13:50:31 -04:00
|
|
|
endif
|
|
|
|
|
2015-05-23 04:02:05 -04:00
|
|
|
let formatters = eval(formatters_var)
|
|
|
|
if len(formatters) == 0
|
2015-05-18 13:27:00 -04:00
|
|
|
" No formatters defined
|
2015-05-23 04:02:05 -04:00
|
|
|
if verbose
|
2015-05-18 13:27:00 -04:00
|
|
|
echoerr "No formatters defined for filetype '".type."'."
|
2013-03-14 13:50:31 -04:00
|
|
|
endif
|
2013-12-20 14:34:38 -05:00
|
|
|
return 0
|
2013-03-14 13:50:31 -04:00
|
|
|
endif
|
2013-03-01 09:06:13 -05:00
|
|
|
|
2015-05-23 04:02:05 -04:00
|
|
|
let b:formatters = formatters
|
2015-05-18 13:27:00 -04:00
|
|
|
return 1
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
2015-05-23 04:02:05 -04:00
|
|
|
" Try all formatters, starting with the currently selected one, until one
|
|
|
|
" works. If none works, autoindent the buffer.
|
|
|
|
function! s:TryAllFormatters(...)
|
2015-05-18 13:27:00 -04:00
|
|
|
" Make sure formatters are defined and detected
|
|
|
|
if !call('<SID>find_formatters', a:000)
|
|
|
|
return 0
|
|
|
|
endif
|
|
|
|
|
|
|
|
" Make sure index exist and is valid
|
|
|
|
if !exists('b:current_formatter_index')
|
|
|
|
let b:current_formatter_index = 0
|
|
|
|
endif
|
|
|
|
if b:current_formatter_index >= len(b:formatters)
|
|
|
|
let b:current_formatter_index = 0
|
|
|
|
endif
|
|
|
|
|
2015-05-23 04:02:05 -04:00
|
|
|
" Try all formatters, starting with selected one
|
2015-05-23 08:25:29 -04:00
|
|
|
let s:index = b:current_formatter_index
|
2015-05-23 04:02:05 -04:00
|
|
|
|
|
|
|
while 1
|
2015-05-23 08:25:29 -04:00
|
|
|
let formatdef_var = 'g:formatdef_'.b:formatters[s:index]
|
2015-05-23 04:02:05 -04:00
|
|
|
" Formatter definition must be existent
|
2015-05-23 08:25:29 -04:00
|
|
|
if !exists(formatdef_var)
|
|
|
|
echoerr "No format definition found in '".formatdef_var."'."
|
2015-05-23 04:02:05 -04:00
|
|
|
return 0
|
|
|
|
endif
|
|
|
|
|
|
|
|
" Eval twice, once for getting definition content,
|
|
|
|
" once for getting the final expression
|
2015-05-23 08:25:29 -04:00
|
|
|
let &formatprg = eval(eval(formatdef_var))
|
2015-05-23 04:02:05 -04:00
|
|
|
if s:TryFormatter()
|
|
|
|
return 1
|
|
|
|
else
|
2015-05-23 08:25:29 -04:00
|
|
|
let s:index = (s:index + 1) % len(b:formatters)
|
2015-05-23 04:02:05 -04:00
|
|
|
endif
|
|
|
|
|
2015-05-23 08:25:29 -04:00
|
|
|
if s:index == b:current_formatter_index
|
|
|
|
" Tried all formatters, none worked
|
2015-05-23 04:02:05 -04:00
|
|
|
return 0
|
|
|
|
endif
|
|
|
|
endwhile
|
|
|
|
|
|
|
|
|
|
|
|
" Autoindent code if no formatters work
|
|
|
|
exe "normal gg=G"
|
2015-05-18 13:27:00 -04:00
|
|
|
|
2013-03-15 18:12:09 -04:00
|
|
|
endfunction
|
2013-03-01 09:06:13 -05:00
|
|
|
|
2015-05-18 13:27:00 -04:00
|
|
|
|
2015-05-23 04:02:05 -04:00
|
|
|
" Call formatter
|
|
|
|
" If stderr is empty, apply result, return 1
|
|
|
|
" Otherwise, return 0
|
|
|
|
function! s:TryFormatter()
|
|
|
|
" Detect verbosity
|
|
|
|
let verbose = &verbose || exists("g:autoformat_verbosemode")
|
2013-03-14 13:50:31 -04:00
|
|
|
|
2015-04-09 04:59:54 -04:00
|
|
|
" Save window state
|
2013-03-15 18:12:09 -04:00
|
|
|
let winview=winsaveview()
|
2013-03-26 18:03:15 -04:00
|
|
|
|
2015-05-18 13:27:00 -04:00
|
|
|
python << EOF
|
|
|
|
import vim, subprocess
|
|
|
|
from subprocess import Popen, PIPE
|
|
|
|
text = '\n'.join(vim.current.buffer[:])
|
|
|
|
formatprg = vim.eval('&formatprg')
|
2015-05-23 04:02:05 -04:00
|
|
|
verbose = vim.eval('verbose')
|
2015-05-18 13:27:00 -04:00
|
|
|
p = subprocess.Popen(formatprg, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
|
|
|
stdoutdata, stderrdata = p.communicate(text)
|
|
|
|
if stderrdata:
|
2015-05-23 04:02:05 -04:00
|
|
|
if verbose:
|
2015-05-23 08:25:29 -04:00
|
|
|
formattername = vim.eval('b:formatters[s:index]')
|
|
|
|
vim.command('echom "Formatter {} has errors: {}. Skipping."'.format(formattername,
|
2015-05-23 04:02:05 -04:00
|
|
|
stderrdata))
|
2015-05-23 08:25:29 -04:00
|
|
|
vim.command('echom "Failing config: {} "'.format(repr(formatprg), stderrdata))
|
2015-05-23 04:02:05 -04:00
|
|
|
vim.command('return 0')
|
2015-05-18 13:27:00 -04:00
|
|
|
else:
|
|
|
|
vim.current.buffer[:] = stdoutdata.split('\n')
|
|
|
|
EOF
|
|
|
|
|
2015-04-09 04:59:54 -04:00
|
|
|
" Recall window state
|
2013-03-15 18:12:09 -04:00
|
|
|
call winrestview(winview)
|
2015-05-23 04:02:05 -04:00
|
|
|
|
|
|
|
return 1
|
2013-03-14 13:50:31 -04:00
|
|
|
endfunction
|
|
|
|
|
2015-05-23 04:02:05 -04:00
|
|
|
|
2015-04-09 04:59:54 -04:00
|
|
|
" Create a command for formatting the entire buffer
|
2015-05-23 04:02:05 -04:00
|
|
|
command! -nargs=? -complete=filetype Autoformat call s:TryAllFormatters(<f-args>)
|
2015-05-18 13:27:00 -04:00
|
|
|
|
|
|
|
|
|
|
|
" Functions for iterating through list of available formatters
|
|
|
|
function! s:NextFormatter()
|
|
|
|
call s:find_formatters()
|
|
|
|
if !exists('b:current_formatter_index')
|
|
|
|
let b:current_formatter_index = 0
|
|
|
|
endif
|
|
|
|
let b:current_formatter_index = (b:current_formatter_index + 1) % len(b:formatters)
|
2015-05-23 08:25:29 -04:00
|
|
|
echom 'Selected formatter: '.b:formatters[b:current_formatter_index]
|
2015-05-18 13:27:00 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:PreviousFormatter()
|
|
|
|
call s:find_formatters()
|
|
|
|
if !exists('b:current_formatter_index')
|
|
|
|
let b:current_formatter_index = 0
|
|
|
|
endif
|
2015-05-23 04:02:05 -04:00
|
|
|
let l = len(b:formatters)
|
|
|
|
let b:current_formatter_index = (b:current_formatter_index - 1 + l) % l
|
2015-05-23 08:25:29 -04:00
|
|
|
echom 'Selected formatter: '.b:formatters[b:current_formatter_index]
|
2015-05-18 13:27:00 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
" Create commands for iterating through formatter list
|
|
|
|
command! NextFormatter call s:NextFormatter()
|
|
|
|
command! PreviousFormatter call s:PreviousFormatter()
|