How to set correct indentation with cinoptons and cinkeys in switch statement? - vim

I'm using indentation style of C++ like LLVM, and clang-format. I need options to be like that:
set cinoptions=:0,g0,(0,Ws,l
set autoindent
set smartindent
set cinkeys=0{,0},0),:,0#,!^F,o,O,e
set cinwords=if,else,while,do,for
Problem with that, that whenever i refer to namespace and press namespace: - it triggers :0 option. When pressed second : - it triggers back. Yes, all is correct. But triggering always for : - very bad for my brain. I wanna static behavior. Not whenever i'm trying to use some namespace and press double :. I need triggering :0 only for the case in switch statement. I hope you can understand what i'm talking about. Please help.
switch(number) {
case 4: // i wanna triggering of:0 only for this line of code.
cout << "Good indentation";
break;
}
if (true) {
namespace: // NOT FOR THAT!
namespace:: // triggers back - all is correct. First triggering is very bad!
}

You're looking for L0; see :h cino-L. It's -1 by default, which means jumping to col 1. It's worth noting the wording in the documentation as well: "If N is non-negative, the indent of the label will be the prevailing indent minus N." -- that's why N = 0 works. It preserves the current indentation level by not subtracting anything from it, and through that, avoiding the jumping.
It only affects labels and not the switch statements' case x:. Note that this means if you want labels to be indented differently, but don't want jumping for the :: operator, you'll probably need to find an LSP with that type of indent support, because cino doesn't support that. You'll either have to live with it jumping on the first : and back on ::, or not having label indentation automatically differ from your normal source code indentation, and having = reset any manual changes you do to label indentation.
Anyway, it also means :0 was never actually triggered. cino's default options meant L-1 was triggered on namespace: - switch case labels aren't the same as normal labels, which meant another option was to blame.
And finally, for the sake of completeness:
set cinoptions=:0,g0,(0,Ws,l,L0

Related

Place-holders used as construct name compromise correct indentation

I wrote a Vim script for the autocompletion of Fortran program units, type definition and so on, taking the cue from vim-latex plugin.
At the moment, if I strike <F5> while the cursor is on the word program, I get the following
PROGRAM <+program_name+>
USE <+used_module_name+>
IMPLICIT NONE
<++>
END PROGRAM <+program_name+>
with the first <+program_name+> visually selected and Vim in select mode. And this is perfect for me.
The problem arises when I use such a placeholder as a label for the IF construct. When I expand if I get
<+name+>: IF (<+logical expression+>) THEN
<++> ! this line is not indented => in turn the following are negative indented
ELSE IF (<+logical expression+>) THEN
<++>
ELSE
<++>
END IF <+name+>
where the second line is not indented due to the fact (at least I suppose!) that the string <+name+> is not a valid name. As a consequence, the following lines move back (obviously when the if is in the first column, the second line is the only one to be wrong).
This also happens for the DO construct, but, strangely, doesn't happen for the SELECT CASE construct:
<+name+>: SELECT CASE (<+case expression+>)
CASE (<+case selector+>)
<++>
CASE DEFAULT
<++>
END SELECT <+name+>
And this is why I think a soultion must exist and be not so complicated.
I decided to solve the problem in the "dirty" way, that is, by inserting spaces in proper position in the command sequence generating the the IF...THEN...ELSE...END IF and DO...END DO constructs. This is not an elegant solution, but I don't think that has so much drawbacks. The only thing to change would be the number of spaces to add manually to the command sequences according to shiftwidth.
As #SatoKatsura suggested in a comment, it'd be better to abandon this road and use existing snippet solutions.

Move over last editing positionS

I want to see complete list of editing positions, not just a last one like '.
Jumps (<c-o> & <c-i>) are not it, since you can edit few times without any jump.
Is something like that possible or plugin should be implemented ?
EDIT
Enter in the blank line some text<esc> then do 0i1<esc> after that $a2<esc> then o<esc>. I want to have a key to return first to 2 then 1. g;/g, do not do that, they see those 2 edits as single one.
SOLUTION
It appears that this works
set fo=
au InsertEnter * set tw=1
au InsertLeave * set tw=78
After that you can use g; / g,
So basically, you want the functionality of the built-in g; / g, commands without the special treatment described at their :help:
When two undo-able changes are in the same line and at a column position less
than 'textwidth' apart only the last one is remembered. This avoids that a
sequence of small changes in a line, for example "xxxxx", adds many positions
to the change list. When 'textwidth' is zero 'wrapmargin' is used. When that
also isn't set a fixed number of 79 is used. Detail: For the computations
bytes are used, not characters, to avoid a speed penalty (this only matters
for multi-byte encodings).
Unfortunately, you only have two options:
Write your own plugin that records the insert positions (e.g. via an :autocmd InsertLeave, but capturing changes from other modes will be harder), and provides mappings to jump to them.
Modify Vim's source code to adapt the mentioned special treatment to what you have in mind.
Edit: try http://lifehacker.com/202093/go-back-in-text-file-time-with-vim-70
it could be what you were looking for
You may want to try:
:ju (show all the "jumps", ie places where you went in the file. Not always places where you edited, though)
If you want to jump directly to the "position n-3" : 3 <c-o> will do that
Another way: g ; to go back and g , to go forward
Another way: You can "mark" positions, and refer to them later
ma mark the current position and labels it "a"
mb mark another position, and labels it "b"
then
'a goes back to position a, 'b goes to position b.
it also works in commands :
:.,'as/^/# / : add "# " in front of the lines from the current one (.) to the one where mark a is ('a)
(etc)
Another way: to quickly jump to the SAME word you are currently over (usefull to jump from function definition to function usage(s): * (until you reach the one you want)
I think what you want is g-. See also :help :undolist. For full details, read
:help undo-tree
:help usr_32.txt
Edit: As the comment pointed out, this is not what the question asked for. I was really thinking of g; and g,, as mentioned by #Olivier Dulac.

Vim smart tabs inside an if statement

I'm using Vim's SmartTabs plugin to alingn C code with tabs up to the indentation level, then spaces for alignment after that. It works great for things like
void fn(int a,
________int b) {
--->...
Tabs are --->, spaces are _. But it doesn't seem to work so well for cases like
--->if(some_variable >
--->--->some_other_variable) {
--->...
In the case above, Vim inserts tabs on the second line inside the parentheses. Is there a way I can modify what Vim sees as a continuation line to include cases like this, so I get:
--->if(some_variable >
--->___some_other_variable) {
--->...
If there's an indentation style that would both allow flexible indentation width according to one's preferences, and consistent alignment, your suggested scheme would be it. Unfortunately, this style requires some basic understanding of the underlying syntax (e.g. whether some_other_variable is part of the line-broken conditional (→ Spaces) or a function call within the conditional (→ Tab)), and this makes implementing it difficult.
I'm not aware of any existing Vim plugin. The 'copyindent' and 'preserveindent' options help a bit, but essentially you have to explicitly insert the non-indent with Space yourself (and probably :set list to verify).
I don't know about that other Editor, but the situation is similar for most other inferior code editors. Without good automatic support, this otherwise elegant style will have a hard time gaining acceptance. I would love to see such a plugin for Vim.

Vim: Use tabs for indentation, spaces for alignment with C source files

Does anybody have her vim setup in a way that uses hard tabs as indentation characters, but does use spaces for alignment? The problem I have is that when starting a continuation line like in
if (condition1 && (anotherlongcondition || /* <-- Here I insert a newline */
|-------|------- whatever /* some additional alignment added automatically */
, then cin (which is a must for me) adds some alignment just the way I prefer positionally, but this alignment is created using as much hard tabs as possible and filling the rest with spaces (as I tried to visualize).
So, in short, cin doesn't really seem to distinguish between indentation and alignment. I'd really like that all the added alignment in the example above is spaces. This way the alignment would be preserved correctly when switching ts temporarily.
To make it clear again, I'd like to be able to write the following code, never pressing <TAB> or <SPACE> in front of the first non-blank character in any line (and not doing any manual shifting or whatever):
void foo(int bar)
{
|-------somestatement;
|-------if (somecondition && (someothercondition ||
|------- whatevercomesnext))
|-------|-------dosomething;
}
I have already tried out ctab.vim, but it focuses on editing an aligned line with soft tabs, which seems silly to me because manual alignment is a task which affords 1-step refinement and not tab-width-step refinement. I did not change the way cin uses mixed tabs and spaces for alignment.
I have not managed to find any built-in way to accomplish that. Perhaps still, there is one? Anyway, I doubt that there's a plugin that does that. Although I admittedly don't vim-script myself and may not have enough experience, I must say that most plugins I tried out only messed up my editor configuration...
In addition to your :set cino=(1, you may also be interested in the 'preserveindent' and 'copyindent' options if you've not encountered them already. They don't completely solve your problem, but they do go some way towards helping.
Okay, sorry for the question. I've finally found some good material for it.
http://vim.1045645.n5.nabble.com/Indent-with-tabs-align-with-spaces-td1183279.html
To sum up, currently vim is not flexible enough for this to be done comfortably.
My workaround currently is using :set cinoptions=(1 which adds only one alignment unit when starting a continuation line. This way, I can be sure that the added alignment is a space (as long as I did not :set ts=1, at least) and add the nice amount of spaces manually. This is still ok in terms of speed and seems to be the least distracting behaviour to me!

Context sensitive word wrap in vi/vim

How can I can specific word wrapping for specific tags. For example, in LaTex I want word wrapping for my paragraphs but not for my figure commands (they are always very long and run off the screen).
Or with Javascript, I want the right margin for code to be at, for example 50 columns, but for the comments to be at only 40 columns
This is not builtin
You could probably script something yourself using a devious combination of `formatexpr` and synID(). I suggest you look at the help of the latter first, because it contains inspirational samples:
for id in synstack(line("."), col("."))
echo synIDattr(id, "name")
endfor
taken from :he synstack
The formatexpr is usually set to something like
:set formatexpr=mylang#Format()
thus delegating to a filetype plugin. You could implement the function to use different margins for different syntax contexts.
Bear in mind
the default formatexpr (if absent, formatprg) are probably no good for a source file (in my experience it has the tendency to string together lines as if they were text paragraphs). But then again, you can implement it any which way you want
that syntax highlighting may become out of sync. I'm not sure what happens when the cursor is at, say, 70% of a large document and you issue ggVGgq. It might not update the syntax highlighting all the way (meaning that your formatexpr function would get the 'wrong' synID() values. You get around this by saying something like
:syntax sync fromstart
this again might impact the highlighting performance depending on the size/complexity of the source and highlighting scripts

Resources