FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > ArchLinux > ArchLinux Pacman Development

 
 
LinkBack Thread Tools
 
Old 02-21-2011, 06:02 PM
Jakob Gruber
 
Default Table formatted output functions

table_display takes a list of lists of strings (representing the table
cells) and displays them formatted as a table.
The exact format depends on the longest string in each column.

Signed-off-by: Jakob Gruber <jakob.gruber@gmail.com>
---
src/pacman/util.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++ +++
src/pacman/util.h | 1 +
2 files changed, 109 insertions(+), 0 deletions(-)

diff --git a/src/pacman/util.c b/src/pacman/util.c
index 85d2d8c..8f7b5e5 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -435,6 +435,114 @@ void string_display(const char *title, const char *string)
printf("
");
}

+static void table_print_line(const alpm_list_t *line,
+ const alpm_list_t *formats)
+{
+ const alpm_list_t *curformat = formats;
+ const alpm_list_t *curcell = line;
+
+ while (curcell && curformat) {
+ printf(alpm_list_getdata(curformat), alpm_list_getdata(curcell));
+ curcell = alpm_list_next(curcell);
+ curformat = alpm_list_next(curformat);
+ }
+
+ printf("
");
+}
+
+/* creates a format string by checking max cell lengths in rows */
+static alpm_list_t *table_create_format(const alpm_list_t *rows)
+{
+ alpm_list_t *format, *curformat;
+ const alpm_list_t *currow, *curcell;
+ char *str, *formatstr;
+ const int padding = 2;
+ int cols, neededcols = 0;
+
+ /* initial format list element */
+ format = alpm_list_add(NULL, NULL);
+
+ /* go through each cell and store the longest string for each
+ * column in the format list */
+ currow = rows;
+ while(currow != NULL) {
+
+ /* starting on new row, reset format pointer to first column */
+ curformat = format;
+
+ /* loop through all row cells and update format pointer if necessary */
+ curcell = alpm_list_getdata(currow);
+ while(curcell != NULL) {
+ if(curformat == NULL) {
+ curformat = alpm_list_last(alpm_list_add(format, NULL));
+ }
+
+ str = alpm_list_getdata(curcell);
+ if(curformat->data == NULL ||
+ strlen(str) > strlen(alpm_list_getdata(curformat)))
+ curformat->data = str;
+
+ curformat = alpm_list_next(curformat);
+ curcell = alpm_list_next(curcell);
+ }
+
+ currow = alpm_list_next(currow);
+ }
+
+ /* now use the column width info to generate format strings */
+ curformat = format;
+ while(curformat != NULL) {
+ cols = strlen(curformat->data) + padding;
+ neededcols += cols;
+
+ str = (alpm_list_next(curformat) != NULL) ? "%%-%ds" : "%%%ds";
+ pm_asprintf(&formatstr, str, cols);
+
+ curformat->data = formatstr;
+ curformat = alpm_list_next(curformat);
+ }
+
+ /* return NULL if terminal is not wide enough */
+ if(neededcols > getcols()) {
+ FREELIST(format);
+ return NULL;
+ }
+
+ return format;
+}
+
+/** Displays the list in table format
+ *
+ * @param title the tables title
+ * @param rows the rows to display as a list of lists of strings. the outer
+ * list represents the rows, the inner list the cells (= columns)
+ *
+ * @return -1 if not enough terminal cols available, else 0
+ */
+int table_display(const char *title, const alpm_list_t *rows)
+{
+ alpm_list_t *i, *formats;
+
+ if(rows == NULL)
+ return 0;
+
+ formats = table_create_format(rows);
+ if(formats == NULL) {
+ return -1;
+ }
+
+ if(title != NULL) {
+ printf("%s

", title);
+ }
+
+ for(i = alpm_list_first(rows); i; i = alpm_list_next(i)) {
+ table_print_line(alpm_list_getdata(i), formats);
+ }
+
+ FREELIST(formats);
+ return 0;
+}
+
void list_display(const char *title, const alpm_list_t *list)
{
const alpm_list_t *i;
diff --git a/src/pacman/util.h b/src/pacman/util.h
index ed03c13..494becf 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -56,6 +56,7 @@ char *size_to_human_string_mb(off_t bytes);
char *size_to_human_string_kb(off_t bytes);
char *size_to_human_string_short(off_t bytes);
void string_display(const char *title, const char *string);
+int table_display(const char *title, const alpm_list_t *rows);
void list_display(const char *title, const alpm_list_t *list);
void list_display_linebreak(const char *title, const alpm_list_t *list);
void display_targets(const alpm_list_t *pkgs, int install);
--
1.7.4.1
 
Old 02-25-2011, 02:21 PM
Dan McGee
 
Default Table formatted output functions

On Mon, Feb 21, 2011 at 1:02 PM, Jakob Gruber <jakob.gruber@gmail.com> wrote:
> table_display takes a list of lists of strings (representing the table
> cells) and displays them formatted as a table.
> The exact format depends on the longest string in each column.
>
> Signed-off-by: Jakob Gruber <jakob.gruber@gmail.com>
> ---
> *src/pacman/util.c | *108 ++++++++++++++++++++++++++++++++++++++++++++++++++ +++
> *src/pacman/util.h | * *1 +
> *2 files changed, 109 insertions(+), 0 deletions(-)

Noticing it now, but please read the coding style document. We always
use {}, even on one line conditionals. We also format all return
statements as return(value). Yes, this one is suspect, but consistency
is more important than anything.

>
> diff --git a/src/pacman/util.c b/src/pacman/util.c
> index 85d2d8c..8f7b5e5 100644
> --- a/src/pacman/util.c
> +++ b/src/pacman/util.c
> @@ -435,6 +435,114 @@ void string_display(const char *title, const char *string)
> * * * *printf("
");
> *}
>
> +static void table_print_line(const alpm_list_t *line,
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * const alpm_list_t *formats)
> +{
> + * * * const alpm_list_t *curformat = formats;
> + * * * const alpm_list_t *curcell = line;
> +
> + * * * while (curcell && curformat) {
> + * * * * * * * printf(alpm_list_getdata(curformat), alpm_list_getdata(curcell));
> + * * * * * * * curcell = alpm_list_next(curcell);
> + * * * * * * * curformat = alpm_list_next(curformat);
> + * * * }
> +
> + * * * printf("
");
> +}
> +
> +/* creates a format string by checking max cell lengths in rows */
> +static alpm_list_t *table_create_format(const alpm_list_t *rows)
> +{
> + * * * alpm_list_t *format, *curformat;
> + * * * const alpm_list_t *currow, *curcell;
> + * * * char *str, *formatstr;
> + * * * const int padding = 2;
> + * * * int cols, neededcols = 0;
> +
> + * * * /* initial format list element */
> + * * * format = alpm_list_add(NULL, NULL);
What's going on here? We always have a NULL first item?

> +
> + * * * /* go through each cell and store the longest string for each
> + * * * ** column in the format list */
> + * * * currow = rows;
> + * * * while(currow != NULL) {
You've wrote a for() loop without the for here and the last line of the block.
> +
> + * * * * * * * /* starting on new row, reset format pointer to first column */
> + * * * * * * * curformat = format;
> +
> + * * * * * * * /* loop through all row cells and update format pointer if necessary */
Which isn't really a format pointer at all, but a pointer to actual data?

> + * * * * * * * curcell = alpm_list_getdata(currow);
> + * * * * * * * while(curcell != NULL) {
> + * * * * * * * * * * * if(curformat == NULL) {
> + * * * * * * * * * * * * * * * curformat = alpm_list_last(alpm_list_add(format, NULL));
This makes assumptions. I doubt we'll ever break it, but alpm_list_add
always needs to be reassigned back to format, in this case, before
doing anything else on it.

> + * * * * * * * * * * * }
> +
> + * * * * * * * * * * * str = alpm_list_getdata(curcell);
> + * * * * * * * * * * * if(curformat->data == NULL ||
> + * * * * * * * * * * * * * * * * * * * strlen(str) > strlen(alpm_list_getdata(curformat)))
> + * * * * * * * * * * * * * * * curformat->data = str;
> +
> + * * * * * * * * * * * curformat = alpm_list_next(curformat);
> + * * * * * * * * * * * curcell = alpm_list_next(curcell);
> + * * * * * * * }
> +
> + * * * * * * * currow = alpm_list_next(currow);
> + * * * }
> +
> + * * * /* now use the column width info to generate format strings */
> + * * * curformat = format;
> + * * * while(curformat != NULL) {
> + * * * * * * * cols = strlen(curformat->data) + padding;
> + * * * * * * * neededcols += cols;
> +
> + * * * * * * * str = (alpm_list_next(curformat) != NULL) ? "%%-%ds" : "%%%ds";
Magic here- everything else seems generic, but why is this last column special?

> + * * * * * * * pm_asprintf(&formatstr, str, cols);
> +
> + * * * * * * * curformat->data = formatstr;
> + * * * * * * * curformat = alpm_list_next(curformat);
> + * * * }
I had a real hard time following all this, but that might just be the
morning brain not working well. Your reuse of curformat->data as first
a immutable string holder and later a alloced format string holder is
particularly hard to wrap the brain around until you see it. I'd
highly recommend not mixing the two for clarity.

input: a list of rows, each with a list of cols (cells)?
output: a list of formats for each col?

> +
> + * * * /* return NULL if terminal is not wide enough */
> + * * * if(neededcols > getcols()) {
> + * * * * * * * FREELIST(format);
> + * * * * * * * return NULL;
> + * * * }
Hmm. Is this likely to happen? Seems odd to then not have anything
printed at all. I think we should truncate strings as necessary, just
like we do in the callback functions.

> +
> + * * * return format;
> +}
> +
> +/** Displays the list in table format
> + *
> + * @param title the tables title
> + * @param rows *the rows to display as a list of lists of strings. the outer
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * list represents the rows, the inner list the cells (= columns)
> + *
> + * @return -1 if not enough terminal cols available, else 0
> + */
> +int table_display(const char *title, const alpm_list_t *rows)
> +{
> + * * * alpm_list_t *i, *formats;
> +
> + * * * if(rows == NULL)
> + * * * * * * * return 0;
> +
> + * * * formats = table_create_format(rows);
> + * * * if(formats == NULL) {
> + * * * * * * * return -1;
> + * * * }
> +
> + * * * if(title != NULL) {
> + * * * * * * * printf("%s

", title);
> + * * * }
> +
> + * * * for(i = alpm_list_first(rows); i; i = alpm_list_next(i)) {
> + * * * * * * * table_print_line(alpm_list_getdata(i), formats);
> + * * * }
> +
> + * * * FREELIST(formats);
> + * * * return 0;
> +}
> +
> *void list_display(const char *title, const alpm_list_t *list)
> *{
> * * * *const alpm_list_t *i;
> diff --git a/src/pacman/util.h b/src/pacman/util.h
> index ed03c13..494becf 100644
> --- a/src/pacman/util.h
> +++ b/src/pacman/util.h
> @@ -56,6 +56,7 @@ char *size_to_human_string_mb(off_t bytes);
> *char *size_to_human_string_kb(off_t bytes);
> *char *size_to_human_string_short(off_t bytes);
> *void string_display(const char *title, const char *string);
> +int table_display(const char *title, const alpm_list_t *rows);
> *void list_display(const char *title, const alpm_list_t *list);
> *void list_display_linebreak(const char *title, const alpm_list_t *list);
> *void display_targets(const alpm_list_t *pkgs, int install);
> --
> 1.7.4.1
>
>
>
 
Old 02-28-2011, 03:32 PM
Jakob Gruber
 
Default Table formatted output functions

On 02/25/2011 04:21 PM, Dan McGee wrote:

I had a real hard time following all this, but that might just be the
morning brain not working well. Your reuse of curformat->data as first
a immutable string holder and later a alloced format string holder is
particularly hard to wrap the brain around until you see it. I'd
highly recommend not mixing the two for clarity.


I made a few changes that should hopefully make this part clearer.
table_display now also takes a list of column headers,
and table_create_format uses them to determine the column count before
looking for the longest strings and creating the formats.
This gets rid of adding the NULL in display_targets (NULL was equal to
an empty line after the header) and the NULL in table_create_format
(which was an initial value which meant "assign the first string we get
to because there aren't any initial values to run strlen() on yet").



input: a list of rows, each with a list of cols (cells)?
output: a list of formats for each col?

Yeah, exactly.


+
+ /* return NULL if terminal is not wide enough */
+ if(neededcols> getcols()) {
+ FREELIST(format);
+ return NULL;
+ }

Hmm. Is this likely to happen? Seems odd to then not have anything
printed at all. I think we should truncate strings as necessary, just
like we do in the callback functions.

It shouldn't happen (often) for regular usage. On an 80 column terminal,
the current upgrade targets (which all have average length names and
versions) takes up about 2/3 of the width. I added an error message at
this spot, but I'm not sure about truncating strings? Currently, the
error is passed up through table_display, display_targets will unset
config->verbosepkglists and run itself again with the default list
display as fallback. Is that behavior acceptable?



+
+ return format;
+}
+
+/** Displays the list in table format
+ *
+ * @param title the tables title
+ * @param rows the rows to display as a list of lists of strings. the outer
+ * list represents the rows, the inner list the cells (= columns)
+ *
+ * @return -1 if not enough terminal cols available, else 0
+ */
+int table_display(const char *title, const alpm_list_t *rows)
+{
+ alpm_list_t *i, *formats;
+
+ if(rows == NULL)
+ return 0;
+
+ formats = table_create_format(rows);
+ if(formats == NULL) {
+ return -1;
+ }
+
+ if(title != NULL) {
+ printf("%s

", title);
+ }
+
+ for(i = alpm_list_first(rows); i; i = alpm_list_next(i)) {
+ table_print_line(alpm_list_getdata(i), formats);
+ }
+
+ FREELIST(formats);
+ return 0;
+}
+
void list_display(const char *title, const alpm_list_t *list)
{
const alpm_list_t *i;
diff --git a/src/pacman/util.h b/src/pacman/util.h
index ed03c13..494becf 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -56,6 +56,7 @@ char *size_to_human_string_mb(off_t bytes);
char *size_to_human_string_kb(off_t bytes);
char *size_to_human_string_short(off_t bytes);
void string_display(const char *title, const char *string);
+int table_display(const char *title, const alpm_list_t *rows);
void list_display(const char *title, const alpm_list_t *list);
void list_display_linebreak(const char *title, const alpm_list_t *list);
void display_targets(const alpm_list_t *pkgs, int install);
--
1.7.4.1
 
Old 02-28-2011, 03:40 PM
Jakob Gruber
 
Default Table formatted output functions

table_display takes a list of lists of strings (representing the table
cells) and displays them formatted as a table.
The exact format depends on the longest string in each column.

Signed-off-by: Jakob Gruber <jakob.gruber@gmail.com>
---
src/pacman/util.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++ +++
src/pacman/util.h | 1 +
2 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/src/pacman/util.c b/src/pacman/util.c
index ba64a77..65656ff 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -435,6 +435,116 @@ void string_display(const char *title, const char *string)
printf("
");
}

+static void table_print_line(const alpm_list_t *line,
+ const alpm_list_t *formats)
+{
+ const alpm_list_t *curformat = formats;
+ const alpm_list_t *curcell = line;
+
+ while(curcell && curformat) {
+ printf(alpm_list_getdata(curformat), alpm_list_getdata(curcell));
+ curcell = alpm_list_next(curcell);
+ curformat = alpm_list_next(curformat);
+ }
+
+ printf("
");
+}
+
+/* creates format strings by checking max cell lengths in cols */
+static alpm_list_t *table_create_format(const alpm_list_t *header,
+ const alpm_list_t *rows)
+{
+ alpm_list_t *longest_str, *longest_strs = NULL;
+ alpm_list_t *formats = NULL;
+ const alpm_list_t *i, *row, *cell;
+ char *str, *formatstr;
+ const int padding = 2;
+ int colwidth, totalwidth = 0;
+ int curcol = 0;
+
+ /* header determines column count and initial values of longest_strs */
+ for(i = header; i; i = alpm_list_next(i)) {
+ longest_strs = alpm_list_add(longest_strs, alpm_list_getdata(i));
+ }
+
+ /* now find the longest string in each column */
+ for(longest_str = longest_strs; longest_str;
+ longest_str = alpm_list_next(longest_str), curcol++) {
+ for(i = rows; i; i = alpm_list_next(i)) {
+ row = alpm_list_getdata(i);
+ cell = alpm_list_nth(row, curcol);
+ str = alpm_list_getdata(cell);
+
+ if(strlen(str) > strlen(alpm_list_getdata(longest_str))) {
+ longest_str->data = str;
+ }
+ }
+ }
+
+ /* now use the column width info to generate format strings */
+ for(i = longest_strs; i; i = alpm_list_next(i)) {
+ colwidth = strlen(alpm_list_getdata(i)) + padding;
+ totalwidth += colwidth;
+
+ /* right align the last column for a cleaner table display */
+ str = (alpm_list_next(i) != NULL) ? "%%-%ds" : "%%%ds";
+ pm_asprintf(&formatstr, str, colwidth);
+
+ formats = alpm_list_add(formats, formatstr);
+ }
+
+ alpm_list_free(longest_strs);
+
+ /* return NULL if terminal is not wide enough */
+ if(totalwidth > getcols()) {
+ fprintf(stderr, _("insufficient columns available for table display
"));
+ FREELIST(formats);
+ return(NULL);
+ }
+
+ return(formats);
+}
+
+/** Displays the list in table format
+ *
+ * @param title the tables title
+ * @param header the column headers. column count is determined by the nr
+ * of headers
+ * @param rows the rows to display as a list of lists of strings. the outer
+ * list represents the rows, the inner list the cells (= columns)
+ *
+ * @return -1 if not enough terminal cols available, else 0
+ */
+int table_display(const char *title, const alpm_list_t *header,
+ const alpm_list_t *rows)
+{
+ const alpm_list_t *i;
+ alpm_list_t *formats;
+
+ if(rows == NULL || header == NULL) {
+ return(0);
+ }
+
+ formats = table_create_format(header, rows);
+ if(formats == NULL) {
+ return(-1);
+ }
+
+ if(title != NULL) {
+ printf("%s

", title);
+ }
+
+ table_print_line(header, formats);
+ printf("
");
+
+ for(i = rows; i; i = alpm_list_next(i)) {
+ table_print_line(alpm_list_getdata(i), formats);
+ }
+
+ FREELIST(formats);
+ return(0);
+}
+
void list_display(const char *title, const alpm_list_t *list)
{
const alpm_list_t *i;
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 6a20ba4..d8ae7d8 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -53,6 +53,7 @@ char *strreplace(const char *str, const char *needle, const char *replace);
alpm_list_t *strsplit(const char *str, const char splitchar);
void string_display(const char *title, const char *string);
double humanize_size(off_t bytes, const char target_unit, int long_labels, const char **label);
+int table_display(const char *title, const alpm_list_t *header, const alpm_list_t *rows);
void list_display(const char *title, const alpm_list_t *list);
void list_display_linebreak(const char *title, const alpm_list_t *list);
void display_targets(const alpm_list_t *pkgs, int install);
--
1.7.4.1
 

Thread Tools




All times are GMT. The time now is 08:27 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org