The rules are currently hardcoded (the first item has highest priority) - If it's a modified entry, it's bold red. - If it's an executable, it's bold green. - If it's a directory, it's bold blue. Personally I'm happy with just that. But people might want to separate other entries from cached ones in "ls -co", anyone? Signed-off-by: Nguyán ThÃi Ngác Duy <pclouds@xxxxxxxxx> --- Bad bad bad hard coding. builtin/ls-files.c | 59 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 50 insertions(+), 9 deletions(-) diff --git a/builtin/ls-files.c b/builtin/ls-files.c index bc438b2..9c8179a 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -14,6 +14,7 @@ #include "resolve-undo.h" #include "string-list.h" #include "column.h" +#include "color.h" static int abbrev; static int show_deleted; @@ -37,6 +38,7 @@ static int error_unmatch; static char *ps_matched; static const char *with_tree; static int exc_given; +static int use_color; static const char *tag_cached = ""; static const char *tag_unmerged = ""; @@ -50,12 +52,18 @@ static const char *tag_resolve_undo = ""; static struct string_list output; static int column_mode; -static void write_name(const char* name, size_t len) +static void write_name(const char* name, size_t len, const char *color) { /* No quoting in column layout. It will be done by the end. */ if (column_mode & COL_MODE) { struct strbuf sb = STRBUF_INIT; - strbuf_add(&sb, name, len); + if (color && use_color) { + strbuf_addstr(&sb, color); + strbuf_add(&sb, name, len); + strbuf_addstr(&sb, GIT_COLOR_RESET); + } + else + strbuf_add(&sb, name, len); string_list_append(&output, strbuf_detach(&sb, NULL)); return; } @@ -81,16 +89,29 @@ static const char *path_too_deep(const char *name) return strchr(name + common, '/'); } +static int ansi_length(const char *s) +{ + const char *p = s; + while (p[0] == '\033') + p += strspn(p + 2, "0123456789;") + 3; + return p - s; +} + static int already_shown(const char *name) { const char *last_item; - int len; + int len, ansi_len; if (!output.nr) return 0; last_item = output.items[output.nr-1].string; len = strlen(last_item); + ansi_len = ansi_length(last_item); + if (ansi_len) { + last_item += ansi_len; + len -= ansi_len + strlen(GIT_COLOR_RESET); + } return !strncmp(last_item, name, len) && name[len] == '/'; } @@ -98,6 +119,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent) { int len = max_prefix_len; const char *too_deep; + struct stat st; if (len >= ent->len) die("git ls-files: internal error - directory entry not superset of prefix"); @@ -111,7 +133,9 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent) len = too_deep ? too_deep - ent->name : ent->len; fputs(tag, stdout); - write_name(ent->name, len); + write_name(ent->name, len, + len < ent->len ? GIT_COLOR_BOLD_BLUE : + (!stat(ent->name, &st) && st.st_mode & S_IXUSR ? GIT_COLOR_BOLD_GREEN : NULL)); } static void show_other_files(struct dir_struct *dir) @@ -179,6 +203,7 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce) { int len = max_prefix_len; const char *too_deep; + struct stat st; int namelen; if (len >= ce_namelen(ce)) @@ -218,7 +243,10 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce) find_unique_abbrev(ce->sha1,abbrev), ce_stage(ce)); } - write_name(ce->name, namelen); + write_name(ce->name, namelen, + namelen < ce_namelen(ce) ? GIT_COLOR_BOLD_BLUE : + (!stat(ce->name, &st) && ce_modified(ce, &st, 0) ? GIT_COLOR_BOLD_RED : + (ce_permissions(ce->ce_mode) == 0755 ? GIT_COLOR_BOLD_GREEN : NULL))); if (debug_mode) { printf(" ctime: %d:%d\n", ce->ce_ctime.sec, ce->ce_ctime.nsec); printf(" mtime: %d:%d\n", ce->ce_mtime.sec, ce->ce_mtime.nsec); @@ -251,7 +279,7 @@ static void show_ru_info(void) printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i], find_unique_abbrev(ui->sha1[i], abbrev), i + 1); - write_name(path, len); + write_name(path, len, NULL); } } } @@ -676,6 +704,16 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) return 0; } +static int ls_config(const char *var, const char *value, void *cb) +{ + if (!strcmp(var, "color.ls")) + use_color = git_config_colorbool(var, value, -1); + else + return git_color_default_config(var, value, cb); + + return 0; +} + static int one_match_pathspec(const char *pathspec) { struct stat st; @@ -724,11 +762,13 @@ static void remove_common_prefix() */ s1 = output.items[output.nr-1].string; - len = strlen(s1); + len = strlen(s1) - ansi_length(s1); for (i = 1; i < output.nr; i++) { int j = 0; s1 = output.items[i-1].string; + s1 += ansi_length(s1); s2 = output.items[i].string; + s2 += ansi_length(s2); while (j < len && s1[j] == s2[j]) j++; len = j; @@ -740,6 +780,7 @@ static void remove_common_prefix() if (len) { for (i = 0; i < output.nr; i++) { char *s = output.items[i].string; + s += ansi_length(s); memcpy(s, s+len, strlen(s) - len + 1); } } @@ -778,12 +819,12 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix) prefix = cmd_prefix; if (prefix) prefix_len = strlen(prefix); - git_config(git_default_config, NULL); + git_config(ls_config, NULL); if (read_cache() < 0) die("index file corrupt"); - column_mode = core_column; + column_mode = core_column | COL_ANSI; argc = parse_options(argc, argv, prefix, builtin_ls_files_options, ls_files_usage, 0); @@ -793,7 +834,7 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix) pathspecs = get_pathspec(prefix, argv); - if (show_modified) + if (show_modified || use_color) refresh_index(&the_index, REFRESH_QUIET, pathspecs, NULL, NULL); if (!pathspecs) { -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html