Why does vim autoindent work inconsistently - vim

Using vim 8.0.1365 on a Macintosh
I don't understand why autoindent fails some of the time.
Both of the code fragments below are indented as I want them to
be when I run the formatter, (both default and the pangloss
indenter). But when I'm in insert mode, the autoindent
doesn't work for the second code fragment.
So code like this gets autoindented as I'd like;
function SayHiToMom () {
message = "Hello, best mom in the world"; <- This line auto-indents, as expected.
send(message); <- and so does this one.
}
But not this code
var svg = d3.select("#chart-area").append("svg")
.attr("width", 400) <- Here, no auto-indent occurs, but that's not really a surprise. I indent by hand.
.attr("height", 400) <- When I start a new line here, no auto-indent occurs, surprising and annoying.

When you have filetype support on, Vim loads a filetype plugin when you load a file of a particular type (like JavaScript) and that file contains multiple settings. In the case of JavaScript, one of those settings is indentexpr, which is a function that's called to automatically provide the right indent.
It appears that in this case, it doesn't handle that case automatically, possibly because nobody ever considered that case in the code. Vim doesn't understand JavaScript natively, so the Vimscript has to do the best it can.
Also, it's possible that someone didn't do this behavior because your line wouldn't intrinsically be considered a continuation line if someone were using the JavaScript style where you don't write semicolons at the end, but instead put them at the beginning of the line if necessary to disambiguate. Vim has to support both styles of JavaScript, even if not everyone agrees that both are a good idea.
Regardless, the header of the file (on my system, /usr/share/vim/vim82/indent/javascript.vim) contains a GitHub URL where you could report this issue and either send a patch or see if someone else would be willing to write one. You could also turn off the indentexpr value by writing something like the following in your .vimrc:
au FileType javascript setl indentexpr=
In that case, you'd get the default autoindent behavior.

Related

How to change JSX indentation rules in VIM?

Currently, I'm using two plugins to format my JS(X) code in VIM:
pangloss/vim-javascript
mxw/vim-jsx
Our team has elected that, when we have React Components whose props spill on to multiple lines, we want those properties to line up with the property on the first line, like so:
Desired:
<Toggle label={dragString} toggled={this.props.canDrag} onToggle={this.toggleDrag}
thumbStyle={toggleStyles.thumbOff}
thumbSwitchedStyle={toggleStyles.thumbOn}
trackStyle={toggleStyles.trackOff}
trackSwitchedStyle={toggleStyles.trackOn}
/>
Instead, it looks like vim-jsx will always indent props on new lines just two spaces (which is what we have our tab size set to):
What actually happens:
<Toggle label={dragString} toggled={this.props.canDrag} onToggle={this.toggleDrag}
thumbStyle={toggleStyles.thumbOff}
thumbSwitchedStyle={toggleStyles.thumbOn}
trackStyle={toggleStyles.trackOff}
trackSwitchedStyle={toggleStyles.trackOn}
/>
Is there a change I can make in my .vimrc or to the vim-jsx plugin code to make React component props on new lines line up with the prop on the first line?
In my case, I already had indentation working as expected for .js files with this line in my .vimrc:
autocmd FileType javascript setlocal shiftwidth=2 tabstop=2
To get similar behavior in .jsx files, I needed to also add:
autocmd FileType javascriptreact setlocal shiftwidth=2 tabstop=2
You can run :set filetype in vim to display the filetype according to vim; in this case javascriptreact.
Unfortunately, there's no easy way to do this. In Vim, indentation works by invoking an "indent expression" stored in the indentexpr setting. The file that does this for JSX in your plugin is here: https://github.com/mxw/vim-jsx/blob/eb656ed96435ccf985668ebd7bb6ceb34b736213/after/indent/jsx.vim
They define a function, called GetJsxIndent, which either delegates to the XML indent, or to the JS indent, or it does something slightly different. Their particular overrides are here: https://github.com/mxw/vim-jsx/blob/eb656ed96435ccf985668ebd7bb6ceb34b736213/after/indent/jsx.vim#L92-L102
Theoretically, you could make your own changes in that area, check where the properties start in the <Toggle line and align to those, but it might end up being much more complicated than it seems at first glance. For instance, they decrease the indent by a single shiftwidth, if the current line is />. With a change like you're proposing, this won't work -- the /> couldn't look at the previous line, it has to find its starting <.
My suggestion would be to open an issue on the vim-jsx project and ask them to implement this, possibly with a setting to turn it on or off. The alternative would be to fork it yourself and try to apply your workaround, but be prepared for it to take some time and effort.
Wanted to update this post, even though it's been a few years. We've been using Prettier for auto-formatting our code, and it takes care of aligning JSX properties properly.
The fix for getting it to format in VIM was adding using the Neoformat Plugin and appending the following to my .vimrc file:
autocmd BufWritePre *.js Neoformat
autocmd FileType javascript setlocal formatprg=prettier\ --stdin\ --parser\ flow
let g:neoformat_try_formatprg = 1 " Use formatprg when available
let g:neoformat_enabled_javascript = ['prettier-eslint', 'prettier']
let g:neoformat_enabled_json = ['prettier-eslint', 'prettier']
let g:neoformat_enabled_css = ['prettier-eslint', 'prettier']
let g:neoformat_enabled_less = ['prettier-eslint', 'prettier']
All my JS(X) code will now be properly formatted every time I save the file (:w)
I'm really happy with this solution, because it eliminates the cognitive load of having to manually format code.

Can I fix Groovy indenting in Vim?

I am trying to use Vim for some Groovy code at work. It doesn't seem to handle autoindents well when semicolons are not used. I've found a few questions related to Ruby and JavaScript with the same issues, but none of the fixes I find work for me. I do have filetype plugin indent on in my .vimrc, and do not set cindent, autoindent, or smartindent. I've tried running setlocal nocindent nosmartindent in a Groovy buffer and reindenting the file with ggVG= just in case there's a plugin setting those behind the scenes, and it still always gets it wrong.
For example, I get this on a small sample (from a personal libGDX sandbox app I'm writing in Groovy)
#Override
void render () {
Gdx.gl.glClearColor(0.75f, 0.75f, 0.75f, 1)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
batch.begin()
batch.draw(img, 0, 0)
font.draw(batch, "Testing", 300, 400)
batch.end()
}
Notice the extra indents after the annotation, the opening brace, and the first line of the function. My .vimrc is fairly complex, but I can post a link to my dotfiles if anyone thinks that will help.
Vim doesn't come with a indent script for groovy. So it tries to use the standard indentation rules which are based on C. These rules use semicolons to determine if a line is ended which is why you get line continuation indents on the second line of the function.
Since vim doesn't include the indent script you can use the groovyindent plugin. Placed in ~/.vim/indent. You also need to run dos2unix on groovy.vim since it contains the wrong line endings.
Since groovy looks very much like simplified perl, for my little groovy (actually nextflow DSL) coding, setting filetype=perl followed by gg=G worked quite nicely.

Turn on Vim plugins for some files, not others?

I recently added filetype plugin indent on to my .vimrc in order to enable special indenting and syntax highlighting for Clojure code (*.clj files). However, it's also causing indenting in my LaTeX files (*.tex). This is annoying when I'm editing, and even more annoying, because the tab characters that get inserted confuse a custom program I use to process my LaTeX files. I know I can make indenting use spaces, but I really just want "intelligent" LaTeX indenting to go away. Actually, I want all intelligent indenting to go away, except where I specifically ask for it.
How can I get correct auto-formatting for Clojure code in Vim, but turn off all special handling of LaTeX files (except for syntax highlighting)?
Sorry if this has already been answered; I haven't succeeded in finding the answer yet.
(Irrelevant editorial comment: Sometimes Vim "upgrades" make me want to go back to Unix 'vi'. OK, not really.)
Each proper filetype plugin script has an inclusion guard at its beginning. If you don't want any of the filetype options for Latex files (i.e. filetype of tex), create a file ~/.vim/ftplugin/tex.vim with these contents:
:let b:did_ftplugin = 1
This causes the default ftplugin from $VIMRUNTIME to abort its execution. The same applies to indent: ~/.vim/indent/tex.vim and b:did_indent is the guard variable.
Alternative
On the other hand, if you just want to undo certain options (e.g. :setlocal expandtab to avoid inserting tabs), you'd put those overriding commands into the so-called after directory: ~/.vim/after/ftplugin/tex.vim.

Using folds with synmaxcol in vim

Sometimes when I'm working on a project I want to play around with some data. Often times the data is on one line and is huge (>25k characters). I understand I could set nowrap and have this line just run off the screen, but I tend to like set wrap for other reasons. So, as a workaround I want to hide these long lines in a marker fold (e.g. {{{ long line }}}). This works fine but I run into a problem with synmaxcol for some reason. If the folded line exceeds synmaxcol then when I open the file, the syntax highlighting runs over. For example:
However, as soon as I open the fold the syntax corrects itself:
Having to open the fold every time is annoying though. As you can see in this example the line is not actually all that long -- it just exceeds synmaxcol. Since synmaxcol is exceeded at a "string" element, the rest of the file is highlighted as a string (so nothing but a singular double quote will stop it).
Why is this happening and how can I fix it? I've tried this with different syntax files and filetypes and it still occurs. I've also tried it with no plugins, a minimal vimrc (containing only syn on) and a modeline to set fdm=marker:synmaxcol=60 and it still happens.
You can manually enter :syntax sync fromstart to force Vim to rescan the syntax from the beginning of the opened file.
I would suggest defining a hotkey for convenience:
noremap <F5> <Esc>:syntax sync fromstart<CR>
inoremap <F5> <C-o>:syntax sync fromstart<CR>
Now you can press F5 to clean up most syntax highlighting problems.
Also, have a look at Vim's fixing syntax highlighting - wiki page
Moreover reading :help :syn-sync-first might shed some more light on the issue.
UPDATE:
I was able to reproduce this behavior on my machine (I'm running Vim 7.3.429).
However, when I wrapped the fold markers {{{ and }}} in block comments, vim correctly rendered the syntax. You can create appropriately wrapped fold-markers using the zf command. See Vim tips: Folding fun.
Normally Vim picks the correct blockcomment string based on the currently active syntax. However, my Vim is pretty vanilla and didn't recognize Ruby syntax. I could specify autocmd FileType ruby set commentstring==begin%s=end in my .vimrc file to set the proper block comment. See :fold-create-marker for more details.
Another solution is to set synmaxcol=0, which will effectively set it to infinity. This causes Vim to check the syntax of the entire line, no matter how long it is. However, I'm not sure what kind of performance penalty you'll have to pay for that.

vim and c++11 lambda: auto indentation

Using vim with c++11 lambda functions is actually poor. Indentation is not working and a lot of brackets are marked as erroneous.
As I know the indent and syntax highlighting for c and c++ is programmed internally and not via a c[...].vim file. Is there any chance to set up vim for c++11, especially for source code with lambda functions? Maybe someone can give a hint how and where to add lambda parsing in the internal vim syntax checking?
EDIT: (example code as requested from comments)
The code should look like the following example but is formatted to a single column.
MyLoop( [](int a, int b){
{
::i++;
for (;;)
{
SomeFunc();
}
cout << "Result: " << a*b<<endl;
}
});
Update for vim 7.4:
Now vim did not longer handle a lambda expression as an error, but it still did NOT do any indentation in the lambda expression and so it is still not usable for c++ anymore :-(
BTW: Has anyone a good auto formatting tool which can be added to vim environment, so that pressing a key externally do the formatting?
Vim 7.4 now has an jN cinoption for "Indent Java anonymous classes correctly." (:help java-cinoptions) This improves indenting behavior for C++11's lambdas.
With these options (put in your ~/.vim/after/ftplugin/cpp.vim):
setlocal cindent cino=j1,(0,ws,Ws
And if I move your for loop's opening brace to the same line (otherwise it's crazy) then vim indents your code like this:
MyLoop( [](int a, int b){
{
::i++;
for (;;) {
SomeFunc();
}
cout << "Result: " << a*b<<endl;
}
});
It doesn't give the hanging indent that you want either. If you move the initial opening brace it its own line, then you get your desired hanging indent.
For all the options, see :help cinoptions-values.
If you want at smarter indenting program, this user recommends set equalprg=clang-format to use ClangFormat so =ip will indent the current paragraph. This won't make vim correctly indent as you type (you need to setup indentexpr for that and that's quite complicated).
There's also a vim plugin that seems to do the same as setting equalprg, but with more code. Not sure if it's any better. It's supposed to be an alternative to clang-format.py (from Cyprian Guerra's answer).
Use
:let c_no_curly_error = 1
You can put that into your vimrc for example.
As for your assumption, it is wrong. There is a c.vim syntax file (in vim runtime). You can see a reference in :help c.vim and the implementation by looking it up in your vim runtime paths (:echo &rtp).
There is this project by Michael Small. I haven't tried it yet, but perhaps it's what you're looking for.
set smartindent autoindent
Then you type above code in vim,you will get the right indentation.
BUT,if you use gg=G or commands that contain "=" to re-indent above code,the indentation is still wrong.
I just struggled with this for a few days, looks like toggling on smartindent with cindent enabled helped me out with it lambda indentation in C++11.
In your ~/.vimrc
set cindent
set smartindent
Hope this helps peeps out.
What you seem to be looking for is clang-format.py from LLVM guys or vim-clang-format from Linda_pp a.k.a. rhysd (thanks idbrii for the latter) - both use clang therefore both support all of the C++11 new structures and you can run it as follows:
:pyf ~/src/llvm.git/tools/clang/tools/clang-format/clang-format.py
or
:ClangFormat
The latter seems better as it (among other features) allows to follow the "one config file for the same behaviour on every environment" rule, especially when you use a VIM add-on manager (e.g. VAM).

Resources