From b83d8223ffee099634a4352443cb56a94ebfcc22 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 19 Oct 2020 12:27:17 -0400 Subject: [PATCH 01/16] implement scroll autocommand --- src/nvim/auevents.lua | 2 ++ src/nvim/buffer_defs.h | 3 +++ src/nvim/edit.c | 25 +++++++++++++++++++++++++ src/nvim/normal.c | 18 ++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 4391d997a7..2d733b0cb7 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -72,6 +72,7 @@ return { 'QuickFixCmdPre', -- before :make, :grep etc. 'QuitPre', -- before :quit 'RemoteReply', -- upon string reception from a remote vim + 'Scroll', -- after scrolling 'SessionLoadPost', -- after loading a session file 'ShellCmdPost', -- after ":!cmd" 'ShellFilterPost', -- after ":1,2!cmd", ":w !cmd", ":r !cmd". @@ -123,6 +124,7 @@ return { -- syntax file nvim_specific = { DirChanged=true, + Scroll=true, Signal=true, TabClosed=true, TabNew=true, diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 1223f2bdab..546054bb19 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1204,6 +1204,9 @@ struct window_S { colnr_T w_skipcol; // starting column when a single line // doesn't fit in the window + linenr_T w_last_topline; ///< last known value for topline + colnr_T w_last_leftcol; ///< last known value for leftcol + // // Layout of the window in the screen. // May need to add "msg_scrolled" to "w_winrow" in rare situations. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index de2346a9d8..447f922767 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1482,6 +1482,31 @@ static void ins_redraw( } } + if (ready && has_event(EVENT_SCROLL) + && (curwin->w_last_topline != curwin->w_topline || + curwin->w_last_leftcol != curwin->w_leftcol)) { + + // XXX is the buf changedtick thing necessary? + // XXX apply_autocmds vs ins_apply_autocmds? + // XXX why can't we re-use normal_check_window_scrolled()? + + aco_save_T aco; + varnumber_T tick = buf_get_changedtick(curbuf); + + // save and restore curwin and curbuf, in case the autocmd changes them + aucmd_prepbuf(&aco, curbuf); + apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); + aucmd_restbuf(&aco); + curbuf->b_last_changedtick_pum = buf_get_changedtick(curbuf); + if (tick != buf_get_changedtick(curbuf)) { // see ins_apply_autocmds() + u_save(curwin->w_cursor.lnum, + (linenr_T)(curwin->w_cursor.lnum + 1)); + } + + curwin->w_last_topline = curwin->w_topline; + curwin->w_last_leftcol = curwin->w_leftcol; + } + if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin) && conceal_cursor_moved) { redrawWinline(curwin, curwin->w_cursor.lnum); diff --git a/src/nvim/normal.c b/src/nvim/normal.c index a51aa0dc07..eb15204c63 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1193,6 +1193,22 @@ static void normal_check_interrupt(NormalState *s) } } +static void normal_check_window_scrolled(NormalState *s) +{ + // XXX why is has_event necessary? + + // Trigger Scroll if the window moved. + if (!finish_op && has_event(EVENT_SCROLL) + && (curwin->w_last_topline != curwin->w_topline || + curwin->w_last_leftcol != curwin->w_leftcol)) { + + apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); + + curwin->w_last_topline = curwin->w_topline; + curwin->w_last_leftcol = curwin->w_leftcol; + } +} + static void normal_check_cursor_moved(NormalState *s) { // Trigger CursorMoved if the cursor moved. @@ -1279,6 +1295,7 @@ static void normal_redraw(NormalState *s) xfree(p); } + // show fileinfo after redraw if (need_fileinfo && !shortmess(SHM_FILEINFO)) { fileinfo(false, true, false); @@ -1318,6 +1335,7 @@ static int normal_check(VimState *state) } else if (do_redraw || stuff_empty()) { normal_check_cursor_moved(s); normal_check_text_changed(s); + normal_check_window_scrolled(s); // Updating diffs from changed() does not always work properly, // esp. updating folds. Do an update just before redrawing if From d4033db6a0a3b9e1f33ca3760377c8a637e80c85 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sat, 24 Oct 2020 04:56:43 -0400 Subject: [PATCH 02/16] scroll: cleanup unnecessary code & comments --- src/nvim/edit.c | 15 --------------- src/nvim/normal.c | 2 -- 2 files changed, 17 deletions(-) diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 447f922767..949f5d5a62 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1486,22 +1486,7 @@ static void ins_redraw( && (curwin->w_last_topline != curwin->w_topline || curwin->w_last_leftcol != curwin->w_leftcol)) { - // XXX is the buf changedtick thing necessary? - // XXX apply_autocmds vs ins_apply_autocmds? - // XXX why can't we re-use normal_check_window_scrolled()? - - aco_save_T aco; - varnumber_T tick = buf_get_changedtick(curbuf); - - // save and restore curwin and curbuf, in case the autocmd changes them - aucmd_prepbuf(&aco, curbuf); apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); - aucmd_restbuf(&aco); - curbuf->b_last_changedtick_pum = buf_get_changedtick(curbuf); - if (tick != buf_get_changedtick(curbuf)) { // see ins_apply_autocmds() - u_save(curwin->w_cursor.lnum, - (linenr_T)(curwin->w_cursor.lnum + 1)); - } curwin->w_last_topline = curwin->w_topline; curwin->w_last_leftcol = curwin->w_leftcol; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index eb15204c63..80ed9bd2b6 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1195,8 +1195,6 @@ static void normal_check_interrupt(NormalState *s) static void normal_check_window_scrolled(NormalState *s) { - // XXX why is has_event necessary? - // Trigger Scroll if the window moved. if (!finish_op && has_event(EVENT_SCROLL) && (curwin->w_last_topline != curwin->w_topline || From ffe1a067df5b28726cc1ab7b440108c84a6e8624 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sat, 24 Oct 2020 04:57:15 -0400 Subject: [PATCH 03/16] docs: add documentation for Scroll autocmd --- runtime/doc/autocmd.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index a6872d0af5..12bd48fdd1 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -800,6 +800,9 @@ RemoteReply When a reply from a Vim that functions as Note that even if an autocommand is defined, the reply should be read with |remote_read()| to consume it. + *Scroll* +Scroll After scrolling the viewport. + *SessionLoadPost* SessionLoadPost After loading the session file created using the |:mksession| command. From bcf79c62bca76b8b2fb5f51e3f83d4c645d91684 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sat, 24 Oct 2020 05:48:00 -0400 Subject: [PATCH 04/16] tests: add test for Scroll autocmd --- test/functional/autocmd/scroll_spec.lua | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 test/functional/autocmd/scroll_spec.lua diff --git a/test/functional/autocmd/scroll_spec.lua b/test/functional/autocmd/scroll_spec.lua new file mode 100644 index 0000000000..f76d80812c --- /dev/null +++ b/test/functional/autocmd/scroll_spec.lua @@ -0,0 +1,24 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local eq = helpers.eq +local eval = helpers.eval +local funcs = helpers.funcs +local source = helpers.source + +describe('Scroll', function() + before_each(clear) + + it('is triggered by scrolling the window', function() + source([[ + let g:scroll = 0 + let g:buf = bufnr('%') + + autocmd scroll * let g:scroll += 1 + + call nvim_buf_set_lines(g:buf, 0, -1, v:true, ['1', '2', '3', '4', '5']) + call feedkeys("\", "n") + ]]) + eq(1, eval('g:scroll')) + end) +end) From a1596f0b0bb7e2a84e062a27fabe618d085a2947 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sat, 24 Oct 2020 20:16:58 -0400 Subject: [PATCH 05/16] scroll: use win->w_viewport_invalid --- src/nvim/buffer_defs.h | 3 --- src/nvim/edit.c | 7 +------ src/nvim/normal.c | 8 +------- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 546054bb19..1223f2bdab 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1204,9 +1204,6 @@ struct window_S { colnr_T w_skipcol; // starting column when a single line // doesn't fit in the window - linenr_T w_last_topline; ///< last known value for topline - colnr_T w_last_leftcol; ///< last known value for leftcol - // // Layout of the window in the screen. // May need to add "msg_scrolled" to "w_winrow" in rare situations. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 949f5d5a62..56202177c0 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1483,13 +1483,8 @@ static void ins_redraw( } if (ready && has_event(EVENT_SCROLL) - && (curwin->w_last_topline != curwin->w_topline || - curwin->w_last_leftcol != curwin->w_leftcol)) { - + && curwin->w_viewport_invalid) { apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); - - curwin->w_last_topline = curwin->w_topline; - curwin->w_last_leftcol = curwin->w_leftcol; } if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin) diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 80ed9bd2b6..2e49108028 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1197,13 +1197,8 @@ static void normal_check_window_scrolled(NormalState *s) { // Trigger Scroll if the window moved. if (!finish_op && has_event(EVENT_SCROLL) - && (curwin->w_last_topline != curwin->w_topline || - curwin->w_last_leftcol != curwin->w_leftcol)) { - + && curwin->w_viewport_invalid) { apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); - - curwin->w_last_topline = curwin->w_topline; - curwin->w_last_leftcol = curwin->w_leftcol; } } @@ -1293,7 +1288,6 @@ static void normal_redraw(NormalState *s) xfree(p); } - // show fileinfo after redraw if (need_fileinfo && !shortmess(SHM_FILEINFO)) { fileinfo(false, true, false); From d2a38dab8085ddb973393ca7f077ff65d64f60ef Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sun, 25 Oct 2020 02:25:22 -0400 Subject: [PATCH 06/16] move.c: dont invalidate viewport when no scroll happened --- src/nvim/move.c | 14 ++++++++++++-- src/nvim/normal.c | 10 ++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/nvim/move.c b/src/nvim/move.c index e2a304efa5..8084461d3a 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1020,7 +1020,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, /* * Scroll the current window down by "line_count" logical lines. "CTRL-Y" */ -void +bool scrolldown ( long line_count, int byfold /* true: count a closed fold as one line */ @@ -1095,17 +1095,21 @@ scrolldown ( foldAdjustCursor(); coladvance(curwin->w_curswant); } + return moved; } /* * Scroll the current window up by "line_count" logical lines. "CTRL-E" */ -void +bool scrollup ( long line_count, int byfold /* true: count a closed fold as one line */ ) { + linenr_T topline = curwin->w_topline; + linenr_T botline = curwin->w_botline; + if ((byfold && hasAnyFolding(curwin)) || curwin->w_p_diff) { // count each sequence of folded lines as one logical line @@ -1148,6 +1152,12 @@ scrollup ( ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL); coladvance(curwin->w_curswant); } + + bool moved = + topline != curwin->w_topline || + botline != curwin->w_botline; + + return moved; } /* diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 2e49108028..f6add44f6a 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -4117,10 +4117,10 @@ void scroll_redraw(int up, long count) int prev_topfill = curwin->w_topfill; linenr_T prev_lnum = curwin->w_cursor.lnum; - if (up) - scrollup(count, true); - else + bool moved = up ? + scrollup(count, true) : scrolldown(count, true); + if (get_scrolloff_value()) { // Adjust the cursor position for 'scrolloff'. Mark w_topline as // valid, otherwise the screen jumps back at the end of the file. @@ -4152,7 +4152,9 @@ void scroll_redraw(int up, long count) } if (curwin->w_cursor.lnum != prev_lnum) coladvance(curwin->w_curswant); - curwin->w_viewport_invalid = true; + // XXX: can `moved` be used to prevent other work here? + if (moved) + curwin->w_viewport_invalid = true; redraw_later(VALID); } From bc21843228ce255bee8108a78c3c509743c8fe0c Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Wed, 28 Oct 2020 03:59:26 -0400 Subject: [PATCH 07/16] feat: implement a working WinScrolled autocmd --- src/nvim/auevents.lua | 4 ++-- src/nvim/buffer_defs.h | 9 +++++++++ src/nvim/edit.c | 7 ++++--- src/nvim/normal.c | 12 ++++++++---- src/nvim/window.c | 24 ++++++++++++++++++++++++ 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 2d733b0cb7..ea2db41668 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -72,7 +72,6 @@ return { 'QuickFixCmdPre', -- before :make, :grep etc. 'QuitPre', -- before :quit 'RemoteReply', -- upon string reception from a remote vim - 'Scroll', -- after scrolling 'SessionLoadPost', -- after loading a session file 'ShellCmdPost', -- after ":!cmd" 'ShellFilterPost', -- after ":1,2!cmd", ":w !cmd", ":r !cmd". @@ -113,6 +112,7 @@ return { 'WinEnter', -- after entering a window 'WinLeave', -- before leaving a window 'WinNew', -- when entering a new window + 'WinScrolled', -- after scrolling a window }, aliases = { BufCreate = 'BufAdd', @@ -124,7 +124,6 @@ return { -- syntax file nvim_specific = { DirChanged=true, - Scroll=true, Signal=true, TabClosed=true, TabNew=true, @@ -134,5 +133,6 @@ return { UIEnter=true, UILeave=true, WinClosed=true, + WinScrolled=true, }, } diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 1223f2bdab..ba71ac6b2b 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1204,6 +1204,15 @@ struct window_S { colnr_T w_skipcol; // starting column when a single line // doesn't fit in the window + /* + * "w_last_topline" and "w_last_leftcol" are used to determine if + * a Scroll autocommand should be emitted. + */ + linenr_T w_last_topline; ///< last known value for topline + colnr_T w_last_leftcol; ///< last known value for leftcol + int w_last_width; ///< last known value for width + int w_last_height; ///< last known value for height + // // Layout of the window in the screen. // May need to add "msg_scrolled" to "w_winrow" in rare situations. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 56202177c0..5ea6716c0a 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1482,9 +1482,10 @@ static void ins_redraw( } } - if (ready && has_event(EVENT_SCROLL) - && curwin->w_viewport_invalid) { - apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); + // Trigger Scroll if viewport changed. + if (ready && has_event(EVENT_WINSCROLLED) + && win_did_scroll(curwin)) { + do_autocmd_winscrolled(curwin); } if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin) diff --git a/src/nvim/normal.c b/src/nvim/normal.c index f6add44f6a..2812297347 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1195,10 +1195,10 @@ static void normal_check_interrupt(NormalState *s) static void normal_check_window_scrolled(NormalState *s) { - // Trigger Scroll if the window moved. - if (!finish_op && has_event(EVENT_SCROLL) - && curwin->w_viewport_invalid) { - apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); + // Trigger Scroll if the viewport changed. + if (!finish_op && has_event(EVENT_WINSCROLLED) + && win_did_scroll(curwin)) { + do_autocmd_winscrolled(curwin); } } @@ -1325,6 +1325,10 @@ static int normal_check(VimState *state) if (skip_redraw || exmode_active) { skip_redraw = false; } else if (do_redraw || stuff_empty()) { + // Need to make sure w_topline and w_leftcol are correct before + // normal_check_window_scrolled() is called. + update_topline(); + normal_check_cursor_moved(s); normal_check_text_changed(s); normal_check_window_scrolled(s); diff --git a/src/nvim/window.c b/src/nvim/window.c index 4931221e7a..bbc039d151 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4965,6 +4965,30 @@ void shell_new_columns(void) win_reconfig_floats(); // The size of floats might change } +/* + * Check if "wp" has scrolled since last time it was checked + */ +bool win_did_scroll(win_T *wp) +{ + return (curwin->w_last_topline != curwin->w_topline || + curwin->w_last_leftcol != curwin->w_leftcol || + curwin->w_last_width != curwin->w_width || + curwin->w_last_height != curwin->w_height); +} + +/* + * Trigger WinScrolled autocmd + */ +void do_autocmd_winscrolled(win_T *wp) +{ + apply_autocmds(EVENT_WINSCROLLED, NULL, NULL, false, curbuf); + + wp->w_last_topline = wp->w_topline; + wp->w_last_leftcol = wp->w_leftcol; + wp->w_last_width = wp->w_width; + wp->w_last_height = wp->w_height; +} + /* * Save the size of all windows in "gap". */ From 929d00db0f02a73aec83f35ae29345d3f239df5a Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Wed, 28 Oct 2020 04:32:25 -0400 Subject: [PATCH 08/16] tests: add functional test for WinScrolled --- test/functional/autocmd/winscrolled_spec.lua | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 test/functional/autocmd/winscrolled_spec.lua diff --git a/test/functional/autocmd/winscrolled_spec.lua b/test/functional/autocmd/winscrolled_spec.lua new file mode 100644 index 0000000000..00160d3771 --- /dev/null +++ b/test/functional/autocmd/winscrolled_spec.lua @@ -0,0 +1,47 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local eq = helpers.eq +local eval = helpers.eval +local funcs = helpers.funcs +local source = helpers.source + +describe('WinScrolled', function() + before_each(clear) + + it('is triggered by scrolling in normal/visual mode', function() + source([[ + let width = winwidth(0) + let lines = [repeat('*', range(width * 2))] + call nvim_buf_set_lines(g:buf, 0, -1, v:true, lines) + + let g:scrolled = 0 + autocmd WinScrolled * let g:scrolled += 1 + normal! zl + normal! + ]]) + eq(1, eval('g:scrolled')) + end) + + it('is triggered when the window scrolls in insert mode', function() + source([[ + let height = winheight(0) + let lines = map(range(height * 2), {_, i -> string(i)}) + call nvim_buf_set_lines(g:buf, 0, -1, v:true, lines) + + let g:scrolled = 0 + autocmd WinScrolled * let g:scrolled += 1 + call feedkeys("LA\", "n") + ]]) + eq(1, eval('g:scrolled')) + end) + + it('is triggered when the window is resized', function() + source([[ + let g:scrolled = 0 + autocmd WinScrolled * let g:scrolled += 1 + wincmd v + ]]) + eq(1, eval('g:scrolled')) + end) +end) From e606654ac24f492cf53d696647aee7b0526ed080 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Wed, 28 Oct 2020 04:49:49 -0400 Subject: [PATCH 09/16] doc: update doc: s/Scroll/WinScrolled/ --- runtime/doc/autocmd.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 12bd48fdd1..75cdc71039 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -800,9 +800,6 @@ RemoteReply When a reply from a Vim that functions as Note that even if an autocommand is defined, the reply should be read with |remote_read()| to consume it. - *Scroll* -Scroll After scrolling the viewport. - *SessionLoadPost* SessionLoadPost After loading the session file created using the |:mksession| command. @@ -1009,6 +1006,9 @@ WinLeave Before leaving a window. If the window to be WinNew When a new window was created. Not done for the first window, when Vim has just started. Before WinEnter. + *WinScrolled* +WinScrolled After scrolling the viewport. + ============================================================================== 6. Patterns *autocmd-pattern* *{pat}* From d9a58573fd599d006518b403385c4b7333d8d1a0 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Fri, 30 Oct 2020 03:22:52 -0400 Subject: [PATCH 10/16] tests: make scroll tests pass --- test/functional/autocmd/scroll_spec.lua | 24 -------------------- test/functional/autocmd/winscrolled_spec.lua | 8 +++---- 2 files changed, 4 insertions(+), 28 deletions(-) delete mode 100644 test/functional/autocmd/scroll_spec.lua diff --git a/test/functional/autocmd/scroll_spec.lua b/test/functional/autocmd/scroll_spec.lua deleted file mode 100644 index f76d80812c..0000000000 --- a/test/functional/autocmd/scroll_spec.lua +++ /dev/null @@ -1,24 +0,0 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local funcs = helpers.funcs -local source = helpers.source - -describe('Scroll', function() - before_each(clear) - - it('is triggered by scrolling the window', function() - source([[ - let g:scroll = 0 - let g:buf = bufnr('%') - - autocmd scroll * let g:scroll += 1 - - call nvim_buf_set_lines(g:buf, 0, -1, v:true, ['1', '2', '3', '4', '5']) - call feedkeys("\", "n") - ]]) - eq(1, eval('g:scroll')) - end) -end) diff --git a/test/functional/autocmd/winscrolled_spec.lua b/test/functional/autocmd/winscrolled_spec.lua index 00160d3771..534fe3dbcd 100644 --- a/test/functional/autocmd/winscrolled_spec.lua +++ b/test/functional/autocmd/winscrolled_spec.lua @@ -12,22 +12,22 @@ describe('WinScrolled', function() it('is triggered by scrolling in normal/visual mode', function() source([[ let width = winwidth(0) - let lines = [repeat('*', range(width * 2))] - call nvim_buf_set_lines(g:buf, 0, -1, v:true, lines) + let lines = [repeat('*', width * 2), repeat('*', width * 2)] + call nvim_buf_set_lines(0, 0, -1, v:true, lines) let g:scrolled = 0 autocmd WinScrolled * let g:scrolled += 1 normal! zl normal! ]]) - eq(1, eval('g:scrolled')) + eq(2, eval('g:scrolled')) end) it('is triggered when the window scrolls in insert mode', function() source([[ let height = winheight(0) let lines = map(range(height * 2), {_, i -> string(i)}) - call nvim_buf_set_lines(g:buf, 0, -1, v:true, lines) + call nvim_buf_set_lines(0, 0, -1, v:true, lines) let g:scrolled = 0 autocmd WinScrolled * let g:scrolled += 1 From a58d06ebfce8cdbc145948bf6a6177d0e9696709 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Fri, 30 Oct 2020 14:18:08 -0400 Subject: [PATCH 11/16] tests: separate scroll test for horizontal/vertical scroll --- test/functional/autocmd/winscrolled_spec.lua | 28 +++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/test/functional/autocmd/winscrolled_spec.lua b/test/functional/autocmd/winscrolled_spec.lua index 534fe3dbcd..646baf08ea 100644 --- a/test/functional/autocmd/winscrolled_spec.lua +++ b/test/functional/autocmd/winscrolled_spec.lua @@ -9,18 +9,34 @@ local source = helpers.source describe('WinScrolled', function() before_each(clear) - it('is triggered by scrolling in normal/visual mode', function() + it('is triggered by scrolling vertically', function() source([[ + set nowrap let width = winwidth(0) - let lines = [repeat('*', width * 2), repeat('*', width * 2)] + let line = '123' . repeat('*', width * 2) + let lines = [line, line] call nvim_buf_set_lines(0, 0, -1, v:true, lines) let g:scrolled = 0 autocmd WinScrolled * let g:scrolled += 1 - normal! zl - normal! + execute "normal! \" ]]) - eq(2, eval('g:scrolled')) + eq(1, eval('g:scrolled')) + end) + + it('is triggered by scrolling horizontally', function() + source([[ + set nowrap + let width = winwidth(0) + let line = '123' . repeat('*', width * 2) + let lines = [line, line] + call nvim_buf_set_lines(0, 0, -1, v:true, lines) + + let g:scrolled = 0 + autocmd WinScrolled * let g:scrolled += 1 + execute "normal! zl" + ]]) + eq(1, eval('g:scrolled')) end) it('is triggered when the window scrolls in insert mode', function() @@ -33,7 +49,7 @@ describe('WinScrolled', function() autocmd WinScrolled * let g:scrolled += 1 call feedkeys("LA\", "n") ]]) - eq(1, eval('g:scrolled')) + eq(2, eval('g:scrolled')) end) it('is triggered when the window is resized', function() From c7c865214655f7d88fde85ed4947f07319c14182 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sun, 1 Nov 2020 05:00:20 -0500 Subject: [PATCH 12/16] fix: remove xxx comment --- src/nvim/normal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 2812297347..f291adaffe 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -4156,7 +4156,6 @@ void scroll_redraw(int up, long count) } if (curwin->w_cursor.lnum != prev_lnum) coladvance(curwin->w_curswant); - // XXX: can `moved` be used to prevent other work here? if (moved) curwin->w_viewport_invalid = true; redraw_later(VALID); From 4ed6f6949737749521b342d164d8695e8958d02f Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Fri, 6 Nov 2020 20:06:40 -0500 Subject: [PATCH 13/16] my fight with the linter --- src/nvim/buffer_defs.h | 6 ++---- src/nvim/move.c | 31 +++++++++++-------------------- src/nvim/normal.c | 6 ++++-- src/nvim/window.c | 17 +++++++---------- 4 files changed, 24 insertions(+), 36 deletions(-) diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 540542f409..b72ca51517 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1230,10 +1230,8 @@ struct window_S { colnr_T w_skipcol; // starting column when a single line // doesn't fit in the window - /* - * "w_last_topline" and "w_last_leftcol" are used to determine if - * a Scroll autocommand should be emitted. - */ + // "w_last_topline" and "w_last_leftcol" are used to determine if + // a Scroll autocommand should be emitted. linenr_T w_last_topline; ///< last known value for topline colnr_T w_last_leftcol; ///< last known value for leftcol int w_last_width; ///< last known value for width diff --git a/src/nvim/move.c b/src/nvim/move.c index 218dcd289d..549a135a5e 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1020,16 +1020,12 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, *ecolp = ecol + coloff; } -/* - * Scroll the current window down by "line_count" logical lines. "CTRL-Y" - */ -bool -scrolldown ( - long line_count, - int byfold /* true: count a closed fold as one line */ -) +/// Scroll the current window down by "line_count" logical lines. "CTRL-Y" +/// @param line_count number of lines to scroll +/// @param byfold if true, count a closed fold as one line +bool scrolldown(long line_count, int byfold) { - int done = 0; /* total # of physical lines done */ + int done = 0; // total # of physical lines done /* Make sure w_topline is at the first of a sequence of folded lines. */ (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); @@ -1101,14 +1097,10 @@ scrolldown ( return moved; } -/* - * Scroll the current window up by "line_count" logical lines. "CTRL-E" - */ -bool -scrollup ( - long line_count, - int byfold /* true: count a closed fold as one line */ -) +/// Scroll the current window up by "line_count" logical lines. "CTRL-E" +/// @param line_count number of lines to scroll +/// @param byfold if true, count a closed fold as one line +bool scrollup(long line_count, int byfold) { linenr_T topline = curwin->w_topline; linenr_T botline = curwin->w_botline; @@ -1156,9 +1148,8 @@ scrollup ( coladvance(curwin->w_curswant); } - bool moved = - topline != curwin->w_topline || - botline != curwin->w_botline; + bool moved = topline != curwin->w_topline + || botline != curwin->w_botline; return moved; } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index b09b99cf35..771ca732f4 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -4158,10 +4158,12 @@ void scroll_redraw(int up, long count) curwin->w_valid |= VALID_TOPLINE; } } - if (curwin->w_cursor.lnum != prev_lnum) + if (curwin->w_cursor.lnum != prev_lnum) { coladvance(curwin->w_curswant); - if (moved) + } + if (moved) { curwin->w_viewport_invalid = true; + } redraw_later(curwin, VALID); } diff --git a/src/nvim/window.c b/src/nvim/window.c index 47b6b7e713..9d918ebeb0 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4975,20 +4975,17 @@ void shell_new_columns(void) win_reconfig_floats(); // The size of floats might change } -/* - * Check if "wp" has scrolled since last time it was checked - */ +/// Check if "wp" has scrolled since last time it was checked +/// @param wp the window to check bool win_did_scroll(win_T *wp) { - return (curwin->w_last_topline != curwin->w_topline || - curwin->w_last_leftcol != curwin->w_leftcol || - curwin->w_last_width != curwin->w_width || - curwin->w_last_height != curwin->w_height); + return (curwin->w_last_topline != curwin->w_topline + || curwin->w_last_leftcol != curwin->w_leftcol + || curwin->w_last_width != curwin->w_width + || curwin->w_last_height != curwin->w_height); } -/* - * Trigger WinScrolled autocmd - */ +/// Trigger WinScrolled autocmd void do_autocmd_winscrolled(win_T *wp) { apply_autocmds(EVENT_WINSCROLLED, NULL, NULL, false, curbuf); From cedfc1b7477060917a31d4f1c526db3da0deb15c Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Fri, 6 Nov 2020 23:44:32 -0500 Subject: [PATCH 14/16] my fight with the linter (tome II) --- test/functional/autocmd/winscrolled_spec.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/test/functional/autocmd/winscrolled_spec.lua b/test/functional/autocmd/winscrolled_spec.lua index 646baf08ea..1ef5a37479 100644 --- a/test/functional/autocmd/winscrolled_spec.lua +++ b/test/functional/autocmd/winscrolled_spec.lua @@ -3,7 +3,6 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq local eval = helpers.eval -local funcs = helpers.funcs local source = helpers.source describe('WinScrolled', function() From d7f639d4e8b46c168f66337bc12233818d39e8ec Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sat, 7 Nov 2020 03:47:52 -0500 Subject: [PATCH 15/16] fix: lint doc-comments --- src/nvim/move.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nvim/move.c b/src/nvim/move.c index 549a135a5e..ccd19a81de 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1021,6 +1021,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, } /// Scroll the current window down by "line_count" logical lines. "CTRL-Y" +/// /// @param line_count number of lines to scroll /// @param byfold if true, count a closed fold as one line bool scrolldown(long line_count, int byfold) @@ -1098,6 +1099,7 @@ bool scrolldown(long line_count, int byfold) } /// Scroll the current window up by "line_count" logical lines. "CTRL-E" +/// /// @param line_count number of lines to scroll /// @param byfold if true, count a closed fold as one line bool scrollup(long line_count, int byfold) From 0fce70252d8e5ccf4cb6f141d1c388966f9f3482 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sat, 7 Nov 2020 06:25:07 -0500 Subject: [PATCH 16/16] doc: fix WinScrolled details --- runtime/doc/autocmd.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 66d15d446a..dbaba1b3ad 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -1012,7 +1012,8 @@ WinNew When a new window was created. Not done for the first window, when Vim has just started. Before WinEnter. *WinScrolled* -WinScrolled After scrolling the viewport. +WinScrolled After scrolling the viewport of the current + window. ==============================================================================