Skip to content

Commit

Permalink
patch 9.0.0061: ml_get error with nested autocommand
Browse files Browse the repository at this point in the history
Problem:    ml_get error with nested autocommand.
Solution:   Also check line numbers for a nested autocommand. (closes #10761)
  • Loading branch information
brammool committed Jul 23, 2022
1 parent b9e7173 commit 5fa9f23
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 10 deletions.
6 changes: 5 additions & 1 deletion src/autocmd.c
Expand Up @@ -2209,9 +2209,13 @@ apply_autocmds_group(
ap->last = FALSE;
ap->last = TRUE;

// Make sure cursor and topline are valid. The first time the current
// values are saved, restored by reset_lnums(). When nested only the
// values are corrected when needed.
if (nesting == 1)
// make sure cursor and topline are valid
check_lnums(TRUE);
else
check_lnums_nested(TRUE);

save_did_emsg = did_emsg;

Expand Down
1 change: 1 addition & 0 deletions src/proto/window.pro
Expand Up @@ -77,6 +77,7 @@ int tabline_height(void);
int min_rows(void);
int only_one_window(void);
void check_lnums(int do_curwin);
void check_lnums_nested(int do_curwin);
void reset_lnums(void);
void make_snapshot(int idx);
void restore_snapshot(int idx, int close_curwin);
Expand Down
19 changes: 19 additions & 0 deletions src/testdir/test_autocmd.vim
Expand Up @@ -2301,6 +2301,25 @@ func Test_autocmd_nested()
call assert_fails('au WinNew * nested nested echo bad', 'E983:')
endfunc

func Test_autocmd_nested_cursor_invalid()
set laststatus=0
copen
cclose
call setline(1, ['foo', 'bar', 'baz'])
3
augroup nested_inv
autocmd User foo ++nested copen
autocmd BufAdd * let &laststatus = 2 - &laststatus
augroup END
doautocmd User foo

augroup nested_inv
au!
augroup END
set laststatus&
bwipe!

This comment has been minimized.

Copy link
@zeertzjq

zeertzjq Jul 23, 2022

Member

This only wipes the quickfix buffer. I think %bwipe! is better here.

This comment has been minimized.

Copy link
@brammool

brammool Jul 25, 2022

Author Contributor

%bwipe! is drastic. I would think "cclose" and then "bwipe!" should also work.

endfunc

func Test_autocmd_once()
" Without ++once WinNew triggers twice
let g:did_split = 0
Expand Down
2 changes: 2 additions & 0 deletions src/version.c
Expand Up @@ -735,6 +735,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
61,
/**/
60,
/**/
Expand Down
39 changes: 30 additions & 9 deletions src/window.c
Expand Up @@ -6770,34 +6770,55 @@ only_one_window(void)
}

/*
* Correct the cursor line number in other windows. Used after changing the
* current buffer, and before applying autocommands.
* When "do_curwin" is TRUE, also check current window.
* Implementation of check_lnums() and check_lnums_nested().
*/
void
check_lnums(int do_curwin)
static void
check_lnums_both(int do_curwin, int nested)
{
win_T *wp;
tabpage_T *tp;

FOR_ALL_TAB_WINDOWS(tp, wp)
if ((do_curwin || wp != curwin) && wp->w_buffer == curbuf)
{
// save the original cursor position and topline
wp->w_save_cursor.w_cursor_save = wp->w_cursor;
wp->w_save_cursor.w_topline_save = wp->w_topline;
if (!nested)
{
// save the original cursor position and topline
wp->w_save_cursor.w_cursor_save = wp->w_cursor;
wp->w_save_cursor.w_topline_save = wp->w_topline;
}

if (wp->w_cursor.lnum > curbuf->b_ml.ml_line_count)
wp->w_cursor.lnum = curbuf->b_ml.ml_line_count;
if (wp->w_topline > curbuf->b_ml.ml_line_count)
wp->w_topline = curbuf->b_ml.ml_line_count;

// save the corrected cursor position and topline
// save the (corrected) cursor position and topline
wp->w_save_cursor.w_cursor_corr = wp->w_cursor;
wp->w_save_cursor.w_topline_corr = wp->w_topline;
}
}

/*
* Correct the cursor line number in other windows. Used after changing the
* current buffer, and before applying autocommands.
* When "do_curwin" is TRUE, also check current window.
*/
void
check_lnums(int do_curwin)
{
check_lnums_both(do_curwin, FALSE);
}

/*
* Like check_lnums() but for when check_lnums() was already called.
*/
void
check_lnums_nested(int do_curwin)
{
check_lnums_both(do_curwin, TRUE);
}

/*
* Reset cursor and topline to its stored values from check_lnums().
* check_lnums() must have been called first!
Expand Down

0 comments on commit 5fa9f23

Please sign in to comment.