War on whitespace: first, a bit of retreat.

This introduces core.whitespace configuration variable that lets
you specify the definition of "whitespace error".

Currently there are two kinds of whitespace errors defined:

 * trailing-space: trailing whitespaces at the end of the line.

 * space-before-tab: a SP appears immediately before HT in the
   indent part of the line.

You can specify the desired types of errors to be detected by
listing their names (unique abbreviations are accepted)
separated by comma.  By default, these two errors are always
detected, as that is the traditional behaviour.  You can disable
detection of a particular type of error by prefixing a '-' in
front of the name of the error, like this:

	[core]
		whitespace = -trailing-space

This patch teaches the code to output colored diff with
DIFF_WHITESPACE color to highlight the detected whitespace
errors to honor the new configuration.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Junio C Hamano 2007-11-02 00:24:27 -07:00
parent e3d6d56f1c
commit a9cc857ada
4 changed files with 70 additions and 5 deletions

View File

@ -602,4 +602,13 @@ extern int diff_auto_refresh_index;
/* match-trees.c */
void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int);
/*
* whitespace rules.
* used by both diff and apply
*/
#define WS_TRAILING_SPACE 01
#define WS_SPACE_BEFORE_TAB 02
#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB)
extern unsigned whitespace_rule;
#endif /* CACHE_H */

View File

@ -246,6 +246,53 @@ static unsigned long get_unit_factor(const char *end)
die("unknown unit: '%s'", end);
}
static struct whitespace_rule {
const char *rule_name;
unsigned rule_bits;
} whitespace_rule_names[] = {
{ "trailing-space", WS_TRAILING_SPACE },
{ "space-before-tab", WS_SPACE_BEFORE_TAB },
};
static unsigned parse_whitespace_rule(const char *string)
{
unsigned rule = WS_DEFAULT_RULE;
while (string) {
int i;
size_t len;
const char *ep;
int negated = 0;
string = string + strspn(string, ", \t\n\r");
ep = strchr(string, ',');
if (!ep)
len = strlen(string);
else
len = ep - string;
if (*string == '-') {
negated = 1;
string++;
len--;
}
if (!len)
break;
for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++) {
if (strncmp(whitespace_rule_names[i].rule_name,
string, len))
continue;
if (negated)
rule &= ~whitespace_rule_names[i].rule_bits;
else
rule |= whitespace_rule_names[i].rule_bits;
break;
}
string = ep;
}
return rule;
}
int git_parse_long(const char *value, long *ret)
{
if (value && *value) {
@ -431,6 +478,11 @@ int git_default_config(const char *var, const char *value)
return 0;
}
if (!strcmp(var, "core.whitespace")) {
whitespace_rule = parse_whitespace_rule(value);
return 0;
}
/* Add other config variables here and to Documentation/config.txt. */
return 0;
}

13
diff.c
View File

@ -508,7 +508,8 @@ static void emit_line_with_ws(int nparents,
for (i = col0; i < len; i++) {
if (line[i] == '\t') {
last_tab_in_indent = i;
if (0 <= last_space_in_indent)
if ((whitespace_rule & WS_SPACE_BEFORE_TAB) &&
0 <= last_space_in_indent)
need_highlight_leading_space = 1;
}
else if (line[i] == ' ')
@ -540,10 +541,12 @@ static void emit_line_with_ws(int nparents,
tail = len - 1;
if (line[tail] == '\n' && i < tail)
tail--;
while (i < tail) {
if (!isspace(line[tail]))
break;
tail--;
if (whitespace_rule & WS_TRAILING_SPACE) {
while (i < tail) {
if (!isspace(line[tail]))
break;
tail--;
}
}
if ((i < tail && line[tail + 1] != '\n')) {
/* This has whitespace between tail+1..len */

View File

@ -35,6 +35,7 @@ int pager_in_use;
int pager_use_color = 1;
char *editor_program;
int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */
unsigned whitespace_rule = WS_DEFAULT_RULE;
/* This is set by setup_git_dir_gently() and/or git_default_config() */
char *git_work_tree_cfg;