|
| 1 | +" Adapted from fatih/vim-go: autoload/go/fmt.vim |
| 2 | +" |
| 3 | +" Copyright 2011 The Go Authors. All rights reserved. |
| 4 | +" Use of this source code is governed by a BSD-style |
| 5 | +" license that can be found in the LICENSE file. |
| 6 | +" |
| 7 | +" Upstream: https://github.com/ziglang/zig.vim |
| 8 | + |
| 9 | +function! zig#fmt#Format() abort |
| 10 | + " Save cursor position and many other things. |
| 11 | + let view = winsaveview() |
| 12 | + |
| 13 | + if !executable('zig') |
| 14 | + echohl Error | echomsg "no zig binary found in PATH" | echohl None |
| 15 | + return |
| 16 | + endif |
| 17 | + |
| 18 | + let cmdline = 'zig fmt --stdin --ast-check' |
| 19 | + let current_buf = bufnr('') |
| 20 | + |
| 21 | + " The formatted code is output on stdout, the errors go on stderr. |
| 22 | + if exists('*systemlist') |
| 23 | + silent let out = systemlist(cmdline, current_buf) |
| 24 | + else |
| 25 | + silent let out = split(system(cmdline, current_buf)) |
| 26 | + endif |
| 27 | + if len(out) == 1 |
| 28 | + if out[0] == "error: unrecognized parameter: '--ast-check'" |
| 29 | + let cmdline = 'zig fmt --stdin' |
| 30 | + if exists('*systemlist') |
| 31 | + silent let out = systemlist(cmdline, current_buf) |
| 32 | + else |
| 33 | + silent let out = split(system(cmdline, current_buf)) |
| 34 | + endif |
| 35 | + endif |
| 36 | + endif |
| 37 | + let err = v:shell_error |
| 38 | + |
| 39 | + |
| 40 | + if err == 0 |
| 41 | + " remove undo point caused via BufWritePre. |
| 42 | + try | silent undojoin | catch | endtry |
| 43 | + |
| 44 | + " Replace the file content with the formatted version. |
| 45 | + if exists('*deletebufline') |
| 46 | + call deletebufline(current_buf, len(out), line('$')) |
| 47 | + else |
| 48 | + silent execute ':' . len(out) . ',' . line('$') . ' delete _' |
| 49 | + endif |
| 50 | + call setline(1, out) |
| 51 | + |
| 52 | + " No errors detected, close the loclist. |
| 53 | + call setloclist(0, [], 'r') |
| 54 | + lclose |
| 55 | + elseif get(g:, 'zig_fmt_parse_errors', 1) |
| 56 | + let errors = s:parse_errors(expand('%'), out) |
| 57 | + |
| 58 | + call setloclist(0, [], 'r', { |
| 59 | + \ 'title': 'Errors', |
| 60 | + \ 'items': errors, |
| 61 | + \ }) |
| 62 | + |
| 63 | + let max_win_height = get(g:, 'zig_fmt_max_window_height', 5) |
| 64 | + " Prevent the loclist from becoming too long. |
| 65 | + let win_height = min([max_win_height, len(errors)]) |
| 66 | + " Open the loclist, but only if there's at least one error to show. |
| 67 | + execute 'silent! lwindow ' . win_height |
| 68 | + endif |
| 69 | + |
| 70 | + call winrestview(view) |
| 71 | + |
| 72 | + if err != 0 |
| 73 | + echohl Error | echomsg "zig fmt returned error" | echohl None |
| 74 | + return |
| 75 | + endif |
| 76 | + |
| 77 | + " Run the syntax highlighter on the updated content and recompute the folds if |
| 78 | + " needed. |
| 79 | + syntax sync fromstart |
| 80 | +endfunction |
| 81 | + |
| 82 | +" parse_errors parses the given errors and returns a list of parsed errors |
| 83 | +function! s:parse_errors(filename, lines) abort |
| 84 | + " list of errors to be put into location list |
| 85 | + let errors = [] |
| 86 | + for line in a:lines |
| 87 | + let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)') |
| 88 | + if !empty(tokens) |
| 89 | + call add(errors,{ |
| 90 | + \"filename": a:filename, |
| 91 | + \"lnum": tokens[2], |
| 92 | + \"col": tokens[3], |
| 93 | + \"text": tokens[4], |
| 94 | + \ }) |
| 95 | + endif |
| 96 | + endfor |
| 97 | + |
| 98 | + return errors |
| 99 | +endfunction |
| 100 | +" vim: sw=2 ts=2 et |
0 commit comments