You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
4.9 KiB
VimL
167 lines
4.9 KiB
VimL
4 years ago
|
" Adapted from fatih/vim-go: autoload/go/fmt.vim
|
||
|
"
|
||
|
" Copyright 2011 The Go Authors. All rights reserved.
|
||
|
" Use of this source code is governed by a BSD-style
|
||
|
" license that can be found in the LICENSE file.
|
||
|
"
|
||
|
function! zig#fmt#Format() abort
|
||
|
if zig#config#FmtExperimental()
|
||
|
" Using winsaveview to save/restore cursor state has the problem of
|
||
|
" closing folds on save:
|
||
|
" https://github.com/fatih/vim-go/issues/502
|
||
|
" One fix is to use mkview instead. Unfortunately, this sometimes causes
|
||
|
" other bad side effects:
|
||
|
" https://github.com/fatih/vim-go/issues/728
|
||
|
" and still closes all folds if foldlevel>0:
|
||
|
" https://github.com/fatih/vim-go/issues/732
|
||
|
let l:curw = {}
|
||
|
try
|
||
|
mkview!
|
||
|
catch
|
||
|
let l:curw = winsaveview()
|
||
|
endtry
|
||
|
|
||
|
" save our undo file to be restored after we are done. This is needed to
|
||
|
" prevent an additional undo jump due to BufWritePre auto command and also
|
||
|
" restore 'redo' history because it's getting being destroyed every
|
||
|
" BufWritePre
|
||
|
let tmpundofile = tempname()
|
||
|
exe 'wundo! ' . tmpundofile
|
||
|
else
|
||
|
" Save cursor position and many other things.
|
||
|
let l:curw = winsaveview()
|
||
|
endif
|
||
|
|
||
|
" Save cursor position and many other things.
|
||
|
let l:curw = winsaveview()
|
||
|
|
||
|
let bin_name = zig#config#FmtCommand()
|
||
|
|
||
|
" Get current position in file
|
||
|
let current_col = col('.')
|
||
|
let orig_line_count = line('$')
|
||
|
|
||
|
" Save current buffer first, else fmt will run on the original file and we
|
||
|
" will lose our changes.
|
||
|
silent! execute 'write' expand('%')
|
||
|
|
||
|
let [l:out, l:err] = zig#fmt#run(bin_name, expand('%'))
|
||
|
|
||
|
if l:err == 0
|
||
|
call zig#fmt#update_file(expand('%'))
|
||
|
elseif !zig#config#FmtFailSilently()
|
||
|
let errors = s:parse_errors(expand('%'), out)
|
||
|
call s:show_errors(errors)
|
||
|
endif
|
||
|
|
||
|
let diff_offset = line('$') - orig_line_count
|
||
|
|
||
|
if zig#config#FmtExperimental()
|
||
|
" restore our undo history
|
||
|
silent! exe 'rundo ' . tmpundofile
|
||
|
call delete(tmpundofile)
|
||
|
|
||
|
" Restore our cursor/windows positions, folds, etc.
|
||
|
if empty(l:curw)
|
||
|
silent! loadview
|
||
|
else
|
||
|
call winrestview(l:curw)
|
||
|
endif
|
||
|
else
|
||
|
" Restore our cursor/windows positions.
|
||
|
call winrestview(l:curw)
|
||
|
endif
|
||
|
|
||
|
" be smart and jump to the line the new statement was added/removed
|
||
|
call cursor(line('.') + diff_offset, current_col)
|
||
|
|
||
|
" Syntax highlighting breaks less often.
|
||
|
syntax sync fromstart
|
||
|
endfunction
|
||
|
|
||
|
" update_file updates the target file with the given formatted source
|
||
|
function! zig#fmt#update_file(target)
|
||
|
" remove undo point caused via BufWritePre
|
||
|
try | silent undojoin | catch | endtry
|
||
|
|
||
|
" reload buffer to reflect latest changes
|
||
|
silent edit!
|
||
|
|
||
|
let l:listtype = zig#list#Type("ZigFmt")
|
||
|
|
||
|
" the title information was introduced with 7.4-2200
|
||
|
" https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640
|
||
|
if has('patch-7.4.2200')
|
||
|
" clean up previous list
|
||
|
if l:listtype == "quickfix"
|
||
|
let l:list_title = getqflist({'title': 1})
|
||
|
else
|
||
|
let l:list_title = getloclist(0, {'title': 1})
|
||
|
endif
|
||
|
else
|
||
|
" can't check the title, so assume that the list was for go fmt.
|
||
|
let l:list_title = {'title': 'Format'}
|
||
|
endif
|
||
|
|
||
|
if has_key(l:list_title, "title") && l:list_title['title'] == "Format"
|
||
|
call zig#list#Clean(l:listtype)
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
" run runs the gofmt/goimport command for the given source file and returns
|
||
|
" the output of the executed command. Target is the real file to be formatted.
|
||
|
function! zig#fmt#run(bin_name, target)
|
||
|
let l:cmd = []
|
||
|
call extend(cmd, a:bin_name)
|
||
|
call extend(cmd, [a:target])
|
||
|
return zig#util#Exec(l:cmd)
|
||
|
endfunction
|
||
|
|
||
|
" parse_errors parses the given errors and returns a list of parsed errors
|
||
|
function! s:parse_errors(filename, content) abort
|
||
|
let splitted = split(a:content, '\n')
|
||
|
|
||
|
" list of errors to be put into location list
|
||
|
let errors = []
|
||
|
for line in splitted
|
||
|
let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)')
|
||
|
if !empty(tokens)
|
||
|
call add(errors,{
|
||
|
\"filename": a:filename,
|
||
|
\"lnum": tokens[2],
|
||
|
\"col": tokens[3],
|
||
|
\"text": tokens[4],
|
||
|
\ })
|
||
|
endif
|
||
|
endfor
|
||
|
|
||
|
return errors
|
||
|
endfunction
|
||
|
|
||
|
" show_errors opens a location list and shows the given errors. If the given
|
||
|
" errors is empty, it closes the the location list
|
||
|
function! s:show_errors(errors) abort
|
||
|
let l:listtype = zig#list#Type("ZigFmt")
|
||
|
if !empty(a:errors)
|
||
|
call zig#list#Populate(l:listtype, a:errors, 'Format')
|
||
|
echohl Error | echomsg "zig fmt returned error" | echohl None
|
||
|
endif
|
||
|
|
||
|
" this closes the window if there are no errors or it opens
|
||
|
" it if there is any
|
||
|
call zig#list#Window(l:listtype, len(a:errors))
|
||
|
endfunction
|
||
|
|
||
|
function! zig#fmt#ToggleFmtAutoSave() abort
|
||
|
if zig#config#FmtAutosave()
|
||
|
call zig#config#SetFmtAutosave(0)
|
||
|
call zig#util#EchoProgress("auto fmt disabled")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
call zig#config#SetFmtAutosave(1)
|
||
|
call zig#util#EchoProgress("auto fmt enabled")
|
||
|
endfunction
|
||
|
|
||
|
" vim: sw=2 ts=2 et
|