Skip to content

Commit

Permalink
Add navigation between merge commits
Browse files Browse the repository at this point in the history
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 Nov 13, 2016
1 parent e59bec5 commit ce03083
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 0 deletions.
1 change: 1 addition & 0 deletions NEWS.adoc
Expand Up @@ -8,6 +8,7 @@ Improvements:


- Support Git's 'diff-highlight' program when `diff-highlight` is set to either - 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. 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. - Add 'A' as a binding to apply a stash without dropping it.
- Bind 'Ctrl-D' and 'Ctrl-U' to half-page movements by default. - Bind 'Ctrl-D' and 'Ctrl-U' to half-page movements by default.
- manual: Mention how to change default Up/Down behavior in diff view. - manual: Mention how to change default Up/Down behavior in diff view.
Expand Down
1 change: 1 addition & 0 deletions include/tig/graph.h
Expand Up @@ -39,6 +39,7 @@ struct graph {
const char *id, const char *parents, bool is_boundary); const char *id, const char *parents, bool is_boundary);
bool (*add_parent)(struct graph *graph, const char *parent); bool (*add_parent)(struct graph *graph, const char *parent);
bool (*render_parents)(struct graph *graph, struct graph_canvas *canvas); 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); void (*foreach_symbol)(const struct graph *graph, const struct graph_canvas *canvas, graph_symbol_iterator_fn fn, void *data);


Expand Down
2 changes: 2 additions & 0 deletions include/tig/request.h
Expand Up @@ -54,6 +54,8 @@
REQ_(MOVE_HALF_PAGE_UP, "Move cursor one page up"), \ REQ_(MOVE_HALF_PAGE_UP, "Move cursor one page up"), \
REQ_(MOVE_FIRST_LINE, "Move cursor to first line"), \ REQ_(MOVE_FIRST_LINE, "Move cursor to first line"), \
REQ_(MOVE_LAST_LINE, "Move cursor to last 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_GROUP("Scrolling") \
REQ_(SCROLL_LINE_UP, "Scroll one line up"), \ REQ_(SCROLL_LINE_UP, "Scroll one line up"), \
Expand Down
1 change: 1 addition & 0 deletions include/tig/search.h
Expand Up @@ -19,6 +19,7 @@
void reset_search(struct view *view); void reset_search(struct view *view);
void search_view(struct view *view, enum request request); void search_view(struct view *view, enum request request);
void find_next(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[]); bool grep_text(struct view *view, const char *text[]);


#endif #endif
Expand Down
7 changes: 7 additions & 0 deletions src/graph-v1.c
Expand Up @@ -312,6 +312,12 @@ graph_render_parents(struct graph *graph_, struct graph_canvas *canvas)
return true; return true;
} }


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

static bool static bool
graph_add_commit(struct graph *graph_, struct graph_canvas *canvas, graph_add_commit(struct graph *graph_, struct graph_canvas *canvas,
const char *id, const char *parents, bool is_boundary) const char *id, const char *parents, bool is_boundary)
Expand Down Expand Up @@ -493,6 +499,7 @@ init_graph_v1(void)
api->add_commit = graph_add_commit; api->add_commit = graph_add_commit;
api->add_parent = graph_add_parent; api->add_parent = graph_add_parent;
api->render_parents = graph_render_parents; api->render_parents = graph_render_parents;
api->is_merge = graph_is_merge;
api->foreach_symbol = graph_foreach_symbol; api->foreach_symbol = graph_foreach_symbol;
api->symbol_to_ascii = graph_symbol_to_ascii; api->symbol_to_ascii = graph_symbol_to_ascii;
api->symbol_to_utf8 = graph_symbol_to_utf8; api->symbol_to_utf8 = graph_symbol_to_utf8;
Expand Down
7 changes: 7 additions & 0 deletions src/graph-v2.c
Expand Up @@ -713,6 +713,12 @@ graph_render_parents(struct graph *graph_ref, struct graph_canvas *canvas)
return true; return true;
} }


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

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


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


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

default: default:
return request; return request;
} }
Expand Down
73 changes: 73 additions & 0 deletions src/search.c
Expand Up @@ -15,6 +15,8 @@
#include "tig/prompt.h" #include "tig/prompt.h"
#include "tig/display.h" #include "tig/display.h"
#include "tig/draw.h" #include "tig/draw.h"
#include "tig/main.h"
#include "tig/graph.h"


DEFINE_ALLOCATOR(realloc_unsigned_ints, unsigned int, 32) DEFINE_ALLOCATOR(realloc_unsigned_ints, unsigned int, 32)


Expand Down Expand Up @@ -159,6 +161,77 @@ find_next(struct view *view, enum request request)
report("%s", get_status_message(code)); 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 void
reset_search(struct view *view) reset_search(struct view *view)
{ {
Expand Down
5 changes: 5 additions & 0 deletions src/tig.c
Expand Up @@ -292,6 +292,11 @@ view_driver(struct view *view, enum request request)
find_next(view, request); find_next(view, request);
break; 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: case REQ_STOP_LOADING:
foreach_view(view, i) { foreach_view(view, i) {
if (view->pipe) if (view->pipe)
Expand Down

0 comments on commit ce03083

Please sign in to comment.