/**
* FILES
* -----
- * '~/.tig'::
+ * '~/.tigrc'::
* User configuration file. See "<<config-options, Configuration options>>"
* section for examples.
*
* [[config-options]]
* User Configuration file
* -----------------------
- * You can permanently set an option by putting it in the `~/.tig` file.
+ * You can permanently set an option by putting it in the `~/.tigrc` file.
* The file consists of a series of 'commands'. Each
* line of the file may contain only one command.
*
* All text after the comment character to the end of the line is ignored.
* You can use comments to annotate your initialization file.
*
- * Configuration Commands
- * ~~~~~~~~~~~~~~~~~~~~~~
+ * Some sample options:
*
- * --
- *
- * *color* object fgcolor bgcolor [attributes]::
+ * ==========================================================================
+ * # Diff colors
+ * color diff-header yellow default
+ * color diff-index blue default
+ * color diff-chunk magenta default
+ * # UI colors
+ * color title-blur white blue
+ * color title-focus white blue bold
+ * ==========================================================================
*
+ * [[color-options]]
+ * Color options
+ * ~~~~~~~~~~~~~
+ * Color options control highlighting and the user interface styles.
* If your terminal supports color, these commands can be used to assign
- * foreground/backgound combinations to certain objects. Optionally, an
- * attribute can be given as the last parameter.
+ * foreground/backgound combinations to certain areas. Optionally, an
+ * attribute can be given as the last parameter. The syntax is:
*
- * Valid objects are described in the "<<color-objs, Color objects>>" section
- * below. Note, object names are case-insensitive, and you may use '-', '_',
- * and '.' interchangeably. So "Diff-Header", "DIFF_HEADER", and "diff.header"
- * are the same.
+ * [verse]
+ * ..........................................................................
+ * *color* 'area' 'fgcolor' 'bgcolor' '[attributes]'
+ * ..........................................................................
*
- * Valid colors include: 'white', 'black', 'green', 'magenta', 'blue', 'cyan',
- * 'yellow', 'red', 'default'. Use 'default' to refer to the default terminal
+ * Valid colors include: *white*, *black*, *green*, *magenta*, *blue*, *cyan*,
+ * *yellow*, *red*, *default*. Use *default* to refer to the default terminal
* colors.
**/
};
/**
- * Valid attributes include: 'normal', 'blink', 'bold', 'dim', 'reverse', 'standout',
- * and 'underline'. Note, not all attributes may be supported by the terminal.
+ * Valid attributes include: *normal*, *blink*, *bold*, *dim*, *reverse*, *standout*,
+ * and *underline*. Note, not all attributes may be supported by the terminal.
**/
static struct int_map attr_map[] = {
};
/**
- * Some example color options:
- *
- * --------------------------------------------------------------------------
- * # Diff colors
- * color diff-header yellow default
- * color diff-index blue default
- * color diff-chunk magenta default
- * # UI colors
- * color title-blur white blue
- * color title-focus white blue bold
- * --------------------------------------------------------------------------
+ * Valid area names are described below. Note, all names are case-insensitive,
+ * and you may use '-', '_', and '.' interchangeably. So "Diff-Header",
+ * "DIFF_HEADER", and "diff.header" are the same.
*
* --
**/
-
-/**
- * [[color-objs]]
- * Color objects
- * ~~~~~~~~~~~~~
- *
- * --
- **/
-
#define LINE_INFO \
/**
* Diff markup::
*
- * Objects concerning diff start, chunks and lines added and deleted.
+ * Options concerning diff start, chunks and lines added and deleted.
*
- * 'diff-header', 'diff-chunk', 'diff-add', 'diff-del'
+ * *diff-header*, *diff-chunk*, *diff-add*, *diff-del*
**/ \
LINE(DIFF_HEADER, "diff --git ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
LINE(DIFF_CHUNK, "@@", COLOR_MAGENTA, COLOR_DEFAULT, 0), \
* Extra diff information emitted by the git diff machinery, such as mode
* changes, rename detection, and similarity.
*
- * 'diff-oldmode', 'diff-newmode', 'diff-copy-from', 'diff-copy-to',
- * 'diff-rename-from', 'diff-rename-to', 'diff-similarity' 'diff-dissimilarity'
- * 'diff-tree', 'diff-index'
+ * *diff-oldmode*, *diff-newmode*, *diff-copy-from*, *diff-copy-to*,
+ * *diff-rename-from*, *diff-rename-to*, *diff-similarity* *diff-dissimilarity*
+ * *diff-tree*, *diff-index*
**/ \
LINE(DIFF_INDEX, "index ", COLOR_BLUE, COLOR_DEFAULT, 0), \
LINE(DIFF_OLDMODE, "old file mode ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
* printed headers , unless `--pretty=raw` was given. This includes lines,
* such as merge info, commit ID, and author and comitter date.
*
- * 'pp-author' 'pp-commit' 'pp-merge' 'pp-date' 'pp-adate' 'pp-cdate'
+ * *pp-author*, *pp-commit*, *pp-merge*, *pp-date*, *pp-adate*, *pp-cdate*
**/ \
LINE(PP_AUTHOR, "Author: ", COLOR_CYAN, COLOR_DEFAULT, 0), \
LINE(PP_COMMIT, "Commit: ", COLOR_MAGENTA, COLOR_DEFAULT, 0), \
* Usually shown when `--pretty=raw` is given, however 'commit' is pretty
* much omnipresent.
*
- * 'commit' 'parent' 'tree' 'author' 'committer'
+ * *commit*, *parent*, *tree*, *author*, *committer*
**/ \
LINE(COMMIT, "commit ", COLOR_GREEN, COLOR_DEFAULT, 0), \
LINE(PARENT, "parent ", COLOR_BLUE, COLOR_DEFAULT, 0), \
*
* For now only `Signed-off-by lines` are colorized.
*
- * 'signoff'
+ * *signoff*
**/ \
LINE(SIGNOFF, " Signed-off-by", COLOR_YELLOW, COLOR_DEFAULT, 0), \
/**
* UI colors::
*
- * Colors for text not matching any of the above: 'default'
+ * Colors for text not matching any of the above: *default*
*
- * Status window colors: 'status'
+ * Status window colors: *status*
*
- * Title window colors: 'title-blur' 'title-focus'
+ * Title window colors: *title-blur*, *title-focus*
*
- * Cursor line colors: 'cursor'
+ * Cursor line colors: *cursor*
*
- * Main view specific: 'main-date' 'main-author' 'main-commit' 'main-delim'
- * 'main-tag' 'main-ref'
+ * Main view specific: *main-date*, *main-author*, *main-commit*, *main-delim*,
+ * *main-tag*, *main-ref*
**/ \
LINE(DEFAULT, "", COLOR_DEFAULT, COLOR_DEFAULT, A_NORMAL), \
LINE(CURSOR, "", COLOR_WHITE, COLOR_GREEN, A_BOLD), \
};
+/*
+ * User config file handling.
+ */
+
#define set_color(color, name, namelen) \
set_from_int_map(color_map, ARRAY_SIZE(color_map), color, name, namelen)
#define set_attribute(attr, name, namelen) \
set_from_int_map(attr_map, ARRAY_SIZE(attr_map), attr, name, namelen)
+static int config_lineno;
+static bool config_errors;
+static char *config_msg;
+
static int
-read_option(char *opt, int optlen, char *value, int valuelen)
+set_option(char *opt, int optlen, char *value, int valuelen)
{
- optlen = strcspn(opt, "#;");
- if (optlen == 0)
- /* The whole line is a comment. */
- return OK;
-
- else if (opt[optlen] != 0)
- /* Part of the option name is a comment, so the value part
- * should be ignored. */
- valuelen = 0;
- else
- /* Else look for comment endings in the value. */
- valuelen = strcspn(value, "#;");
-
- opt[optlen] = value[valuelen] = 0;
-
/* Reads: "color" object fgcolor bgcolor [attr] */
if (!strcmp(opt, "color")) {
struct line_info *info;
value = chomp_string(value);
valuelen = strcspn(value, " \t");
info = get_line_info(value, valuelen);
- if (!info)
+ if (!info) {
+ config_msg = "Unknown color name";
return ERR;
+ }
value = chomp_string(value + valuelen);
valuelen = strcspn(value, " \t");
- if (set_color(&info->fg, value, valuelen) == ERR)
+ if (set_color(&info->fg, value, valuelen) == ERR) {
+ config_msg = "Unknown color";
return ERR;
+ }
value = chomp_string(value + valuelen);
valuelen = strcspn(value, " \t");
- if (set_color(&info->bg, value, valuelen) == ERR)
+ if (set_color(&info->bg, value, valuelen) == ERR) {
+ config_msg = "Unknown color";
return ERR;
+ }
value = chomp_string(value + valuelen);
if (*value &&
- set_attribute(&info->attr, value, strlen(value)) == ERR)
+ set_attribute(&info->attr, value, strlen(value)) == ERR) {
+ config_msg = "Unknown attribute";
return ERR;
+ }
return OK;
}
}
static int
+read_option(char *opt, int optlen, char *value, int valuelen)
+{
+ config_lineno++;
+ config_msg = "Internal error";
+
+ optlen = strcspn(opt, "#;");
+ if (optlen == 0) {
+ /* The whole line is a commend or empty. */
+ return OK;
+
+ } else if (opt[optlen] != 0) {
+ /* Part of the option name is a comment, so the value part
+ * should be ignored. */
+ valuelen = 0;
+ opt[optlen] = value[valuelen] = 0;
+ } else {
+ /* Else look for comment endings in the value. */
+ valuelen = strcspn(value, "#;");
+ value[valuelen] = 0;
+ }
+
+ if (set_option(opt, optlen, value, valuelen) == ERR) {
+ fprintf(stderr, "Error on line %d, near '%.*s' option: %s\n",
+ config_lineno, optlen, opt, config_msg);
+ config_errors = TRUE;
+ }
+
+ /* Always keep going if errors are encountered. */
+ return OK;
+}
+
+static int
load_options(void)
{
char *home = getenv("HOME");
char buf[1024];
FILE *file;
+ config_lineno = 0;
+ config_errors = FALSE;
+
if (!home ||
- snprintf(buf, sizeof(buf), "%s/.tig", home) >= sizeof(buf))
+ snprintf(buf, sizeof(buf), "%s/.tigrc", home) >= sizeof(buf))
return ERR;
/* It's ok that the file doesn't exist. */
if (!file)
return OK;
- return read_properties(file, " \t", read_option);
+ if (read_properties(file, " \t", read_option) == ERR ||
+ config_errors == TRUE)
+ fprintf(stderr, "Errors while loading %s.\n", buf);
+
+ return OK;
}
valuelen = 0;
}
- if (namelen)
- state = read_property(name, namelen, value, valuelen);
+ state = read_property(name, namelen, value, valuelen);
}
if (state != ERR && ferror(pipe))
*
* - Locale support.
*
+ * - Make '?' show a one page keybinding cheat sheet.
+ *
* COPYRIGHT
* ---------
* Copyright (c) 2006 Jonas Fonseca <fonseca@diku.dk>