Skip to content

Commit

Permalink
Expose %(file_old), the filename before a rename or deletion (#1132)
Browse files Browse the repository at this point in the history
This improves interaction with external tools that require file names.

Implemented by extending diff_get_pathname.
We don't handle prefixes like "diff --cc" when computing %(file_old),
because we can't tell yet if such a line is "old" or "new".
Git only uses these combined headers for binary files, and other edge
cases, see: PAGER='less +1206' git show 75ae10b:combine-diff.c
Anyway, this is not really important because %(file) already has the
correct name.

An alternative (partial) solution would be to change %(file) to the
old filename but only for deleted files. I decided against this;
while it would be convenient for some basic scenarios, it hides
information which makes scripting more difficult.

Another, more general solution for these kinds of problems would be
to allow to pipe the raw diff to user scripts.
  • Loading branch information
krobelus authored Oct 4, 2021
1 parent cbeaabd commit 5a23214
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 16 deletions.
8 changes: 8 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Release notes
=============

master
------

Improvements:
- Expose `%(file_old)`, useful for deleted and renamed files.

Bug fixes:

tig-2.5.4
---------

Expand Down
1 change: 1 addition & 0 deletions doc/manual.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ following variables.
|%(directory) |The current directory path in the tree view or
"." if undefined.
|%(file) |The currently selected file.
|%(file_old) |The old filename of the currently selected file.
|%(lineno) |The currently selected line number. Defaults to 0.
|%(lineno_old) |The currently selected line number, before the diff
was applied. Defaults to 0.
Expand Down
1 change: 1 addition & 0 deletions doc/tigrc.5.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,7 @@ following variable names, which are substituted before commands are run:
|%(directory) |The current directory path in the tree view or
"." if undefined.
|%(file) |The currently selected file.
|%(file_old) |The old filename of the currently selected file.
|%(lineno) |The currently selected line number. Defaults to 0.
|%(lineno_old) |The currently selected line number, before the diff
was applied. Defaults to 0.
Expand Down
1 change: 1 addition & 0 deletions include/tig/argv.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ typedef unsigned long argv_number;
_(argv_string, branch, "", "") \
_(argv_string, directory, ".", "") \
_(argv_string, file, "", "") \
_(argv_string, file_old, "", "") \
_(argv_string, head, "", "HEAD") \
_(argv_number, lineno, "", 0) \
_(argv_number, lineno_old, "", 0) \
Expand Down
2 changes: 1 addition & 1 deletion include/tig/diff.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ enum status_code diff_init_highlight(struct view *view, struct diff_state *state
bool diff_done_highlight(struct diff_state *state);

unsigned int diff_get_lineno(struct view *view, struct line *line, bool old);
const char *diff_get_pathname(struct view *view, struct line *line);
const char *diff_get_pathname(struct view *view, struct line *line, bool old);

extern struct view diff_view;

Expand Down
36 changes: 22 additions & 14 deletions src/diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ diff_save_line(struct view *view, struct diff_state *state, enum open_flags flag
{
if (flags & OPEN_RELOAD) {
struct line *line = &view->line[view->pos.lineno];
const char *file = view_has_line(view, line) ? diff_get_pathname(view, line) : NULL;
const char *file = view_has_line(view, line) ? diff_get_pathname(view, line, false) : NULL;

if (file) {
state->file = get_path(file);
Expand All @@ -463,7 +463,7 @@ diff_restore_line(struct view *view, struct diff_state *state)
return;

while ((line = find_prev_line_by_type(view, line, LINE_DIFF_HEADER))) {
const char *file = diff_get_pathname(view, line);
const char *file = diff_get_pathname(view, line, false);

if (file && !strcmp(file, state->file))
break;
Expand Down Expand Up @@ -711,7 +711,7 @@ diff_trace_origin(struct view *view, struct line *line)
}

const char *
diff_get_pathname(struct view *view, struct line *line)
diff_get_pathname(struct view *view, struct line *line, bool old)
{
struct line *header;
const char *dst;
Expand All @@ -723,26 +723,28 @@ diff_get_pathname(struct view *view, struct line *line)
if (!header)
return NULL;

for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
dst = strstr(box_text(header), prefixes[i]);
if (dst)
return dst + strlen(prefixes[i]);
if (!old) {
for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
dst = strstr(box_text(header), prefixes[i]);
if (dst)
return dst + strlen(prefixes[i]);
}
}

header = find_next_line_by_type(view, header, LINE_DIFF_ADD_FILE);
header = find_next_line_by_type(view, header, old ? LINE_DIFF_DEL_FILE : LINE_DIFF_ADD_FILE);
if (!header)
return NULL;

name = box_text(header);
if (!prefixcmp(name, "+++ "))
if (old ? !prefixcmp(name, "--- ") : !prefixcmp(name, "+++ "))
name += STRING_SIZE("+++ ");

if (opt_diff_noprefix)
return name;

/* Handle mnemonic prefixes, such as "b/" and "w/". */
if (!prefixcmp(name, "b/") || !prefixcmp(name, "w/"))
name += STRING_SIZE("b/");
if (!prefixcmp(name, "a/") || !prefixcmp(name, "b/") || !prefixcmp(name, "i/") || !prefixcmp(name, "w/"))
name += STRING_SIZE("a/");
return name;
}

Expand All @@ -757,7 +759,7 @@ diff_common_edit(struct view *view, enum request request, struct line *line)
file = view->env->file;
lineno = view->env->lineno;
} else {
file = diff_get_pathname(view, line);
file = diff_get_pathname(view, line, false);
lineno = diff_get_lineno(view, line, false);
}

Expand Down Expand Up @@ -806,9 +808,12 @@ diff_common_select(struct view *view, struct line *line, const char *changes_msg
if (line->type == LINE_DIFF_STAT) {
struct line *header = diff_find_header_from_stat(view, line);
if (header) {
const char *file = diff_get_pathname(view, header);
const char *file = diff_get_pathname(view, header, false);

if (file) {
const char *old_file = diff_get_pathname(view, header, true);
if (old_file)
string_format(view->env->file_old, "%s", old_file);
string_format(view->env->file, "%s", file);
view->env->lineno = view->env->goto_lineno = 0;
view->env->blob[0] = 0;
Expand All @@ -818,9 +823,12 @@ diff_common_select(struct view *view, struct line *line, const char *changes_msg
string_format(view->ref, "Press '%s' to jump to file diff",
get_view_key(view, REQ_ENTER));
} else {
const char *file = diff_get_pathname(view, line);
const char *file = diff_get_pathname(view, line, false);

if (file) {
const char *old_file = diff_get_pathname(view, line, true);
if (old_file)
string_format(view->env->file_old, "%s", old_file);
if (changes_msg)
string_format(view->ref, "%s to '%s'", changes_msg, file);
string_format(view->env->file, "%s", file);
Expand Down
2 changes: 1 addition & 1 deletion src/stage.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ stage_request(struct view *view, enum request request, struct line *line)
if (stage_status.new.name[0]) {
string_copy(view->env->file, stage_status.new.name);
} else {
const char *file = diff_get_pathname(view, line);
const char *file = diff_get_pathname(view, line, false);

if (file)
string_ncopy(view->env->file, file, strlen(file));
Expand Down

0 comments on commit 5a23214

Please sign in to comment.