I like to indent my shell scripts with two spaces instead of a TAB. So, I set setlocal shiftwidth=2 in ~/.vim/after/ftplugin/sh.vim. It works, but I noticed that when the indentation level gets greater than 8 spaces, Vim replaces them with a tab. So, I also added "setlocal expandtab" in this file.

Unfortunately, this replaces all tabs by 8 spaces, even the ones inserted when I press the TAB key.

I'm looking for suitable settings to always have indentation (automatic or manual) composed of spaces only, but still insert a real tab when I press the TAB key.

On other Q&A, I found functions to toggle between spaces and tabs, but I'm looking for a solution which doesn't involve any kind of toggling.

Likewise, sticking with shiftwidth only and use :retab from time to time after momentarily enabling expandtab would not be a suitable solution (let alone the fact that since tabs and spaces are indistinguishable on screen, I wouldn't know when a file needs to be "retabbed").

1 Answer 1


You can always type a literal tab using <c-v><tab>. Thus, you can set expandtab to always keep indent spaces, and use

inoremap <tab> <c-v><tab>

to always insert a tab character when pressing the tab key. You should not use :retab at all in this case, since it will convert your tabs into spaces.

  • This works like a charm ! I used inoremap <buffer> <tab> <c-v><tab> to make it local to the buffer, since it will be used in an "after" file for Vim's default sh filetype plugin. Also, a bit of explanation for people (like me) not familiar with Vim's map commands: noremap stands for non recursive map, and not no remap, as one would intuitively think. The starting i makes it active only in Insert mode.
    – MoonSweep
    Mar 14, 2018 at 11:21
  • This is a Vimscript line which can easily be written in Lua like this: vim.api.nvim_set_keymap('i', '<tab>', '<c-v><tab>', { noremap = true }). Thanks to this Reddit comment.
    – Sufian
    Nov 11, 2023 at 17:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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