"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Mark Jamsek <mark@jamsek.com>
Subject:
fix tog diff J keymap when last commit is selected from hsplit log
To:
gameoftrees@openbsd.org
Date:
Wed, 03 Jul 2024 00:14:04 +1000

Download raw body.

Thread
This is a fix of another diff view J keymap case that presents when
selecting the last visible commit in the horizontally split log view and
then toggling fullscreen. The view fails to load the next commit when
entering the J keymap due to too broad a predicate; the line selection
clamp should only be applied when scrolling from a focused, horizontally
split log view and not when scrolling from the diff view with J.

This can be seen by running the added regress without the fix applied,
although it might be best observed with a manual test by running tog in
an 80x24 xterm and entering:

	S	# toggle horizontal split
	4j	# jump to 5th commit
	return	# open diff view in hsplit
	F	# toggle fullscreen diff view
	J	# diff view won't load the next commit

There's also an off-by-one in the calculation to determine how many
commits we need to populate the log, which is revealed if that part of
this diff (i.e., first hunk) is reverted. By entering 20J instead of J
in the above manual test case to continue the scroll beyond the last
loaded (i.e., 24th) commit, the 25th commit will not be loaded--it gets
stuck on the 24th. There's a test added to cover this too.

ok?

-----------------------------------------------
commit 9edd7675a0eaa4433ac94be5e8f2c0c95abc1042
from: Mark Jamsek <mark@jamsek.dev>
date: Tue Jul  2 13:35:38 2024 UTC
 
 fix diff view J keymap to diff the next commit in the log
 
 When the last visible commit in the log view is selected while in a log/diff
 horizontal split, and fullscreen is then toggled in the diff view, the user
 cannot scroll to the next commit with the diff view J keymap due to a bad
 predicate guarding a clamp to prevent scrolling off-screen that should only
 be applied when in the horizontally split log view and not when scrolling
 from the diff view. The fix also reveals an off-by-one in the subsequent
 commit loading logic that also breaks J when attempting to scroll beyond the
 last loaded commit. New regress added to cover these cases.
 
 M  regress/tog/diff.sh  |  115+  6-
 M  tog/tog.c            |    3+  2-

2 files changed, 118 insertions(+), 8 deletions(-)

diff af206a198055a86eba0f4d54303cb456001ff133 9edd7675a0eaa4433ac94be5e8f2c0c95abc1042
commit - af206a198055a86eba0f4d54303cb456001ff133
commit + 9edd7675a0eaa4433ac94be5e8f2c0c95abc1042
blob - 479afa04f1c6c1a787ee26b12295c42f732bfa08
blob + 04f4fa4c3cfbec150ae760c462178f05c608149e
--- regress/tog/diff.sh
+++ regress/tog/diff.sh
@@ -131,9 +131,9 @@ EOF
 	test_done "$testroot" "$ret"
 }
 
-test_diff_J_keymap_on_last_loaded_commit()
+test_diff_J_keymap()
 {
-	test_init diff_J_keymap_on_last_loaded_commit 94 24
+	test_init diff_J_keymap 94 24
 
 	local i=0
 
@@ -142,19 +142,32 @@ test_diff_J_keymap_on_last_loaded_commit()
 	while [ "$i" -lt 32 ]; do
 		echo $i > alpha
 		git commit -aqm $i
+		# Get timestamp, and blob and commit IDs
+		# of the diff views to be screendumped.
 		if [ $i -eq 6 ]; then
 			local id6=$(git_show_head .)
 			local blobid6=$(get_blob_id . "" alpha)
 		elif [ $i -eq 7 ]; then
 			local id7=$(git_show_head .)
 			local blobid7=$(get_blob_id . "" alpha)
-			local author_time=$(git_show_author_time .)
+			local author_time7=$(git_show_author_time .)
+		elif [ $i -eq 25 ]; then
+			local id25=$(git_show_head .)
+			local blobid25=$(get_blob_id . "" alpha)
+		elif [ $i -eq 26 ]; then
+			local id26=$(git_show_head .)
+			local blobid26=$(get_blob_id . "" alpha)
+			local author_time26=$(git_show_author_time .)
 		fi
 		i=$(( i + 1 ))
 	done
 
-	local date=`date -u -r $author_time +"%a %b %e %X %Y UTC"`
+	local date7=`date -u -r $author_time7 +"%a %b %e %X %Y UTC"`
+	local date26=`date -u -r $author_time26 +"%a %b %e %X %Y UTC"`
 
+	# Test that J loads the diff view of the next commit when
+	# currently viewing the last commit loaded in the log view.
+
 	cat <<EOF >$TOG_TEST_SCRIPT
 KEY_ENTER	open diff view of selected commit
 S		toggle horizontal split
@@ -170,7 +183,7 @@ EOF
 [1/20] diff $id6 $id7
 commit $id7
 from: Flan Hacker <flan_hacker@openbsd.org>
-date: $date
+date: $date7
 
 7
 
@@ -202,6 +215,102 @@ EOF
 		return 1
 	fi
 
+	# Test that J loads the diff view of the next commit when currently
+	# viewing the last visible commit in the horizontally split log view.
+
+	cat <<EOF >$TOG_TEST_SCRIPT
+S		toggle horizontal split
+4j		move to last visible commit when in horizontal split
+KEY_ENTER	open diff view of selected commit
+F		toggle fullscreen
+J		move down to next commit in the log
+SCREENDUMP
+EOF
+
+	cat <<EOF >$testroot/view.expected
+[1/20] diff $id25 $id26
+commit $id26
+from: Flan Hacker <flan_hacker@openbsd.org>
+date: $date26
+
+26
+
+M  alpha  |  1+  1-
+
+1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit - $id25
+commit + $id26
+blob - $blobid25
+blob + $blobid26
+--- alpha
++++ alpha
+@@ -1 +1 @@
+-25
++26
+
+
+
+(END)
+EOF
+
+	tog log
+	cmp -s $testroot/view.expected $testroot/view
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		diff -u $testroot/view.expected $testroot/view
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	# Test J correctly requests the log to load more commits when
+	# scrolling beyond the last loaded commit from the diff view.
+
+	cat <<EOF >$TOG_TEST_SCRIPT
+S		toggle horizontal split
+4j		move to the 5th commit
+KEY_ENTER	open diff view of selected commit
+F		toggle fullscreen
+20J		scroll down and load diff of the 25th commit
+SCREENDUMP
+EOF
+
+	cat <<EOF >$testroot/view.expected
+[1/20] diff $id6 $id7
+commit $id7
+from: Flan Hacker <flan_hacker@openbsd.org>
+date: $date7
+
+7
+
+M  alpha  |  1+  1-
+
+1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit - $id6
+commit + $id7
+blob - $blobid6
+blob + $blobid7
+--- alpha
++++ alpha
+@@ -1 +1 @@
+-6
++7
+
+
+
+(END)
+EOF
+
+	tog log
+	cmp -s $testroot/view.expected $testroot/view
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		diff -u $testroot/view.expected $testroot/view
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
 	test_done "$testroot" "$ret"
 }
 
@@ -377,5 +486,5 @@ test_diff_commit_keywords()
 test_parseargs "$@"
 run_test test_diff_contiguous_commits
 run_test test_diff_arbitrary_commits
-run_test test_diff_J_keymap_on_last_loaded_commit
+run_test test_diff_J_keymap
 run_test test_diff_commit_keywords
blob - 499fad18a7c542dd22ce8d4b489207884559d884
blob + b8146cfeb30ec9156a8c21c672e2e62f2b8666cd
--- tog/tog.c
+++ tog/tog.c
@@ -3099,7 +3099,7 @@ log_scroll_down(struct tog_view *view, int maxscroll)
 	if (s->last_displayed_entry == NULL)
 		return NULL;
 
-	ncommits_needed = s->last_displayed_entry->idx + 1 + maxscroll;
+	ncommits_needed = s->last_displayed_entry->idx + 2 + maxscroll;
 	if (s->commits->ncommits < ncommits_needed &&
 	    !s->thread_args.log_complete) {
 		/*
@@ -4013,7 +4013,8 @@ log_move_cursor_down(struct tog_view *view, int page)
 	 * We might necessarily overshoot in horizontal
 	 * splits; if so, select the last displayed commit.
 	 */
-	if (s->first_displayed_entry && s->last_displayed_entry) {
+	if (view_is_hsplit_top(view) && s->first_displayed_entry &&
+	    s->last_displayed_entry) {
 		s->selected = MIN(s->selected,
 		    s->last_displayed_entry->idx -
 		    s->first_displayed_entry->idx);


-- 
Mark Jamsek <https://bsdbox.org>
GPG: F2FF 13DE 6A06 C471 CA80  E6E2 2930 DC66 86EE CF68