Add color commands for stuff in util
Signed-off-by: Daniel Wallace <daniel.wallace@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@archlinux.org>
+ * Copyright (c) 2002-2006 by Judd Vinet <jvinet@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
", _("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("
");
+ 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('
');
+ }
+}
+
+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
", _("None"));
+ } else {
+ const alpm_list_t *i;
+ /* Print the first element */
+ indentprint((const char *)list->data, len, maxcols);
+ printf("
");
+ /* 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("
");
+ }
+ }
+}
+
+/* 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("
");
+
+ 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("
");
+
+ /* 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
"), 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
"), size, label);
+ }
+ if(rsize > 0 && isize == 0) {
+ size = humanize_size(rsize, 'M', 2, &label);
+ color_printf(COLOR_WHITE_COLON, _("Total Removed Size: %.2f %s
"), 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
"), 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
"), 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, "
");
+ 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
is missing, resulting in broken output (FS#27909) */
+ if(!isatty(fileno(stdin))) {
+ fprintf(stream, "%s
", 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] = ' ';
+
+ 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, " |