In the buffer
With :set shiftwidth=4 expandtab, you have typed the third line and the cursor is still in insert mode after the closing parenthesis:
def load(path):
with open(path) as f:
data = json.load(f)
^
After typing <C-t>:
def load(path):
with open(path) as f:
data = json.load(f)
^
The line moves right by four spaces, and the cursor moves with it, so it is still after the ). You are still in insert mode, so you can keep typing, and the next character lands at the end of the line as if nothing had happened.
When you would reach for it
You are typing a line and notice it belongs one level deeper, or one level shallower, than where autoindent put it. The usual fix is <Esc>, >>, then A to get back to the end of the line. That is three steps, and it breaks your typing. <C-t> and its twin <C-d> reindent the line from where you are, wherever the cursor is, and leave you in insert mode. This is the fastest way to fix indentation in YAML, Python, and nested lists while you are still writing them.
Gotchas
- The step size is
shiftwidth, nottabstop. Undervim -u NONE,shiftwidthis 8 andexpandtabis off, so<C-t>on a line with four spaces of indent produces a single tab character. Setshiftwidthandexpandtabfor the filetype, or<C-t>puts in indent that does not match the rest of the file. - The result rounds to a multiple of
shiftwidth. Withshiftwidth=4, a line indented by three spaces goes to four after<C-t>, not seven.<C-d>rounds the other way: six spaces withshiftwidth=4go to four. This is the fix you usually want, but it can surprise you on a line that was deliberately misaligned. - It reindents the whole line, not the text after the cursor. In the middle of
data = json.load(f),<C-t>does not insert spaces at the cursor. It moves the entire line, and the cursor keeps its place in the text. If you wanted whitespace at the cursor, use<Tab>. - In Neovim and some setups, a completion plugin or a custom mapping may already use
<C-t>or<C-d>in insert mode. If nothing happens, run:verbose imap <C-t>to see what owns it.
Variants
<C-d>
Removes one shiftwidth of indent. With shiftwidth=2, - name: a (six spaces) becomes - name: a (four spaces), and you stay in insert mode.
0<C-d>
Type 0 and then <C-d> to remove all indent from the line. Vim deletes the 0 you typed as well, so x becomes x.
^<C-d>
Removes all indent from the current line only. With autoindent on, the next line you open gets the old indent back. Use this for a C label or a preprocessor line like #ifdef DEBUG that has to start in column 1 in the middle of an indented block.