fix cnfind display logic to match cndump
All checks were successful
Build / build (push) Successful in 15s

This commit is contained in:
Gregory Gauthier 2026-01-30 16:17:06 +00:00
parent 8e8f92f53a
commit b658afeefa
2 changed files with 123 additions and 20 deletions

View File

@ -9,10 +9,29 @@
#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 #define MAX_LENGTH 500
#define DATE_LENGTH 10 #define DATE_LENGTH 10
#define TIME_LENGTH 5 #define TIME_LENGTH 5
#define TXTMSG_LENGTH 125 #define TXTMSG_LENGTH 125
#define DEFAULT_TERM_WIDTH 80
#define MIN_TEXT_WIDTH 20
/* Fixed column widths (ln + date + time + category + separators) */
#define FIXED_COLS (5 + DATE_LENGTH + TIME_LENGTH + CATEGORY_LENGTH + 20)
/* Output settings */
static int g_simple_mode = 0;
static int g_text_width = TXTMSG_LENGTH;
typedef struct { typedef struct {
char date[DATE_LENGTH + 1]; char date[DATE_LENGTH + 1];
@ -22,6 +41,37 @@ typedef struct {
int line_num; int line_num;
} Entry; } Entry;
/* Get terminal width */
static int get_terminal_width(void) {
#if defined(__MSDOS__) || defined(__DOS__)
return 80;
#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;
}
/* Case-insensitive substring search */ /* Case-insensitive substring search */
static char *stristr(const char *haystack, const char *needle) { static char *stristr(const char *haystack, const char *needle) {
const char *h; const char *h;
@ -147,33 +197,76 @@ 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_simple_separator(void) {
int i;
int total_width = 5 + DATE_LENGTH + TIME_LENGTH + CATEGORY_LENGTH + g_text_width + 12;
for (i = 0; i < total_width; i++) printf("-");
printf("\n");
}
void print_header(int is_archive) { void print_header(int is_archive) {
print_horizontal_line('+', '+', '+', '='); const char *text_label = is_archive ? "Free Text (ARCHIVED)" : "Free Text";
printf("| %-3s | %-*s | %-*s | %-*s | %-*s |\n",
"Ln", if (g_simple_mode) {
DATE_LENGTH, "Date", printf("%-3s %-*s %-*s %-*s %s\n",
TIME_LENGTH, "Time", "Ln",
CATEGORY_LENGTH, "Category", DATE_LENGTH, "Date",
TXTMSG_LENGTH, is_archive ? "Free Text (ARCHIVED)" : "Free Text"); TIME_LENGTH, "Time",
print_horizontal_line('+', '+', '+', '='); CATEGORY_LENGTH, "Category",
text_label);
print_simple_separator();
} else {
print_horizontal_line('+', '+', '+', '=');
printf("| %-3s | %-*s | %-*s | %-*s | %-*s |\n",
"Ln",
DATE_LENGTH, "Date",
TIME_LENGTH, "Time",
CATEGORY_LENGTH, "Category",
g_text_width, text_label);
print_horizontal_line('+', '+', '+', '=');
}
} }
void print_footer(void) { void print_footer(void) {
print_horizontal_line('+', '+', '+', '-'); if (!g_simple_mode) {
print_horizontal_line('+', '+', '+', '-');
}
} }
void print_entry(const Entry *entry) { void print_entry(const Entry *entry) {
printf("| %3d | %-*s | %-*s | %-*s | %-*s |\n", char truncated_text[TXTMSG_LENGTH + 1];
entry->line_num, int text_len;
DATE_LENGTH, entry->date,
TIME_LENGTH, entry->time, /* Truncate text if needed */
CATEGORY_LENGTH, entry->category, text_len = (int)strlen(entry->text);
TXTMSG_LENGTH, 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("%3d %-*s %-*s %-*s %s\n",
entry->line_num,
DATE_LENGTH, entry->date,
TIME_LENGTH, entry->time,
CATEGORY_LENGTH, entry->category,
truncated_text);
} else {
printf("| %3d | %-*s | %-*s | %-*s | %-*s |\n",
entry->line_num,
DATE_LENGTH, entry->date,
TIME_LENGTH, entry->time,
CATEGORY_LENGTH, entry->category,
g_text_width, truncated_text);
}
} }
void print_usage(const char *prog_name) { void print_usage(const char *prog_name) {
@ -186,6 +279,7 @@ void print_usage(const char *prog_name) {
fprintf(stderr, " -d DATE Filter by date (YYYY-MM-DD)\n"); fprintf(stderr, " -d DATE Filter by date (YYYY-MM-DD)\n");
fprintf(stderr, " -i Case-sensitive search (default is case-insensitive)\n"); fprintf(stderr, " -i Case-sensitive search (default is case-insensitive)\n");
fprintf(stderr, " -n Show only count of matches\n"); fprintf(stderr, " -n Show only count of matches\n");
fprintf(stderr, " -s, --simple Simple output (no box borders)\n");
fprintf(stderr, " -a, --archive Search archived entries instead of active\n"); fprintf(stderr, " -a, --archive Search archived entries instead of active\n");
fprintf(stderr, " -h, --help Show this help message\n"); fprintf(stderr, " -h, --help Show this help message\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
@ -244,6 +338,9 @@ int main(int argc, char *argv[]) {
else if (strcmp(argv[i], "-n") == 0) { else if (strcmp(argv[i], "-n") == 0) {
count_only = 1; count_only = 1;
} }
else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--simple") == 0) {
g_simple_mode = 1;
}
else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--archive") == 0) { else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--archive") == 0) {
search_archive = 1; search_archive = 1;
} }
@ -277,7 +374,7 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
notesfile = fopen(file_path, "r"); notesfile = fopen(file_path, "r");
if (notesfile == NULL) { if (notesfile == NULL) {
if (search_archive) { if (search_archive) {
fprintf(stderr, "No archived entries found.\n"); fprintf(stderr, "No archived entries found.\n");
@ -288,6 +385,9 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
/* Calculate dynamic text width based on terminal */
g_text_width = calc_text_width(get_terminal_width());
/* Search entries */ /* Search entries */
while (fgets(line, MAX_LENGTH, notesfile) != NULL) { while (fgets(line, MAX_LENGTH, notesfile) != NULL) {
int matches = 1; int matches = 1;

View File

@ -56,18 +56,21 @@ void print_cndump(void) {
void print_cnfind(void) { void print_cnfind(void) {
printf("cnfind - Search notes by text, category, or date\n"); printf("cnfind - Search notes by text, category, or date\n");
printf("\n"); printf("\n");
printf("Usage: cnfind [-c CAT] [-d DATE] [-i] [-n] [-a] [PATTERN]\n"); printf("Usage: cnfind [-c CAT] [-d DATE] [-i] [-n] [-s] [-a] [PATTERN]\n");
printf("\n"); printf("\n");
printf("Options:\n"); printf("Options:\n");
printf(" -c CATEGORY Filter by category\n"); printf(" -c CATEGORY Filter by category\n");
printf(" -d DATE Filter by date (YYYY-MM-DD)\n"); printf(" -d DATE Filter by date (YYYY-MM-DD)\n");
printf(" -i Case-sensitive search\n"); printf(" -i Case-sensitive search\n");
printf(" -n Show only match count\n"); printf(" -n Show only match count\n");
printf(" -s, --simple Simple output (no box borders)\n");
printf(" -a, --archive Search archived entries\n"); printf(" -a, --archive Search archived entries\n");
printf("\n"); printf("\n");
printf("Output adapts to terminal width automatically.\n");
printf("\n");
printf("Examples:\n"); printf("Examples:\n");
printf(" cnfind meeting Search for 'meeting'\n"); printf(" cnfind meeting Search for 'meeting'\n");
printf(" cnfind -c Work Show Work category\n"); printf(" cnfind -s -c Work Show Work category (simple)\n");
printf(" cnfind -a meeting Search archive\n"); printf(" cnfind -a meeting Search archive\n");
} }