diff --git a/NEWS b/NEWS
new file mode 100644
-index 0000000..fcaa853
+index 0000000..d93fb04
--- /dev/null
+++ b/NEWS
-@@ -0,0 +1,156 @@
+@@ -0,0 +1,159 @@
+Release notes
+=============
+
+ - Stage view: add stage-next action to jump to next diff chunk that can
+ be staged. By default bound to '@'.
+ - Configure: check for the ncurses header files.
++ - Add author-width option to costumize the width of the author column.
++ For example, put the following in ~/.tigrc: set author-width = 10
+
+Bug fixes:
+
+ keybinding to launch the merge tool in the status view.
+ - Fix problem with $(cmd) usage in shell code. Some shells (jsh)
+ installed as /bin/sh does not support it.
++ - Do not show incomplete boundary commits when --no-walk is used.
+ - Documentation: Rename gitlink macro to support AsciiDoc 8.2.3.
+
+tig-0.11
+ - Status view: Add support for opening files in an editor. Bound to 'e'
+ by default.
+ - Tree view: use a stack for remembering the lines for parent tree.
+diff --git a/TODO b/TODO
+index 437f0d4..919734a 100644
+--- a/TODO
++++ b/TODO
+@@ -28,3 +28,6 @@ Features that should be explored.
+
+ - Color the revgraph to make it easier to follow branches. Idea by
+ Dominik Vogt
++
++ - Allow names in the author column to be abbreviated to initials.
++ Will optimize screen usage for the blame view.
diff --git a/asciidoc.conf b/asciidoc.conf
index 630552c..90fdb6a 100644
--- a/asciidoc.conf
Online resources:
diff --git a/tig.c b/tig.c
-index 5280da8..3802204 100644
+index 5280da8..8362ecf 100644
--- a/tig.c
+++ b/tig.c
@@ -45,7 +45,15 @@
REQ_(TREE_PARENT, "Switch to parent directory in tree view"), \
REQ_(EDIT, "Open in editor"), \
REQ_(NONE, "Do nothing")
-@@ -438,10 +446,11 @@ static const char usage[] =
+@@ -438,11 +446,12 @@ static const char usage[] =
static bool opt_date = TRUE;
static bool opt_author = TRUE;
static bool opt_line_number = FALSE;
static bool opt_show_refs = TRUE;
static int opt_num_interval = NUMBER_INTERVAL;
-static int opt_tab_size = TABSIZE;
+-static enum request opt_request = REQ_VIEW_MAIN;
+static int opt_tab_size = TAB_SIZE;
- static enum request opt_request = REQ_VIEW_MAIN;
++static int opt_author_cols = AUTHOR_COLS-1;
static char opt_cmd[SIZEOF_STR] = "";
static char opt_path[SIZEOF_STR] = "";
-@@ -612,7 +621,8 @@ LINE(BLAME_ID, "", COLOR_MAGENTA, COLOR_DEFAULT, 0)
+ static char opt_file[SIZEOF_STR] = "";
+@@ -461,34 +470,32 @@ static char opt_git_dir[SIZEOF_STR] = "";
+ static signed char opt_is_inside_work_tree = -1; /* set to TRUE or FALSE */
+ static char opt_editor[SIZEOF_STR] = "";
+
+-static bool
++static enum request
+ parse_options(int argc, char *argv[])
+ {
++ enum request request = REQ_VIEW_MAIN;
+ size_t buf_size;
+ char *subcommand;
+ bool seen_dashdash = FALSE;
+ int i;
+
+ if (!isatty(STDIN_FILENO)) {
+- opt_request = REQ_VIEW_PAGER;
+ opt_pipe = stdin;
+- return TRUE;
++ return REQ_VIEW_PAGER;
+ }
+
+ if (argc <= 1)
+- return TRUE;
++ return REQ_VIEW_MAIN;
+
+ subcommand = argv[1];
+ if (!strcmp(subcommand, "status") || !strcmp(subcommand, "-S")) {
+- opt_request = REQ_VIEW_STATUS;
+ if (!strcmp(subcommand, "-S"))
+ warn("`-S' has been deprecated; use `tig status' instead");
+ if (argc > 2)
+ warn("ignoring arguments after `%s'", subcommand);
+- return TRUE;
++ return REQ_VIEW_STATUS;
+
+ } else if (!strcmp(subcommand, "blame")) {
+- opt_request = REQ_VIEW_BLAME;
+ if (argc <= 2 || argc > 4)
+ die("invalid number of options to blame\n\n%s", usage);
+
+@@ -499,14 +506,13 @@ parse_options(int argc, char *argv[])
+ }
+
+ string_ncopy(opt_file, argv[i], strlen(argv[i]));
+- return TRUE;
++ return REQ_VIEW_BLAME;
+
+ } else if (!strcmp(subcommand, "show")) {
+- opt_request = REQ_VIEW_DIFF;
++ request = REQ_VIEW_DIFF;
+
+ } else if (!strcmp(subcommand, "log") || !strcmp(subcommand, "diff")) {
+- opt_request = subcommand[0] == 'l'
+- ? REQ_VIEW_LOG : REQ_VIEW_DIFF;
++ request = subcommand[0] == 'l' ? REQ_VIEW_LOG : REQ_VIEW_DIFF;
+ warn("`tig %s' has been deprecated", subcommand);
+
+ } else {
+@@ -530,11 +536,11 @@ parse_options(int argc, char *argv[])
+
+ } else if (!strcmp(opt, "-v") || !strcmp(opt, "--version")) {
+ printf("tig version %s\n", TIG_VERSION);
+- return FALSE;
++ return REQ_NONE;
+
+ } else if (!strcmp(opt, "-h") || !strcmp(opt, "--help")) {
+ printf("%s\n", usage);
+- return FALSE;
++ return REQ_NONE;
+ }
+
+ opt_cmd[buf_size++] = ' ';
+@@ -545,7 +551,7 @@ parse_options(int argc, char *argv[])
+
+ opt_cmd[buf_size] = 0;
+
+- return TRUE;
++ return request;
+ }
+
+
+@@ -612,7 +618,8 @@ LINE(BLAME_ID, "", COLOR_MAGENTA, COLOR_DEFAULT, 0)
enum line_type {
#define LINE(type, line, fg, bg, attr) \
LINE_##type
#undef LINE
};
-@@ -731,7 +741,8 @@ static struct keybinding default_keybindings[] = {
+@@ -731,7 +738,8 @@ static struct keybinding default_keybindings[] = {
{ KEY_UP, REQ_PREVIOUS },
{ KEY_DOWN, REQ_NEXT },
{ 'R', REQ_REFRESH },
/* Cursor navigation */
{ 'k', REQ_MOVE_UP },
-@@ -769,6 +780,7 @@ static struct keybinding default_keybindings[] = {
+@@ -769,6 +777,7 @@ static struct keybinding default_keybindings[] = {
{ ':', REQ_PROMPT },
{ 'u', REQ_STATUS_UPDATE },
{ 'M', REQ_STATUS_MERGE },
{ ',', REQ_TREE_PARENT },
{ 'e', REQ_EDIT },
-@@ -954,22 +966,23 @@ static size_t run_requests;
+@@ -954,22 +963,23 @@ static size_t run_requests;
static enum request
add_run_request(enum keymap keymap, int key, int argc, char **argv)
{
return REQ_NONE + run_requests;
}
-@@ -1126,6 +1139,11 @@ option_set_command(int argc, char *argv[])
+@@ -1087,6 +1097,14 @@ static bool parse_bool(const char *s)
+ !strcmp(s, "yes")) ? TRUE : FALSE;
+ }
+
++static int
++parse_int(const char *s, int default_value, int min, int max)
++{
++ int value = atoi(s);
++
++ return (value < min || value > max) ? default_value : value;
++}
++
+ /* Wants: name = value */
+ static int
+ option_set_command(int argc, char *argv[])
+@@ -1126,13 +1144,23 @@ option_set_command(int argc, char *argv[])
return OK;
}
+ }
+
if (!strcmp(argv[0], "line-number-interval")) {
- opt_num_interval = atoi(argv[2]);
+- opt_num_interval = atoi(argv[2]);
++ opt_num_interval = parse_int(argv[2], opt_num_interval, 1, 1024);
++ return OK;
++ }
++
++ if (!strcmp(argv[0], "author-width")) {
++ opt_author_cols = parse_int(argv[2], opt_author_cols, 0, 1024);
+ return OK;
+ }
+
+ if (!strcmp(argv[0], "tab-size")) {
+- opt_tab_size = atoi(argv[2]);
++ opt_tab_size = parse_int(argv[2], opt_tab_size, 1, 1024);
return OK;
-@@ -1391,6 +1409,11 @@ struct view {
+ }
+
+@@ -1391,6 +1419,11 @@ struct view {
size_t line_size; /* Total number of used lines */
unsigned int digits; /* Number of digits in the lines member. */
/* Loading */
FILE *pipe;
time_t start_time;
-@@ -1404,7 +1427,7 @@ struct view_ops {
+@@ -1404,7 +1437,7 @@ struct view_ops {
/* Read one line; updates view->line. */
bool (*read)(struct view *view, char *data);
/* Draw one line; @lineno must be < view->height. */
/* Depending on view handle a special requests. */
enum request (*request)(struct view *view, enum request request, struct line *line);
/* Search for regex in a line. */
-@@ -1451,107 +1474,175 @@ static struct view views[] = {
+@@ -1451,107 +1484,175 @@ static struct view views[] = {
#define view_is_displayed(view) \
(view == display[0] || view == display[1])
static int
-draw_lineno(struct view *view, unsigned int lineno, int max, bool selected)
+draw_space(struct view *view, enum line_type type, int max, int spaces)
- {
-- static char fmt[] = "%1ld";
-- char number[10] = " ";
++{
+ static char space[] = " ";
+ int col = 0;
+
+
+static bool
+draw_lineno(struct view *view, unsigned int lineno)
-+{
+ {
+- static char fmt[] = "%1ld";
+- char number[10] = " ";
+ char number[10];
int digits3 = view->digits < 3 ? 3 : view->digits;
int max_number = MIN(digits3, STRING_SIZE(number));
}
static bool
-@@ -1569,19 +1660,21 @@ draw_view_line(struct view *view, unsigned int lineno)
+@@ -1569,19 +1670,21 @@ draw_view_line(struct view *view, unsigned int lineno)
line = &view->line[view->offset + lineno];
wmove(view->win, lineno, 0);
scrollok(view->win, TRUE);
return draw_ok;
-@@ -2070,10 +2163,13 @@ search_view(struct view *view, enum request request)
+@@ -2070,10 +2173,13 @@ search_view(struct view *view, enum request request)
*/
static void
set_nonblocking_input(FALSE);
if (view->pipe == stdin)
fclose(view->pipe);
-@@ -2085,9 +2181,6 @@ end_update(struct view *view)
+@@ -2085,9 +2191,6 @@ end_update(struct view *view)
static bool
begin_update(struct view *view)
{
if (opt_cmd[0]) {
string_copy(view->cmd, opt_cmd);
opt_cmd[0] = 0;
-@@ -2291,21 +2384,18 @@ update_view(struct view *view)
+@@ -2289,23 +2392,20 @@ update_view(struct view *view)
+ update_view_title(view);
+
check_pipe:
- if (ferror(view->pipe)) {
+- if (ferror(view->pipe)) {
++ if (ferror(view->pipe) && errno != 0) {
report("Failed to read: %s", strerror(errno));
- goto end;
+ end_update(view, TRUE);
return FALSE;
}
-@@ -2340,7 +2430,7 @@ enum open_flags {
+@@ -2340,7 +2440,7 @@ enum open_flags {
OPEN_SPLIT = 1, /* Split current view. */
OPEN_BACKGROUNDED = 2, /* Backgrounded. */
OPEN_RELOAD = 4, /* Reload view even if it is the current. */
};
static void
-@@ -2381,6 +2471,9 @@ open_view(struct view *prev, enum request request, enum open_flags flags)
+@@ -2381,6 +2481,9 @@ open_view(struct view *prev, enum request request, enum open_flags flags)
(nviews == 1 && base_view != display[0]))
resize_display();
if (view->ops->open) {
if (!view->ops->open(view)) {
report("Failed to load %s view", view->name);
-@@ -2722,7 +2815,7 @@ view_driver(struct view *view, enum request request)
+@@ -2702,11 +2805,6 @@ view_driver(struct view *view, enum request request)
+ redraw_display();
+ break;
+
+- case REQ_PROMPT:
+- /* Always reload^Wrerun commands from the prompt. */
+- open_view(view, opt_request, OPEN_RELOAD);
+- break;
+-
+ case REQ_SEARCH:
+ case REQ_SEARCH_BACK:
+ search_view(view, request);
+@@ -2722,7 +2820,7 @@ view_driver(struct view *view, enum request request)
view = &views[i];
if (view->pipe)
report("Stopped loading the %s view", view->name),
}
break;
-@@ -2780,49 +2873,14 @@ view_driver(struct view *view, enum request request)
+@@ -2741,12 +2839,10 @@ view_driver(struct view *view, enum request request)
+ report("Nothing to edit");
+ break;
+
+-
+ case REQ_ENTER:
+ report("Nothing to enter");
+ break;
+
+-
+ case REQ_VIEW_CLOSE:
+ /* XXX: Mark closed views by letting view->parent point to the
+ * view itself. Parents to closed view should never be
+@@ -2780,49 +2876,14 @@ view_driver(struct view *view, enum request request)
*/
static bool
- if (col >= view->width)
- return TRUE;
- }
-
+-
- if (!selected)
- wattrset(view->win, get_line_attr(line->type));
-
- int cols_max = view->width - col_offset - col;
- char *pos = text;
- int cols;
--
+
- if (*text == '\t') {
- text++;
- assert(sizeof(spaces) > TABSIZE);
return TRUE;
}
-@@ -3525,9 +3583,6 @@ blame_read_file(struct view *view, char *line)
+@@ -3525,9 +3586,6 @@ blame_read_file(struct view *view, char *line)
size_t linelen = strlen(line);
struct blame *blame = malloc(sizeof(*blame) + linelen);
blame->commit = NULL;
strncpy(blame->text, line, linelen);
blame->text[linelen] = 0;
-@@ -3606,51 +3661,32 @@ blame_read(struct view *view, char *line)
+@@ -3606,51 +3664,32 @@ blame_read(struct view *view, char *line)
}
static bool
{
struct blame *blame = line->data;
- int col = 0;
-+ struct tm *time = NULL;
-+ char *id = NULL, *author = NULL;
-
+-
- if (opt_date) {
- struct tm *time = blame->commit && *blame->commit->filename
- ? &blame->commit->time : NULL;
--
++ struct tm *time = NULL;
++ char *id = NULL, *author = NULL;
+
- col += draw_date(view, time, view->width, selected);
- if (col >= view->width)
- return TRUE;
- wmove(view->win, lineno, col);
- }
+ if (opt_author &&
-+ draw_field(view, LINE_MAIN_AUTHOR, author, AUTHOR_COLS, TRUE))
++ draw_field(view, LINE_MAIN_AUTHOR, author, opt_author_cols, TRUE))
+ return TRUE;
- {
return TRUE;
}
-@@ -3692,23 +3728,23 @@ blame_grep(struct view *view, struct line *line)
+@@ -3692,23 +3731,23 @@ blame_grep(struct view *view, struct line *line)
struct blame_commit *commit = blame->commit;
regmatch_t pmatch;
#undef MATCH
}
-@@ -3759,6 +3795,8 @@ struct status {
+@@ -3759,6 +3798,8 @@ struct status {
static char status_onbranch[SIZEOF_STR];
static struct status stage_status;
static enum line_type stage_line_type;
/* Get fields from the diff line:
* :100644 100644 06a5d6ae9eca55be2e0e585a152e6b1336f2b20e 0000000000000000000000000000000000000000 M
-@@ -3977,7 +4015,7 @@ status_open(struct view *view)
+@@ -3977,7 +4018,7 @@ status_open(struct view *view)
return FALSE;
}
if (!status_run(view, indexcmd, indexstatus, LINE_STAT_STAGED) ||
!status_run(view, STATUS_DIFF_FILES_CMD, 0, LINE_STAT_UNSTAGED) ||
-@@ -4009,46 +4047,36 @@ status_open(struct view *view)
+@@ -4009,46 +4050,36 @@ status_open(struct view *view)
}
static bool
text = status_onbranch;
break;
-@@ -4056,15 +4084,16 @@ status_draw(struct view *view, struct line *line, unsigned int lineno, bool sele
+@@ -4056,15 +4087,16 @@ status_draw(struct view *view, struct line *line, unsigned int lineno, bool sele
return FALSE;
}
} else {
return TRUE;
}
-@@ -4159,6 +4188,7 @@ status_enter(struct view *view, struct line *line)
+@@ -4159,6 +4191,7 @@ status_enter(struct view *view, struct line *line)
}
stage_line_type = line->type;
string_format(VIEW(REQ_VIEW_STAGE)->ref, info, stage_status.new.name);
}
-@@ -4303,11 +4333,14 @@ status_update(struct view *view)
+@@ -4303,11 +4336,14 @@ status_update(struct view *view)
return FALSE;
}
}
return TRUE;
-@@ -4545,6 +4578,18 @@ stage_update(struct view *view, struct line *line)
+@@ -4545,6 +4581,18 @@ stage_update(struct view *view, struct line *line)
return FALSE;
}
} else if (!status_update_file(&stage_status, stage_line_type)) {
report("Failed to update file");
return FALSE;
-@@ -4553,14 +4598,60 @@ stage_update(struct view *view, struct line *line)
+@@ -4553,14 +4601,60 @@ stage_update(struct view *view, struct line *line)
return TRUE;
}
case REQ_EDIT:
if (!stage_status.new.name[0])
return request;
-@@ -4732,7 +4823,7 @@ draw_rev_graph(struct rev_graph *graph)
+@@ -4732,7 +4826,7 @@ draw_rev_graph(struct rev_graph *graph)
};
enum { DEFAULT, RSHARP, RDIAG, LDIAG };
static struct rev_filler fillers[] = {
{ '`', '.' },
{ '\'', ' ' },
{ '/', ' ' },
-@@ -4741,6 +4832,9 @@ draw_rev_graph(struct rev_graph *graph)
+@@ -4741,6 +4835,9 @@ draw_rev_graph(struct rev_graph *graph)
struct rev_filler *filler;
size_t i;
filler = &fillers[DEFAULT];
for (i = 0; i < graph->pos; i++) {
-@@ -4824,100 +4918,54 @@ update_rev_graph(struct rev_graph *graph)
+@@ -4824,100 +4921,54 @@ update_rev_graph(struct rev_graph *graph)
*/
static bool
- if (type != LINE_CURSOR)
- wattrset(view->win, A_NORMAL);
+ if (opt_author &&
-+ draw_field(view, LINE_MAIN_AUTHOR, commit->author, AUTHOR_COLS, TRUE))
++ draw_field(view, LINE_MAIN_AUTHOR, commit->author, opt_author_cols, TRUE))
+ return TRUE;
- wmove(view->win, lineno, col);
return TRUE;
}
-@@ -5061,10 +5109,26 @@ main_request(struct view *view, enum request request, struct line *line)
+@@ -4932,6 +4983,14 @@ main_read(struct view *view, char *line)
+ if (!line) {
+ if (!view->lines && !view->parent)
+ die("No revisions match the given arguments.");
++ if (view->lines > 0) {
++ commit = view->line[view->lines - 1].data;
++ if (!*commit->author) {
++ view->lines--;
++ free(commit);
++ graph->commit = NULL;
++ }
++ }
+ update_rev_graph(graph);
+ return TRUE;
+ }
+@@ -5061,10 +5120,26 @@ main_request(struct view *view, enum request request, struct line *line)
}
static bool
char buf[DATE_COLS + 1];
regmatch_t pmatch;
-@@ -5073,13 +5137,24 @@ main_grep(struct view *view, struct line *line)
+@@ -5073,13 +5148,24 @@ main_grep(struct view *view, struct line *line)
switch (state) {
case S_TITLE: text = commit->title; break;
default:
return FALSE;
}
-@@ -5216,13 +5291,14 @@ utf8_to_unicode(const char *string, size_t length)
+@@ -5216,13 +5302,14 @@ utf8_to_unicode(const char *string, size_t length)
*
* Returns the number of bytes to output from string to satisfy max_width. */
static size_t
*trimmed = 0;
while (string < end) {
-@@ -5243,17 +5319,20 @@ utf8_length(const char *string, size_t max_width, int *trimmed, bool reserve)
+@@ -5243,17 +5330,20 @@ utf8_length(const char *string, size_t max_width, int *trimmed, bool reserve)
break;
ucwidth = unicode_width(unicode);
}
return string - start;
-@@ -5365,6 +5444,11 @@ init_display(void)
+@@ -5365,6 +5455,11 @@ init_display(void)
/* Enable keyboard mapping */
keypad(status_win, TRUE);
wbkgdset(status_win, get_line_attr(LINE_STATUS));
}
static char *
+@@ -5773,11 +5868,12 @@ main(int argc, char *argv[])
+ if (load_git_config() == ERR)
+ die("Failed to load repo config.");
+
+- if (!parse_options(argc, argv))
++ request = parse_options(argc, argv);
++ if (request == REQ_NONE)
+ return 0;
+
+ /* Require a git repository unless when running in pager mode. */
+- if (!opt_git_dir[0] && opt_request != REQ_VIEW_PAGER)
++ if (!opt_git_dir[0] && request != REQ_VIEW_PAGER)
+ die("Not a git repository");
+
+ if (*opt_encoding && strcasecmp(opt_encoding, "UTF-8"))
+@@ -5795,8 +5891,6 @@ main(int argc, char *argv[])
+ for (i = 0; i < ARRAY_SIZE(views) && (view = &views[i]); i++)
+ view->cmd_env = getenv(view->cmd_env);
+
+- request = opt_request;
+-
+ init_display();
+
+ while (view_driver(display[current_view], request)) {
+@@ -5827,11 +5921,13 @@ main(int argc, char *argv[])
+
+ if (cmd && string_format(opt_cmd, "git %s", cmd)) {
+ if (strncmp(cmd, "show", 4) && isspace(cmd[4])) {
+- opt_request = REQ_VIEW_DIFF;
++ request = REQ_VIEW_DIFF;
+ } else {
+- opt_request = REQ_VIEW_PAGER;
++ request = REQ_VIEW_PAGER;
+ }
+- break;
++
++ /* Always reload^Wrerun commands from the prompt. */
++ open_view(view, request, OPEN_RELOAD);
+ }
+
+ request = REQ_NONE;
diff --git a/tigrc.5.txt b/tigrc.5.txt
-index 369fc65..00fd186 100644
+index 369fc65..471aab3 100644
--- a/tigrc.5.txt
+++ b/tigrc.5.txt
-@@ -47,6 +47,7 @@ set show-date = yes # Show commit date?
+@@ -47,6 +47,8 @@ set show-date = yes # Show commit date?
set show-rev-graph = yes # Show revision graph?
set show-refs = yes # Show references?
set show-line-numbers = no # Show line numbers?
++set author-width = 10 # Set width of the author column
+set line-graphics = no # Disable graphics characters
set line-number-interval = 5 # Interval between line numbers
set tab-size = 8 # Number of spaces per tab
set encoding = "UTF-8" # Commit encoding
-@@ -81,6 +82,10 @@ The following variables can be set:
+@@ -81,6 +83,14 @@ The following variables can be set:
(branches, tags, and remotes) in the main view on start-up. Can all be
toggled.
++'author-width' (int)::
++
++ Width of the author column.
++
+'line-graphics' (bool)::
+
+ Whether to use graphic characters for line drawing.
'line-number-interval' (int)::
Interval between line numbers. Note, you have to toggle on line
-@@ -259,6 +264,7 @@ toggle-rev-graph Toggle revision graph visualization
+@@ -259,6 +269,7 @@ toggle-rev-graph Toggle revision graph visualization
toggle-refs Toggle reference display
status-update Update file status
status-merge Resolve unmerged file
tree-parent Switch to parent directory in tree view
edit Open in editor
------------------------------------------------------------------------------
-@@ -343,6 +349,7 @@ Main view colors:
+@@ -343,6 +354,7 @@ Main view colors:
------------------------------------------------------------------------------
main-author The commit author.
main-revgraph The revision graph.
main-head Label of the current branch.
main-remote Label of a remote.
main-tracked Label of the remote tracked by the current branch.
-@@ -431,4 +438,4 @@ Licensed under the terms of the GNU General Public License.
+@@ -431,4 +443,4 @@ Licensed under the terms of the GNU General Public License.
SEE ALSO
--------