aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAxel Forsman <axelsfor@gmail.com>2022-08-22 06:48:18 +0200
committerGitHub <noreply@github.com>2022-08-21 21:48:18 -0700
commitd4d27c41b3298c25ae62bc067472bef37bc61c99 (patch)
tree46f56c3cafeb1a59535959a08bc0da36c1eca563
parent4f6d0d6da971ee837864bf96aa28cc24c2d58b5a (diff)
downloadrneovim-d4d27c41b3298c25ae62bc067472bef37bc61c99.tar.gz
rneovim-d4d27c41b3298c25ae62bc067472bef37bc61c99.tar.bz2
rneovim-d4d27c41b3298c25ae62bc067472bef37bc61c99.zip
fix(edit.c): indentkeys double indent after "!" #12894
which is both unexpected and different from the Vim behaviour. Indent was triggered once by the '!' check in insert_execute(), and inserting the char was correctly skipped, but then triggered again in insert_check() (provided that cindent was not being ignored after manual indentation, i.e. `can_cindent == true`). While this is the smallest fix, another solution would be to remove VimState#check and instead move that to *_enter()/-_execute(), since the control flow is pretty unnecessarily convoluted as is. That would also have the benefit of differing less from the Vim source code.
-rw-r--r--src/nvim/edit.c15
-rw-r--r--test/functional/editor/mode_insert_spec.lua8
2 files changed, 16 insertions, 7 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 6583ac8584..dc856f01fe 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -624,16 +624,17 @@ static int insert_execute(VimState *state, int key)
}
if (cindent_on() && ctrl_x_mode_none()) {
+ s->line_is_white = inindent(0);
// A key name preceded by a bang means this key is not to be
// inserted. Skip ahead to the re-indenting below.
- // A key name preceded by a star means that indenting has to be
- // done before inserting the key.
- s->line_is_white = inindent(0);
- if (in_cinkeys(s->c, '!', s->line_is_white)) {
- insert_do_cindent(s);
+ if (in_cinkeys(s->c, '!', s->line_is_white)
+ && stop_arrow() == OK) {
+ do_c_expr_indent();
return 1; // continue
}
+ // A key name preceded by a star means that indenting has to be
+ // done before inserting the key.
if (can_cindent && in_cinkeys(s->c, '*', s->line_is_white)
&& stop_arrow() == OK) {
do_c_expr_indent();
@@ -3657,7 +3658,7 @@ void fix_indent(void)
/// Check that "cinkeys" contains the key "keytyped",
/// when == '*': Only if key is preceded with '*' (indent before insert)
/// when == '!': Only if key is preceded with '!' (don't insert)
-/// when == ' ': Only if key is not preceded with '*' (indent afterwards)
+/// when == ' ': Only if key is not preceded with '*' or '!' (indent afterwards)
///
/// "keytyped" can have a few special values:
/// KEY_OPEN_FORW :
@@ -3697,7 +3698,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
case '!':
try_match = (*look == '!'); break;
default:
- try_match = (*look != '*'); break;
+ try_match = (*look != '*') && (*look != '!'); break;
}
if (*look == '*' || *look == '!') {
look++;
diff --git a/test/functional/editor/mode_insert_spec.lua b/test/functional/editor/mode_insert_spec.lua
index e3d3cdbd85..cd51a65be3 100644
--- a/test/functional/editor/mode_insert_spec.lua
+++ b/test/functional/editor/mode_insert_spec.lua
@@ -6,12 +6,20 @@ local expect = helpers.expect
local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
+local curbuf_contents = helpers.curbuf_contents
describe('insert-mode', function()
before_each(function()
clear()
end)
+ it('indents only once after "!" keys #12894', function()
+ command('let counter = []')
+ command('set indentexpr=len(add(counter,0))')
+ feed('i<C-F>x')
+ eq(' x', curbuf_contents())
+ end)
+
it('CTRL-@', function()
-- Inserts last-inserted text, leaves insert-mode.
insert('hello')