From 1d6b7df7205652c424661833d41ec4aeb8341ea0 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Tue, 6 May 2014 21:02:57 -0400 Subject: [PATCH] Preserve the cursor position when changing the diff context Fixes #284 --- include/tig/diff.h | 5 ++ src/diff.c | 61 +++++++++++++++ src/stage.c | 7 ++ test/diff/diff-context-test | 186 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 259 insertions(+) create mode 100755 test/diff/diff-context-test diff --git a/include/tig/diff.h b/include/tig/diff.h index fd0819a..1588757 100644 --- a/include/tig/diff.h +++ b/include/tig/diff.h @@ -21,12 +21,17 @@ struct diff_state { bool after_diff; bool reading_diff_stat; bool combined_diff; + const char *file; + unsigned int lineno; + struct position pos; }; enum request diff_common_edit(struct view *view, enum request request, struct line *line); bool diff_common_read(struct view *view, const char *data, struct diff_state *state); enum request diff_common_enter(struct view *view, enum request request, struct line *line); struct line *diff_common_add_diff_stat(struct view *view, const char *text, size_t offset); +void diff_save_line(struct view *view, struct diff_state *state, enum open_flags flags); +void diff_restore_line(struct view *view, struct diff_state *state); unsigned int diff_get_lineno(struct view *view, struct line *line); const char *diff_get_pathname(struct view *view, struct line *line); diff --git a/src/diff.c b/src/diff.c index 4bbd60c..fa9d613 100644 --- a/src/diff.c +++ b/src/diff.c @@ -32,6 +32,8 @@ diff_open(struct view *view, enum open_flags flags) "--", "%(fileargs)", NULL }; + diff_save_line(view, view->private, flags); + return begin_update(view, NULL, diff_argv, flags); } @@ -164,6 +166,61 @@ diff_common_enter(struct view *view, enum request request, struct line *line) } } +void +diff_save_line(struct view *view, struct diff_state *state, enum open_flags flags) +{ + 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; + + if (file) { + state->file = get_path(file); + state->lineno = diff_get_lineno(view, line); + state->pos = view->pos; + } + } +} + +void +diff_restore_line(struct view *view, struct diff_state *state) +{ + struct line *line = &view->line[view->lines - 1]; + + if (!state->file) + return; + + while ((line = find_prev_line_by_type(view, line, LINE_DIFF_HEADER))) { + const char *file = diff_get_pathname(view, line); + + if (file && !strcmp(file, state->file)) + break; + line--; + } + + state->file = NULL; + + if (!line) + return; + + while ((line = find_next_line_by_type(view, line, LINE_DIFF_CHUNK))) { + unsigned int lineno = diff_get_lineno(view, line); + + for (line++; view_has_line(view, line) && line->type != LINE_DIFF_CHUNK; line++) { + if (lineno == state->lineno) { + unsigned long lineno = line - view->line; + unsigned long offset = lineno - (state->pos.lineno - state->pos.offset); + + goto_view_line(view, offset, lineno); + redraw_view(view); + return; + } + if (line->type != LINE_DIFF_DEL && + line->type != LINE_DIFF_DEL2) + lineno++; + } + } +} + static bool diff_read(struct view *view, struct buffer *buf) { @@ -187,6 +244,9 @@ diff_read(struct view *view, struct buffer *buf) return FALSE; } } + + diff_restore_line(view, state); + return TRUE; } @@ -411,6 +471,7 @@ diff_select(struct view *view, struct line *line) if (file) { string_format(view->ref, "Changes to '%s'", file); string_format(view->env->file, "%s", file); + view->env->lineno = diff_get_lineno(view, line); view->env->blob[0] = 0; } else { string_ncopy(view->ref, view->ops->id, strlen(view->ops->id)); diff --git a/src/stage.c b/src/stage.c index 2a9050f..bfdbbfb 100644 --- a/src/stage.c +++ b/src/stage.c @@ -475,6 +475,7 @@ stage_open(struct view *view, enum open_flags flags) }; static const char *file_argv[] = { repo.cdup, stage_status.new.name, NULL }; const char **argv = NULL; + struct stage_state *state = view->private; if (!stage_line_type) { report("No stage content, press %s to open the status view and choose file", @@ -517,6 +518,9 @@ stage_open(struct view *view, enum open_flags flags) return FALSE; } + if (stage_line_type != LINE_STAT_UNTRACKED) + diff_save_line(view, &state->diff, flags); + view->vid[0] = 0; view->dir = repo.cdup; return begin_update(view, NULL, NULL, flags); @@ -535,6 +539,9 @@ stage_read(struct view *view, struct buffer *buf) return TRUE; } + if (!buf) + diff_restore_line(view, &state->diff); + if (buf && diff_common_read(view, buf->data, &state->diff)) return TRUE; diff --git a/test/diff/diff-context-test b/test/diff/diff-context-test new file mode 100755 index 0000000..fd39951 --- /dev/null +++ b/test/diff/diff-context-test @@ -0,0 +1,186 @@ +#!/bin/sh + +. libtest.sh +. libgit.sh + +steps ' + :save-display diff-default.screen + + :21 + ] + :save-display diff-u4.screen + + ] + :save-display diff-u5.screen + + :toggle diff-context +5 + :save-display diff-u10.screen + + [ + [ + :save-display diff-u8.screen +' + +in_work_dir create_repo_from_tgz "$base_dir/files/scala-js-benchmarks.tgz" + +test_tig show master^ + +assert_equals 'diff-default.screen' < +AuthorDate: Sat Mar 1 15:59:02 2014 -0500 +Commit: Jonas Fonseca +CommitDate: Sat Mar 1 15:59:02 2014 -0500 + + Add type parameter for js.Dynamic +--- + common/src/main/scala/org/scalajs/benchmark/Benchmark.scala | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/common/src/main/scala/org/scalajs/benchmark/Benchmark.scala b/commo +index 65f914a..3aa4320 100644 +--- a/common/src/main/scala/org/scalajs/benchmark/Benchmark.scala ++++ b/common/src/main/scala/org/scalajs/benchmark/Benchmark.scala +@@ -15,7 +15,7 @@ object Benchmark { + val benchmarks = js.Array[Benchmark]() + val benchmarkApps = js.Array[BenchmarkApp]() + +- val global = js.Dynamic.global.asInstanceOf[js.Dictionary] ++ val global = js.Dynamic.global.asInstanceOf[js.Dictionary[js.Any]] + global("runScalaJSBenchmarks") = runBenchmarks _ + global("initScalaJSBenchmarkApps") = initBenchmarkApps _ + + + + + +[diff] a1dcf1aaa11470978db1d5d8bcf9e16201eb70ff - line 1 of 24 100% +EOF + +assert_equals 'diff-u4.screen' < +AuthorDate: Sat Mar 1 15:59:02 2014 -0500 +Commit: Jonas Fonseca +CommitDate: Sat Mar 1 15:59:02 2014 -0500 + + Add type parameter for js.Dynamic +--- + common/src/main/scala/org/scalajs/benchmark/Benchmark.scala | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/common/src/main/scala/org/scalajs/benchmark/Benchmark.scala b/commo +index 65f914a..3aa4320 100644 +--- a/common/src/main/scala/org/scalajs/benchmark/Benchmark.scala ++++ b/common/src/main/scala/org/scalajs/benchmark/Benchmark.scala +@@ -14,9 +14,9 @@ import scala.scalajs.js + object Benchmark { + val benchmarks = js.Array[Benchmark]() + val benchmarkApps = js.Array[BenchmarkApp]() + +- val global = js.Dynamic.global.asInstanceOf[js.Dictionary] ++ val global = js.Dynamic.global.asInstanceOf[js.Dictionary[js.Any]] + global("runScalaJSBenchmarks") = runBenchmarks _ + global("initScalaJSBenchmarkApps") = initBenchmarkApps _ + + def add(benchmark: Benchmark) { + + +[diff] Changes to 'common/src/main/scala/org/scalajs/benchmark/Benchmark.sca100% +EOF + +assert_equals 'diff-u5.screen' < +AuthorDate: Sat Mar 1 15:59:02 2014 -0500 +Commit: Jonas Fonseca +CommitDate: Sat Mar 1 15:59:02 2014 -0500 + + Add type parameter for js.Dynamic +--- + common/src/main/scala/org/scalajs/benchmark/Benchmark.scala | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/common/src/main/scala/org/scalajs/benchmark/Benchmark.scala b/commo +index 65f914a..3aa4320 100644 +--- a/common/src/main/scala/org/scalajs/benchmark/Benchmark.scala ++++ b/common/src/main/scala/org/scalajs/benchmark/Benchmark.scala +@@ -13,11 +13,11 @@ import scala.scalajs.js + + object Benchmark { + val benchmarks = js.Array[Benchmark]() + val benchmarkApps = js.Array[BenchmarkApp]() + +- val global = js.Dynamic.global.asInstanceOf[js.Dictionary] ++ val global = js.Dynamic.global.asInstanceOf[js.Dictionary[js.Any]] + global("runScalaJSBenchmarks") = runBenchmarks _ + global("initScalaJSBenchmarkApps") = initBenchmarkApps _ + + def add(benchmark: Benchmark) { + benchmarks.push(benchmark) + +[diff] Changes to 'common/src/main/scala/org/scalajs/benchmark/Benchmark.sca100% +EOF + +assert_equals 'diff-u10.screen' <