From 6613abee935a18d692315e5ed47b28e98d25553d Mon Sep 17 00:00:00 2001 From: Chris Pickel Date: Tue, 19 Apr 2016 10:31:16 +0200 Subject: [PATCH] Add builtin gn formatter. Chrome uses BUILD.gn files to build on most platforms. The command includes a built-in formatter. --- autoload/codefmt.vim | 70 ++++++++++++++++++++++++++++++++++++++++++++ doc/codefmt.txt | 5 ++++ instant/flags.vim | 4 +++ plugin/register.vim | 1 + vroom/gn.vroom | 63 +++++++++++++++++++++++++++++++++++++++ vroom/main.vroom | 1 + 6 files changed, 144 insertions(+) create mode 100644 vroom/gn.vroom diff --git a/autoload/codefmt.vim b/autoload/codefmt.vim index c5c13cd..c2eae3e 100644 --- a/autoload/codefmt.vim +++ b/autoload/codefmt.vim @@ -445,6 +445,76 @@ function! codefmt#GetYAPFFormatter() abort endfunction +"" +" @private +" Formatter: gn +function! codefmt#GetGnFormatter() abort + let l:url = 'https://www.chromium.org/developers/how-tos/install-depot-tools' + let l:formatter = { + \ 'name': 'gn', + \ 'setup_instructions': 'install Chromium depot_tools (' . l:url . ')'} + + function l:formatter.IsAvailable() abort + return executable(s:plugin.Flag('gn_executable')) + endfunction + + function l:formatter.AppliesToBuffer() abort + return &filetype is# 'gn' + endfunction + + "" + " Run `gn format` to format the whole file. + " + " We implement Format(), and not FormatRange{,s}(), because gn doesn't + " provide a hook for formatting a range, and all gn files are supposed + " to be fully formatted anyway. + function l:formatter.Format() abort + let l:executable = s:plugin.Flag('gn_executable') + let l:cmd = [ l:executable, 'format', '--stdin' ] + let l:input = join(getline(1, line('$')), "\n") + + " gn itself prints errors to stdout, but if the error comes from the + " gn.py wrapper script, it is printed to stderr. Use stdout as the + " error message if stderr is empty. + let l:result = maktaba#syscall#Create(l:cmd).WithStdin(l:input).Call(0) + if !empty(l:result.stdout) + let l:output = l:result.stdout + else + let l:output = l:result.stderr + endif + + " Other formatters generally catch failure as an exception, but + " v:exception contains stderr in that case, and gn prints errors to + " stdout, so we need to check for a shell error ourselves. + if !v:shell_error + let l:formatted = split(l:output, "\n") + call maktaba#buffer#Overwrite(1, line('$'), l:formatted) + else + let l:errors = [] + for line in split(l:output, "\n") + let l:tokens = matchlist(line, '\C\v^ERROR at :(\d+):(\d+):\s*(.*)') + if !empty(l:tokens) + call add(l:errors, { + \ "filename": @%, + \ "lnum": l:tokens[1], + \ "col": l:tokens[2], + \ "text": l:tokens[3]}) + endif + endfor + + if empty(l:errors) + " Couldn't parse errors; display the whole error message. + call maktaba#error#Shout('Error formatting file: %s', l:output) + else + call setqflist(l:errors, 'r') + cc 1 + endif + endif + endfunction + + return l:formatter +endfunction + "" " Checks whether {formatter} is available. " NOTE: If IsAvailable checks are disabled via diff --git a/doc/codefmt.txt b/doc/codefmt.txt index 4ced1f9..35b2ee6 100644 --- a/doc/codefmt.txt +++ b/doc/codefmt.txt @@ -52,6 +52,10 @@ Default: 'js-beautify' ` The path to the yapf executable. Default: 'yapf' ` + *codefmt:gn_executable* +The path to the gn executable. +Default: 'gn' ` + *codefmt:plugin[autocmds]* Configures whether plugin/autocmds.vim should be loaded. Default: 1 ` @@ -94,6 +98,7 @@ The current list of defaults by filetype is: * c, cpp, proto, javascript: clang-format * go: gofmt * python: autopep8, yapf + * gn: gn ============================================================================== DICTIONARIES *codefmt-dicts* diff --git a/instant/flags.vim b/instant/flags.vim index a631fc5..88853a4 100644 --- a/instant/flags.vim +++ b/instant/flags.vim @@ -75,3 +75,7 @@ call s:plugin.Flag('js_beautify_executable', 'js-beautify') "" " The path to the yapf executable. call s:plugin.Flag('yapf_executable', 'yapf') + +"" +" The path to the gn executable. +call s:plugin.Flag('gn_executable', 'gn') diff --git a/plugin/register.vim b/plugin/register.vim index c290548..b2b653f 100644 --- a/plugin/register.vim +++ b/plugin/register.vim @@ -26,3 +26,4 @@ call s:registry.AddExtension(codefmt#GetClangFormatFormatter()) call s:registry.AddExtension(codefmt#GetGofmtFormatter()) call s:registry.AddExtension(codefmt#GetYAPFFormatter()) call s:registry.AddExtension(codefmt#GetAutopep8Formatter()) +call s:registry.AddExtension(codefmt#GetGnFormatter()) diff --git a/vroom/gn.vroom b/vroom/gn.vroom new file mode 100644 index 0000000..22945a6 --- /dev/null +++ b/vroom/gn.vroom @@ -0,0 +1,63 @@ +The built-in gn formatter knows how to format gn build files. +If you aren't familiar with basic codefmt usage yet, see main.vroom first. + +We'll set up codefmt and configure the vroom environment, then jump into some +examples. + + :source $VROOMDIR/setupvroom.vim + + :let g:repeat_calls = [] + :function FakeRepeat(...) + | call add(g:repeat_calls, a:000) + :endfunction + :call maktaba#test#Override('repeat#set', 'FakeRepeat') + + :call codefmt#SetWhetherToPerformIsAvailableChecksForTesting(0) + + +The gn formatter expects the gn executable to be installed on your system. + + % buildconfig = "//build/config/BUILDCONFIG.gn" + :FormatCode gn + ! gn .* + $ buildconfig = "//build/config/BUILDCONFIG.gn" + +The name or path of the gn executable can be configured via the +gn_executable flag if the default of "gn" doesn't work. + + :Glaive codefmt gn_executable='mygn' + :FormatCode gn + ! mygn .* + $ buildconfig = "//build/config/BUILDCONFIG.gn" + :Glaive codefmt gn_executable='gn' + + +You can format any buffer with gn specifying the formatter explicitly. + + @clear + % executable("hello") { sources = ["hello.c"] } + :FormatCode gn + ! gn format --stdin .*2>.* + $ executable("hello") { + $ sources = [ + $ "hello.c", + $ ] + $ } + executable("hello") { + sources = [ + "hello.c", + ] + } + @end + +The gn filetype will use the gn formatter by default. + + @clear + % buildconfig = "//build/config/BUILDCONFIG.gn" + + :set filetype=gn + :FormatCode + ! gn .* + $ buildconfig = "//build/config/BUILDCONFIG.gn" + + :set filetype= diff --git a/vroom/main.vroom b/vroom/main.vroom index 1f6edee..3d0c6db 100644 --- a/vroom/main.vroom +++ b/vroom/main.vroom @@ -13,6 +13,7 @@ directory cover various topics of codefmt usage: * clangformat.vroom - Configuring and using the built-in clang-format formatter * gofmt.vroom - Configuring and using the built-in gofmt formatter * yapf.vroom - Configuring and using the built-in yapf formatter +* gn.vroom - Configuring and using the built-in gn formatter * autocmd.vroom - Automatic hooks like format-on-save * extensions.vroom - Adding additional formatters for codefmt to use