lib/colors: allow to temporary disable colors

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2014-04-30 14:51:46 +02:00
parent 570b32100f
commit e66a662726
3 changed files with 82 additions and 31 deletions

View File

@ -727,7 +727,7 @@ static int ui_init(struct cfdisk *cf __attribute__((__unused__)))
init_pair(i, color_pairs[i][0], color_pairs[i][1]); init_pair(i, color_pairs[i][0], color_pairs[i][1]);
} }
#else #else
colors_init(UL_COLORMODE_NEVER, "cfdisk"); colors_off();
#endif #endif
cbreak(); cbreak();

View File

@ -57,6 +57,11 @@ extern int colors_init(int mode, const char *util_name);
/* Returns 1 or 0 */ /* Returns 1 or 0 */
extern int colors_wanted(void); extern int colors_wanted(void);
/* temporary enable/disable colors */
extern void colors_off(void);
extern void colors_on(void);
/* Set the color to CLR_SCHEME */ /* Set the color to CLR_SCHEME */
extern void color_fenable(const char *clr_scheme, FILE *f); extern void color_fenable(const char *clr_scheme, FILE *f);
@ -73,6 +78,7 @@ static inline void color_disable(void)
color_fdisable(stdout); color_fdisable(stdout);
} }
extern const char *colorscheme_from_string(const char *str); extern const char *colorscheme_from_string(const char *str);

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2012 Ondrej Oprala <ooprala@redhat.com> * Copyright (C) 2012 Ondrej Oprala <ooprala@redhat.com>
* Copyright (C) 2014 Karel Zak <kzak@redhat.com>
* *
* This file may be distributed under the terms of the * This file may be distributed under the terms of the
* GNU Lesser General Public License. * GNU Lesser General Public License.
@ -14,6 +15,9 @@
#include "xalloc.h" #include "xalloc.h"
#include "pathnames.h" #include "pathnames.h"
/*
* terminal-colors.d file types
*/
enum { enum {
UL_COLORFILE_DISABLE, /* .disable */ UL_COLORFILE_DISABLE, /* .disable */
UL_COLORFILE_ENABLE, /* .enable */ UL_COLORFILE_ENABLE, /* .enable */
@ -22,6 +26,20 @@ enum {
__UL_COLORFILE_COUNT __UL_COLORFILE_COUNT
}; };
/*
* Global colors control struct
*
* The terminal-colors.d/ evaluation is based on "scores":
*
* filename score
* ---------------------------------------
* type 1
* @termname.type 10 + 1
* utilname.type 20 + 1
* utilname@termname.type 20 + 10 + 1
*
* the match with higher score wins. The score is per type.
*/
struct ul_color_ctl { struct ul_color_ctl {
const char *utilname; /* util name */ const char *utilname; /* util name */
const char *termname; /* terminal name ($TERM) */ const char *termname; /* terminal name ($TERM) */
@ -29,13 +47,18 @@ struct ul_color_ctl {
char *scheme; /* path to scheme */ char *scheme; /* path to scheme */
int mode; /* UL_COLORMODE_* */ int mode; /* UL_COLORMODE_* */
int use_colors; /* based on mode and scores[] */ unsigned int has_colors : 1, /* based on mode and scores[] */
int scores[__UL_COLORFILE_COUNT]; disabled : 1, /* disable colors */
configured : 1; /* terminal-colors.d parsed */
int scores[__UL_COLORFILE_COUNT]; /* the best match */
}; };
static struct ul_color_ctl ul_colors; static struct ul_color_ctl ul_colors;
/*
* Reset control struct (note that we don't allocate the struct)
*/
static void colors_reset(struct ul_color_ctl *cc) static void colors_reset(struct ul_color_ctl *cc)
{ {
if (!cc) if (!cc)
@ -79,6 +102,9 @@ static void colors_debug(struct ul_color_ctl *cc)
#endif #endif
/*
* Parses [[<utilname>][@<termname>].]<type>
*/
static int filename_to_tokens(const char *str, static int filename_to_tokens(const char *str,
const char **name, size_t *namesz, const char **name, size_t *namesz,
const char **term, size_t *termsz, const char **term, size_t *termsz,
@ -123,16 +149,10 @@ static int filename_to_tokens(const char *str,
return 0; return 0;
} }
/* /*
* Checks for: * Scans @dirname and select the best matches for UL_COLORFILE_* types.
* * The result is stored to cc->scores. The path to the best "scheme"
* filename score * file is stored to cc->scheme.
* ---------------------------------
* type 1
* @termname.type 10 + 1
* utilname.type 20 + 1
* utilname@termname.type 20 + 10 + 1
*/ */
static int colors_readdir(struct ul_color_ctl *cc, const char *dirname) static int colors_readdir(struct ul_color_ctl *cc, const char *dirname)
{ {
@ -205,11 +225,15 @@ static int colors_readdir(struct ul_color_ctl *cc, const char *dirname)
return rc; return rc;
} }
/* atexit() wrapper */
static void colors_deinit(void) static void colors_deinit(void)
{ {
colors_reset(&ul_colors); colors_reset(&ul_colors);
} }
/*
* Returns path to $XDG_CONFIG_HOME/terminal-colors.d
*/
static char *colors_get_homedir(char *buf, size_t bufsz) static char *colors_get_homedir(char *buf, size_t bufsz)
{ {
char *p = getenv("XDG_CONFIG_HOME"); char *p = getenv("XDG_CONFIG_HOME");
@ -228,6 +252,27 @@ static char *colors_get_homedir(char *buf, size_t bufsz)
return NULL; return NULL;
} }
static int colors_read_configuration(struct ul_color_ctl *cc)
{
int rc = -ENOENT;
char *dirname, buf[PATH_MAX];
cc->termname = getenv("TERM");
dirname = colors_get_homedir(buf, sizeof(buf));
if (dirname)
rc = colors_readdir(cc, dirname); /* ~/.config */
if (rc == -EPERM || rc == -EACCES || rc == -ENOENT)
rc = colors_readdir(cc, _PATH_TERMCOLORS_DIR); /* /etc */
cc->configured = 1;
return rc;
}
/*
* Initialize private color control struct, @mode is UL_COLORMODE_*
* and @name is util argv[0]
*/
int colors_init(int mode, const char *name) int colors_init(int mode, const char *name)
{ {
int atty = -1; int atty = -1;
@ -237,17 +282,7 @@ int colors_init(int mode, const char *name)
cc->mode = mode; cc->mode = mode;
if (mode == UL_COLORMODE_UNDEF && (atty = isatty(STDOUT_FILENO))) { if (mode == UL_COLORMODE_UNDEF && (atty = isatty(STDOUT_FILENO))) {
int rc = -ENOENT; int rc = colors_read_configuration(cc);
char *dirname, buf[PATH_MAX];
cc->termname = getenv("TERM");
dirname = colors_get_homedir(buf, sizeof(buf));
if (dirname)
rc = colors_readdir(cc, dirname); /* ~/.config */
if (rc == -EPERM || rc == -EACCES || rc == -ENOENT)
rc = colors_readdir(cc, _PATH_TERMCOLORS_DIR); /* /etc */
if (rc) if (rc)
cc->mode = UL_COLORMODE_AUTO; cc->mode = UL_COLORMODE_AUTO;
else { else {
@ -264,32 +299,42 @@ int colors_init(int mode, const char *name)
switch (cc->mode) { switch (cc->mode) {
case UL_COLORMODE_AUTO: case UL_COLORMODE_AUTO:
cc->use_colors = atty == -1 ? isatty(STDOUT_FILENO) : atty; cc->has_colors = atty == -1 ? isatty(STDOUT_FILENO) : atty;
break; break;
case UL_COLORMODE_ALWAYS: case UL_COLORMODE_ALWAYS:
cc->use_colors = 1; cc->has_colors = 1;
break; break;
case UL_COLORMODE_NEVER: case UL_COLORMODE_NEVER:
default: default:
cc->use_colors = 0; cc->has_colors = 0;
} }
return cc->use_colors; return cc->has_colors;
}
void colors_off(void)
{
ul_colors.disabled = 1;
}
void colors_on(void)
{
ul_colors.disabled = 0;
} }
int colors_wanted(void) int colors_wanted(void)
{ {
return ul_colors.use_colors; return !ul_colors.disabled && ul_colors.has_colors;
} }
void color_fenable(const char *color_scheme, FILE *f) void color_fenable(const char *color_scheme, FILE *f)
{ {
if (ul_colors.use_colors && color_scheme) if (!ul_colors.disabled && ul_colors.has_colors && color_scheme)
fputs(color_scheme, f); fputs(color_scheme, f);
} }
void color_fdisable(FILE *f) void color_fdisable(FILE *f)
{ {
if (ul_colors.use_colors) if (!ul_colors.disabled && ul_colors.has_colors)
fputs(UL_COLOR_RESET, f); fputs(UL_COLOR_RESET, f);
} }