211

When I work on files in python, I sometimes mistake tabs for spaces and vice versa. Is there a way I can get Vim to display a character for a tab instead of a tab?

2
  • 1
    Just as a side note, you can configure to convert all tabs to spaces with retab every time you save the file.
    – 0xc0de
    Commented Mar 15, 2019 at 10:12
  • If you have installed vim-faq, you can get an offline answer there: :h vim-faq and search /invisible. The hard to memorize tag is :h faq-19.8.
    – Hotschke
    Commented Jul 23, 2019 at 7:50

9 Answers 9

223

Yes, use listchars:

set list
set listchars=tab:>-

If you put these two lines in your .vimrc, tabs will be shown as > for the start position and - through the rest of the tab.

(Sidenote: listchars can also show trailing spaces with trail:x (replace x with the character you want to use for a trailing space), which can be useful as well.)

7
  • 20
    Note: I like to use set listchars=tab:!·,trail:·, IMHO · is a lot clearer than a - ... You need a fairly recent Vim version for this to work btw (not sure which exactly, I think 7.3.x)... Commented Feb 5, 2015 at 15:07
  • 20
    I like using the unicode character as it is slightly smaller than >. Currently I see trailing white space by marking the eol (though I may try the above). My settings are: set listchars=eol:¬,tab:▸\ and Commented Feb 6, 2015 at 21:43
  • 7
    This one works the best for me set listchars=eol:·,tab:⍿·,trail:×· as it is very clean.
    – 71GA
    Commented Dec 30, 2019 at 4:20
  • 1
    Here's what I'm currently using: set listchars=tab:┌┬┐,trail:·. (The non-ASCII characters are: 250c:BOX DRAWINGS LIGHT DOWN AND RIGHT, 252c:BOX DRAWINGS LIGHT DOWN AND HORIZONTAL, 2510:BOX DRAWINGS LIGHT DOWN AND LEFT, b7:MIDDLE DOT.) Commented Jun 25, 2020 at 0:24
  • 4
    FYI you can get ▸ by typing <c-k>PR (see :help digraph) Commented Mar 29, 2021 at 8:12
79

The basic answer is :set list, which causes tabs to display as ^I.

However, I recommend going beyond that. Just :set list is problematic in that it fails to preserve visual alignment on screen. For example:

%.o: %.cpp
^Ig++ -c $<

doesn't look good, especially when you expect the g of g++ to appear under the first p of cpp (assuming tabstop=8).

Therefore, I suggest that in your .vimrc you put something like :set listchars=tab:␉· (To be clear, that's Unicode character U+2409 SYMBOL FOR HORIZONTAL TABULATION followed by U+00B7 MIDDLE DOT.)

As explained in :help listchars, a two-character setting for tab:xy causes visual alignment to be preserved:

tab:xy        Two characters to be used to show a tab.  The first
              char is used once.  The second char is repeated to
              fill the space that the tab normally occupies.
              "tab:>-" will show a tab that takes four spaces as
              ">---".  When omitted, a tab is show as ^I.

The example above would appear on screen as:

%.o: %.cpp
␉·······g++ -c $<

Personally, I go all-out with my listchars:

:set listchars=eol:⏎,tab:␉·,trail:␠,nbsp:⎵

These characters are distinctive enough that they rarely appear literally in document text.

To type these special characters into your vimrc, type Ctrl-vu23CE while in Insert Mode, as explained in :help utf-8-typing.

2
  • 4
    See also set lcs=tab:├─
    – sch
    Commented Feb 5, 2015 at 15:33
  • this just gave me a ? at eol
    – WendyG
    Commented Oct 7, 2019 at 12:45
39

Highlighting tabs

Temporary Tab highlighting

For occasional use, one can simply highlight all tabs in a document using the following search / command:

/\t

To remove the highlighting, simply type :noh which is short for :nohlsearch —no high lighting.

Permanent Tab highlighting

" Highlight tabs as errors.
" https://vi.stackexchange.com/a/9353/3168
match Error /\t/

Tab highlighting in vim

More highlighting

For more of these useful highlighting commands —including combined with trailing whitespace and making this permanent— see the Vim wiki.

2
  • 6
    You can also use :match Error /\t/ to highlight tabs (or any other pattern for that matter) independently from the search register and hlsearch (type :match to clear it). Commented Aug 25, 2016 at 22:56
  • 1
    @Carpetsmoker One can find a whole lot more of these useful highlighting commands (including combined with trailing whitespace!) on the Vim wiki about highlighting unwanted spaces. Commented Aug 26, 2016 at 19:05
10

I personally like the use of the plugin indentLine, which displays a vertical line at indentation levels.

It is of great help especially in python, where the indentation is important.

(Image taken from the link above)

Among other things, it provides a toggle command, that can be mapped to a key combination, so that you can turn it off, when you don't need it.

4
  • 4
    I believe this plugin is intended for spaces indenting though?
    – Jake Byman
    Commented Dec 11, 2017 at 18:02
  • 1
    Indeed: > This plugin is used for displaying thin vertical lines at each indentation level for code indented with spaces. For code indented with tabs I think there is no need to support it, because you can use :set list lcs=tab:\|\ (here is a space).
    – thiagowfx
    Commented Jul 6, 2020 at 3:22
  • indent guide supports tabs as well: github.com/nathanaelkane/vim-indent-guides
    – aderchox
    Commented Jul 28, 2020 at 5:13
  • Is there a way to also display tabs (well i don't want tabs but lines to connect the brackets) in empty lines?
    – 71GA
    Commented Mar 14, 2021 at 19:30
7

Easiest method is to do :set list, which will show tabs as ^I and end of line as $.

I like to use a mapping that calls

:set invlist 

to toggle between regular display and list display.

For example:

:nmap <leader>l :set invlist<cr>

This allows me to quickly check if there are tab vs space problems and then go back to a regular display.

5

You may want to show tabs differently in a regular terminal and gvim.

set list!
if has('gui_running')
    set listchars=tab:▶\ ,trail:·,extends:\#,nbsp:.
else
    set listchars=tab:>.,trail:.,extends:\#,nbsp:.
endif

(Adding for completeness, in case others find it useful).

5

This can be easily achieved using listchars by specifying the tab as: ,tab:\ \ ┊,

By providing two escaped spaces in front of your tab declaration, vim will repeat the spaces. This is opposed to the default, where vim prefers the second character as the repeating character.

This achieves a similar effect to using a plugin like IndentLine without the overhead. Here's an example of what it might look like using the following complete listchars config:

set listchars=eol:↓,tab:\ \ ┊,trail:●,extends:…,precedes:…,space:·

source code

3
  • 2
    Welcome to Vi and Vim! Do note that the top 2 answers (and a few of the others as well) already mention this solution.
    – D. Ben Knoble
    Commented Jul 14, 2020 at 12:52
  • 1
    @D.BenKnoble Thank you for the friendly welcome and feedback! However, I disagree. This is an alternative to @mike's response. While the other responses do reference listchars, none of them explain how to achieve repeating the left character to achieve the same result as a plugin like IndentLine.
    – Swivel
    Commented Jul 17, 2020 at 6:47
  • 1
    @D.BenKnoble I've reworded my answer to hopefully clarify how my answer differs from the others mentioned.
    – Swivel
    Commented Jul 17, 2020 at 6:54
3

I combined @john-om approach with this character Unicode Character 'ZERO WIDTH SPACE' (U+200B) and indentLine plugin. So, if I use spaces, plugin show nice formated indents, if I use tabs, pipes are the only visible mark and that is what I want. I can also toggle tab's marks.

" indicate tabs
:nmap <leader>l :set invlist<cr>
set list listchars=tab:❘⠀,trail:·,extends:»,precedes:«,nbsp:×
1
  • 1
    I like this one, it is a lot more cleaner, I just added the eol to the end of it, set list listchars=tab:❘⠀,extends:»,precedes:«,nbsp:×,eol:⏎ Commented Jan 27, 2022 at 8:49
1

I like VSCode's "render whitespace" display

I customize vim's space and tab chars like vscode, i.e. use dark gray color dot for space char, use arrow char for tab.

My vim configuration

"\u21A6 is ⇥
"set listchars=eol:$,tab:⇥¬¬,trail:·,extends:>,precedes:<,space:·
" 0x1F862 is 🡢
" https://vi.stackexchange.com/questions/422/displaying-tabs-as-characters
set listchars=tab:🡢\ ,trail:·,extends:>,precedes:<,space:·
" Set the list char color
" https://vi.stackexchange.com/questions/6136/how-to-dim-characters-from-set-list/6140#6140
" :hi SpecialKey ctermfg=grey guifg=grey50
" https://gist.github.com/morumo/9405368
:hi SpecialKey ctermfg=darkgray guifg=gray70

enter image description here

enter image description here

My emacs configuration

Btw, I also tried to configure the render display in my emacs configuration:

;; https://github.com/jameshintaro/.emacs/
;;http://ergoemacs.org/emacs/whitespace-mode.html
(require 'whitespace)
(setq whitespace-style
      '(face tabs tab-mark spaces space-mark))

(setq whitespace-display-mappings
      '(
        (space-mark ?\u3000 [?□])  ; 全角スペース
        (space-mark ?\u0020 [?\xB7])  ; 半角スペース
        (newline-mark ?\n   [?$ ?\n]) ; 改行記号
        ;(tab-mark   ?\t   [?\x2192 ?\t]) ; tab
    (tab-mark   ?\t   [?\x1F862 ?\t]) ; tab
        ) )

(setq whitespace-space-regexp "\\([\x0020\x3000]+\\)" )

;(set-face-foreground 'whitespace-space "Goldenrod1")
(set-face-foreground 'whitespace-space "Azure4")
(set-face-background 'whitespace-space 'nil)
(set-face-bold-p 'whitespace-space t)

;;(set-face-foreground 'whitespace-tab "DarkOliveGreen1")
(set-face-foreground 'whitespace-tab "Azure4")
(set-face-background 'whitespace-tab nil)
(set-face-underline  'whitespace-tab t)

;;(set-face-foreground 'whitespace-newline  "DimGray")
;;(set-face-background 'whitespace-newline 'nil)

Which looks like the following: enter image description here

enter image description here

1
  • 10x, was really missing that
    – Roman M
    Commented Sep 20, 2023 at 11:19

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