I like cindent, smartindent and =% features in vim, which properly indents the code.
But, I have one problem with this, it indents everything with 8 spaces, and if I have few nested ifs, it can be very long line like here, though having so many nested ifs in first place is another question.
4 int main()
5 {
6 if(x)
7 {
8 if(u)
9 {
10 if(y)
11 {
12 }
13 }
14 }
15 }
I tried to set ts=1 and still it doesnt work.
Is there any way to make default indentation level to 4 spaces while using these features?
Edit
set sw=4 solved the problem. No wonder vim always surprises me :)
I believe you're looking for shiftwidth, abbreviated sw.
Edit: a couple quotes from documentation:
shiftwidth: Number of spaces to use for each step of (auto)indent. Used for |'cindent'|, |>>|, |<<|, etc.
tabstop: Number of spaces that a <Tab> in the file counts for.
expandtab: In Insert mode: Use the appropriate number of spaces to insert a <Tab>. Spaces are used in indents with the '>' and '<' commands and when 'autoindent' is on.
smarttab: When on, a <Tab> in front of a line inserts blanks according to 'shiftwidth'. 'tabstop' is used in other places.
Depending on your style, you may have to change more than one of these. Have a look at their help entries if you need more clarification!
Try setting shiftwidth (sw) to 4.
And, if you want to use spaces instead of tabs, set expandtab (et). Then you can change all those tabs to spaces with :retab.
Related
After reading Vim regex replace with n characters, I've known how to replace tabs by spaces:
:%s/^\v(\t)*/\=repeat(repeat(' ',4),strlen(submatch(0)))/g
The command above allows me to replace n tabs at the beginning of each line with n four-spaces.
Now I want to inverse it: replace n four-spaces with n tabs at the beginning of each line, I think the command should be :%s/^\v( )*/\=repeat("\t",strlen(submatch(0)))/g, but it doesn't work: if there is one four-space, it will be replaced by four tabs (but I want to make it only one tab) after executing the command.
Besides, is it possible to get the length of tab of vim so that I can make the command as below?
:%s/^\v(\t)*/\=repeat(repeat(' ',getSizeOfTab()),strlen(submatch(0)))/g
You can get the value of an option in Vimscript by prepending &. So, the size of tab is &tabstop, or &ts. There's also &softtabstop (&sts), pick which one you actually care about.
Whereas you needed to multiply the number of spaces with size of tab, you need to divide the number of tabs. Then there's the remainder to take care of. So, first set your tabstop:
:set ts=4
Then you can convert from tabs to spaces and from spaces to tabs like this:
:%s/^\v(\t)*/\=repeat(repeat(' ',&ts),strlen(submatch(0)))/g
:%s#^\v( )*#\=repeat("\t",strlen(submatch(0))/&ts).repeat(' ',strlen(submatch(0))%&ts)#g
(changed the separator from / to # because I needed / for division :P )
However... it seems you're reinventing the wheel here. :help :retab! and :help 'expandtab'. First set tabstop as above, then:
:set et | ret!
:set noet | ret!
The first one will change tabs to spaces; the second one, spaces to tabs, according to tabstop.
I am currently thrown into a new project where the indentation style is a bit special. The basic rule is to use 'keyword+blank' spaces to indent the next line.
For example:
if () {
// indent 3 spaces here
}
while () {
// indent 6 spaces here
}
There are some (or a lot) of exeptions:
else if: use same number of spaces as if (3)
case in switch/case (2 spaces)
...
1) Is there already a plugin available that can do it for me? According to one of the developers this is called 'smart identation'. Unfortunately VIM's smartindent does something different.
2) If the answer to 1 is no. Is there an easy way to configure vim to respect these rules?
I'm not aware of any such plugin, and IMHO this scheme is anything but smart.
However, it is entirely possible to write a custom indent plugin that implements the exact requirements that you have. See :help 'indentexpr'; also, Vim ships with several indent plugins in $VIMRUNTIME/indent/*.vim that can serve as inspiration.
Basically, the algorithm would be like this:
Check the previous line for one of the keywords (if, while, and so on).
If there's a match, calculate the offset and add that to the previous line's indent (indent(v:lnum - 1)); else, use the previous line's indent as is.
If the line contains a }, find the line with the matching {, and use the indent from that line.
It appears, surprisingly, that more self-selected SO devs prefer to indent via tabs rather than spaces. Some people brought up the argument that you can use tabs to indent, and spaces to align. In theory this sounds cool, but in practice I suspect it would be more of a pain than anything, seeing as you can't see which character you have (unless you like turning on that sort of thing).
So I had an idea - why not the editors? Why shouldn't editors let you configure the number of spaces you're going to use to indent, but also the appearance of those spaces. That is:
Normal:
class MyClass:
____def myfun():
________somevariable = 42
________volts = 40000000 # If you're into that sort of thing.
________________________________# Not well-formatted Python, though.
Leading indent set to appear as 2 spaces:
class MyClass:
__def myfun():
____somevariable = 42
____volts = 400000000
Is it possible to do something like this with vim? I know it's totally possible to write a post-open/pre-save command to replace the contents, which might work the same... but I'm more curious if it's possible, in vim, to make it appear as though the leading spaces are less (or more) than they actually are?
Yes, you can, using the conceal feature. Demonstration (using the markup from your example text and a different replacement character instead of spaces for effect):
:syntax match Indent "\%(^\%(__\)*\)\#<=__" conceal cchar=#
:set conceallevel=2 concealcursor=nvic
The pattern matches every pair of __ at the beginning of the line, and replaces (conceals) each with a single #, effectively reducing the visible indent.
As a purely visual feature, I don't find it very useful though, and would prefer the post-open / pre-save solution you seem to be aware of.
I want to count lines in a range, not matter what range, but let it be, say, a visual block.
What is the shortest way to do it. All that comes to my mind is something like: '<,'>s/.//n
but I don't believe it is the shortest way.
So, can somebody give me a hint?
In visual mode, press gC-g
Typical output:
Selected 7 of 22 Lines; 8 of 32 Words; 201 of 491 Chars; 201 of 497 Bytes-- VISUAL LINE --
Source: :he count-items (discoverable as: :heTabTab...)
Set the option showcmd (:h 'sc'), and you will never ever need to type anything to know how many lines are selected -- at first, as I forget that I've set this option, I didn't understand the point of your question. ^^'
Otherwise, if you want to obtain that number programmatically, it's simply:
:echo line("'>") - line("'<") + 1
From within a range-function, it can also be obtained by a:lastline-a:firstline+1. (:h function-range-example)
'<,'>s///n is one character shorter. :-)
If I just want to know the number of lines in a visual selection I usually just yank it (hit y). It'll say "5 lines yanked" or "block of 5 lines yanked" depending on the type of selection.
I noted that the 'showbreak' symbol is highlighted with the highlight "NonText" color-element. NonText is also used for the EOL Characters.
I would like to keep the highlight-color for the EOL characters but want to change it for the showbreak symbol is that possible?
Another problem is that my showbreak symbol is not displayed.
I would like to use this symbol "↳" and put it in the linenumbers column (using set cpoptions+=n). I can't find out how to display the symbol and how to put a space after the showbreak symbol (between the text and the symbol).
Can anyone help me?
I don't think you're going to get highlighting to be different than the EOL character, at least I am not aware of a way to do that.
For the second part I can help with. I was able to get "↳ " to show up in my line number column with the following settings:
let &showbreak = '↳ '
set wrap
set cpo=n
Note that there is a space after the ↳. This lines up nice until you have > 9 lines in the file. If you wanted it to line up with the last character of the number column regardless of the number of lines I'm not sure what you're going to have to do.
Edit: I've recently written a proof-of-concept function for someone on IRC that highlights the first character on a line that has been wrapped with a different highlight group. It hasn't been tested much but it seems to work. Not exactly what you're looking for but maybe it's worth a look.
:help hl-NonText makes it pretty clear that you cannot have different colors for the 'showbreak' string and other non-text strings, of which eol is a member (see :help 'listchars'):
NonText
'~' and '#' at the end of the window, characters from 'showbreak' and
other characters that do not really exist in the text (e.g., ">"
displayed when a double-wide character doesn't fit at the end of the
line).
If you're willing to accept this limitation (#elliottcable) hi! link NonText LineNr will match the 'showbreak' string to the line number colors.
If you really wanted to get clever, as a compromise you could create a mapping or command to toggle between ':set list' and ':set nolist' that would also adjust the NonText highlight setting simultaneously.
If you use :set relativenumber (added in vim 7.3), :set showbreak=↳\ \ \ will reliably keep your 'showbreak' neatly lined up since the number width will not change as you navigate through the file. (This in addition to the :set cpo+=n and :set wrap #Randy Morris mentioned in his answer.)
You'll definitely need UTF-8 for the ↳ character, since it does not appear in other encodings. I'd strongly recommend you carefully document your encoding problems, with details about how to reproduce them along with your OS, its version, and the :version output of vim, and post them as separate questions. UTF-8 should be helping you wrangle multiple languages rather than being an impediment.