add dump output customization
This commit is contained in:
parent
347c39412b
commit
174680e764
@ -1,6 +1,6 @@
|
|||||||
# cnotes
|
# cnotes
|
||||||
|
|
||||||
A simple command-line note-taking system written in strict C89/ANSI C for maximum portability.
|
A simple command-line logging and note-taking system written in strict C89/ANSI C for maximum portability.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@ -59,10 +59,11 @@ Options:
|
|||||||
|
|
||||||
### cndump
|
### cndump
|
||||||
|
|
||||||
Display all notes in a formatted table.
|
Display all notes in a formatted table. Output width adapts to terminal size automatically.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cndump # display all notes
|
cndump # display all notes (boxed table)
|
||||||
|
cndump -s # simple output (no box borders)
|
||||||
cndump -d # sort by date (newest first)
|
cndump -d # sort by date (newest first)
|
||||||
cndump -c # sort by category
|
cndump -c # sort by category
|
||||||
cndump -r # reverse sort order
|
cndump -r # reverse sort order
|
||||||
@ -75,6 +76,7 @@ Options:
|
|||||||
- `-c, --category` - Sort by category
|
- `-c, --category` - Sort by category
|
||||||
- `-r, --reverse` - Reverse sort order
|
- `-r, --reverse` - Reverse sort order
|
||||||
- `-a, --archive` - Show archived entries instead of active
|
- `-a, --archive` - Show archived entries instead of active
|
||||||
|
- `-s, --simple` - Simple output without box borders
|
||||||
|
|
||||||
### cncount
|
### cncount
|
||||||
|
|
||||||
|
|||||||
119
src/cndump.c
119
src/cndump.c
@ -8,10 +8,25 @@
|
|||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
/* Terminal width detection */
|
||||||
|
#if defined(__MSDOS__) || defined(__DOS__)
|
||||||
|
/* DOS: assume 80 columns */
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_LENGTH 500 /* Allow fgets to read up to this many characters */
|
#define MAX_LENGTH 500 /* Allow fgets to read up to this many characters */
|
||||||
#define DATE_LENGTH 10 /* YYYY-MM-DD */
|
#define DATE_LENGTH 10 /* YYYY-MM-DD */
|
||||||
#define TIME_LENGTH 5 /* HH:MM */
|
#define TIME_LENGTH 5 /* HH:MM */
|
||||||
#define TXTMSG_LENGTH 125 /* Max length of a text message */
|
#define TXTMSG_LENGTH 125 /* Max length of a text message */
|
||||||
|
#define DEFAULT_TERM_WIDTH 80
|
||||||
|
#define MIN_TEXT_WIDTH 20 /* Minimum width for free text column */
|
||||||
|
|
||||||
|
/* Fixed column widths (date + time + category + separators) */
|
||||||
|
#define FIXED_COLS (DATE_LENGTH + TIME_LENGTH + CATEGORY_LENGTH + 16)
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -23,6 +38,12 @@ typedef enum {
|
|||||||
/* Global variable to control sort order: 1 for ascending, -1 for descending */
|
/* Global variable to control sort order: 1 for ascending, -1 for descending */
|
||||||
static int g_sort_order = -1; /* Default: descending (newest/Z-A first) */
|
static int g_sort_order = -1; /* Default: descending (newest/Z-A first) */
|
||||||
|
|
||||||
|
/* Output mode: 0 = boxed table, 1 = simple */
|
||||||
|
static int g_simple_mode = 0;
|
||||||
|
|
||||||
|
/* Dynamic text column width */
|
||||||
|
static int g_text_width = TXTMSG_LENGTH;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char date[DATE_LENGTH +1]; /* YYYY-MM-DD\0 */
|
char date[DATE_LENGTH +1]; /* YYYY-MM-DD\0 */
|
||||||
@ -47,6 +68,37 @@ static int compare_by_category(const void *a, const void *b) {
|
|||||||
return strcmp(entry_b->category, entry_a->category) * g_sort_order;
|
return strcmp(entry_b->category, entry_a->category) * g_sort_order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get terminal width */
|
||||||
|
static int get_terminal_width(void) {
|
||||||
|
#if defined(__MSDOS__) || defined(__DOS__)
|
||||||
|
return 80; /* Standard DOS text mode */
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||||
|
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
|
||||||
|
return csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||||
|
}
|
||||||
|
return DEFAULT_TERM_WIDTH;
|
||||||
|
#else
|
||||||
|
struct winsize ws;
|
||||||
|
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0) {
|
||||||
|
return ws.ws_col;
|
||||||
|
}
|
||||||
|
return DEFAULT_TERM_WIDTH;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate text column width based on terminal size */
|
||||||
|
static int calc_text_width(int term_width) {
|
||||||
|
int available = term_width - FIXED_COLS;
|
||||||
|
if (available < MIN_TEXT_WIDTH) {
|
||||||
|
available = MIN_TEXT_WIDTH;
|
||||||
|
}
|
||||||
|
if (available > TXTMSG_LENGTH) {
|
||||||
|
available = TXTMSG_LENGTH;
|
||||||
|
}
|
||||||
|
return available;
|
||||||
|
}
|
||||||
|
|
||||||
void print_horizontal_line(char left, char middle, char right, char fill) {
|
void print_horizontal_line(char left, char middle, char right, char fill) {
|
||||||
int i;
|
int i;
|
||||||
printf("%c", left);
|
printf("%c", left);
|
||||||
@ -63,36 +115,74 @@ void print_horizontal_line(char left, char middle, char right, char fill) {
|
|||||||
for (i = 0; i < CATEGORY_LENGTH + 2; i++) printf("%c", fill);
|
for (i = 0; i < CATEGORY_LENGTH + 2; i++) printf("%c", fill);
|
||||||
printf("%c", middle);
|
printf("%c", middle);
|
||||||
|
|
||||||
/* Free text column */
|
/* Free text column (dynamic width) */
|
||||||
for (i = 0; i < TXTMSG_LENGTH + 2; i++) printf("%c", fill);
|
for (i = 0; i < g_text_width + 2; i++) printf("%c", fill);
|
||||||
printf("%c\n", right);
|
printf("%c\n", right);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_header(int is_archive) {
|
void print_simple_separator(void) {
|
||||||
/* Top border (double line) */
|
int i;
|
||||||
print_horizontal_line('+', '+', '+', '=');
|
int total_width = DATE_LENGTH + TIME_LENGTH + CATEGORY_LENGTH + g_text_width + 9;
|
||||||
|
for (i = 0; i < total_width; i++) printf("-");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* Header row */
|
void print_header(int is_archive) {
|
||||||
|
const char *text_label = is_archive ? "Free Text (ARCHIVED)" : "Free Text";
|
||||||
|
|
||||||
|
if (g_simple_mode) {
|
||||||
|
/* Simple mode: header row with separator line */
|
||||||
|
printf("%-*s %-*s %-*s %s\n",
|
||||||
|
DATE_LENGTH, "Date",
|
||||||
|
TIME_LENGTH, "Time",
|
||||||
|
CATEGORY_LENGTH, "Category",
|
||||||
|
text_label);
|
||||||
|
print_simple_separator();
|
||||||
|
} else {
|
||||||
|
/* Boxed mode: full table borders */
|
||||||
|
print_horizontal_line('+', '+', '+', '=');
|
||||||
printf("| %-*s | %-*s | %-*s | %-*s |\n",
|
printf("| %-*s | %-*s | %-*s | %-*s |\n",
|
||||||
DATE_LENGTH, "Date",
|
DATE_LENGTH, "Date",
|
||||||
TIME_LENGTH, "Time",
|
TIME_LENGTH, "Time",
|
||||||
CATEGORY_LENGTH, "Category",
|
CATEGORY_LENGTH, "Category",
|
||||||
TXTMSG_LENGTH, is_archive ? "Free Text (ARCHIVED)" : "Free Text");
|
g_text_width, text_label);
|
||||||
|
|
||||||
/* Bottom border (double line) */
|
|
||||||
print_horizontal_line('+', '+', '+', '=');
|
print_horizontal_line('+', '+', '+', '=');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void print_footer(void) {
|
void print_footer(void) {
|
||||||
|
if (!g_simple_mode) {
|
||||||
print_horizontal_line('+', '+', '+', '-');
|
print_horizontal_line('+', '+', '+', '-');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void print_entry(const Entry *entry) {
|
void print_entry(const Entry *entry) {
|
||||||
|
char truncated_text[TXTMSG_LENGTH + 1];
|
||||||
|
int text_len;
|
||||||
|
|
||||||
|
/* Truncate text if needed */
|
||||||
|
text_len = (int)strlen(entry->text);
|
||||||
|
if (text_len > g_text_width) {
|
||||||
|
strncpy(truncated_text, entry->text, g_text_width - 3);
|
||||||
|
truncated_text[g_text_width - 3] = '\0';
|
||||||
|
strcat(truncated_text, "...");
|
||||||
|
} else {
|
||||||
|
strcpy(truncated_text, entry->text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_simple_mode) {
|
||||||
|
printf("%-*s %-*s %-*s %s\n",
|
||||||
|
DATE_LENGTH, entry->date,
|
||||||
|
TIME_LENGTH, entry->time,
|
||||||
|
CATEGORY_LENGTH, entry->category,
|
||||||
|
truncated_text);
|
||||||
|
} else {
|
||||||
printf("| %-*s | %-*s | %-*s | %-*s |\n",
|
printf("| %-*s | %-*s | %-*s | %-*s |\n",
|
||||||
DATE_LENGTH, entry->date,
|
DATE_LENGTH, entry->date,
|
||||||
TIME_LENGTH, entry->time,
|
TIME_LENGTH, entry->time,
|
||||||
CATEGORY_LENGTH, entry->category,
|
CATEGORY_LENGTH, entry->category,
|
||||||
TXTMSG_LENGTH, entry->text);
|
g_text_width, truncated_text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -190,13 +280,14 @@ int get_cnotes_path(char *buffer, size_t bufsize, const char *filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void print_usage(const char *prog_name) {
|
void print_usage(const char *prog_name) {
|
||||||
fprintf(stderr, "Usage: %s [-d|--date] [-c|--category] [-r|--reverse] [-a|--archive]\n", prog_name);
|
fprintf(stderr, "Usage: %s [-d|--date] [-c|--category] [-r|--reverse] [-a|--archive] [-s|--simple]\n", prog_name);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "Options:\n");
|
fprintf(stderr, "Options:\n");
|
||||||
fprintf(stderr, " -d, --date Sort by date/time\n");
|
fprintf(stderr, " -d, --date Sort by date/time\n");
|
||||||
fprintf(stderr, " -c, --category Sort by category\n");
|
fprintf(stderr, " -c, --category Sort by category\n");
|
||||||
fprintf(stderr, " -r, --reverse Reverse sort order\n");
|
fprintf(stderr, " -r, --reverse Reverse sort order\n");
|
||||||
fprintf(stderr, " -a, --archive Show archived entries instead of active\n");
|
fprintf(stderr, " -a, --archive Show archived entries instead of active\n");
|
||||||
|
fprintf(stderr, " -s, --simple Simple output (no box borders)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
@ -243,6 +334,9 @@ int main(int argc, char *argv[]) {
|
|||||||
else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--archive") == 0) {
|
else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--archive") == 0) {
|
||||||
show_archive = 1;
|
show_archive = 1;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--simple") == 0) {
|
||||||
|
g_simple_mode = 1;
|
||||||
|
}
|
||||||
else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
|
else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
free(entries);
|
free(entries);
|
||||||
@ -306,6 +400,9 @@ int main(int argc, char *argv[]) {
|
|||||||
qsort(entries, entry_count, sizeof(Entry), compare_by_category);
|
qsort(entries, entry_count, sizeof(Entry), compare_by_category);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate dynamic text width based on terminal */
|
||||||
|
g_text_width = calc_text_width(get_terminal_width());
|
||||||
|
|
||||||
/* Print the table */
|
/* Print the table */
|
||||||
print_header(show_archive);
|
print_header(show_archive);
|
||||||
for (i = 0; i < entry_count; i++) {
|
for (i = 0; i < entry_count; i++) {
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void print_overview(void) {
|
void print_overview(void) {
|
||||||
printf("cnotes - Command-line note-taking system\n");
|
printf("cnotes - Command-line logging / note-taking system\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Commands:\n");
|
printf("Commands:\n");
|
||||||
printf(" cnadd Add a new note entry\n");
|
printf(" cnadd Add a new note entry\n");
|
||||||
@ -35,16 +35,20 @@ void print_cnadd(void) {
|
|||||||
void print_cndump(void) {
|
void print_cndump(void) {
|
||||||
printf("cndump - Display all notes in a formatted table\n");
|
printf("cndump - Display all notes in a formatted table\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Usage: cndump [-d] [-c] [-r] [-a]\n");
|
printf("Usage: cndump [-d] [-c] [-r] [-a] [-s]\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf(" -d, --date Sort by date/time (newest first)\n");
|
printf(" -d, --date Sort by date/time (newest first)\n");
|
||||||
printf(" -c, --category Sort by category\n");
|
printf(" -c, --category Sort by category\n");
|
||||||
printf(" -r, --reverse Reverse sort order\n");
|
printf(" -r, --reverse Reverse sort order\n");
|
||||||
printf(" -a, --archive Show archived entries\n");
|
printf(" -a, --archive Show archived entries\n");
|
||||||
|
printf(" -s, --simple Simple output (no box borders)\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Output adapts to terminal width automatically.\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Examples:\n");
|
printf("Examples:\n");
|
||||||
printf(" cndump Display all notes\n");
|
printf(" cndump Display all notes\n");
|
||||||
|
printf(" cndump -s Simple format (no borders)\n");
|
||||||
printf(" cndump -d Sort by date\n");
|
printf(" cndump -d Sort by date\n");
|
||||||
printf(" cndump -a Show archived notes\n");
|
printf(" cndump -a Show archived notes\n");
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user