Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

text is scrolled for 'nosplitscroll' when window has folds #11234

Closed
wants to merge 4 commits into from

Conversation

luukvbaal
Copy link
Contributor

Problem: Text is scrolled for 'nosplitscroll' when window has folds.
Solution: Take into account fold length when calculating cursor position to avoid scrolling.

The current scroll behavior makes no sense whatsoever when folds are present(I was aware earlier but had ignored it until now as I don't really use folds). Adds a new function win_walk_fold() that moves the cursor a certain amount of lines up or down closed folds. Should it live in fold.c? Does fold.c already contain a similar function I could have reused? I'll check myself once more and look into adding a test. Could do with some testing, not sure if this works properly for nested folds and whatnot. Only tested with fold.c default fold state so far.

@codecov
Copy link

codecov bot commented Sep 26, 2022

Codecov Report

Merging #11234 (b77315b) into master (838b746) will decrease coverage by 0.02%.
The diff coverage is 93.93%.

@@            Coverage Diff             @@
##           master   #11234      +/-   ##
==========================================
- Coverage   81.82%   81.79%   -0.03%     
==========================================
  Files         162      162              
  Lines      188749   188777      +28     
  Branches    42918    42947      +29     
==========================================
- Hits       154441   154412      -29     
- Misses      21759    21816      +57     
  Partials    12549    12549              
Flag Coverage Δ
huge-clang-none 82.71% <93.93%> (-0.01%) ⬇️
huge-gcc-none 54.64% <44.61%> (-0.01%) ⬇️
huge-gcc-testgui ?
huge-gcc-unittests 0.29% <0.00%> (-0.01%) ⬇️
linux 82.40% <93.93%> (-0.10%) ⬇️
mingw-x64-HUGE 76.49% <90.32%> (+<0.01%) ⬆️
mingw-x86-HUGE 77.36% <90.32%> (+0.01%) ⬆️
windows 78.14% <90.32%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/edit.c 86.41% <88.00%> (+0.07%) ⬆️
src/normal.c 90.93% <92.85%> (+<0.01%) ⬆️
src/window.c 89.00% <100.00%> (+0.06%) ⬆️
src/gui_gtk_x11.c 51.00% <0.00%> (-0.59%) ⬇️
src/message.c 78.67% <0.00%> (-0.34%) ⬇️
src/buffer.c 86.51% <0.00%> (-0.27%) ⬇️
src/regexp_nfa.c 89.44% <0.00%> (-0.27%) ⬇️
src/optionstr.c 91.07% <0.00%> (-0.27%) ⬇️
src/hardcopy.c 76.83% <0.00%> (-0.22%) ⬇️
src/insexpand.c 88.21% <0.00%> (-0.18%) ⬇️
... and 16 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@luukvbaal
Copy link
Contributor Author

Test added, ready as far as I'm concerned.

Problem:	Text is scrolled for 'nosplitscroll' when window has folds.
Solution:	Take into account fold length when calculating cursor
position to avoid scrolling.
@luukvbaal
Copy link
Contributor Author

Latest commit should improve test coverage.

@brammool
Copy link
Contributor

brammool commented Sep 26, 2022 via email

@luukvbaal
Copy link
Contributor Author

Right, it currently works as intended and the test is added. I'll see if I can reuse cursor_up/down.

@luukvbaal
Copy link
Contributor Author

Yeah no those functions only operate on curwin/buf(sensibly). But indeed they basically do what I want. Do you think it would be worth mis-using curwin/temp by setting it temporarily in win_fix_scroll, assuming the same result can be achieved? Or is adding win_walk_fold fine?

@luukvbaal
Copy link
Contributor Author

Hmm it would look like this in theory. Would be nice if it worked but it doesn't seem to(yet).

diff --git a/src/window.c b/src/window.c
index ceceb7383..3a961b0ce 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6362,6 +6362,8 @@ win_fix_scroll(int resize)
 {
     win_T    *wp;
     linenr_T lnum;
+    win_T *curwp = curwin;
+    buf_T *curbp = curbuf;
 
     skip_update_topline = TRUE;  // avoid scrolling in curs_columns()
     FOR_ALL_WINDOWS(wp)
@@ -6375,13 +6377,15 @@ win_fix_scroll(int resize)
 		lnum = wp->w_cursor.lnum;
 		int diff = (wp->w_winrow - wp->w_prev_winrow)
 					    + (wp->w_height - wp->w_prev_height);
-#ifdef FEAT_FOLDING
-		if (hasAnyFolding(wp))
-		    win_walk_fold(wp, wp->w_botline - 1, abs(diff), diff > 0);
+		wp->w_cursor.lnum = wp->w_botline - 1;
+		curwin = wp;
+		curbuf = wp->w_buffer;
+		if (diff > 0)
+		    cursor_down(diff, FALSE);
 		else
-#endif
-		    wp->w_cursor.lnum = MIN(wp->w_buffer->b_ml.ml_line_count,
-					    wp->w_botline - 1 + diff);
+		    cursor_up(diff, FALSE);
+		curwin = curwp;
+		curbuf = curbp;
 		// Bring the new cursor position to the bottom of the screen.
 		wp->w_fraction = FRACTION_MULT;
 		scroll_to_fraction(wp, wp->w_prev_height);
@@ -6413,9 +6417,6 @@ win_fix_scroll(int resize)
 win_fix_cursor(int normal)
 {
     win_T    *wp = curwin;
-#ifdef FEAT_FOLDING
-    int      fold = hasAnyFolding(wp);
-#endif
     long     so = get_scrolloff_value();
     linenr_T nlnum = 0;
     linenr_T lnum = wp->w_cursor.lnum;
@@ -6430,15 +6431,10 @@ win_fix_cursor(int normal)
 #endif
 
     so = MIN(wp->w_height / 2, so);
-    top = wp->w_topline + so;
-    bot = wp->w_botline - 1 - so;
-#ifdef FEAT_FOLDING
-    if (fold && so)
-    {
-	top = win_walk_fold(wp, wp->w_topline, so, TRUE);
-	bot = win_walk_fold(wp, wp->w_botline - 1, so, FALSE);
-    }
-#endif
+    wp->w_cursor.lnum = wp->w_topline;
+    top = (cursor_down(so, FALSE), wp->w_cursor.lnum);
+    wp->w_cursor.lnum = wp->w_botline - 1;
+    bot = (cursor_up(so, FALSE), wp->w_cursor.lnum);
 
     // Check if cursor position is above or below visible range.
     if (lnum > bot && (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1)
@@ -6465,36 +6461,6 @@ win_fix_cursor(int normal)
     }
 }
 
-/*
- * Walk cursor "steps" up or down from "start".  Return resulting cursor lnum.
- */
-#ifdef FEAT_FOLDING
-    static linenr_T
-win_walk_fold(win_T *wp, linenr_T start, int steps, int down)
-{
-    long       fold_len;
-    foldinfo_T foldinfo;
-
-    wp->w_cursor.lnum = start;
-
-    while (steps-- && wp->w_cursor.lnum > 1
-	    && wp->w_cursor.lnum < wp->w_buffer->b_ml.ml_line_count)
-    {
-	fold_len = foldedCount(wp, wp->w_cursor.lnum, &foldinfo);
-
-	if (down)
-	    wp->w_cursor.lnum += fold_len ? fold_len : 1;
-	else
-	{
-	    fold_len = fold_len ? foldedCount(wp, foldinfo.fi_lnum, NULL) : 1;
-	    wp->w_cursor.lnum -= fold_len;
-	}
-    }
-
-    return wp->w_cursor.lnum;
-}
-#endif
-
 /*
  * Set the height of a window.
  * "height" excludes any window toolbar.

@brammool
Copy link
Contributor

brammool commented Sep 26, 2022 via email

@luukvbaal
Copy link
Contributor Author

Yes, it seems to work(didn't work before because I was passing a negative value to cursor_up()). Thanks for pointing me in the right direction(even though I already got it working), of course it's better to reuse code and I would have never though to have looked in edit.c.

Yes refactoring to accept a window pointer shouldn't be hard, do you think it's preffered over setting it temporarily in win_fix_scroll()?

I don't think the coladvance() call harms and it's probably preferred in win_fix_cursor() and only redundant(not harmful) in win_fix_scroll() since it's only used for scroll position. Not sure it's necessary to refactor it out.

@luukvbaal
Copy link
Contributor Author

Does the sharthand comma notation have precendence in vim?
Or better yet we could we have cursor_up/down return w_cursor.lnum? It only returns FAIL/OK currently so it shouldn't be a problem, can return 0 instead of FAIL.

In other words, do you want

wp->w_cursor.lnum = wp->w_topline;
cursor_down(wp, so, FALSE)
top = wp->w_cursor.lnum;
wp->w_cursor.lnum = wp->w_botline - 1;
cursor_up(wp, so, FALSE)
bot = wp->w_cursor.lnum;

,

wp->w_cursor.lnum = wp->w_topline;
top = (cursor_down(wp, so, FALSE), wp->w_cursor.lnum);
wp->w_cursor.lnum = wp->w_botline - 1;
bot = (cursor_up(wp, so, FALSE), wp->w_cursor.lnum);

or

wp->w_cursor.lnum = wp->w_topline;
top = cursor_down(wp, so, FALSE);
wp->w_cursor.lnum = wp->w_botline - 1;
bot = cursor_up(wp, so, FALSE);

@luukvbaal
Copy link
Contributor Author

Second commit re-uses cursor_up/down and seems to provide the same correct behavior as my earlier solution. Ready now as far as I'm concerned.

@brammool
Copy link
Contributor

brammool commented Sep 26, 2022 via email

@brammool
Copy link
Contributor

brammool commented Sep 26, 2022 via email

@brammool
Copy link
Contributor

brammool commented Sep 26, 2022 via email

@luukvbaal
Copy link
Contributor Author

That call to coladvance if "wp == curwin" looks strange. I would rather split it in two functions, as I originally suggested.

Is introducing this what you had in mind or am I misunderstanding?

cursor_down_advance(...)
{
    cursor_down(...)
    coladvance(wp->w_curswant);
}

@luukvbaal
Copy link
Contributor Author

That call to coladvance if "wp == curwin" looks strange. I would rather split it in two functions, as I originally suggested.

Is introducing this what you had in mind or am I misunderstanding?

cursor_down_advance(...)
{
    cursor_down(...)
    coladvance(wp->w_curswant);
}

Assuming yes, the latest commit does just that. Anyhow, the patch is functional. Do as you see fit with the implementation(or elaborate on any structural changes and I can do it if you like).

@brammool
Copy link
Contributor

brammool commented Sep 27, 2022 via email

@brammool brammool closed this in 7c1cbb6 Sep 27, 2022
@luukvbaal
Copy link
Contributor Author

I rather move the inner part of the functions to a separate function, so that we don't have to change all the calls. Also need to change hasFolding() to hasFoldingWin(). I'll take care of it.

I think you still might need to update the calls that check for "cursor_up/down == OK", now that we are returning cursor.lnum. For example in edit.c:4723.

- if (cursor_up(1L, TRUE) == OK) 
+ if (cursor_up(1L, TRUE))

@luukvbaal
Copy link
Contributor Author

I rather move the inner part of the functions to a separate function, so that we don't have to change all the calls. Also need to change hasFolding() to hasFoldingWin(). I'll take care of it.

I think you still might need to update the calls that check for "cursor_up/down == OK", now that we are returning cursor.lnum. For example in edit.c:4723.

- if (cursor_up(1L, TRUE) == OK) 
+ if (cursor_up(1L, TRUE))

Nevermind, I see only cursor_up_inner has the new return type.

@luukvbaal
Copy link
Contributor Author

I do see the test is failing(it didn't on my branch), I'll see if I can spot the issue.

@luukvbaal
Copy link
Contributor Author

I do see the test is failing(it didn't on my branch), I'll see if I can spot the issue.

I think you simply forgot to add the fourth screendump file "Test_nosplitscroll_fold_4.dump".

@brammool
Copy link
Contributor

brammool commented Sep 27, 2022 via email

brammool pushed a commit that referenced this pull request Sep 27, 2022
Problem:    Dump file missing.
Solution:   Add the missing dump file. (issue #11234)
zeertzjq added a commit to luukvbaal/neovim that referenced this pull request Oct 6, 2022
vim-patch:9.0.0445: when opening/closing window text moves up/down

Problem:    When opening/closing window text moves up/down.
Solution:   Add the 'splitscroll' option.  When off text will keep its
            position as much as possible.
vim/vim@29ab524

vim-patch:9.0.0455: a few problems with 'splitscroll'

Problem:    A few problems with 'splitscroll'.
Solution:   Fix 'splitscroll' problems. (Luuk van Baal, closes vim/vim#11117)
vim/vim@5ed3917

vim-patch:9.0.0461: 'scroll' is not always updated

Problem:    'scroll' is not always updated.
Solution:   Call win_init_size() at the right place.
vim/vim@470a141

vim-patch:9.0.0465: cursor moves when cmdwin is closed when 'splitscroll' is off

Problem:    Cursor moves when cmdwin is closed when 'splitscroll' is off.
Solution:   Temporarily set 'splitscroll' when jumping back to the original
            window. (closes vim/vim#11128)
vim/vim@e697d48

vim-patch:9.0.0469: cursor moves if cmdwin is closed when 'splitscroll' is off

Problem:    Cursor moves if cmdwin is closed when 'splitscroll' is off.
Solution:   Skip win_fix_cursor if called when cmdwin is open or closing.
            (Luuk van Baal, closes vim/vim#11134)
vim/vim@3735f11

vim-patch:9.0.0478: test for 'splitscroll' takes too much time

Problem:    Test for 'splitscroll' takes too much time.
Solution:   Only test some of the combinations. (Luuk van Baal, closes vim/vim#11139)
vim/vim@594f9e0

vim-patch:9.0.0486: text scrolled with 'nosplitscroll', autocmd win and help

Problem:    Text scrolled with 'nosplitscroll', autocmd win opened and help
            window closed.
Solution:   Skip win_fix_scroll() in more situations. (Luuk van Baal,
            closes vim/vim#11150)
vim/vim@d5bc762

vim-patch:9.0.0505: various problems with 'nosplitscroll'

Problem:    Various problems with 'nosplitscroll'.
Solution:   Fix 'nosplitscroll' problems. (Luuk van Baal, closes vim/vim#11166)
vim/vim@faf1d41

vim-patch:9.0.0555: scrolling with 'nosplitscroll' in callback changing curwin

Problem:    Scrolling with 'nosplitscroll' in callback changing curwin.
Solution:   Invalidate w_cline_row in the right place. (Luuk van Baal,
            closes vim/vim#11185)
vim/vim@20e5856

vim-patch:9.0.0603: with 'nosplitscroll' folds are not handled correctly

Problem:    With 'nosplitscroll' folds are not handled correctly.
Solution:   Take care of closed folds when moving the cursor. (Luuk van Baal,
            closes vim/vim#11234)
vim/vim@7c1cbb6

vim-patch:9.0.0605: dump file missing

Problem:    Dump file missing.
Solution:   Add the missing dump file. (issue vim/vim#11234)
vim/vim@439a2ba

vim-patch:9.0.0647: the 'splitscroll' option is not a good name

Problem:    The 'splitscroll' option is not a good name.
Solution:   Rename 'splitscroll' to 'splitkeep' and make it a string option,
            also supporting "topline". (Luuk van Baal, closes vim/vim#11258)
vim/vim@13ece2a

vim-patch:9.0.0667: ml_get error when 'splitkeep' is "screen"

Problem:    ml_get error when 'splitkeep' is "screen". (Marius Gedminas)
Solution:   Check the botline is not too large. (Luuk van Baal,
            closes vim/vim#11293, closes vim/vim#11292)
vim/vim@346823d
zeertzjq pushed a commit to neovim/neovim that referenced this pull request Oct 6, 2022
vim-patch:9.0.0445: when opening/closing window text moves up/down

Problem:    When opening/closing window text moves up/down.
Solution:   Add the 'splitscroll' option.  When off text will keep its
            position as much as possible.
vim/vim@29ab524

vim-patch:9.0.0455: a few problems with 'splitscroll'

Problem:    A few problems with 'splitscroll'.
Solution:   Fix 'splitscroll' problems. (Luuk van Baal, closes vim/vim#11117)
vim/vim@5ed3917

vim-patch:9.0.0461: 'scroll' is not always updated

Problem:    'scroll' is not always updated.
Solution:   Call win_init_size() at the right place.
vim/vim@470a141

vim-patch:9.0.0465: cursor moves when cmdwin is closed when 'splitscroll' is off

Problem:    Cursor moves when cmdwin is closed when 'splitscroll' is off.
Solution:   Temporarily set 'splitscroll' when jumping back to the original
            window. (closes vim/vim#11128)
vim/vim@e697d48

vim-patch:9.0.0469: cursor moves if cmdwin is closed when 'splitscroll' is off

Problem:    Cursor moves if cmdwin is closed when 'splitscroll' is off.
Solution:   Skip win_fix_cursor if called when cmdwin is open or closing.
            (Luuk van Baal, closes vim/vim#11134)
vim/vim@3735f11

vim-patch:9.0.0478: test for 'splitscroll' takes too much time

Problem:    Test for 'splitscroll' takes too much time.
Solution:   Only test some of the combinations. (Luuk van Baal, closes vim/vim#11139)
vim/vim@594f9e0

vim-patch:9.0.0486: text scrolled with 'nosplitscroll', autocmd win and help

Problem:    Text scrolled with 'nosplitscroll', autocmd win opened and help
            window closed.
Solution:   Skip win_fix_scroll() in more situations. (Luuk van Baal,
            closes vim/vim#11150)
vim/vim@d5bc762

vim-patch:9.0.0505: various problems with 'nosplitscroll'

Problem:    Various problems with 'nosplitscroll'.
Solution:   Fix 'nosplitscroll' problems. (Luuk van Baal, closes vim/vim#11166)
vim/vim@faf1d41

vim-patch:9.0.0555: scrolling with 'nosplitscroll' in callback changing curwin

Problem:    Scrolling with 'nosplitscroll' in callback changing curwin.
Solution:   Invalidate w_cline_row in the right place. (Luuk van Baal,
            closes vim/vim#11185)
vim/vim@20e5856

vim-patch:9.0.0603: with 'nosplitscroll' folds are not handled correctly

Problem:    With 'nosplitscroll' folds are not handled correctly.
Solution:   Take care of closed folds when moving the cursor. (Luuk van Baal,
            closes vim/vim#11234)
vim/vim@7c1cbb6

vim-patch:9.0.0605: dump file missing

Problem:    Dump file missing.
Solution:   Add the missing dump file. (issue vim/vim#11234)
vim/vim@439a2ba

vim-patch:9.0.0647: the 'splitscroll' option is not a good name

Problem:    The 'splitscroll' option is not a good name.
Solution:   Rename 'splitscroll' to 'splitkeep' and make it a string option,
            also supporting "topline". (Luuk van Baal, closes vim/vim#11258)
vim/vim@13ece2a

vim-patch:9.0.0667: ml_get error when 'splitkeep' is "screen"

Problem:    ml_get error when 'splitkeep' is "screen". (Marius Gedminas)
Solution:   Check the botline is not too large. (Luuk van Baal,
            closes vim/vim#11293, closes vim/vim#11292)
vim/vim@346823d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants