aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorsten Töpper <atsutane@freethoughts.de>2025-07-25 19:15:55 +0200
committerThorsten Töpper <atsutane@freethoughts.de>2025-07-25 19:15:55 +0200
commitf8e91cb52f07a75a1d9f6b812297a7464b30dcce (patch)
tree9e28b0bd4b9782c893a711a79671e474576ca3ff
parent0aa13572dfaed70ed7d13d99fa1b07511103af7a (diff)
downloaddir_monitor-f8e91cb52f07a75a1d9f6b812297a7464b30dcce.tar.gz
dir_monitor-f8e91cb52f07a75a1d9f6b812297a7464b30dcce.tar.bz2
output: --print-boxed for visual table
-rw-r--r--include/options.h1
-rw-r--r--man/dir_monitor.1.adoc3
-rw-r--r--src/options.c9
-rw-r--r--src/output.c135
4 files changed, 135 insertions, 13 deletions
diff --git a/include/options.h b/include/options.h
index 062d120..c62474d 100644
--- a/include/options.h
+++ b/include/options.h
@@ -28,6 +28,7 @@ enum esort_type { SORT_BY_NAME, SORT_BY_SIZE, SORT_BY_TIME };
extern bool option_sort_reverse_order;
extern enum esort_type option_sort_type;
+extern bool option_print_boxed_table;
extern bool option_print_header;
extern bool option_show_hidden_entries;
extern bool option_timestamp_long;
diff --git a/man/dir_monitor.1.adoc b/man/dir_monitor.1.adoc
index d3ed9fe..b1d4787 100644
--- a/man/dir_monitor.1.adoc
+++ b/man/dir_monitor.1.adoc
@@ -28,6 +28,9 @@ define columns to print, details below
**--long-timestamp**, **-t**::
Print timestamp in long form 'yyyymmdd HH:MM:SS ZONE'
+**--print-boxed**::
+Print output in form of a boxed table
+
**--print-header**, **-H**::
Print a header above the columns
diff --git a/src/options.c b/src/options.c
index efc4169..65f8310 100644
--- a/src/options.c
+++ b/src/options.c
@@ -21,6 +21,7 @@ struct option long_options[] = {
{ "help", no_argument, 0, 0 },
{ "format-string", required_argument, 0, 0 },
{ "long-timestamp", no_argument, 0, 0 },
+ { "print-boxed", no_argument, 0, 0 },
{ "print-header", no_argument, 0, 0 },
{ "reverse-sort", no_argument, 0, 0 },
{ "show-hidden-entries", no_argument, 0, 0 },
@@ -31,6 +32,7 @@ struct option long_options[] = {
bool option_sort_reverse_order = false;
enum esort_type option_sort_type = SORT_BY_SIZE;
+bool option_print_boxed_table = false;
bool option_print_header = false;
bool option_show_hidden_entries = false;
bool option_timestamp_long = false;
@@ -57,6 +59,8 @@ void usage(char *executable) {
"define columns to print, details below");
fprintf(stderr, " %-25s %2s %10s - %s\n", "--long-timestamp", "-t", "",
"Print timestamp in long form yyyymmdd HH:MM:SS ZONE");
+ fprintf(stderr, " %-25s %2s %10s - %s\n", "--print-boxed", "", "",
+ "Print a boxed table");
fprintf(stderr, " %-25s %2s %10s - %s\n", "--print-header", "-H", "",
"Print a header above the columns");
fprintf(stderr, " %-25s %2s %10s - %s\n", "--reverse-sort", "", "",
@@ -112,6 +116,11 @@ void set_option(const char *option_name, char *option_argument) {
return;
}
+ if (strcmp("print-boxed", option_name) == 0) {
+ option_print_boxed_table = true;
+ return;
+ }
+
if (strcmp("print-header", option_name) == 0) {
option_print_header = true;
return;
diff --git a/src/output.c b/src/output.c
index 45f04a6..3cf68af 100644
--- a/src/output.c
+++ b/src/output.c
@@ -5,6 +5,7 @@
* vim:ts=4:sw=4:expandtab
*/
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
@@ -27,7 +28,13 @@
#define DM_OUT_FORMAT_MAX_LEN 80
-#define out_vsep fputc('|', stdout)
+#define box_cross '+'
+#define box_hsep '-'
+#define box_vsep '|'
+
+#define out_cross() fputc(box_cross, stdout)
+#define out_hsep() fputc(box_hsep, stdout)
+#define out_vsep() fputc(box_vsep, stdout)
#define out_print_newline() fputc('\n', stdout)
#define out_print_fname(x) printf(" %s ", x->fname)
@@ -42,7 +49,12 @@ void out_print_time_by_option(struct list_node *ptr);
void out_print_type(struct list_node *ptr);
void out_print_user_name(struct list_node *ptr);
-void out_print_format_string_header(const char *format);
+void out_print_format_string_header(const char *format, size_t longest_fname);
+
+size_t get_longest_filename(struct list_head *list);
+
+
+char *global_sep_line = NULL;
/* === IMPLEMENTATION === */
@@ -85,6 +97,19 @@ inline int fputc_width_x(char c, size_t x, FILE *fdout) {
return 1;
}
+/* basic 4 due to formatted output */
+inline size_t get_longest_filename(struct list_head *list) {
+ size_t rc = 4, tmp = 0;
+ struct list_node *ptr = NULL;
+ if (list == NULL) { return 0; }
+ ptr = list->first;
+ while (ptr != NULL) {
+ tmp = strlen(ptr->fname);
+ if (tmp>rc) { rc = tmp; }
+ ptr = ptr->next;
+ }
+ return rc;
+}
/* === FORMATTING RELATED FUNCTIONS === */
@@ -289,24 +314,44 @@ inline void out_print_permissions(struct list_node *ptr) {
printf(" %4o ", mode);
}
-inline void out_print_format_string_header(const char *format) {
- size_t i=0, format_len=0;
- char header[4096] = "";
+inline void out_print_format_string_header(const char *format, size_t longest_fname) {
+ size_t i=0, j=0, k=0, format_len=0, tmp = 0;
+ char header[4096] = "", sep_line[4096] = "";
char *pos = header;
- if (format == NULL) return;
+ if (format == NULL || longest_fname == 0) return;
DBGTRC("DEBUG: format string: \"%s\"\n", format);
format_len = strnlen(format, DM_OUT_FORMAT_MAX_LEN);
+
+ if (option_print_boxed_table) {
+ if (global_sep_line != NULL) { free(global_sep_line); }
+ pos[0] = box_vsep;
+ pos++;
+ sep_line[j++] = box_cross;
+ }
+
+#define LOCAL_EXTEND_SEP_LINE() { \
+ if (option_print_boxed_table) { \
+ tmp = strlen(pos); \
+ for (k=0; k<tmp; k++) { sep_line[j++] = box_hsep; } \
+ sep_line[j++] = box_cross; pos[tmp] = box_vsep; } }
+
/* Prevent buffer overflow, with the header string 32 byte buffer */
for (i=0; (i < format_len) && (strlen(header) < 4064); i++) {
switch (format[i]) {
case 'n':
sprintf(pos, " FILE ");
+ tmp = strlen(pos);
+ for (k=0; k<longest_fname-4; k++) {
+ pos[tmp+k] = ' ';
+ }
+ LOCAL_EXTEND_SEP_LINE();
break;
case 's':
sprintf(pos, " %11s ", "SIZE ");
+ LOCAL_EXTEND_SEP_LINE();
break;
case 't':
if (option_timestamp_long) {
@@ -314,6 +359,7 @@ inline void out_print_format_string_header(const char *format) {
} else {
sprintf(pos, " %c%-7s ", toupper(option_time_field), "TIME");
}
+ LOCAL_EXTEND_SEP_LINE();
break;
case 'A':
if (option_timestamp_long) {
@@ -321,6 +367,7 @@ inline void out_print_format_string_header(const char *format) {
} else {
sprintf(pos, " %-8s ", "ATIME");
}
+ LOCAL_EXTEND_SEP_LINE();
break;
case 'C':
if (option_timestamp_long) {
@@ -328,6 +375,7 @@ inline void out_print_format_string_header(const char *format) {
} else {
sprintf(pos, " %-8s ", "CTIME");
}
+ LOCAL_EXTEND_SEP_LINE();
break;
case 'M':
if (option_timestamp_long) {
@@ -335,24 +383,31 @@ inline void out_print_format_string_header(const char *format) {
} else {
sprintf(pos, " %-8s ", "MTIME");
}
+ LOCAL_EXTEND_SEP_LINE();
break;
case 'T':
sprintf(pos, " %-12s ", "TYPE");
+ LOCAL_EXTEND_SEP_LINE();
break;
case 'u':
sprintf(pos, " %-4s ", "UID");
+ LOCAL_EXTEND_SEP_LINE();
break;
case 'g':
sprintf(pos, " %-4s ", "GID");
+ LOCAL_EXTEND_SEP_LINE();
break;
case 'U':
sprintf(pos, " %-10s ", "USER");
+ LOCAL_EXTEND_SEP_LINE();
break;
case 'G':
sprintf(pos, " %-10s ", "GROUP");
+ LOCAL_EXTEND_SEP_LINE();
break;
case 'p':
sprintf(pos, " %-4s ", "PERM");
+ LOCAL_EXTEND_SEP_LINE();
break;
case ' ':
break;
@@ -362,9 +417,24 @@ inline void out_print_format_string_header(const char *format) {
};
pos = &header[strlen(header)];
}
- printf("%s\n", header);
- fputc_width_x('-', strlen(header), stdout);
+ /* Output to stdout */
+ if (option_print_boxed_table) {
+ fputs(sep_line, stdout);
+ out_print_newline();
+ }
+ fputs(header, stdout);
out_print_newline();
+ if (option_print_boxed_table) {
+ tmp = strlen(sep_line);
+ fputs(sep_line, stdout);
+ if ((global_sep_line = calloc(tmp+1, sizeof(char))) != NULL) {
+ memcpy(global_sep_line, sep_line, tmp);
+ }
+ } else {
+ fputc_width_x('-', strlen(header), stdout);
+ }
+ out_print_newline();
+#undef LOCAL_EXTEND_SEP_LINE
}
/* === END OF FORMATTING FUNCTIONS === */
@@ -375,6 +445,7 @@ void print_list(struct list_head *list) {
struct list_head *lh = list;
struct list_node *ptr;
size_t total_size = 0;
+ size_t longest_fname = 0, i = 0;
if (list == NULL) return;
if (option_sort_reverse_order) {
@@ -385,15 +456,24 @@ void print_list(struct list_head *list) {
}
}
+ longest_fname = get_longest_filename(list);
+
if (option_print_header) {
- out_print_format_string_header("stn");
+ out_print_format_string_header("stn", longest_fname);
}
ptr = lh->first;
while (ptr != NULL) {
+ if (option_print_boxed_table) out_vsep();
out_print_size(ptr);
+ if (option_print_boxed_table) out_vsep();
out_print_time_by_option(ptr);
+ if (option_print_boxed_table) out_vsep();
out_print_fname(ptr);
+ if (option_print_boxed_table) {
+ for (i=0; i<(longest_fname-strlen(ptr->fname)); i++) fputc(' ', stdout);
+ out_vsep();
+ }
out_print_newline();
/* Linux: Neither man stat(2) nor stat(3type) declare why struct stat field st_size
@@ -405,7 +485,12 @@ void print_list(struct list_head *list) {
total_size += (ptr->ln_stat.st_size>0) ? (unsigned long int)ptr->ln_stat.st_size : 0;
ptr = ptr->next;
}
- fputc_all_cols('=', stdout);
+ if (option_print_boxed_table && global_sep_line != NULL) {
+ fputs(global_sep_line, stdout);
+ } else {
+ fputc_all_cols('=', stdout);
+ }
+ out_print_newline();
printf("\nTotal size: %lu %s\n", ((total_size>1024) ? total_size/1024 : total_size),
((total_size >= 1024) ? "kB" : ""));
@@ -432,7 +517,8 @@ void print_list(struct list_head *list) {
void print_list_formatted(const char *format, struct list_head *list) {
struct list_head *lh = list;
struct list_node *ptr;
- size_t format_len = 0, i = 0;
+ size_t format_len = 0, i = 0, j = 0;
+ size_t longest_fname = 0;
size_t total_size = 0;
if (format == NULL || format[0] == '\0') {
@@ -458,49 +544,67 @@ void print_list_formatted(const char *format, struct list_head *list) {
format_len = strnlen(format, DM_OUT_FORMAT_MAX_LEN);
DBGTRC("DEBUG: format_len = %lu\n", format_len);
+ longest_fname = get_longest_filename(list);
+
if (option_print_header) {
- out_print_format_string_header(format);
+ out_print_format_string_header(format, longest_fname);
}
ptr = lh->first;
while (ptr != NULL) {
+ if (option_print_boxed_table) { out_vsep(); }
for (i=0; i < format_len; i++) {
switch (format[i]) {
case 'n':
out_print_fname(ptr);
+ for (j=0; j<(longest_fname - strlen(ptr->fname)); j++) {
+ fputc(' ', stdout);
+ }
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 's':
out_print_size(ptr);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 't':
out_print_time_by_option(ptr);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 'A':
out_print_time(ptr->ln_stat.st_atim.tv_sec);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 'C':
out_print_time(ptr->ln_stat.st_ctim.tv_sec);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 'M':
out_print_time(ptr->ln_stat.st_mtim.tv_sec);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 'T':
out_print_type(ptr);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 'u':
out_print_uid(ptr);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 'g':
out_print_gid(ptr);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 'U':
out_print_user_name(ptr);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 'G':
out_print_group_name(ptr);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case 'p':
out_print_permissions(ptr);
+ if (option_print_boxed_table) { out_vsep(); }
break;
case ' ': /* just ignore this without warning */
break;
@@ -513,7 +617,12 @@ void print_list_formatted(const char *format, struct list_head *list) {
total_size += (ptr->ln_stat.st_size>0) ? (unsigned long int)ptr->ln_stat.st_size : 0;
ptr = ptr->next;
}
- fputc_all_cols('=', stdout);
+ if (option_print_boxed_table && global_sep_line != NULL) {
+ fputs(global_sep_line, stdout);
+ } else {
+ fputc_all_cols('=', stdout);
+ }
+ out_print_newline();
printf("\nTotal size: %lu %s\n", ((total_size>1024) ? total_size/1024 : total_size),
((total_size >= 1024) ? "kB" : ""));
if (lh != list) destroy_list(lh);