Code

Add support for 256 colors by allowing "colorN" names similar to Mutt
[tig.git] / tig.c
diff --git a/tig.c b/tig.c
index d99307e5fdd4cfcba86cf181f47e5fc2206d0273..79afdb1a11f8ab83dba1b7129c21b102fb42533a 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -676,20 +676,24 @@ io_write(struct io *io, const void *buf, size_t bufsize)
 }
 
 static bool
-run_io_buf(const char **argv, char buf[], size_t bufsize)
+io_read_buf(struct io *io, char buf[], size_t bufsize)
 {
-       struct io io = {};
        bool error;
 
-       if (!run_io_rd(&io, argv, FORMAT_NONE))
-               return FALSE;
+       io->buf = io->bufpos = buf;
+       io->bufalloc = bufsize;
+       error = !io_get(io, '\n', TRUE) && io_error(io);
+       io->buf = NULL;
+
+       return done_io(io) || error;
+}
 
-       io.buf = io.bufpos = buf;
-       io.bufalloc = bufsize;
-       error = !io_get(&io, '\n', TRUE) && io_error(&io);
-       io.buf = NULL;
+static bool
+run_io_buf(const char **argv, char buf[], size_t bufsize)
+{
+       struct io io = {};
 
-       return done_io(&io) || error;
+       return run_io_rd(&io, argv, FORMAT_NONE) && io_read_buf(&io, buf, bufsize);
 }
 
 static int
@@ -1384,9 +1388,28 @@ static struct enum_map attr_map[] = {
        ATTR_MAP(UNDERLINE),
 };
 
-#define set_color(color, name)         map_enum(color, color_map, name)
 #define set_attribute(attr, name)      map_enum(attr, attr_map, name)
 
+static int
+parse_int(int *opt, const char *arg, int min, int max)
+{
+       int value = atoi(arg);
+
+       if (min <= value && value <= max)
+               *opt = value;
+       return OK;
+}
+
+static bool
+set_color(int *color, const char *name)
+{
+       if (map_enum(color, color_map, name))
+               return TRUE;
+       if (!prefixcmp(name, "color"))
+               return parse_int(color, name + 5, 0, 255) == OK;
+       return FALSE;
+}
+
 static int   config_lineno;
 static bool  config_errors;
 static const char *config_msg;
@@ -1439,16 +1462,6 @@ static int parse_bool(bool *opt, const char *arg)
        return OK;
 }
 
-static int
-parse_int(int *opt, const char *arg, int min, int max)
-{
-       int value = atoi(arg);
-
-       if (min <= value && value <= max)
-               *opt = value;
-       return OK;
-}
-
 static int
 parse_string(char *opt, const char *arg, size_t optsize)
 {
@@ -1659,11 +1672,8 @@ load_options(void)
 
        add_builtin_run_requests();
 
-       if (!tigrc_system) {
-               if (!string_format(buf, "%s/tigrc", SYSCONFDIR))
-                       return ERR;
-               tigrc_system = buf;
-       }
+       if (!tigrc_system)
+               tigrc_system = SYSCONFDIR "/tigrc";
        load_option_file(tigrc_system);
 
        if (!tigrc_user) {
@@ -2923,9 +2933,7 @@ add_line_format(struct view *view, enum line_type type, const char *fmt, ...)
 enum open_flags {
        OPEN_DEFAULT = 0,       /* Use default view switching. */
        OPEN_SPLIT = 1,         /* Split current view. */
-       OPEN_BACKGROUNDED = 2,  /* Backgrounded. */
        OPEN_RELOAD = 4,        /* Reload view even if it is the current. */
-       OPEN_NOMAXIMIZE = 8,    /* Do not maximize the current view. */
        OPEN_REFRESH = 16,      /* Refresh view using previous command. */
        OPEN_PREPARED = 32,     /* Open already prepared command. */
 };
@@ -2933,10 +2941,9 @@ enum open_flags {
 static void
 open_view(struct view *prev, enum request request, enum open_flags flags)
 {
-       bool backgrounded = !!(flags & OPEN_BACKGROUNDED);
        bool split = !!(flags & OPEN_SPLIT);
        bool reload = !!(flags & (OPEN_RELOAD | OPEN_REFRESH | OPEN_PREPARED));
-       bool nomaximize = !!(flags & (OPEN_NOMAXIMIZE | OPEN_REFRESH));
+       bool nomaximize = !!(flags & OPEN_REFRESH);
        struct view *view = VIEW(request);
        int nviews = displayed_views();
        struct view *base_view = display[0];
@@ -2953,8 +2960,7 @@ open_view(struct view *prev, enum request request, enum open_flags flags)
 
        if (split) {
                display[1] = view;
-               if (!backgrounded)
-                       current_view = 1;
+               current_view = 1;
        } else if (!nomaximize) {
                /* Maximize the current view. */
                memset(display, 0, sizeof(display));
@@ -2993,7 +2999,7 @@ open_view(struct view *prev, enum request request, enum open_flags flags)
        }
 
        if (prev && view != prev) {
-               if (split && !backgrounded) {
+               if (split) {
                        /* "Blur" the previous view. */
                        update_view_title(prev);
                }
@@ -3011,11 +3017,6 @@ open_view(struct view *prev, enum request request, enum open_flags flags)
                redraw_view(view);
                report("");
        }
-
-       /* If the view is backgrounded the above calls to report()
-        * won't redraw the view title. */
-       if (backgrounded)
-               update_view_title(view);
 }
 
 static void
@@ -3317,6 +3318,22 @@ view_driver(struct view *view, enum request request)
  * View backend utilities
  */
 
+static void
+parse_timezone(time_t *time, const char *zone)
+{
+       long tz;
+
+       tz  = ('0' - zone[1]) * 60 * 60 * 10;
+       tz += ('0' - zone[2]) * 60 * 60;
+       tz += ('0' - zone[3]) * 60;
+       tz += ('0' - zone[4]);
+
+       if (zone[0] == '-')
+               tz = -tz;
+
+       *time -= tz;
+}
+
 /* Parse author lines where the name may be empty:
  *     author  <email@address.tld> 1138474660 +0100
  */
@@ -3344,20 +3361,8 @@ parse_author_line(char *ident, char *author, size_t authorsize, struct tm *tm)
                char *zone = strchr(secs, ' ');
                time_t time = (time_t) atol(secs);
 
-               if (zone && strlen(zone) == STRING_SIZE(" +0700")) {
-                       long tz;
-
-                       zone++;
-                       tz  = ('0' - zone[1]) * 60 * 60 * 10;
-                       tz += ('0' - zone[2]) * 60 * 60;
-                       tz += ('0' - zone[3]) * 60;
-                       tz += ('0' - zone[4]) * 60;
-
-                       if (zone[0] == '-')
-                               tz = -tz;
-
-                       time -= tz;
-               }
+               if (zone && strlen(zone) == STRING_SIZE(" +0700"))
+                       parse_timezone(&time, zone + 1);
 
                gmtime_r(&time, tm);
        }
@@ -4346,17 +4351,7 @@ blame_read(struct view *view, char *line)
                author_time = (time_t) atol(line);
 
        } else if (match_blame_header("author-tz ", &line)) {
-               long tz;
-
-               tz  = ('0' - line[1]) * 60 * 60 * 10;
-               tz += ('0' - line[2]) * 60 * 60;
-               tz += ('0' - line[3]) * 60;
-               tz += ('0' - line[4]) * 60;
-
-               if (line[0] == '-')
-                       tz = -tz;
-
-               author_time -= tz;
+               parse_timezone(&author_time, line);
                gmtime_r(&author_time, &commit->time);
 
        } else if (match_blame_header("summary ", &line)) {
@@ -4720,6 +4715,55 @@ status_restore(struct view *view)
        view->p_restore = FALSE;
 }
 
+static void
+status_update_onbranch(void)
+{
+       static const char *paths[][2] = {
+               { "rebase-apply/rebasing",      "Rebasing" },
+               { "rebase-apply/applying",      "Applying mailbox" },
+               { "rebase-apply/",              "Rebasing mailbox" },
+               { "rebase-merge/interactive",   "Interactive rebase" },
+               { "rebase-merge/",              "Rebase merge" },
+               { "MERGE_HEAD",                 "Merging" },
+               { "BISECT_LOG",                 "Bisecting" },
+               { "HEAD",                       "On branch" },
+       };
+       char buf[SIZEOF_STR];
+       struct stat stat;
+       int i;
+
+       if (is_initial_commit()) {
+               string_copy(status_onbranch, "Initial commit");
+               return;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(paths); i++) {
+               char *head = opt_head;
+
+               if (!string_format(buf, "%s/%s", opt_git_dir, paths[i][0]) ||
+                   lstat(buf, &stat) < 0)
+                       continue;
+
+               if (!*opt_head) {
+                       struct io io = {};
+
+                       if (string_format(buf, "%s/rebase-merge/head-name", opt_git_dir) &&
+                           io_open(&io, buf) &&
+                           io_read_buf(&io, buf, sizeof(buf))) {
+                               head = chomp_string(buf);
+                               if (!prefixcmp(head, "refs/heads/"))
+                                       head += STRING_SIZE("refs/heads/");
+                       }
+               }
+
+               if (!string_format(status_onbranch, "%s %s", paths[i][1], head))
+                       string_copy(status_onbranch, opt_head);
+               return;
+       }
+
+       string_copy(status_onbranch, "Not currently on any branch");
+}
+
 /* First parse staged info using git-diff-index(1), then parse unstaged
  * info using git-diff-files(1), and finally untracked files using
  * git-ls-files(1). */
@@ -4729,12 +4773,7 @@ status_open(struct view *view)
        reset_view(view);
 
        add_line_data(view, NULL, LINE_STAT_HEAD);
-       if (is_initial_commit())
-               string_copy(status_onbranch, "Initial commit");
-       else if (!*opt_head)
-               string_copy(status_onbranch, "Not currently on any branch");
-       else if (!string_format(status_onbranch, "On branch %s", opt_head))
-               return FALSE;
+       status_update_onbranch();
 
        run_io_bg(update_index_argv);
 
@@ -5452,7 +5491,7 @@ stage_request(struct view *view, enum request request, struct line *line)
        }
 
        VIEW(REQ_VIEW_STATUS)->p_restore = TRUE;
-       open_view(view, REQ_VIEW_STATUS, OPEN_RELOAD | OPEN_NOMAXIMIZE);
+       open_view(view, REQ_VIEW_STATUS, OPEN_REFRESH);
 
        /* Check whether the staged entry still exists, and close the
         * stage view if it doesn't. */