[pacman-dev] [PATCH 02/11] Add color commands for stuff in util
Daniel Wallace
daniel.wallace at gatech.edu
Sun Aug 5 05:46:38 EDT 2012
Signed-off-by: Daniel Wallace <daniel.wallace at gatech.edu>
---
src/pacman/color.c | 728 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/pacman/color.h | 70 ++++++
src/pacman/util.c | 35 ++-
src/pacman/util.h | 6 +
4 files changed, 830 insertions(+), 9 deletions(-)
create mode 100644 src/pacman/color.c
create mode 100644 src/pacman/color.h
diff --git a/src/pacman/color.c b/src/pacman/color.c
new file mode 100644
index 0000000..d1b2d5e
--- /dev/null
+++ b/src/pacman/color.c
@@ -0,0 +1,728 @@
+/*
+ * util.c
+ *
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev at archlinux.org>
+ * Copyright (c) 2002-2006 by Judd Vinet <jvinet at zeroflux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdint.h> /* intmax_t */
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <limits.h>
+#include <wchar.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h> /* tcflush */
+#endif
+
+#include <alpm.h>
+#include <alpm_list.h>
+
+/* pacman */
+#include "util.h"
+#include "conf.h"
+#include "callback.h"
+#include "color.h"
+
+#define COLOR_LEN 8
+
+typedef struct __colortab_t {
+ char red[COLOR_LEN + 1];
+ char green[COLOR_LEN + 1];
+ char yellow[COLOR_LEN + 1];
+ char blue[COLOR_LEN + 1];
+ char magenta[COLOR_LEN + 1];
+ char cyan[COLOR_LEN + 1];
+ char white[COLOR_LEN + 1];
+ char none[COLOR_LEN + 1];
+} colortab_t;
+
+static colortab_t colortab;
+
+
+void color_list_display(const colordata_t *colors_title, const char *title, const alpm_list_t *list,
+ unsigned short maxcols)
+{
+ const alpm_list_t *i;
+ size_t len = 0;
+
+ if(title) {
+ len = string_length(title) + 1;
+ color_printf(colors_title, "%s ", title);
+ }
+
+ if(!list) {
+ printf("%s\n", _("None"));
+ } else {
+ size_t cols = len;
+ const char *str = list->data;
+ fputs(str, stdout);
+ cols += string_length(str);
+ for(i = alpm_list_next(list); i; i = alpm_list_next(i)) {
+ str = i->data;
+ size_t s = string_length(str);
+ /* wrap only if we have enough usable column space */
+ if(maxcols > len && cols + s + 2 >= maxcols) {
+ size_t j;
+ cols = len;
+ printf("\n");
+ for(j = 1; j <= len; j++) {
+ printf(" ");
+ }
+ } else if(cols != len) {
+ /* 2 spaces are added if this is not the first element on a line. */
+ printf(" ");
+ cols += 2;
+ }
+ fputs(str, stdout);
+ cols += s;
+ }
+ putchar('\n');
+ }
+}
+
+void color_list_display_linebreak(const colordata_t *colors_title, const char *title, const alpm_list_t *list,
+ unsigned short maxcols)
+{
+ unsigned short len = 0;
+
+ if(title) {
+ len = (unsigned short)string_length(title) + 1;
+ color_printf(colors_title, "%s ", title);
+ }
+
+ if(!list) {
+ printf("%s\n", _("None"));
+ } else {
+ const alpm_list_t *i;
+ /* Print the first element */
+ indentprint((const char *)list->data, len, maxcols);
+ printf("\n");
+ /* Print the rest */
+ for(i = alpm_list_next(list); i; i = alpm_list_next(i)) {
+ size_t j;
+ for(j = 1; j <= len; j++) {
+ printf(" ");
+ }
+ indentprint((const char *)i->data, len, maxcols);
+ printf("\n");
+ }
+ }
+}
+
+/* prepare a list of pkgs to display */
+void _color_display_targets(alpm_list_t *targets, int verbose)
+{
+ char *str;
+ const char *label;
+ double size;
+ off_t isize = 0, rsize = 0, dlsize = 0;
+ unsigned short cols;
+ alpm_list_t *i, *rows = NULL, *names = NULL;
+
+ if(!targets) {
+ return;
+ }
+
+ /* gather package info */
+ for(i = targets; i; i = alpm_list_next(i)) {
+ pm_target_t *target = i->data;
+
+ if(target->install) {
+ dlsize += alpm_pkg_download_size(target->install);
+ isize += alpm_pkg_get_isize(target->install);
+ }
+ if(target->remove) {
+ /* add up size of all removed packages */
+ rsize += alpm_pkg_get_isize(target->remove);
+ }
+ }
+
+ /* form data for both verbose and non-verbose display */
+ for(i = targets; i; i = alpm_list_next(i)) {
+ pm_target_t *target = i->data;
+
+ rows = alpm_list_add(rows, create_verbose_row(target));
+ if(target->install) {
+ pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(target->install),
+ alpm_pkg_get_version(target->install));
+ } else if(isize == 0) {
+ pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(target->remove),
+ alpm_pkg_get_version(target->remove));
+ } else {
+ pm_asprintf(&str, "%s-%s [removal]", alpm_pkg_get_name(target->remove),
+ alpm_pkg_get_version(target->remove));
+ }
+ names = alpm_list_add(names, str);
+ }
+
+ /* print to screen */
+ pm_asprintf(&str, _("Targets (%d):"), alpm_list_count(targets));
+ printf("\n");
+
+ cols = getcols(fileno(stdout));
+ if(verbose) {
+ alpm_list_t *header = create_verbose_header();
+ if(table_display(str, header, rows, cols) != 0) {
+ /* fallback to list display if table wouldn't fit */
+ color_list_display(COLOR_YELLOW_ALL, str, names, cols);
+ }
+ alpm_list_free(header);
+ } else {
+ color_list_display(COLOR_YELLOW_ALL, str, names, cols);
+ }
+ printf("\n");
+
+ /* rows is a list of lists of strings, free inner lists here */
+ for(i = rows; i; i = alpm_list_next(i)) {
+ alpm_list_t *lp = i->data;
+ FREELIST(lp);
+ }
+ alpm_list_free(rows);
+ FREELIST(names);
+ free(str);
+
+ if(dlsize > 0 || config->op_s_downloadonly) {
+ size = humanize_size(dlsize, 'M', 2, &label);
+ color_printf(COLOR_WHITE_COLON, _("Total Download Size: %.2f %s\n"), size, label);
+ }
+ if(!config->op_s_downloadonly) {
+ if(isize > 0) {
+ size = humanize_size(isize, 'M', 2, &label);
+ color_printf(COLOR_WHITE_COLON, _("Total Installed Size: %.2f %s\n"), size, label);
+ }
+ if(rsize > 0 && isize == 0) {
+ size = humanize_size(rsize, 'M', 2, &label);
+ color_printf(COLOR_WHITE_COLON, _("Total Removed Size: %.2f %s\n"), size, label);
+ }
+ /* only show this net value if different from raw installed size */
+ if(isize > 0 && rsize > 0) {
+ size = humanize_size(isize - rsize, 'M', 2, &label);
+ color_printf(COLOR_WHITE_COLON, _("Net Upgrade Size: %.2f %s\n"), size, label);
+ }
+ }
+}
+void color_display_repo_list(const char *dbname, alpm_list_t *list,
+ unsigned short cols)
+{
+ const char *prefix= " ";
+
+ color_printf(COLOR_BLUE_ALL, ":: ");
+ color_printf(COLOR_WHITE_ALL, _("Repository %s\n"), dbname);
+ color_list_display(NULL, prefix, list, cols);
+}
+
+/* presents a prompt and gets a Y/N answer */
+static int color_question(const colordata_t *colors, short preset, char *fmt, va_list args)
+{
+ char response[32];
+ FILE *stream;
+
+ if(config->noconfirm) {
+ stream = stdout;
+ } else {
+ /* Use stderr so questions are always displayed when redirecting output */
+ stream = stderr;
+ }
+
+ /* ensure all text makes it to the screen before we prompt the user */
+ fflush(stdout);
+ fflush(stderr);
+
+ color_vfprintf(stream, colors, fmt, args);
+
+ if(preset) {
+ fprintf(stream, " %s ", _("[Y/n]"));
+ } else {
+ fprintf(stream, " %s ", _("[y/N]"));
+ }
+
+ if(config->noconfirm) {
+ fprintf(stream, "\n");
+ return preset;
+ }
+
+ fflush(stream);
+ flush_term_input(fileno(stdin));
+
+ if(fgets(response, sizeof(response), stdin)) {
+ strtrim(response);
+ if(strlen(response) == 0) {
+ return preset;
+ }
+
+ /* if stdin is piped, response does not get printed out, and as a result
+ * a \n is missing, resulting in broken output (FS#27909) */
+ if(!isatty(fileno(stdin))) {
+ fprintf(stream, "%s\n", response);
+ }
+
+ if(strcasecmp(response, _("Y")) == 0 || strcasecmp(response, _("YES")) == 0) {
+ return 1;
+ } else if(strcasecmp(response, _("N")) == 0 || strcasecmp(response, _("NO")) == 0) {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int color_yesno(const colordata_t *colors, char *fmt, ...)
+{
+ int ret;
+ va_list args;
+
+ va_start(args, fmt);
+ ret = color_question(colors, 1, fmt, args);
+ va_end(args);
+
+ return ret;
+}
+
+int color_noyes(const colordata_t *colors, char *fmt, ...)
+{
+ int ret;
+ va_list args;
+
+ va_start(args, fmt);
+ ret = color_question(colors, 0, fmt, args);
+ va_end(args);
+
+ return ret;
+}
+
+int color_pm_vasprintf(char **string, alpm_loglevel_t level, const char *format, va_list args)
+{
+ int ret = 0;
+ char *msg = NULL;
+
+ /* if current logmask does not overlap with level, do not print msg */
+ if(!(config->logmask & level)) {
+ return ret;
+ }
+
+ /* print the message using va_arg list */
+ ret = vasprintf(&msg, format, args);
+
+ /* print a prefix to the message */
+ if(isatty(fileno(stdout))) {
+ switch(level) {
+ case ALPM_LOG_ERROR:
+ pm_asprintf(string, "%s%s%s%s", colortab.red, _("error: "), colortab.none, msg);
+ break;
+ case ALPM_LOG_WARNING:
+ pm_asprintf(string, "%s%s%s%s", colortab.yellow, _("warning: "), colortab.none, msg);
+ break;
+ case ALPM_LOG_DEBUG:
+ pm_asprintf(string, "debug: %s", msg);
+ break;
+ case ALPM_LOG_FUNCTION:
+ pm_asprintf(string, "function: %s", msg);
+ break;
+ default:
+ pm_asprintf(string, "%s", msg);
+ break;
+ }
+ } else {
+ switch(level) {
+ case ALPM_LOG_ERROR:
+ pm_asprintf(string, _("error: %s"), msg);
+ break;
+ case ALPM_LOG_WARNING:
+ pm_asprintf(string, _("warning: %s"), msg);
+ break;
+ case ALPM_LOG_DEBUG:
+ pm_asprintf(string, "debug: %s", msg);
+ break;
+ case ALPM_LOG_FUNCTION:
+ pm_asprintf(string, "function: %s", msg);
+ break;
+ default:
+ pm_asprintf(string, "%s", msg);
+ break;
+ }
+ }
+ free(msg);
+
+ return ret;
+}
+
+int color_pm_vfprintf(FILE *stream, alpm_loglevel_t level, const char *format, va_list args)
+{
+ int ret = 0;
+
+ /* if current logmask does not overlap with level, do not print msg */
+ if(!(config->logmask & level)) {
+ return ret;
+ }
+
+#if defined(PACMAN_DEBUG)
+ /* If debug is on, we'll timestamp the output */
+ if(config->logmask & ALPM_LOG_DEBUG) {
+ time_t t;
+ struct tm *tmp;
+ char timestr[10] = {0};
+
+ t = time(NULL);
+ tmp = localtime(&t);
+ strftime(timestr, 9, "%H:%M:%S", tmp);
+ timestr[8] = '\0';
+
+ fprintf(stream, "[%s] ", timestr);
+ }
+#endif
+
+ /* print a prefix to the message */
+ switch(level) {
+ case ALPM_LOG_ERROR:
+ color_fprintf(stream, COLOR_RED_ALL, _("error: "));
+ break;
+ case ALPM_LOG_WARNING:
+ color_fprintf(stream, COLOR_YELLOW_ALL, _("warning: "));
+ break;
+ case ALPM_LOG_DEBUG:
+ fprintf(stream, "debug: ");
+ break;
+ case ALPM_LOG_FUNCTION:
+ fprintf(stream, "function: ");
+ break;
+ default:
+ break;
+ }
+
+ /* print the message using va_arg list */
+ ret = vfprintf(stream, format, args);
+ return ret;
+}
+
+/* pacman-color */
+
+int _set_color_sequence(const char* name, char* dest)
+{
+ int ret = 0;
+
+ if(strcmp(name, "black") == 0) {
+ strncpy(dest, "\033[0;30m", COLOR_LEN);
+ } else if(strcmp(name, "red") == 0) {
+ strncpy(dest, "\033[0;31m", COLOR_LEN);
+ } else if(strcmp(name, "green") == 0) {
+ strncpy(dest, "\033[0;32m", COLOR_LEN);
+ } else if(strcmp(name, "yellow") == 0) {
+ strncpy(dest, "\033[0;33m", COLOR_LEN);
+ } else if(strcmp(name, "blue") == 0) {
+ strncpy(dest, "\033[0;34m", COLOR_LEN);
+ } else if(strcmp(name, "magenta") == 0) {
+ strncpy(dest, "\033[0;35m", COLOR_LEN);
+ } else if(strcmp(name, "cyan") == 0) {
+ strncpy(dest, "\033[0;36m", COLOR_LEN);
+ } else if(strcmp(name, "white") == 0) {
+ strncpy(dest, "\033[0;37m", COLOR_LEN);
+ } else if(strcmp(name, "gray") == 0) {
+ strncpy(dest, "\033[1;30m", COLOR_LEN);
+ } else if(strcmp(name, "intensive red") == 0) {
+ strncpy(dest, "\033[1;31m", COLOR_LEN);
+ } else if(strcmp(name, "intensive green") == 0) {
+ strncpy(dest, "\033[1;32m", COLOR_LEN);
+ } else if(strcmp(name, "intensive yellow") == 0) {
+ strncpy(dest, "\033[1;33m", COLOR_LEN);
+ } else if(strcmp(name, "intensive blue") == 0) {
+ strncpy(dest, "\033[1;34m", COLOR_LEN);
+ } else if(strcmp(name, "intensive magenta") == 0) {
+ strncpy(dest, "\033[1;35m", COLOR_LEN);
+ } else if(strcmp(name, "intensive cyan") == 0) {
+ strncpy(dest, "\033[1;36m", COLOR_LEN);
+ } else if(strcmp(name, "intensive white") == 0) {
+ strncpy(dest, "\033[1;37m", COLOR_LEN);
+ } else if(strcmp(name, "intensive foreground") == 0) {
+ strncpy(dest, "\033[m\033[1m", COLOR_LEN);
+ } else if(strcmp(name, "none") == 0) {
+ strncpy(dest, "\033[m", COLOR_LEN);
+ } else {
+ ret = 1;
+ }
+ dest[COLOR_LEN] = '\0';
+ return(ret);
+}
+
+void _insert_color(FILE* stream, color_t color)
+{
+ switch(color) {
+ case COLOR_RED:
+ fprintf(stream, colortab.red);
+ break;
+ case COLOR_GREEN:
+ fprintf(stream, colortab.green);
+ break;
+ case COLOR_YELLOW:
+ fprintf(stream, colortab.yellow);
+ break;
+ case COLOR_BLUE:
+ fprintf(stream, colortab.blue);
+ break;
+ case COLOR_MAGENTA:
+ fprintf(stream, colortab.magenta);
+ break;
+ case COLOR_CYAN:
+ fprintf(stream, colortab.cyan);
+ break;
+ case COLOR_WHITE:
+ fprintf(stream, colortab.white);
+ break;
+ case COLOR_NONE:
+ fprintf(stream, colortab.none);
+ break;
+ default:;
+ }
+}
+
+int _parsecolorconfig(colortab_t* colortab, char* file)
+{
+ _set_color_sequence("intensive red", colortab->red);
+ _set_color_sequence("intensive green", colortab->green);
+ _set_color_sequence("intensive yellow", colortab->yellow);
+ _set_color_sequence("intensive blue", colortab->blue);
+ _set_color_sequence("intensive magenta", colortab->magenta);
+ _set_color_sequence("intensive cyan", colortab->cyan);
+ _set_color_sequence("intensive foreground", colortab->white);
+ _set_color_sequence("none", colortab->none);
+
+ FILE* fp = NULL;
+ int linenum = 0;
+ char line[PATH_MAX+1];
+ char* ptr;
+
+ fp = fopen(file, "r");
+ if(fp == NULL) {
+ pm_printf(ALPM_LOG_ERROR, _("config file %s could not be read.\n"), file);
+ return 1;
+ }
+ while(fgets(line, PATH_MAX, fp)) {
+ linenum++;
+ strtrim(line);
+
+ if(strlen(line) == 0 || line[0] == '#') {
+ continue;
+ }
+ if((ptr = strchr(line, '#'))) {
+ *ptr = '\0';
+ }
+
+ char* key = line;
+ ptr = line;
+ strsep(&ptr, "=");
+ strtrim(key);
+ strtrim(ptr);
+
+ if(key == NULL) {
+ pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: syntax error in config file- missing key.\n"),
+ file, linenum);
+ return 1;
+ }
+ if(strcmp(key, "Red") == 0) {
+ if(_set_color_sequence(ptr, colortab->red)) {
+ pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"),
+ file, linenum, ptr);
+ }
+ } else if(strcmp(key, "Green") == 0) {
+ if(_set_color_sequence(ptr, colortab->green)) {
+ pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"),
+ file, linenum, ptr);
+ }
+ } else if(strcmp(key, "Yellow") == 0) {
+ if(_set_color_sequence(ptr, colortab->yellow)) {
+ pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"),
+ file, linenum, ptr);
+ }
+ } else if(strcmp(key, "Blue") == 0) {
+ if(_set_color_sequence(ptr, colortab->blue)) {
+ pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"),
+ file, linenum, ptr);
+ }
+ } else if(strcmp(key, "Magenta") == 0) {
+ if(_set_color_sequence(ptr, colortab->magenta)) {
+ pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"),
+ file, linenum, ptr);
+ }
+ } else if(strcmp(key, "Cyan") == 0) {
+ if(_set_color_sequence(ptr, colortab->cyan)) {
+ pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"),
+ file, linenum, ptr);
+ }
+ } else if(strcmp(key, "White") == 0) {
+ if(_set_color_sequence(ptr, colortab->white)) {
+ pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"),
+ file, linenum, ptr);
+ }
+ } else {
+ pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"),
+ file, linenum, key);
+ return(1);
+ }
+ }
+ return(0);
+}
+
+int parsecolorconfig()
+{
+ return(_parsecolorconfig(&colortab, config->colorfile));
+}
+
+int color_vfprintf(FILE* stream, const colordata_t* colors, const char* format, va_list args)
+{
+ int ret = 0;
+
+ if(isatty(fileno(stream)) && colors) {
+ char* msg = NULL;
+ ret = vasprintf(&msg, format, args);
+ if(msg == NULL) {
+ return(ret);
+ }
+
+ const colordata_t* colorpos = colors;
+ color_t colorlast = COLOR_NONE;
+ int len = strlen(msg) + 1;
+ wchar_t* wcstr = calloc(len, sizeof(wchar_t));
+ len = mbstowcs(wcstr, msg, len);
+ free(msg);
+ const wchar_t *strpos = wcstr;
+
+ while(*strpos) {
+ if(colorpos->color != COLOR_END &&
+ ((colorpos->separator == SEP_ANY) ||
+ (colorpos->separator == SEP_LINE && *strpos == L'\n') ||
+ (colorpos->separator == SEP_COLON && (*strpos == L':' || *strpos == L':')))) {
+ _insert_color(stream, colorpos->color);
+ colorlast = colorpos->color;
+ colorpos++;
+ }
+ fprintf(stream, "%lc", (wint_t)*strpos);
+ strpos++;
+ }
+ free(wcstr);
+
+ if(colorlast != COLOR_NONE) {
+ _insert_color(stream, COLOR_NONE);
+ }
+ } else {
+ ret = vfprintf(stream, format, args);
+ }
+ return(ret);
+}
+
+int color_fprintf(FILE* stream, const colordata_t* colors, const char* format, ...)
+{
+ int ret;
+ va_list args;
+ va_start(args, format);
+ ret = color_vfprintf(stream, colors, format, args);
+ va_end(args);
+ return(ret);
+}
+
+int color_printf(const colordata_t* colors, const char* format, ...)
+{
+ int ret;
+ va_list args;
+ va_start(args, format);
+ ret = color_vfprintf(stdout, colors, format, args);
+ va_end(args);
+ return(ret);
+}
+
+void color_string_display(const colordata_t* colors_title, const char* title, const colordata_t* colors_string, const char* string)
+{
+ if(title) {
+ color_printf(colors_title, "%s ", title);
+ }
+ if(string == NULL || string[0] == '\0') {
+ printf(_("None"));
+ } else {
+ color_printf(colors_string, "%s", string);
+ }
+ printf("\n");
+}
+
+const colordata_t COLOR_WHITE_ALL[] = {
+ { SEP_ANY, COLOR_WHITE },
+ { SEP_LINE, COLOR_NONE },
+ { SEP_ANY, COLOR_END } };
+
+const colordata_t COLOR_GREEN_ALL[] = {
+ { SEP_ANY, COLOR_GREEN },
+ { SEP_LINE, COLOR_NONE },
+ { SEP_ANY, COLOR_END } };
+
+const colordata_t COLOR_RED_ALL[] = {
+ { SEP_ANY, COLOR_RED },
+ { SEP_LINE, COLOR_NONE },
+ { SEP_ANY, COLOR_END } };
+
+const colordata_t COLOR_BLUE_ALL[] = {
+ { SEP_ANY, COLOR_BLUE },
+ { SEP_LINE, COLOR_NONE },
+ { SEP_ANY, COLOR_END } };
+
+const colordata_t COLOR_YELLOW_ALL[] = {
+ { SEP_ANY, COLOR_YELLOW },
+ { SEP_LINE, COLOR_NONE },
+ { SEP_ANY, COLOR_END } };
+
+const colordata_t COLOR_MAGENTA_ALL[] = {
+ { SEP_ANY, COLOR_MAGENTA },
+ { SEP_LINE, COLOR_NONE },
+ { SEP_ANY, COLOR_END } };
+
+const colordata_t COLOR_CYAN_ALL[] = {
+ { SEP_ANY, COLOR_CYAN },
+ { SEP_LINE, COLOR_NONE },
+ { SEP_ANY, COLOR_END } };
+
+const colordata_t COLOR_DOUBLECOLON[] = {
+ { SEP_ANY, COLOR_BLUE },
+ { SEP_ANY, COLOR_SAME },
+ { SEP_ANY, COLOR_WHITE },
+ { SEP_LINE, COLOR_NONE },
+ { SEP_ANY, COLOR_END } };
+
+const colordata_t COLOR_DOUBLECOLON2[] = {
+ { SEP_ANY, COLOR_BLUE },
+ { SEP_ANY, COLOR_SAME },
+ { SEP_ANY, COLOR_WHITE },
+ { SEP_LINE, COLOR_NONE },
+ { SEP_ANY, COLOR_BLUE },
+ { SEP_ANY, COLOR_SAME },
+ { SEP_ANY, COLOR_WHITE },
+ { SEP_LINE, COLOR_NONE },
+ { SEP_ANY, COLOR_END } };
+
+const colordata_t COLOR_WHITE_COLON[] = {
+ { SEP_ANY, COLOR_WHITE },
+ { SEP_COLON, COLOR_SAME },
+ { SEP_ANY, COLOR_NONE },
+ { SEP_ANY, COLOR_END } };
+
+/* vim: set ts=2 sw=2 noet: */
diff --git a/src/pacman/color.h b/src/pacman/color.h
new file mode 100644
index 0000000..c833e2e
--- /dev/null
+++ b/src/pacman/color.h
@@ -0,0 +1,70 @@
+#ifndef _PM_COLOR_H
+#define _PM_COLOR_H
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <alpm_list.h>
+
+/* pacman-color */
+typedef enum _separator_t {
+ SEP_ANY = 0,
+ SEP_LINE,
+ SEP_COLON,
+} separator_t;
+
+typedef enum _color_t {
+ COLOR_END = 0,
+ COLOR_SAME,
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_YELLOW,
+ COLOR_BLUE,
+ COLOR_MAGENTA,
+ COLOR_CYAN,
+ COLOR_WHITE,
+ COLOR_NONE,
+} color_t;
+
+typedef struct _colordata_t {
+ separator_t separator;
+ color_t color;
+} colordata_t;
+
+extern const colordata_t COLOR_WHITE_ALL[];
+extern const colordata_t COLOR_GREEN_ALL[];
+extern const colordata_t COLOR_RED_ALL[];
+extern const colordata_t COLOR_BLUE_ALL[];
+extern const colordata_t COLOR_YELLOW_ALL[];
+extern const colordata_t COLOR_MAGENTA_ALL[];
+extern const colordata_t COLOR_CYAN_ALL[];
+extern const colordata_t COLOR_DOUBLECOLON[];
+extern const colordata_t COLOR_DOUBLECOLON2[];
+extern const colordata_t COLOR_WHITE_COLON[];
+
+/* util.c */
+
+void color_list_display(const colordata_t *colors_title, const char *title, const alpm_list_t *list,
+ unsigned short maxcols);
+void color_list_display_linebreak(const colordata_t *colors_title, const char *title, const alpm_list_t *list,
+ unsigned short maxcols);
+void _color_display_targets(alpm_list_t *targets, int verbose);
+void color_display_repo_list(const char *dbname, alpm_list_t *list,
+ unsigned short col);
+int color_yesno(const colordata_t *colors, char *fmt, ...);
+int color_noyes(const colordata_t *colors, char *fmt, ...);
+int color_pm_vasprintf(char **string, alpm_loglevel_t level, const char *format, va_list args);
+int color_pm_vfprintf(FILE *stream, alpm_loglevel_t level, const char *format, va_list args);
+int _set_color_sequence(const char* name, char* dest);
+void _insert_color(FILE* stream, color_t color);
+int parsecolorconfig();
+int color_fprintf(FILE* stream, const colordata_t* colors, const char* format, ...) __attribute__((format(printf,3,4)));
+int color_printf(const colordata_t* colors, const char* format, ...) __attribute__((format(printf,2,3)));
+
+int color_vfprintf(FILE* stream, const colordata_t* colors, const char* format, va_list args) __attribute__((format(printf,3,0)));
+
+void color_string_display(const colordata_t* colors_title, const char* title, const colordata_t* colors_string, const char* string);
+
+#endif
+/* vim: set ts=2 sw=2 noet: */
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 7f7f6a7..f750542 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -45,6 +45,7 @@
#include "util.h"
#include "conf.h"
#include "callback.h"
+#include "color.h"
int trans_init(alpm_transflag_t flags, int check_valid)
@@ -130,7 +131,7 @@ int check_syncdbs(size_t need_repos, int check_valid)
}
/* discard unhandled input on the terminal's input buffer */
-static int flush_term_input(int fd) {
+int flush_term_input(int fd) {
#ifdef HAVE_TCFLUSH
if(isatty(fd)) {
return tcflush(fd, TCIFLUSH);
@@ -442,7 +443,7 @@ alpm_list_t *strsplit(const char *str, const char splitchar)
return list;
}
-static size_t string_length(const char *s)
+size_t string_length(const char *s)
{
int len;
wchar_t *wcstr;
@@ -605,7 +606,7 @@ static size_t table_calc_widths(const alpm_list_t *header,
* @param cols the number of columns available in the terminal
* @return -1 if not enough terminal cols available, else 0
*/
-static int table_display(const char *title, const alpm_list_t *header,
+int table_display(const char *title, const alpm_list_t *header,
const alpm_list_t *rows, unsigned short cols)
{
const unsigned short padding = 2;
@@ -794,7 +795,7 @@ void signature_display(const char *title, alpm_siglist_t *siglist,
}
/* creates a header row for use with table_display */
-static alpm_list_t *create_verbose_header(void)
+alpm_list_t *create_verbose_header(void)
{
alpm_list_t *res = NULL;
char *str;
@@ -814,7 +815,7 @@ static alpm_list_t *create_verbose_header(void)
}
/* returns package info as list of strings */
-static alpm_list_t *create_verbose_row(pm_target_t *target)
+alpm_list_t *create_verbose_row(pm_target_t *target)
{
char *str;
off_t size = 0;
@@ -1007,7 +1008,11 @@ void display_targets(void)
}
targets = alpm_list_msort(targets, alpm_list_count(targets), target_cmp);
- _display_targets(targets, config->verbosepkglists);
+ if (config->color) {
+ _color_display_targets(targets, config->verbosepkglists);
+ } else {
+ _display_targets(targets, config->verbosepkglists);
+ }
FREELIST(targets);
}
@@ -1263,7 +1268,11 @@ void select_display(const alpm_list_t *pkglist)
if(!dbname)
dbname = alpm_db_get_name(db);
if(strcmp(alpm_db_get_name(db), dbname) != 0) {
- display_repo_list(dbname, list, cols);
+ if (config->color) {
+ color_display_repo_list(dbname, list, cols);
+ } else {
+ display_repo_list(dbname, list, cols);
+ }
FREELIST(list);
dbname = alpm_db_get_name(db);
}
@@ -1272,7 +1281,11 @@ void select_display(const alpm_list_t *pkglist)
list = alpm_list_add(list, string);
nth++;
}
- display_repo_list(dbname, list, cols);
+ if (config->color) {
+ color_display_repo_list(dbname, list, cols);
+ } else {
+ display_repo_list(dbname, list, cols);
+ }
FREELIST(list);
}
@@ -1551,7 +1564,11 @@ int pm_printf(alpm_loglevel_t level, const char *format, ...)
/* print the message using va_arg list */
va_start(args, format);
- ret = pm_vfprintf(stderr, level, format, args);
+ if (config->color) {
+ ret = color_pm_vfprintf(stderr, level, format, args);
+ } else {
+ ret = pm_vfprintf(stderr, level, format, args);
+ }
va_end(args);
return ret;
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 0dfdc85..d15164f 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -47,6 +47,7 @@ int trans_init(alpm_transflag_t flags, int check_valid);
int trans_release(void);
int needs_root(void);
int check_syncdbs(size_t need_repos, int check_valid);
+int flush_term_input(int fd);
unsigned short getcols(int fd);
int rmrf(const char *path);
const char *mbasename(const char *path);
@@ -55,15 +56,20 @@ void indentprint(const char *str, unsigned short indent, unsigned short cols);
size_t strtrim(char *str);
char *strreplace(const char *str, const char *needle, const char *replace);
alpm_list_t *strsplit(const char *str, const char splitchar);
+size_t string_length(const char *s);
void string_display(const char *title, const char *string, unsigned short cols);
double humanize_size(off_t bytes, const char target_unit, int precision,
const char **label);
+int table_display(const char *title, const alpm_list_t *header,
+ const alpm_list_t *rows, unsigned short cols);
void list_display(const char *title, const alpm_list_t *list,
unsigned short maxcols);
void list_display_linebreak(const char *title, const alpm_list_t *list,
unsigned short maxcols);
void signature_display(const char *title, alpm_siglist_t *siglist,
unsigned short maxcols);
+alpm_list_t *create_verbose_header(void);
+alpm_list_t *create_verbose_row(pm_target_t *target);
void display_targets(void);
int str_cmp(const void *s1, const void *s2);
void display_new_optdepends(alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg);
--
1.7.11.4
More information about the pacman-dev
mailing list