google / vim-codefmt Goto Github PK
View Code? Open in Web Editor NEWVim plugin for syntax-aware code formatting
License: Apache License 2.0
Vim plugin for syntax-aware code formatting
License: Apache License 2.0
steps to reproduce:
:FormatCode
or :FormatLines
on selectionit throws:
ERROR(NotFound): Library "codefmtlib" could not be installed, because there are no library installers registered with maktaba.
it works as expected
Even though the tests stub out the actual system calls to clang-format and gofmt, they're not completely hermetic because they depend on whether 'clang-format' and 'gofmt' are actual executables on the path on the host where the tests are being run.
This causes vroom failures like
FAILED on line 030: Multiple failures:
Unexpected message:
Not available. codefmt doesn't have a default formatter for this buffer.
Expected system call not received.
Got no chance to inject response:
EXPECT: clang-format -style file -assume-filename .*foo.cc .*2>.* (regex mode)
STDOUT: void f() {
int i;
SomeFunction(parameter, // comment
i);
}
Messages:
Not available. codefmt doesn't have a default formatter for this buffer.
Failed command on line 030:
:FormatCode
Queued system controls are:
EXPECT: clang-format -style file -assume-filename .*foo.cc .*2>.* (regex mode)
STDOUT: void f() {
int i;
SomeFunction(parameter, // comment
i);
}
No system calls received. Perhaps your --shell is broken?
Last few commands (most recent last) were:
:let g:repo = fnamemodify($VROOMFILE, ':p:h:h')<CR>
:execute 'source' g:repo . '/bootstrap.vim'<CR>
:call maktaba#syscall#SetUsableShellRegex('\v<shell\.vroomfaker$')<CR>
:filetype plugin on<CR>
:let g:repeat_calls = []<CR>
:function FakeRepeat(...)<CR> call add(g:repeat_calls, a:000)<CR><CR>
:endfunction<CR>
:call maktaba#test#Override('repeat#set', 'FakeRepeat')<CR>
:silent file foo.cc<CR>
:set filetype=cpp<CR>
ivoid f() {int i; SomeFunction(parameter,// comment<CR>i);}<ESC>
:FormatCode<CR>
There's no way to actually stub out executable()
calls in vroom, so we'll either need to provide some override to actually change the plugin behavior for testing or monkey patch the IsAvailable()
function on the formatters we're testing.
The codefmt vroom files are pretty good for test coverage right now but not very friendly and readable as "executable documentation". Compare to the glaive docs at https://github.com/google/vim-glaive/tree/master/vroom as an A+ example. Improvements to consider:
Lots of vim plugins have fancy screencasts (animated GIFs) in the README.md showcasing plugin features. The codefmt plugin has several useful features that would make a nice screencast.
We should create a screencast and embed it in our README.md. If we could also include a keyboard monitor in the screencast, that would help show off all the handy mappings.
When using goimports via our gofmt formatter as suggested in the docs, the goimports path-based inference doesn't work because we don't tell goimports about the path. It does support a --srcdir
argument we could pass.
We'd have to make it conditional and detect basename(gofmt_executable) == 'goimports'
or something like that because gofmt doesn't support any --srcdir
arg.
Since vim already has settings that correspond to indent size and max line length, it would be great to have an option to hook those up to automatically match vim's 'shiftwidth' and 'textwidth' settings, since I've already configured formatting settings once and shouldn't be forced to repeat myself. There could be a single global setting to enable the feature and a buffer-local override so you could still work around corner cases.
The indent and line length settings will vary from formatter to formatter and support will need to be implemented per-formatter. It could either be explicitly part of the API or formatters could just check the relevant preferences and vim settings themselves in the formatter code.
I notice that clang-format has just added a -sort-includes
option (presumably to what will become clang-format 3.8, but we should verify that); see http://llvm.org/viewvc/llvm-project?view=revision&revision=248367.
This is passed by default by clang-format's own example (Python-based) integration (which we don't use). We should work out whether include sorting (assuming you format that region) is something that makes sense to enable by default. (Yes?)
We probably want to wait until clang-format 3.8 is actually out before adding this, though.
The announcement claims this plugin supports cpp & js natively.
so after installing with vundle ( as provided in the readme file )
when I try to :FormatCode
on .cpp or .js files I get following error:
Not available. codefmt doesn't have a default formatter for this buffer.
What I am missing? Should one use VAM or install any additional plugins? Thanks in advance.
For some types of files you might want to run more than one formatter, for instance sort C++ includes (which clang-format doesn't handle) and then format with clang-format. Could codefmt support configuring a list of formatters instead of a single formatter? E.g.
AutoFormatBuffer sortincludes,clang-format
let b:codefmt_formatter = ['sortincludes', 'clang-format']
related to #4
assign it to me
We should have a formatter for fixjsstyle from the Closure Linter suite (https://developers.google.com/closure/utilities/docs/linter_howto).
Newer versions of clang-format support a -cursor=<uint>
option to precisely maintain cursor position from before formatting and output a JSON structure as the first line of output indicating the final cursor position after formatting.
We should add support to codefmt to hook into this mechanism and precisely preserve the cursor position when formatting with clang-format. If lots of users are still using an older clang-format version that doesn't accept the -cursor
flag, we could have a flag to control whether to use the cursor preservation and/or detect support by reading the version number from clang-format --version
.
Maktaba now has a built-in maktaba#extension#
mechanism that's designed to replace codefmtlib and similar plugins. We should switch codefmt to use it and deprecate the codefmtlib repo.
when I upgrade to vim 7.4.1910
the plugin throws exception
Error detected while processing function maktaba#flags#AddCallback[1]..maktaba#ensure#IsCallable:
line 9:
E605: Exception not caught: ERROR(BadValue): Dictionary with keys ['dict', 'func', 'Apply', 'Call', 'WithContext', 'arglist', 'WithArgs'] is not a maktaba function.
Error detected while processing function maktaba#plugin#Detect:
line 2:
E170: Missing :endfor
but vim 7.4.1864 did not
We must go deeper.
when I run :Formatcode
, it turns out:
Error formatting file: ERROR(ShellError): Error running: clang-format --version
[root@fe4524cdab25 ~]# clang-format -version
LLVM (http://llvm.org/):
LLVM version 3.4.2
Optimized build.
Built Dec 7 2015 (09:37:36).
Default target: x86_64-redhat-linux-gnu
Host CPU: x86-64
Codefmt should have support for formatting Java source code if/when a Java formatting tool exists.
It's possible something hacky could be done to organize Java imports without any kind of full-fledged Java formatting tool.
In autoload/codefmt
, we have:
let s:plugin = maktaba#plugin#Get('codefmt')
let s:plugin_root = expand('<sfile>:p:h:h:h')
let s:registry = s:plugin.GetExtensionRegistry()
call s:registry.SetValidator('codefmt#EnsureFormatter')
If the first time we enter this, we already have extensions registered for codefmt, then the call to SetValidator()
will end up executing codefmt#EnsureFormatter
. But that function doesn't yet exist, and codefmt's autoload hasn't yet finished loading, so we'll load it again, and try to loop forever:
Vim(call):E132: Function call depth is higher than 'maxfuncdepth'
In practice, you can trigger this by installing codefmt, adding an extension via Maktaba, and then running (e.g.) :FormatCode
, which triggers the autoload.
The simple solution is to move the SetValidator()
call down to after where EnsureFormatter()
has been defined (and remove s:plugin_root
, which is unused). However, I wonder whether we should instead call SetValidator()
from instant/register.vim
or similar? It seems odd that we'd defer setting up the validator until the first call to a codefmt#
function.
(This also means that the default formatters won't be registered until that first call, though that's not actually observable, since they're always lower-priority that ones added externally.)
If you have a file that does not parse correctly by Python, yapf returns an error, and does not print anything to stdout. codefmt reads the stdout from yapf, and replaces the vim buffer with it, which means that a file with the below contents (note the missing end quote)
print 'hello
will be emptied when codefmt is run.
If I try to generate the codefmtlib docs with vimdoc, I get an AssertionError about line length:
Traceback (most recent call last):
File "/usr/bin/vimdoc", line 5, in <module>
vimdoc.__main__.main()
File "/usr/lib/python3/dist-packages/vimdoc/__main__.py", line 19, in main
Helpfile(module, docdir).Write()
File "/usr/lib/python3/dist-packages/vimdoc/output.py", line 28, in Write
self.WriteHeader()
File "/usr/lib/python3/dist-packages/vimdoc/output.py", line 42, in WriteHeader
self.Print(line)
File "/usr/lib/python3/dist-packages/vimdoc/output.py", line 172, in Print
assert len(line) <= self.WIDTH
AssertionError
This is because the description field in addon-info.json is too long and triggers google/vimdoc#82. It's probably worth shortening up the description, regardless of what happens with the vimdoc bug, and leaving the detailed explanation for the intro section.
Codefmt should have support for formatting Bazel BUILD files and *.bzl files if/when a tool for formatting Bazel files is publicly available.
In b2277e9, @Kashomon split out all the plugins into different files, which is great for readability, but not so great for loading time.
Locally, my vim startup time (measured using time vim -c ':quit'
) increases from about 875ms to 935ms as a result of this change (+60ms mean, 95%CI +24ms to +94ms, N=13).
60ms isn't much, but I'm not sure it's really worthwhile?
Would be nice to have some practical examples in the docs of how to:
:NoAutoFormatBuffer
.The instructions read:
" Add maktaba and codefmt to the runtimepath.
" (The latter must be installed before it can be used.)
Plugin 'google/vim-maktaba'
Plugin 'google/vim-codefmt'
" Also add Glaive, which is used to configure codefmt's maktaba flags. See
" `:help :Glaive` for usage.
Plugin 'google/vim-glaive'
call glaive#Install()
" Optional: Enable codefmt's default mappings on the <Leader>= prefix.
Glaive codefmt plugin[mappings]
I do not think this will work, unless we stick a call vundle#end()
between the last Plugin
line, and the call glaive#Install()
. See chiphogg/vim-vtd#20 for an example of the problems this could cause. (The associated commit also gives an example of how to improve the instructions.)
It would be nice to have a mode to detect which lines you had touched in this editing session and only format those ranges.
We'd need a way to decide between this behavior and formatting the whole buffer. One option would be a new :FormatChangedLines
and :AutoFormatChangedLines
command that would work as variants of :FormatCode
and :AutoFormatBuffer
.
(Forwarding a report from someone else)
I am using the codefmt plugin for Go, by including:
Glug codefmt gofmt_executable="goimports"
Glug codefmt-google
autocmd FileType go AutoFormatBuffer gofmt
And it looks like it doesn't clear the quick fix list when all errors are fixed. E.g.:
I have 3 errors, and if I save, the quick fix window shows the three of them.
If I fix 1, and save, the quick fix window correctly shows only two of them.
If now I fix the 2 remaining ones, and save, the quick fix window doesn't update at all.
It looks like we only call "setqflist" in the case of errors:
https://github.com/google/vim-codefmt/blob/master/autoload/codefmt.vim#L320
but never clear it if there are no errors.
codefmt depends upon (and documents) a minimum version of Maktaba (currently 1.1; soon to be 1.9). The codefmt CI tests should check out that version, not HEAD, so that we can make sure that we can work with the version we've specified.
(Locally, codefmt will use whatever's available locally, which will probably be HEAD, so I don't think we'd be losing any test coverage by doing that.)
Unless anyone objects, I'd like to:
vim-maktaba
covering the releases we've made..travis.yml
to clone a named Maktaba release.(I think it's okay to keep depending on Glaive HEAD, since that's not really undergoing much development, and is only needed for the tests.)
The google-rlint tool (https://code.google.com/p/google-rlint/) can reformat R code to the Google R Style Guide. We should add it as an available formatter for the r filetype.
Hello,
I have *.BUILD files in my repository which are BUILD files implemented for dependencies to my bazel-built project (For example, jpeg.BUILD for building libjpeg). I have the following line set up in my vimrc:
augroup autoformat_settings
autocmd FileType bzl AutoFormatBuffer buildifier
" ...
augroup END
This works for formatting BUILD files, but if I have a file with the name following the *.BUILD convention for third party builds the file is not automatically formatted. Even more, if I run :FormatCode
in the file, the following message is printed:
Not available, codefmt doesn't have a default formatter for this buffer.
I have to use :FormatCode buildifier
directly for it to work.
How can I specify the default formatter for *.BUILD files?
Currently, if formatters want to report errors, they update the quickfix list directly. (As shipped, only the gofmt formatter does this, but it would also make sense for e.g. google-java-format, were we to add support for that.) It would be nice to make it easier for formatters to report errors.
Additionally, we have some questions around when formatters should clear the quickfix list (e.g. #58), and I'm not sure how stacked formatters (#44) would work if formatters were managing the quickfix list individually.
I've been wondering whether formatters could pass a structured error list to codefmt somehow, and then codefmt itself could be responsible for merging/populating/hiding the quickfix list as appropriate, consistently.
As a strawman, perhaps FormatRange()
(etc) could return a list of (line, column, message)? (Or accept a callback instead, if that sounds like a restrictive API? Would the line numbers be relative to the start of the range, for range formatting?)
And/or, since most formatters can get errors by looking for "file:line:column: error" on stderr, it might even be work providing a helper that handled exactly that pattern directly.
In clang-format's help, it calls itself "a tool to format C/C++/Obj-C code", but the current AppliesToBuffer check on the clang-format formatter only checks for cpp, proto, and javascript filetypes.
We should enable it as a default formatter for filetypes c, objc, and objcpp so that if people use :FormatCode
on these filetypes with no explicit formatter, they will get code formatted with clang-format instead of seeing Not available. codefmt doesn't have a default formatter for this buffer
.
I try to use :FormatCode
, it throws:
Error formatting file: ERROR(ShellError): Error running: clang-format -style file -assume-filename /Users/shiyang/test.c -lines 1:29 -cursor 134 -sort-includes
clang-format: Unknown command line argument '-sort-includes'. Try: 'clang-format -help'
clang-format: Did you mean '-style'?
my clang-format version:
➜ ~ clang-format -version
clang-format version 3.8.0 (tags/google/testing/2015-07-31)
Maybe I've missed it, but it's not obvious to me how to write a plugin that plays nice with vim-codefmt
. We have a custom code formatter at work, and I'd really like to write a lightweight internal plugin that uses codefmt to do the heavy interface lifting.
Any tips?
Formatters right now take a range and modify the buffer as a side-effect, e.g.
function someformatter.FormatRange(startline, endline) abort
let l:lines = getline(1, line('$'))
let l:result = maktaba#syscall#Create(…).WithStdin(join(l:lines, "\n")).Call()
call maktaba#buffer#Overwrite(1, line('$'), split(l:result.stdout, "\n"))
endfunction
codefmt itself has very little insight into what the formatter is doing, and the amount of boilerplate is also a little annoying. Things can get weird if e.g. FormatRange is called multiple times to process multiple ranges, especially with formatters that try to populate errors into the quickfix list.
A different approach would be to pass a codefmt handle and implement formatter operations in terms of that handle, like
formattable.GetLines([start], [end])
formattable.SetLines({lines})
formattable.SetLines({start}, {end}, {lines})
formattable.SetCursor({row}, {col})
formattable.AddError({error}, [row], [col])
A simple formatter would look like
function someformatter.FormatRange(startline, endline, formattable) abort
let l:input = join(a:formattable.GetLines(), "\n")
let l:result = maktaba#syscall#Create(…).WithStdin(l:input).Call()
call a:formattable.SetLines(l:result.stdout)
endfunction
Some advantages are that it can make some formatting operations more convenient and anti-patterns like overwriting files on disk less natural. If we run into wonkiness as we enable fancy features like format-changed-lines-on-save (multiple ranges), it could help solve issues like that, too.
Dart has a formatter: https://github.com/dart-lang/dart_style. Codefmt should support invoking dartfmt to format Dart code.
It would be useful to log an info message whenever codefmt triggers and modifies the buffer, especially for cases where it triggers automatically on save.
It should be possible to verify whether the buffer was actually changed by checking b:changedtick
before and after running the formatter so we can avoid logging a message if the formatter had no effect.
autopep8 allows configuring the indent-size and max-line-length to use as well as listing error codes to be ignored like --ignore=E226,E302,E41
. It's currently possible to configure those via pep8 config files by putting something like the following in ~/.config/pep8 or a per-project setup.cfg or tox.ini:
[pep8]
indent-size = 2
max-line-length = 100
ignore = E226,E302,E41
Config files work pretty well in most cases, but it still would be nice to be able to configure via vimscript for some cases. I'm thinking there should be a flag and/or buffer-local variable that can be used to pass config to autopep8.
In particular, since vim already has settings that correspond to indent size and max line length, it would be great to have an option to hook those up to automatically match vim's 'shiftwidth' and 'textwidth' settings, since I've already configured formatting settings once and shouldn't be forced to repeat myself.
Newline at the end of the file required at my company. Please preserve.
The google C++ style guide recommends to sort include directives alphabetically. https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Names_and_Order_of_Includes
It would be nice if codefmt's FormatCode could also do this.
Codefmt should implement a google/google-java-format formatter to be used on projects that follow Google's Java style guide such as google/truth.
clang-format supports ts files (formatted like js files). Would it be possible to add it as a file type?
Codefmt raises a few questions like why not just use formatprg that we should officially answer in the docs, pbb in README.md.
I added a bit of FAQ content to https://github.com/google/vim-codefmt/wiki/Formatter-Integration-Guide. Part or all of that can be merged into a main FAQ.
Say you have :AutoFormatBuffer
enabled and you're editing file. Then you change a line, save it, because why not. You then go to another line and hit .
to replay that change, it reformats the code.
In my opinion it's pretty clear that the behavior is weird in this situation. I honestly don't see when having code formatting be something that is repeatable via .
is useful but I'd be interested to hear the reasoning behind it.
https://github.com/google/vim-codefmt/blob/master/autoload/codefmt.vim#L450
I'd send a PR removing that or making it configurable, but I though I'd open a conversation first.
What do y'all think?
Some filetypes have terrible default indenting logic (using the = mapping) and also have a formatter fast enough and robust enough to drop in as the formatting implementation for the = mapping. You can do this by adding something like the following to your vimrc:
function s:AddCodefmtEqualMapping() abort
" Replace all the various ={motion} keys to codefmt
nnoremap <buffer> = :set opfunc=codefmt#FormatMap<CR>g@
nnoremap <buffer> == :FormatLines<CR>
vnoremap <buffer> = :FormatLines<CR>
endfunction
augroup codefmt_equal
autocmd FileType cpp,proto call s:AddCodefmtEqualMapping()
augroup END
We should add an example like this into the codefmt help and explain what to expect + caveats when you use it.
Hi
I am getting this error while trying to do use :FormatCode in my C++ code.
ERROR(NotFound): Library "codefmtlib" could not be installed, because there are no library installers registered with maktaba
Here's my vimrc
set nocompatible
filetype off
" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'gmarik/Vundle.vim'
Plugin 'google/vim-maktaba'
Plugin 'google/vim-glaive'
Plugin 'google/vim-codefmtlib'
Plugin 'google/vim-codefmt'
call vundle#end()
" Now we can turn our filetype functionality back on
filetype plugin indent on
Can someone please help me identify the issue.
Thanks
As noted in #48, we seem to have some cases where a formatter's FormatRanges()
will be invoked with an empty a:ranges
. Either that, or we're unnecessarily checking for emptiness in the clang-format formatter.
Unless I'm missing something, this doesn't seem like it's useful; the interface with formatters should say that this is impossible, and we should remove the checks we have.
We have some code to require a minimum maktaba version in bootstrap.vim, but if you're not using bootstrap.vim then you'll never get any warning that your maktaba version is too old. We should move that check somewhere it will get executed for all users. instant/flags.vim would probably be a good place.
Lots of formatters have extra config users may want to pass, and creating a top-level flag for each one will get cumbersome. We should consider a generic mechanism for passing flags through to formatters.
Factors to consider:
--type
to js-beautify and find that it conflicts with the --type
flag we already pass by default.--aosp
flag when working on Android Java, but then be surprised if it's applied to other Java code they're working on later..clang-format
or .editorconfig
, not something codefmt-specific, and codefmt should just try to be smart about detecting and not conflicting with such config where appropriate.A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.