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

From:
Mark Jamsek <mark@jamsek.com>
Subject:
Re: configurable diff algorithm for tog
To:
gameoftrees@openbsd.org
Date:
Fri, 1 Jul 2022 22:39:10 +1000

Download raw body.

Thread
On 22-07-01 12:32pm, Stefan Sperling wrote:
> On Fri, Jul 01, 2022 at 03:15:31PM +1000, Mark Jamsek wrote:
> > On 22-07-01 12:15am, Stefan Sperling wrote:
> > > Make the diff algorithm used by 'tog diff' and 'tog blame' configurable.
> > > This allows people (like me) who prefer slow and tidy Patience diffs over
> > > quick and ugly Myers diffs to tell tog about this preference.
> > > 
> > > As a bonus, the diff algorithm can be toggled at run-time, in both the
> > > diff view and the blame view, by pressing the A key.
> > > 
> > > ok?
> > 
> > Nice! Works as described.
> > 
> > ok with or without tiny nit below
> 
> Thanks!
> 
> The previous diff had a problem. When both a blame and a diff view were
> displayed, and the diff algorithm was switched in one of the two views,
> only the view which was processing input got updated. The other view was
> now out of sync with the current diff algorithm setting.
> 
> The new patch below does not have this problem. If the diff algorithm is
> changed in any view, all relevant views will be regenerated.

Reads nicer too. Makes sense doing this in view_input() now.

I think you left a couple fprintf()s in reset_{blame,diff}_view();
otherwise ok.

> diff 4b752015b5208a96c2d1b6c1c6b8589884b8b2b6 026bef347ee0d2a3a411a47420b9aec1a00aec3e
> commit - 4b752015b5208a96c2d1b6c1c6b8589884b8b2b6
> commit + 026bef347ee0d2a3a411a47420b9aec1a00aec3e
> blob - 728ba5ee9e20edbde20ed7f0c2ff1cbabad89c0b
> blob + ed0412fd13daaa1ea18139730716db483ba49274
> --- tog/tog.1
> +++ tog/tog.1
> @@ -295,6 +295,12 @@ Find the Nth previous line which matches the current s
>  (default: 1).
>  .It Cm w
>  Toggle display of whitespace-only changes.
> +.It Cm A
> +Change the diff algorithm.
> +Supported diff algorithms are Myers and Patience. 
> +This is a global setting which also affects the
> +.Cm blame
> +view.
>  .El
>  .Pp
>  The options for
> @@ -379,6 +385,12 @@ Find the Nth next line which matches the current searc
>  .It Cm N
>  Find the Nth previous line which matches the current search pattern
>  (default: 1).
> +.It Cm A
> +Change the diff algorithm.
> +Supported diff algorithms are Myers and Patience. 
> +This is a global setting which also affects the
> +.Cm diff
> +view.
>  .El
>  .Pp
>  The options for
> @@ -560,7 +572,15 @@ work tree, use the repository path associated with thi
>  .El
>  .El
>  .Sh ENVIRONMENT
> -.Bl -tag -width TOG_COLORS
> +.Bl -tag -width TOG_DIFF_ALGORITHM
> +.It Ev TOG_DIFF_ALGORITHM
> +Determines the default diff algorithm used by
> +.Nm .
> +Valid values are
> +.Dq patience
> +and
> +.Dq myers .
> +If unset, the Myers diff algorithm will be used by default.
>  .It Ev TOG_COLORS
>  .Nm
>  shows colorized output if this variable is set to a non-empty value.
> blob - 800384dacf0faed4893832dd2760af45e28cb8c7
> blob + 56481e67ad1e36e598bf01561c6b3ec76fea52c2
> --- tog/tog.c
> +++ tog/tog.c
> @@ -136,6 +136,7 @@ STAILQ_HEAD(tog_colors, tog_color);
>  
>  static struct got_reflist_head tog_refs = TAILQ_HEAD_INITIALIZER(tog_refs);
>  static struct got_reflist_object_id_map *tog_refs_idmap;
> +static enum got_diff_algorithm tog_diff_algo = GOT_DIFF_ALGORITHM_MYERS;
>  
>  static const struct got_error *
>  tog_ref_cmp_by_name(void *arg, int *cmp, struct got_reference *re1,
> @@ -321,7 +322,6 @@ struct tog_diff_view_state {
>  	int first_displayed_line;
>  	int last_displayed_line;
>  	int eof;
> -	enum got_diff_algorithm diff_algo;
>  	int diff_context;
>  	int ignore_whitespace;
>  	int force_text_diff;
> @@ -544,6 +544,7 @@ struct tog_view {
>  	const struct got_error *(*show)(struct tog_view *);
>  	const struct got_error *(*input)(struct tog_view **,
>  	    struct tog_view *, int);
> +	const struct got_error *(*reset)(struct tog_view *);
>  	const struct got_error *(*close)(struct tog_view *);
>  
>  	const struct got_error *(*search_start)(struct tog_view *);
> @@ -567,6 +568,7 @@ static const struct got_error *open_diff_view(struct t
>  static const struct got_error *show_diff_view(struct tog_view *);
>  static const struct got_error *input_diff_view(struct tog_view **,
>      struct tog_view *, int);
> +static const struct got_error *reset_diff_view(struct tog_view *);
>  static const struct got_error* close_diff_view(struct tog_view *);
>  static const struct got_error *search_start_diff_view(struct tog_view *);
>  static const struct got_error *search_next_diff_view(struct tog_view *);
> @@ -586,6 +588,7 @@ static const struct got_error *open_blame_view(struct 
>  static const struct got_error *show_blame_view(struct tog_view *);
>  static const struct got_error *input_blame_view(struct tog_view **,
>      struct tog_view *, int);
> +static const struct got_error *reset_blame_view(struct tog_view *);
>  static const struct got_error *close_blame_view(struct tog_view *);
>  static const struct got_error *search_start_blame_view(struct tog_view *);
>  static const struct got_error *search_next_blame_view(struct tog_view *);
> @@ -651,7 +654,6 @@ tog_fatal_signal_received(void)
>  	    tog_sigint_received || tog_sigint_received);
>  }
>  
> -
>  static const struct got_error *
>  view_close(struct tog_view *view)
>  {
> @@ -1217,6 +1219,24 @@ view_input(struct tog_view **new, int *done, struct to
>  		} else
>  			err = view->input(new, view, ch);
>  		break;
> +	case 'A':
> +		if (tog_diff_algo == GOT_DIFF_ALGORITHM_MYERS)
> +			tog_diff_algo = GOT_DIFF_ALGORITHM_PATIENCE;
> +		else
> +			tog_diff_algo = GOT_DIFF_ALGORITHM_MYERS;
> +		TAILQ_FOREACH(v, views, entry) {
> +			if (v->reset) {
> +				err = v->reset(v);
> +				if (err)
> +					return err;
> +			}
> +			if (v->child && v->child->reset) {
> +				err = v->child->reset(v->child);
> +				if (err)
> +					return err;
> +			}
> +		}
> +		break;
>  	default:
>  		err = view->input(new, view, ch);
>  		break;
> @@ -3966,13 +3986,13 @@ create_diff(struct tog_diff_view_state *s)
>  	case GOT_OBJ_TYPE_BLOB:
>  		err = got_diff_objects_as_blobs(&s->line_offsets, &s->nlines,
>  		    s->f1, s->f2, s->fd1, s->fd2, s->id1, s->id2,
> -		    s->label1, s->label2, s->diff_algo, s->diff_context,
> +		    s->label1, s->label2, tog_diff_algo, s->diff_context,
>  		    s->ignore_whitespace, s->force_text_diff, s->repo, s->f);
>  		break;
>  	case GOT_OBJ_TYPE_TREE:
>  		err = got_diff_objects_as_trees(&s->line_offsets, &s->nlines,
>  		    s->f1, s->f2, s->fd1, s->fd2, s->id1, s->id2, NULL, "", "",
> -		    s->diff_algo, s->diff_context, s->ignore_whitespace,
> +		    tog_diff_algo, s->diff_context, s->ignore_whitespace,
>  		    s->force_text_diff, s->repo, s->f);
>  		break;
>  	case GOT_OBJ_TYPE_COMMIT: {
> @@ -4008,7 +4028,7 @@ create_diff(struct tog_diff_view_state *s)
>  
>  		err = got_diff_objects_as_commits(&s->line_offsets, &s->nlines,
>  		    s->f1, s->f2, s->fd1, s->fd2, s->id1, s->id2, NULL,
> -		    s->diff_algo, s->diff_context, s->ignore_whitespace,
> +		    tog_diff_algo, s->diff_context, s->ignore_whitespace,
>  		    s->force_text_diff, s->repo, s->f);
>  		break;
>  	}
> @@ -4219,7 +4239,6 @@ open_diff_view(struct tog_view *view, struct got_objec
>  
>  	s->first_displayed_line = 1;
>  	s->last_displayed_line = view->nlines;
> -	s->diff_algo = GOT_DIFF_ALGORITHM_MYERS;
>  	s->diff_context = diff_context;
>  	s->ignore_whitespace = ignore_whitespace;
>  	s->force_text_diff = force_text_diff;
> @@ -4273,6 +4292,7 @@ open_diff_view(struct tog_view *view, struct got_objec
>  
>  	view->show = show_diff_view;
>  	view->input = input_diff_view;
> +	view->reset = reset_diff_view;
>  	view->close = close_diff_view;
>  	view->search_start = search_start_diff_view;
>  	view->search_next = search_next_diff_view;
> @@ -4343,6 +4363,22 @@ set_selected_commit(struct tog_diff_view_state *s,
>  }
>  
>  static const struct got_error *
> +reset_diff_view(struct tog_view *view)
> +{
> +	struct tog_diff_view_state *s = &view->state.diff;
> +
> +	fprintf(stderr, "%s\n", __func__);

here    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

> +	view->count = 0;
> +	wclear(view->window);
> +	s->first_displayed_line = 1;
> +	s->last_displayed_line = view->nlines;
> +	s->matched_line = 0;
> +	diff_view_indicate_progress(view);
> +	return create_diff(s);
> +}
> +
> +static const struct got_error *
>  input_diff_view(struct tog_view **new_view, struct tog_view *view, int ch)
>  {
>  	const struct got_error *err = NULL;
> @@ -4381,13 +4417,7 @@ input_diff_view(struct tog_view **new_view, struct tog
>  			s->force_text_diff = !s->force_text_diff;
>  		if (ch == 'w')
>  			s->ignore_whitespace = !s->ignore_whitespace;
> -		wclear(view->window);
> -		s->first_displayed_line = 1;
> -		s->last_displayed_line = view->nlines;
> -		s->matched_line = 0;
> -		diff_view_indicate_progress(view);
> -		err = create_diff(s);
> -		view->count = 0;
> +		err = reset_diff_view(view);
>  		break;
>  	case 'g':
>  	case KEY_HOME:
> @@ -4950,7 +4980,7 @@ blame_thread(void *arg)
>  		goto done;
>  
>  	err = got_blame(ta->path, a->commit_id, ta->repo,
> -	    GOT_DIFF_ALGORITHM_MYERS, blame_cb, ta->cb_args,
> +	    tog_diff_algo, blame_cb, ta->cb_args,
>  	    ta->cancel_cb, ta->cancel_arg, fd1, fd2, f1, f2);
>  	if (err && err->code == GOT_ERR_CANCELLED)
>  		err = NULL;
> @@ -5225,6 +5255,7 @@ open_blame_view(struct tog_view *view, char *path,
>  
>  	view->show = show_blame_view;
>  	view->input = input_blame_view;
> +	view->reset = reset_blame_view;
>  	view->close = close_blame_view;
>  	view->search_start = search_start_blame_view;
>  	view->search_next = search_next_blame_view;
> @@ -5641,6 +5672,22 @@ input_blame_view(struct tog_view **new_view, struct to
>  }
>  
>  static const struct got_error *
> +reset_blame_view(struct tog_view *view)
> +{
> +	const struct got_error *err;
> +	struct tog_blame_view_state *s = &view->state.blame;
> +
> +	fprintf(stderr, "%s\n", __func__);

here    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

> +	view->count = 0;
> +	s->done = 1;
> +	err = stop_blame(&s->blame);
> +	s->done = 0;
> +	if (err)
> +		return err;
> +	return run_blame(view);
> +}
> +
> +static const struct got_error *
>  cmd_blame(int argc, char *argv[])
>  {
>  	const struct got_error *error;
> @@ -7839,6 +7886,7 @@ main(int argc, char *argv[])
>  	    { "version", no_argument, NULL, 'V' },
>  	    { NULL, 0, NULL, 0}
>  	};
> +	char *diff_algo_str = NULL;
>  
>  	setlocale(LC_CTYPE, "");
>  
> @@ -7892,6 +7940,14 @@ main(int argc, char *argv[])
>  		}
>  	}
>  
> +	diff_algo_str = getenv("TOG_DIFF_ALGORITHM");
> +	if (diff_algo_str) {
> +		if (strcasecmp(diff_algo_str, "patience") == 0)
> +			tog_diff_algo = GOT_DIFF_ALGORITHM_PATIENCE;
> +		if (strcasecmp(diff_algo_str, "myers") == 0)
> +			tog_diff_algo = GOT_DIFF_ALGORITHM_MYERS;
> +	}
> +
>  	if (cmd == NULL) {
>  		if (argc != 1)
>  			usage(0, 1);
> 

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