Lim H.
Lim H.

Reputation: 10050

Change 2-space indent to 4-space in vim

I've some codes copied from the Internet that have 2-space indenting and I want to change it into 4-space indenting. I wonder if there is a short vim routine to accomplish the task without having to write vim script? Here is how I'm currently doing it with an HTML file:

In short qa0vt<yp<esc>jq

Pitfalls:

The macro fails for a blank line or a line that doesn't start with "<". And I have no idea how to extend this solution to non-HTML file.

Upvotes: 117

Views: 48660

Answers (8)

yihui.dev
yihui.dev

Reputation: 602

In addition to @spro's answer, I put this in my .vimrc

command! -range=% Format :<line1>,<line2>s/^\s*/&&

Just type :Format.

With visual selection, this only formats the selected lines.

Without visual selection, this formats the whole file.

Upvotes: 1

htaccess
htaccess

Reputation: 3110

This is a variant of the regex based answers.

I have a bash script in my local bin directory that will double the amount of whitespace at the start of a line. Input can be stdin or a file:

$ cat ~/bin/dblsp
#!/bin/bash

file=${1--}

while IFS= read -r line; do
    echo "$line" | sed 's/\s*/&&/'
done < <(cat -- "$file")

I use this within vim by visually selecting a line and issuing the following command:

:'<,'>!dblsp

This saves me the need to type (or remember) the regex.

I also use it in maps like the following:

nnoremap <leader>] `[V`]!dblsp<CR>

which will apply it to a block of recently pasted text. I usually use the following map to paste rather than :set paste

nnoremap <leader>p :r !xclip -o<CR>

My usual workflow is:

  • select code snippet (eg the example code on this page is 2 spaces but I want 4)
  • paste code snippet (,p)
  • change spacing (,])

or simply changing the indent on yanked blocks pasted from another buffer.

Upvotes: 0

Chase Vasic
Chase Vasic

Reputation: 121

This is a very old question, however all the answers are ... wrong ... Vim has a very easy way to reindent the entire file. I learned this after writing my own function to do it, so I'm in the same ignorance boat ;)

type

gg=G

this is assuming that you have your tabstop set to what you like, (so for the OP it would be ts=4)

I learned this from http://vim.wikia.com/wiki/Fix_indentation , which mentions

In normal mode, typing gg=G will reindent the entire file. This is a special case; = is an operator. Just like d or y, it will act on any text that you move over with a cursor motion command. In this case, gg positions the cursor on the first line, then =G re-indents from the current cursor position to the end of the buffer.

Upvotes: 10

spro
spro

Reputation: 1593

What I do is very similar to esneider and cforbish's approaches, but a bit quicker to type:

:%s/^\s*/&&

Simply replaces leading space (spaces or tabs) with twice as much leading space (& is substituted with the matched expression).

Upvotes: 43

esneider
esneider

Reputation: 589

Similar (but somewhat simpler) to cforbish's answer, this regex will duplicate the leading spaces

:%s/^\( \+\)/\1\1

Or you can use this other regex to transform 2-spaces into 4-spaces, preserving single spaces (and odd amounts in general)

:%s/^\(\(  \)\+\)/\1\1

That is,

  • 1 space ⇢ 1 space
  • 2 spaces ⇢ 4 spaces
  • 3 spaces ⇢ 5 spaces
  • 4 spaces ⇢ 8 spaces

Upvotes: 1

Daan Bakker
Daan Bakker

Reputation: 6332

A general way of changing the indent is by changing the tabstop:

Paste your file into an empty buffer, then:

:set ts=2 sts=2 noet
:retab!

This changes every 2 spaces to a TAB character, then:

:set ts=4 sts=4 et
:retab

This changes every TAB to 4 spaces.

The advantage of this method is that you can also use it the other way around, to convert from 4 to 2 spaces for example.

Upvotes: 204

cforbish
cforbish

Reputation: 8819

I used this regular expression (it doubles the number of leading spaces):

%s;^\(\s\+\);\=repeat(' ', len(submatch(0))*2);g

Upvotes: 3

perreal
perreal

Reputation: 97948

It may be possible with :set shiftwidth=4 and gg=G.

Upvotes: 76

Related Questions