From: Mikhail Subject: tog: cycle a searches and movements To: gameoftrees@openbsd.org Date: Fri, 10 Feb 2023 20:32:32 +0300 When I made a patch to make tog respect current cursor position in log view searches Mark said that he would like to see cycle searches in log view, like it's done in an editors (won't vouch for exact wording, though). When Mark had done his work on next/prev hunk/file keybindings I noticed that it was done with cycling (jump to the first file/hunk after hitting "next" on last one and vice verse). Personally I would want to have all searches and movements the way we have a search done in log view - stop after last hunk/file, primarily because I found myself cycling around while reviewing >moderate diffs. This patch introduces cycle searches/movement customization through TOG_CYCLE_MOVEMENT environment variable, when set - all searches and movements inside diff view will cycle, when it's NULL - we will stop after last match. What do you think about the idea and implementation? diff /home/misha/work/got commit - faf054c3d5fbad3a55534ebe525d58156c7aad27 path + /home/misha/work/got blob - 667bfe283076f37b6cb5690da6b2a98d9aae516a file + tog/tog.1 --- tog/tog.1 +++ tog/tog.1 @@ -773,6 +773,10 @@ is used. If not set, the default value .Dq magenta is used. +.It Ev TOG_CYCLE_MOVEMENT +If set tog will start searches and hunk/file movement +(in diff view) from the beginning of the view when hit +the last match or last section. .It Ev TOG_DIFF_ALGORITHM Determines the default diff algorithm used by .Nm . blob - 59f6749677b14d49ad79028572ac387a766ff9db file + tog/tog.c --- tog/tog.c +++ tog/tog.c @@ -3332,6 +3332,24 @@ search_next_log_view(struct tog_view *view) view->search_next_done = (s->matched_entry == NULL ? TOG_SEARCH_HAVE_NONE : TOG_SEARCH_NO_MORE); + + if (view->search_next_done == + TOG_SEARCH_NO_MORE && + getenv("TOG_CYCLE_MOVEMENT")) { + if (view->searching == + TOG_SEARCH_FORWARD) { + entry = + TAILQ_FIRST( + &s->commits->head); + } else { + entry = + TAILQ_LAST( + &s->commits->head, + commit_queue_head); + } + goto matchit; + } + s->search_entry = NULL; return NULL; } @@ -3344,6 +3362,7 @@ search_next_log_view(struct tog_view *view) return trigger_log_thread(view, 0); } +matchit: err = match_commit(&have_match, entry->id, entry->commit, &view->regex); if (err) @@ -4982,6 +5001,11 @@ search_next_view_match(struct tog_view *view) break; } + if (getenv("TOG_CYCLE_MOVEMENT") == NULL) { + view->search_next_done = TOG_SEARCH_NO_MORE; + break; + } + if (view->searching == TOG_SEARCH_FORWARD) lineno = 1; else @@ -5270,8 +5294,12 @@ diff_prev_index(struct tog_diff_view_state *s, enum go i = start = s->first_displayed_line - 1; while (s->lines[i].type != type) { - if (i == 0) - i = s->nlines - 1; + if (i == 0) { + if (getenv("TOG_CYCLE_MOVEMENT") == NULL) + return; + else + i = s->nlines - 1; + } if (--i == start) return; /* do nothing, requested type not in file */ } @@ -5288,8 +5316,12 @@ diff_next_index(struct tog_diff_view_state *s, enum go i = start = s->first_displayed_line + 1; while (s->lines[i].type != type) { - if (i == s->nlines - 1) - i = 0; + if (i == s->nlines - 1) { + if (getenv("TOG_CYCLE_MOVEMENT") == NULL) + return; + else + i = 0; + } if (++i == start) return; /* do nothing, requested type not in file */ } @@ -7278,7 +7310,8 @@ search_next_tree_view(struct tog_view *view) while (1) { if (te == NULL) { - if (s->matched_entry == NULL) { + if (s->matched_entry == NULL || + getenv("TOG_CYCLE_MOVEMENT") == NULL) { view->search_next_done = TOG_SEARCH_HAVE_MORE; return NULL; } @@ -8036,7 +8069,8 @@ search_next_ref_view(struct tog_view *view) while (1) { if (re == NULL) { - if (s->matched_entry == NULL) { + if (s->matched_entry == NULL || + getenv("TOG_CYCLE_MOVEMENT") == NULL) { view->search_next_done = TOG_SEARCH_HAVE_MORE; return NULL; }