0

My .vimrc:

:set tabstop=2
:set shiftwidth=2
:set ai
:set expandtab

My workflow:

  • vi filename
  • type space spacetextenter, cursor is now under 't', indented with 2 spaces. As expected.
  • :set paste
  • paste block of text that is indented using spaces, pasted as expected
  • :set ai (to go back to auto indenting)
  • type space spacetextenter, cursor is now under 't', indented with 1 tab. I expected this would be indented with spaces.

Where am I going wrong? I've used this .vimrc setup in the past and it's worked normally. Not really sure where it's going wrong.

Using: VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Apr 27 2022 06:12:50)

3
  • 2
    Welcome to Vi and Vim! Why are you using :set ai instead of :set nopaste to undo the effects of 'paste' mode? I think that might be related to your issue. Do you still reproduce if you use :set nopaste in that step instead?
    – filbranden
    Aug 3 at 17:09
  • If you look at :help 'paste' you'll see that it resets quite a few options, including 'expandtab', so maybe that's what's happening here?
    – filbranden
    Aug 3 at 17:10
  • @filbranden :set nopaste works in the expected manner. I've always used :set ai and it worked the way I wanted before. Very strange. Not sure what was different. Thanks. I'll just have to remember :set nopaste in future :)
    – psx
    Aug 3 at 17:27

1 Answer 1

3

The issue you're having is due to the 'paste' option having an effect on a series of other options and not simply disabling auto-indent. (See :help 'paste' for a list of all options that are affected by it.)

When you try to undo it by simply running :set ai, you're still leaving behind most of the other side-effects, in particular 'expandtab' having been reset, which probably explains why you're seeing this specific side-effect of getting automatic indentation with tabs instead of spaces.

In order to prevent this issue, use :set nopaste instead of :set ai to disable paste mode.


You might want to consider adopting the vim-unimpaired plug-in, which includes a few commands (]op, [op and yop) to start insert in 'paste' mode and automatically leave 'paste' mode once you leave insert mode, so you don't need to use an explicit command to leave 'paste' mode.

I also add an Insert mode binding for Ctrl+E to start 'paste' mode from Insert mode:

inoremap <C-e> <C-g>u<C-o>:execute "normal \<Plug>unimpairedPaste"<cr>

(Note that the above mapping depends on the vim-unimpaired plug-in being available. The <C-g>u at the beginning breaks the undo sequence, so that if you use u to undo after a paste it will only undo the paste itself and not what you inserted while in Insert mode before pasting.)


If you prefer not to load a Vim plug-in, you can accomplish something similar to the part of disabling 'paste' at the end of an Insert with an autocmd for the InsertLeave event:

augroup Paste
  autocmd!
  autocmd InsertLeave * set nopaste
augroup END

The above will execute a :set nopaste every time you leave Insert mode.

You can also use the 'pastetoggle' option to set a hotkey to enter or leave 'paste' mode from Insert mode. For example:

set pastetoggle=<C-e>

But personally I prefer the inoremap mentioned above, because typically I prefer to leave Insert mode and have the autocmd disable paste mode rather than switch it on and off while staying in Insert mode. Additionally, I like the feature of the mapping that breaks the undo sequence. So for those reasons I typically end up avoiding 'pastetoggle', but it might work well for you.

2
  • 1
    Don’t forget pastetoggle ;)
    – D. Ben Knoble
    Aug 3 at 21:22
  • 1
    Thanks for the very detailed answer! Just tried the autocmd, and it works brilliantly.
    – psx
    Aug 4 at 9:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.