>From 63bad71ad245d9f1da8800f678743b6516e4adfa Mon Sep 17 00:00:00 2001
From: Jakob Gruber <jakob.gruber@gmail.com>
Date: Sun, 20 Feb 2011 15:00:26 +0100
Subject: [PATCH 6/6] New VerbosePkgLists option

If enabled, displays package lists for upgrade, sync and remove
operations formatted as a table. Falls back to default list display if
insufficient terminal columns are available.

Example output (-Su):

Targets (25):

Pkg Name          New Version           Old Version          Size

asciidoc          8.6.4-1               8.6.3-1           0.15 MB
chromium          9.0.597.94-2          9.0.597.94-1     17.80 MB
...
wine              1.3.14-1              1.3.13-2         24.67 MB

Total Download Size:    158.41 MB
Total Installed Size:   693.05 MB

Example output (-S, some targets already installed):

kdeedu-kturtle     4.6.0-1                      0.22 MB
kdeedu-kwordquiz   4.6.0-1                      1.06 MB
kdeedu-marble      4.6.0-1      4.6.0-1        14.95 MB

Example output (-R):

Remove (15):

Pkg Name                 Old Version       Size

kdeutils-sweeper         4.6.0-1        0.12 MB
kdeutils-superkaramba    4.6.0-1        1.08 MB
kdeutils-printer-applet  4.6.0-1        0.16 MB
kdeutils-kwallet         4.6.0-1        0.81 MB

Signed-off-by: Jakob Gruber <jakob.gruber@gmail.com>
---
 doc/pacman.conf.5.txt |    5 +++
 etc/pacman.conf.in    |    1 +
 src/pacman/conf.h     |    1 +
 src/pacman/pacman.c   |    3 ++
 src/pacman/util.c     |   95 ++++++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 101 insertions(+), 4 deletions(-)

diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index cb4c589..063d305 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -168,6 +168,11 @@ Options
 	Performs an approximate check for adequate available disk space before
 	installing packages.
 
+*VerbosePkgLists*::
+	Displays name, version and size of target packages formatted
+	as a table.
+
+
 Repository Sections
 -------------------
 Each repository section defines a section name and at least one location where
diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in
index 1105db9..bf5925f 100644
--- a/etc/pacman.conf.in
+++ b/etc/pacman.conf.in
@@ -34,6 +34,7 @@ Architecture = auto
 #UseDelta
 #TotalDownload
 #CheckSpace
+#VerbosePkgLists
 
 #
 # REPOSITORIES
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 92c379f..f440090 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -70,6 +70,7 @@ typedef struct __config_t {
 	/* conf file options */
 	unsigned short chomp; /* I Love Candy! */
 	unsigned short showsize; /* show individual package sizes */
+	unsigned short verbosepkglists; /* format target pkg lists as table */
 	/* When downloading, display the amount downloaded, rate, ETA, and percent
 	 * downloaded of the total download list */
 	unsigned short totaldownload;
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 984bd1b..4cf14bb 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -967,6 +967,9 @@ static int _parse_options(char *key, char *value)
 		} else if(strcmp(key, "ShowSize") == 0) {
 			config->showsize = 1;
 			pm_printf(PM_LOG_DEBUG, "config: showsize\n");
+		} else if(strcmp(key, "VerbosePkgLists") == 0) {
+			config->verbosepkglists = 1;
+			pm_printf(PM_LOG_DEBUG, "config: verbosepkglists\n");
 		} else if(strcmp(key, "UseDelta") == 0) {
 			alpm_option_set_usedelta(1);
 			pm_printf(PM_LOG_DEBUG, "config: usedelta\n");
diff --git a/src/pacman/util.c b/src/pacman/util.c
index ad9a336..4209ff7 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -607,6 +607,62 @@ void list_display_linebreak(const char *title, const alpm_list_t *list)
 	}
 }
 
+/* creates a header row for use with table_display */
+static alpm_list_t *create_verbose_header(int install)
+{
+	alpm_list_t *res = NULL;
+	char *str;
+
+	pm_asprintf(&str, "%s", _("Pkg Name"));
+	res = alpm_list_add(res, str);
+	if(install) {
+		pm_asprintf(&str, "%s", _("New Version"));
+		res = alpm_list_add(res, str);
+	}
+	pm_asprintf(&str, "%s", _("Old Version"));
+	res = alpm_list_add(res, str);
+	pm_asprintf(&str, "%s", _("Size"));
+	res = alpm_list_add(res, str);
+
+	return res;
+}
+
+/** Generates a table row with package info *
+ *
+ * @param pkg	the package
+ * @param install	if value is zero format for remove operation,
+ * 								otherwise for installation
+ *
+ * @return a list of strings representing the current row
+ */
+static alpm_list_t *create_verbose_row(pmpkg_t *pkg, int install)
+{
+	char *str;
+	alpm_list_t *ret = NULL;
+	pmdb_t *ldb = alpm_option_get_localdb();
+
+	/* a row consists of the package name, */
+	pm_asprintf(&str,"%s", alpm_pkg_get_name(pkg));
+	ret = alpm_list_add(ret, str);
+
+	/* (new version,) old version */
+	pm_asprintf(&str,"%s", alpm_pkg_get_version(pkg));
+	ret = alpm_list_add(ret, str);
+
+	if(install) {
+		pmpkg_t *oldpkg = alpm_db_get_pkg(ldb, alpm_pkg_get_name(pkg));
+		pm_asprintf(&str, "%s",
+				oldpkg != NULL ? alpm_pkg_get_version(oldpkg) : "");
+		ret = alpm_list_add(ret, str);
+	}
+
+	/* and size */
+	str = size_to_human_string_mb(alpm_pkg_get_size(pkg));
+	ret = alpm_list_add(ret, str);
+
+	return ret;
+}
+
 /* returns package info as a string */
 static char *create_list_element(pmpkg_t *pkg)
 {
@@ -628,7 +684,7 @@ void display_targets(const alpm_list_t *pkgs, int install)
 	const char *title;
 	const alpm_list_t *i;
 	off_t isize = 0, dlsize = 0;
-	alpm_list_t *targets = NULL;
+	alpm_list_t *j, *lp, *targets = NULL;
 
 	if(!pkgs) {
 		return;
@@ -636,19 +692,40 @@ void display_targets(const alpm_list_t *pkgs, int install)
 
 	title = install ? _("Targets (%d):") : _("Remove (%d):");
 
+	if(config->verbosepkglists) {
+		/* create table header and add an empty line after it */
+		targets = alpm_list_add(targets, create_verbose_header(install));
+		targets = alpm_list_add(targets, NULL);
+	}
+
+	/* gather pkg infos */
 	for(i = pkgs; i; i = alpm_list_next(i)) {
 		pmpkg_t *pkg = alpm_list_getdata(i);
 
 		dlsize += alpm_pkg_download_size(pkg);
 		isize += alpm_pkg_get_isize(pkg);
 
-		targets = alpm_list_add(targets, create_list_element(pkg));
+		if(config->verbosepkglists) {
+			targets = alpm_list_add(targets, create_verbose_row(pkg, install));
+		} else {
+			targets = alpm_list_add(targets, create_list_element(pkg));
+		}
 	}
 
+	/* print to screen */
 	pm_asprintf(&str, title, alpm_list_count(pkgs));
 
 	printf("\n");
-	list_display(str, targets);
+	if(config->verbosepkglists) {
+		if(table_display(str, targets) != 0) {
+			printf(_("Insufficient columns available, using default list display...\n"));
+			config->verbosepkglists = 0;
+			display_targets(pkgs, install);
+			goto out;
+		}
+	} else {
+		list_display(str, targets);
+	}
 	printf("\n");
 
 	if(install) {
@@ -667,8 +744,18 @@ void display_targets(const alpm_list_t *pkgs, int install)
 	}
 
 out:
+	/* cleanup */
+	if(config->verbosepkglists) {
+		/* targets is a list of lists of strings, free inner lists here */
+		for(j = alpm_list_first(targets); j; j = alpm_list_next(j)) {
+			lp = alpm_list_getdata(j);
+			FREELIST(lp);
+		}
+		alpm_list_free(targets);
+	} else {
+		FREELIST(targets);
+	}
 	free(str);
-	FREELIST(targets);
 }
 
 static off_t pkg_get_size(pmpkg_t *pkg)
-- 
1.7.4.1

