I set tab configuration in ~/.vimrc as below:
set ts=4 sts=4 sw=4
I notice that if the word is 4 characters long or above, the cursor shift into right 4 spaces as in configuration for tabstop.
But if the word is less than 4 characters long, it didn't shift into 4 spaces.
Example:
'name' + <Tab>: tab produced correct number of spaces (i.e 4 spaces)
'age' + <Tab>: tab produced wrong number of spaces (i.e 1 space only)
Why is it ?
Does the word length effect tab?
What can I do if I want to shift the cursor to 4 spaces as configured regardless of the word length?
Thanks a lot
You’re probably inserting regular tabs, which display variable-width according to what’s before and after. I find having set list on is really handy for this (though you probably won’t like the default listchars settings).
If you really want spaces (which I find better anyway, set expandtab.
Also, most long-time users recommend leaving tabstop at 8, since you can’t control how wide every one’s tabs are.
The way that the tabstop, shiftwidth, and softtabstop options work is that they control indentation to certain points that are commonly referred to as "tab stops". In other words, they're designed to always indent to a column that's a multiple of the setting.
So if your tab stops are at multiples of 4, then hitting the Tab key will cause the cursor to indent to a column that is the next multiple of 4. This is the behavior of inserting a literal tab (U+0009, CHARACTER TABULATION) into a document and then rendering it on a normal terminal (except that the width is usually 8 there). This results in text that is aligned at fixed columns, which is the desired style for most programming languages and text markup formats.
As you've noted, this does result in different amounts of indent if the words are different lengths. Typically in code, we would just cause the second column to be at the next tab stop and not care that the indents are of different lengths. That is, in your example, we'd hit Tab once on the first line and twice on the second, and start the next column at column 8.
I'm not aware of any way to force Vim to insert a specific number of spaces other than the standard editing commands. Normally users who are in this situation just hit Space four times if they really want four spaces and not an indentation to the next tab stop. You can of course create a mapping if you need to do that a lot.
Related
In vim, when I format the following paragraph in a plain text file using gqip, the formatter indents it like an enumerated list.
Original paragraph:
Here is some text including a number
3 in the paragraph, which may be
regarded as the start of a numbered
list when I format it.
Formatted (after gqip):
Here is some text including a number
3 in the paragraph, which may be
regarded as the start of a numbered
list when I format it.
The problem is that vim aligns the word "regarded" as if the line "3 in the paragraph..." somehow means "(3) in the paragraph". In my opinion, this is a bug in the formatting rules, because there are obvious counter-examples that occur frequently in ordinary text. So how can I refine this indentation rule to apply only when there is list-like punctuation on the number? For example, I think this is ok:
Here is some text including a number
3) in the paragraph, which may be
regarded as the start of a numbered
list when I format it.
There are counter-examples to this rule as well, but at least the error occurs less frequently. The rule could be further refined by checking for balanced parentheses--i.e.:
Here is some text (including a number
3) in the paragraph, which is not
regarded as the start of a numbered
list when I format it (because the
parenthesis is accounted for by the
opening parenthesis on line 1).
See :h fo-table 's n letter meaning, then see :h formatlistpat, which is used to recogize a list header:
" 'formatlistpat' 'flp' string (default: "^\s*\d\+[\]:.)}\t ]\s*")
" ignore '3 ' by removing space in pattern
let &formatlistpat='^\s*\d\+[\]:.)}\t]\s*'
" ignore (\n3) or [\n3] or {\n3} by adding a preceding NOT match
let &formatlistpat='\([\[({]\s*\n\)\#<!\_^\s*\d\+[\]:.)}\t]\s*'
Emacs has a function called open-rectangle, which allows you to select a rectangular region (i.e. Vim's visual block mode), then hit a key combination to fill that rectangle with spaces, pushing any existing content out to the right:
This is really useful when working with vertically-aligned columns of text. I feel like I should be able to do this easily in Vim too, using visual block + a search & replace. But I can't seem to figure out why my search & replace isn't bound to my rectangle when I try it.
:'<,'>s/\^/ /
This actually indents the whole line, instead of opening up this selected region. I've tried replacing:
:'<,'>s/\v(.*)/ \1/
But that has the same effect. How can I get my pattern to understand that I only want to replace each line in the selected block with spaces + the selected area? Simple replacements like just changing letters work, but using ^ or .* doesn't work the way I'd expect.
I am aware of the ability to hit "I" and insert some spaces the drop back into normal mode, but that is harder to judge when you're indenting by a large amount, over many lines.
How about:
yPgvr<Space>
This yanks the block and pastes it to duplicate it, then re-selects the original block and replaces it with spaces.
Another way:
Visual-block select only one column.
Hit nI<Space><Esc> with n being the number of blank columns you want.
As a variation on romainl's answer, I have this:
vnoremap <C-Space> I<Space><Esc>gv
It allows both insertion of n spaces at once via a prepended count, and iterative adding of columns by repeated application of the mapping.
Suppose I have the piece of text below with the cursor staying at the first A currently,
AAAA
BBB
CC
D
How can I add spaces in front of each line to make it like, and it would be great if the number of columns of spaces can be specified on-the-fly, e.g., two here.
AAAA
BBB
CC
D
I would imagine there is a way to do it quickly in visual mode, but any ideas?
Currently I'm copying the first column of text in visual mode twice, and replace the entire two column to spaces, which involves > 5 keystrokes, too cumbersome.
Constraint:
Sorry that I didn't state the question clearly and might create some confusions.
The target is only part of a larger file, so it would be great if the number of rows and columns starting from the first A can be specified.
Edit:
Thank both #DeepYellow and #Johnsyweb, apparently >} and >ap are all great tips that I was not aware of, and they both could be valid answers before I clarified on the specific requirement for the answer to my question, but in any case, #luser droog 's answer stands out as the only viable answer. Thank you everyone!
I'd use :%s/^/ /
You could also specify a range of lines :10,15s/^/ /
Or a relative range :.,+5s/^/ /
Or use regular expressions for the locations :/A/,/D/>.
For copying code to paste on SO, I usually use sed from the terminal sed 's/^/ /' filename
Shortcut
I just learned a new trick for this. You enter visual mode v, select the region (with regular movement commands), then hit : which gives you this:
:'<,'>
ready for you to type just the command part of the above commands, the marks '< and '> being automatically set to the bounds of the visual selection.
To select and indent the current paragraph:
vip>
or
vip:>
followed by enter.
Edit:
As requested in the comments, you can also add spaces to the middle of a line using a regex quantifier \{n} on the any meta-character ..
:%s/^.\{14}/& /
This adds a space 14 chars from the left on each line. Of course % could be replaced by any of the above options for specifying the range of an ex command.
When on the first A, I'd go in block visual mode ctrl-v, select the lines you want to modify, press I (insert mode with capital i), and apply any changes I want for the first line. Leaving visual mode esc will apply all changes on the first line to all lines.
Probably not the most efficient on number of key-strokes, but gives you all the freedom you want before leaving visual mode. I don't like it when I have to specify by hand the line and column range in a regex command.
I'd use >}.
Where...
>: Shifts right and
}: means until the end of the paragraph
Hope this helps.
Ctrl + v (to enter in visual mode)
Use the arrow keys to select the lines
Shift + i (takes you to insert mode)
Hit space keys or whatever you want to type in front of the selected lines.
Save the changes (Use :w) and now you will see the changes in all the selected lines.
I would do like Nigu. Another solution is to use :normal:
<S-v> to enter VISUAL-LINE mode
3j or jjj or /D<CR> to select the lines
:norm I<Space><Space>, the correct range ('<,'>) being inserted automatically
:normal is probably a bit overkill for this specific case but sometimes you may want to perform a bunch of complex operations on a range of lines.
You can select the lines in visual mode, and type >. This assumes that you've set your tabs up to insert spaces, e.g.:
setl expandtab
setl shiftwidth=4
setl tabstop=4
(replace 4 with your preference in indentation)
If the lines form a paragraph, >ap in normal mode will shift the whole paragraph above and below the current position.
Let's assume you want to shift a block of code:
setup the count of spaces used by each shift command, :set shiftwidth=1, default is 8.
press Ctrl+v in appropriate place and move cursor up k or down j to select some area.
press > to shift the block and . to repeat the action until desired position (if cursor is missed, turn back with h or b).
Another thing you could try is a macro. If you do not know already, you start a macro with q and select the register to save the macro... so to save your macro in register a you would type qa in normal mode.
At the bottom there should be something that says recording. Now just do your movement as you would like.
So in this case you wanted 2 spaces in front of every line, so with your cursor already at the beginning of the first line, go into insert mode, and hit space twice. Now hit escape to go to normal mode, then down to the next line, then to the beginning of that line, and press q. This ends and saves the macro
(so that it is all in one place, this is the full list of key combinations you would do, where <esc> is when you press the escape key, and <space> is where you hit the space bar: qai<space><space><esc>j0q This saves the macro in register a )
Now to play the macro back you do # followed by the register you saved it in... so in this example #a. Now the second line will also have 2 spaces in front of them.
Macros can also run multiple times, so if I did 3#a the macro would run 3 times, and you would be done with this.
I like using macros for this like this because it is more intuitive to me, because I can do exactly what I want it to do, and just replay it multiple times.
I was looking for similar solution, and use this variation
VG:norm[N]I
N = numbers of spaces to insert.
V=Crtl-V
*** Notice *** put space immediate after I.
What's the easiest way to delete the first 2 spaces for each line using VIM? Basically it's repeating "2x" for each line.
Clarification: here the assumption is the first 2 characters are spaces. So the question is about doing indentation for multiple lines together.
Enter visual block mode with Ctrl-V (or Ctrl-Q if you use Ctrl-V for paste);
Select the area to delete with the arrows;
Then press d to delete the selected area.
Press Esc
Some more options. You can decided which is the "easiest way".
Remove the first 2 characters of every line:
:%normal 2x
Remove first 2 characters of every line, only if they're spaces:
:%s/^ /
Note that the last slash is optional, and is only here so that you can see the two spaces. Without the slash, it's only 7 characters, including the :.
Move indentation to left for every line:
:%normal <<
You could also use a search and replace (in the ex editor, accessed via the : character):
Remove first two characters no matter what:
%s/^.\{2}//
Remove first two white space characters (must be at the beginning and both must be whitespace... any line not matching that criteria will be skipped):
%s/^\s\{2}//
Assuming a shiftwidth=2, then using shift with a range of %
:%<
Two spaces, or two characters? (2x does the latter.)
:[range]s/^ //
deletes two blanks at the beginning of each line; use % (equivalent to 1,$) as [range] do to this for the entire file.
:[range]s/^..//
deletes the first two characters of each line, whatever they are. (Note that it deletes two characters, not necessarily two columns; a tab character counts as one character).
If what you're really doing is changing indentation, you can use the < command to decrease it, or the > command to increase it. Set shiftwidth to control how far it shifts, e.g.
:set shiftwidth=2
I'd try one of two approaches:
Do column editing on the block to delete using Ctrl+V (often mapped to Ctrl+Q).
Record a macro on the first row using q1 (or any other number/letter you want to denote the recording register), then replay that macro multiple times using #1 (to use my previous example. Even better, use a preceding number to tell it how many times to run - 10#1 to run that macro 10 times, for example. It does, however, depends on what you recorded - make sure to rewind the cursor 0 or drop one line j, if that's relevant.
I'd also add: learn how to configure indentation for vim. Then a simple gg=G will do the trick.
I have word lists where the word or expression in Spanish is separated by its translation with a colon (":"). I want to make two columns, one for Spanish, the other for English. In vim I tried with
:%s/:/^I^I^I/g
But it does not give the desired output. The different columns are not aligned.
When deleting the colon by hand and inserting the number of tabs with the same amount of tab strokes, it always ends up aligned.
Any idea how to solve this, preferably in vim?
On a Linux/*nix system I use column(1)
:%!column -s':' -t
followed by
:%retab!
I'd probable do a
:s/:/^I/g
followed by a
:set ts=25
Where 25 is the length of the longest word expected + 2. So, if you expect the longest word of your input (on the left side of the colon) to be 12 characters, I'd choose something around 14 instead.
With Tabular.vim it's quite easy, just type :Tab /:\zs and it does the rest.
When in insert mode a setting of yours makes tab to reach a nth column. This is set with the 'softtabstop' settings if I am right.
For those tasks you could use a plugin like Align.vim or Tabularize.
Another option is to insert a huge number of spaces, and then use Visual Block with < operator as many times as necessary, if you have to do it once. Otherwise prefer reusable methods.