fmt.vim 2.8 KB

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