diff --git a/README.md b/README.md index 804f630..7ef7eec 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 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 @@ -59,10 +59,11 @@ Options: ### cndump -Display all notes in a formatted table. +Display all notes in a formatted table. Output width adapts to terminal size automatically. ```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 -c # sort by category cndump -r # reverse sort order @@ -75,6 +76,7 @@ Options: - `-c, --category` - Sort by category - `-r, --reverse` - Reverse sort order - `-a, --archive` - Show archived entries instead of active +- `-s, --simple` - Simple output without box borders ### cncount diff --git a/src/cndump.c b/src/cndump.c index 76cfa99..3cca255 100644 --- a/src/cndump.c +++ b/src/cndump.c @@ -8,10 +8,25 @@ #include "platform.h" #include "config.h" +/* Terminal width detection */ +#if defined(__MSDOS__) || defined(__DOS__) + /* DOS: assume 80 columns */ +#elif defined(_WIN32) + #include +#else + #include + #include +#endif + #define MAX_LENGTH 500 /* Allow fgets to read up to this many characters */ #define DATE_LENGTH 10 /* YYYY-MM-DD */ #define TIME_LENGTH 5 /* HH:MM */ #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 { @@ -23,6 +38,12 @@ typedef enum { /* Global variable to control sort order: 1 for ascending, -1 for descending */ 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 { 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; } +/* 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) { int i; 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); printf("%c", middle); - /* Free text column */ - for (i = 0; i < TXTMSG_LENGTH + 2; i++) printf("%c", fill); + /* Free text column (dynamic width) */ + for (i = 0; i < g_text_width + 2; i++) printf("%c", fill); printf("%c\n", right); } +void print_simple_separator(void) { + int i; + int total_width = DATE_LENGTH + TIME_LENGTH + CATEGORY_LENGTH + g_text_width + 9; + for (i = 0; i < total_width; i++) printf("-"); + printf("\n"); +} + void print_header(int is_archive) { - /* Top border (double line) */ - print_horizontal_line('+', '+', '+', '='); + const char *text_label = is_archive ? "Free Text (ARCHIVED)" : "Free Text"; - /* Header row */ - printf("| %-*s | %-*s | %-*s | %-*s |\n", - DATE_LENGTH, "Date", - TIME_LENGTH, "Time", - CATEGORY_LENGTH, "Category", - TXTMSG_LENGTH, is_archive ? "Free Text (ARCHIVED)" : "Free Text"); - - /* Bottom border (double line) */ - print_horizontal_line('+', '+', '+', '='); + 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", + DATE_LENGTH, "Date", + TIME_LENGTH, "Time", + CATEGORY_LENGTH, "Category", + g_text_width, text_label); + print_horizontal_line('+', '+', '+', '='); + } } void print_footer(void) { - print_horizontal_line('+', '+', '+', '-'); + if (!g_simple_mode) { + print_horizontal_line('+', '+', '+', '-'); + } } void print_entry(const Entry *entry) { - printf("| %-*s | %-*s | %-*s | %-*s |\n", - DATE_LENGTH, entry->date, - TIME_LENGTH, entry->time, - CATEGORY_LENGTH, entry->category, - TXTMSG_LENGTH, entry->text); + 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", + DATE_LENGTH, entry->date, + TIME_LENGTH, entry->time, + CATEGORY_LENGTH, entry->category, + 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) { - 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, "Options:\n"); fprintf(stderr, " -d, --date Sort by date/time\n"); fprintf(stderr, " -c, --category Sort by category\n"); fprintf(stderr, " -r, --reverse Reverse sort order\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[]) { @@ -243,6 +334,9 @@ int main(int argc, char *argv[]) { else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--archive") == 0) { 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) { print_usage(argv[0]); free(entries); @@ -306,6 +400,9 @@ int main(int argc, char *argv[]) { 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_header(show_archive); for (i = 0; i < entry_count; i++) { diff --git a/src/cnhelp.c b/src/cnhelp.c index aa9aa60..8bc1b0e 100644 --- a/src/cnhelp.c +++ b/src/cnhelp.c @@ -6,7 +6,7 @@ #include void print_overview(void) { - printf("cnotes - Command-line note-taking system\n"); + printf("cnotes - Command-line logging / note-taking system\n"); printf("\n"); printf("Commands:\n"); printf(" cnadd Add a new note entry\n"); @@ -35,16 +35,20 @@ void print_cnadd(void) { void print_cndump(void) { printf("cndump - Display all notes in a formatted table\n"); printf("\n"); - printf("Usage: cndump [-d] [-c] [-r] [-a]\n"); + printf("Usage: cndump [-d] [-c] [-r] [-a] [-s]\n"); printf("\n"); printf("Options:\n"); printf(" -d, --date Sort by date/time (newest first)\n"); printf(" -c, --category Sort by category\n"); printf(" -r, --reverse Reverse sort order\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("Examples:\n"); printf(" cndump Display all notes\n"); + printf(" cndump -s Simple format (no borders)\n"); printf(" cndump -d Sort by date\n"); printf(" cndump -a Show archived notes\n"); }