Skip to content
Permalink
Browse files

Add navigation between merge commits

Allow skipping forward and backward between merge commits by means of
two actions “move-next-merge” and “move-prev-merge”. The search
considers all lines containing the merge symbol.
  • Loading branch information...
phi-gamma authored and jonas committed Sep 18, 2016
1 parent e59bec5 commit ce030833ea666764b40646fe9c901e8bf7204783
Showing with 103 additions and 0 deletions.
  1. +1 −0 NEWS.adoc
  2. +1 −0 include/tig/graph.h
  3. +2 −0 include/tig/request.h
  4. +1 −0 include/tig/search.h
  5. +7 −0 src/graph-v1.c
  6. +7 −0 src/graph-v2.c
  7. +6 −0 src/main.c
  8. +73 −0 src/search.c
  9. +5 −0 src/tig.c
@@ -8,6 +8,7 @@ Improvements:

- Support Git's 'diff-highlight' program when `diff-highlight` is set to either
true or the path of the script to use for post-processing.
- Add navigation between merge commits. (GH #525)
- Add 'A' as a binding to apply a stash without dropping it.
- Bind 'Ctrl-D' and 'Ctrl-U' to half-page movements by default.
- manual: Mention how to change default Up/Down behavior in diff view.
@@ -39,6 +39,7 @@ struct graph {
const char *id, const char *parents, bool is_boundary);
bool (*add_parent)(struct graph *graph, const char *parent);
bool (*render_parents)(struct graph *graph, struct graph_canvas *canvas);
bool (*is_merge)(struct graph_canvas *canvas);

void (*foreach_symbol)(const struct graph *graph, const struct graph_canvas *canvas, graph_symbol_iterator_fn fn, void *data);

@@ -54,6 +54,8 @@
REQ_(MOVE_HALF_PAGE_UP, "Move cursor one page up"), \
REQ_(MOVE_FIRST_LINE, "Move cursor to first line"), \
REQ_(MOVE_LAST_LINE, "Move cursor to last line"), \
REQ_(MOVE_NEXT_MERGE, "Move cursor to next merge commit"), \
REQ_(MOVE_PREV_MERGE, "Move cursor to previous merge commit"), \
\
REQ_GROUP("Scrolling") \
REQ_(SCROLL_LINE_UP, "Scroll one line up"), \
@@ -19,6 +19,7 @@
void reset_search(struct view *view);
void search_view(struct view *view, enum request request);
void find_next(struct view *view, enum request request);
void find_merge(struct view *view, enum request request);
bool grep_text(struct view *view, const char *text[]);

#endif
@@ -312,6 +312,12 @@ graph_render_parents(struct graph *graph_, struct graph_canvas *canvas)
return true;
}

static bool
graph_is_merge(struct graph_canvas *canvas)
{
return !!canvas->symbols->merge;
}

static bool
graph_add_commit(struct graph *graph_, struct graph_canvas *canvas,
const char *id, const char *parents, bool is_boundary)
@@ -493,6 +499,7 @@ init_graph_v1(void)
api->add_commit = graph_add_commit;
api->add_parent = graph_add_parent;
api->render_parents = graph_render_parents;
api->is_merge = graph_is_merge;
api->foreach_symbol = graph_foreach_symbol;
api->symbol_to_ascii = graph_symbol_to_ascii;
api->symbol_to_utf8 = graph_symbol_to_utf8;
@@ -713,6 +713,12 @@ graph_render_parents(struct graph *graph_ref, struct graph_canvas *canvas)
return true;
}

static bool
graph_is_merge(struct graph_canvas *canvas)
{
return !!canvas->symbols->merge;
}

static bool
graph_add_commit(struct graph *graph_ref, struct graph_canvas *canvas,
const char *id, const char *parents, bool is_boundary)
@@ -1109,6 +1115,7 @@ init_graph_v2(void)
api->done_rendering = done_graph_rendering;
api->add_commit = graph_add_commit;
api->add_parent = graph_add_parent;
api->is_merge = graph_is_merge;
api->render_parents = graph_render_parents;
api->foreach_symbol = graph_foreach_symbol;
api->symbol_to_ascii = graph_symbol_to_ascii;
@@ -24,6 +24,7 @@
#include "tig/stage.h"
#include "tig/main.h"
#include "tig/diff.h"
#include "tig/search.h"

/*
* Main view backend
@@ -536,6 +537,11 @@ main_request(struct view *view, enum request request, struct line *line)
goto_id(view, "%(commit)^", true, false);
break;

case REQ_MOVE_NEXT_MERGE:
case REQ_MOVE_PREV_MERGE:
find_merge(view, request);
break;

default:
return request;
}
@@ -15,6 +15,8 @@
#include "tig/prompt.h"
#include "tig/display.h"
#include "tig/draw.h"
#include "tig/main.h"
#include "tig/graph.h"

DEFINE_ALLOCATOR(realloc_unsigned_ints, unsigned int, 32)

@@ -159,6 +161,77 @@ find_next(struct view *view, enum request request)
report("%s", get_status_message(code));
}

static enum status_code
find_next_merge_line(struct view *view, int direction, bool wrapped)
{
enum status_code code = -1;
int dist;
size_t max;

if (wrapped)
max = view->lines;
else
max = direction > 0 ? view->lines - view->pos.lineno
: view->pos.lineno;

for (dist = direction; abs(dist) < max; dist += direction) {
ssize_t lineno = view->pos.lineno + dist;
if (lineno < 0)
lineno += view->lines;
else if (lineno >= view->lines)
lineno -= view->lines;

struct line *line = &view->line[lineno];
struct commit *commit = line->data;
struct graph_canvas *canvas = &commit->graph;
struct view_column_data column_data;

if (!view->ops->get_column_data(view, line, &column_data))
continue;

if (column_data.graph && !column_data.graph->is_merge(canvas))
continue;

select_view_line(view, lineno);
code = SUCCESS;
break;
}

return code;
}

static enum status_code
find_next_merge(struct view *view, enum request request)
{
int direction;
enum status_code code;

switch (request) {
case REQ_MOVE_NEXT_MERGE:
direction = 1;
break;

case REQ_MOVE_PREV_MERGE:
direction = -1;
break;

default:
return error("Invalid request searching for next merge");
}

code = find_next_merge_line(view, direction, opt_wrap_search);

return code == SUCCESS ? code : success("No merge commit found");
}

void
find_merge(struct view *view, enum request request)
{
enum status_code code = find_next_merge(view, request);

report("%s", get_status_message(code));
}

void
reset_search(struct view *view)
{
@@ -292,6 +292,11 @@ view_driver(struct view *view, enum request request)
find_next(view, request);
break;

case REQ_MOVE_NEXT_MERGE:
case REQ_MOVE_PREV_MERGE:
report("Moving between merge commits is not supported by the %s view", view->name);
break;

case REQ_STOP_LOADING:
foreach_view(view, i) {
if (view->pipe)

0 comments on commit ce03083

Please sign in to comment.
You can’t perform that action at this time.