Reputation: 38543
I have set autoindent
I go to a line, press A and <CR>
which gets me to the next line and inserts an indent. However if I press Esc the cursor jumps to the beginning of the line and the indent is gone.
I have to go about and press tabs to get to the right place again.
I know the help says:
If you do not type anything on the new line except <BS> or CTRL-D and then type
<Esc>, CTRL-O or <CR>, the indent is deleted again.
Is there a way to disable this, or at least a workaround?
Upvotes: 21
Views: 2318
Reputation: 471
Thanks to @EdanMaor for the S
and cc
suggestions, they are helpful. Something that started to make this bearable for me was the <C-f>
(control-f) binding in insert mode, which performs the equivalent of ==
(but with the convenience of insert mode). It's set by default in the indentkeys option.
So if you go into insert mode, start writing and see indent is 0 (cursor indicated by |
char):
function main() {
// ...
// ... deeply nested function...
function something() {
console.log("ok");
// Star|ted writing a comment
console.log("after");
}
// ...
}
you can hit <C-f>
and it will indent on the spot, even if your cursor is in the middle of the line:
function main() {
// ...
// ... deeply nested function...
function something() {
console.log("ok");
// Star|ted writing a comment
console.log("after");
}
// ...
}
I experimented with this mapping to make it more automatic:
:nnoremap I I<c-f>
It automatically indents the line whenever you insert at the beginning of the line. I'm sure there are ways to make it more seamless.
For the issues with python files, for me it was due to the default python plugin (running neovim v0.9.1). It runs the python#GetIndent()
function when pressing ==
or <C-f>
, which doesn't pick up the previous indent you would expect.
I added these few lines to the end of the python#GetIndent()
function (right before the default return of -1). It seems to fix the issue, but I'm sure it's broken in some way.
if a:lnum - plnum < 3
if getline(a:lnum) =~ '^\s*def\>'
" dedent if current line is a def (maybe class too?)
return max([indent(plnum) - shiftwidth(), 0])
else
" keep same indent as previous line
return indent(plnum)
endif
endif
The python#GetIndent
function is defined in $VIMRUNTIME/autoload/python.vim
. If you can't edit it, you can copy the whole file into ~/.config/nvim/after/plugin/python.vim
for neovim, and ~/.vim/after/plugin/python.vim
for vim, then do the edits there.
References:
:h i_ctrl-f
:h 'indentkeys'
:h 'indentexpr'
https://learnvim.irian.to/customize/vim_runtime
$VIMRUNTIME/indent/python.vim
, which refers to a function in $VIMRUNTIME/autoload/python.vim
Upvotes: 1
Reputation: 315
consider I use 'o' to start a newline. I add below config in _vimrc(notice I have ':set autoindent')
" ugly hack to start newline and keep indent
nnoremap o ox<BS>
nnoremap O Ox<BS>
Upvotes: 4
Reputation: 38543
Alright, I figured this out.
Based on Edan Maor's answer, S or cc should enter insert mode with the proper level of indentation.
...except when it doesn't :)
This works under two circumstances.
cindent
is set, it will insert indent based on C formatting rulesindentexpr
is set.I found that the best solution is to have this is my .vimrc
set autoindent
set indentexpr=GetIndent()
function GetIndent()
let lnum = prevnonblank(v:lnum - 1)
let ind = indent(lnum)
return ind
endfunction
Now when I press S or cc, it will insert the same indent as on the previous non-blank line.
Upvotes: 4
Reputation: 13571
I had want to achieve the same effect, but because I want the plugin showing indent to work properly. This is my workaround: I've found that <enter>
in normal mode is almost useless. It only moves the cursor one line down, which could be achieved by j
.
So I added this in my .vimrc
:
nmap <cr> o.<c-h><esc>
Whenever I need a blank line for its indentation, I'd use <enter>
instead.
Upvotes: 0
Reputation: 78
It may be worth noting that with proper plugins S
and cc
seem to work properly again. It is most likely python-mode that is fixing this.
https://github.com/klen/python-mode
Upvotes: 1
Reputation: 10052
I had this exact problem until two days ago.
There is no way to disable this, but luckily, you don't need to, because instead:
Enter insert mode with S
or cc
. Entering insert mode again with S
will enter insert mode with the proper level of indentation, making the fact that Vim deleted the indents unimportant.
Note: I found that this trick worked for me most places. But for some reason, it did not work with Python files. I'm guessing it's something to do with the Python filetype messing with its own indentation functions, or something along those lines.
Edit:
Another trick, you can define cpoptions in a way that, if you're on a line with an indent and move the cursor, it will preserve the indent. This won't solve your problem of hitting Esc
right away, but it's a related issue that might also be bothering you.
Upvotes: 9
Reputation: 38654
A simple way is to press '.' (or any char), escape, then press x to remove the char. The indent should be preserved.
Upvotes: 4