From 18f591e79f857e5f25501d04d09044753f6aded9 Mon Sep 17 00:00:00 2001 From: marcusDenslow Date: Sun, 29 Jun 2025 16:56:43 -0600 Subject: [PATCH] this is a test --- diff_viewer.c | 838 ++++++++++++++++++++++++++------------------------ 1 file changed, 431 insertions(+), 407 deletions(-) diff --git a/diff_viewer.c b/diff_viewer.c index da16c32..e842102 100644 --- a/diff_viewer.c +++ b/diff_viewer.c @@ -2,495 +2,519 @@ * diff_viewer.c * Interactive diff viewer implementation */ +// thisis a test #include "diff_viewer.h" +#include #include #include #include -#include #include #include -#include +#include /** * Initialize the diff viewer */ int init_diff_viewer(DiffViewer *viewer) { - if (!viewer) return 0; - - memset(viewer, 0, sizeof(DiffViewer)); - viewer->selected_file = 0; - viewer->diff_scroll_offset = 0; - viewer->current_mode = MODE_FILE_LIST; // Start in file list mode - - get_terminal_size(&viewer->terminal_width, &viewer->terminal_height); - viewer->file_panel_width = viewer->terminal_width * 0.3; // 30% of screen width - - return 1; + if (!viewer) + return 0; + + memset(viewer, 0, sizeof(DiffViewer)); + viewer->selected_file = 0; + viewer->diff_scroll_offset = 0; + viewer->current_mode = MODE_FILE_LIST; // Start in file list mode + + get_terminal_size(&viewer->terminal_width, &viewer->terminal_height); + viewer->file_panel_width = + viewer->terminal_width * 0.3; // 30% of screen width + + return 1; } /** * Get terminal size */ void get_terminal_size(int *width, int *height) { - struct winsize w; - ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); - *width = w.ws_col; - *height = w.ws_row; + struct winsize w; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + *width = w.ws_col; + *height = w.ws_row; } /** * Get list of changed files from git */ int get_changed_files(DiffViewer *viewer) { - if (!viewer) return 0; - - FILE *fp = popen("git status --porcelain 2>/dev/null", "r"); - if (!fp) return 0; - - viewer->file_count = 0; - char line[512]; - - while (fgets(line, sizeof(line), fp) != NULL && viewer->file_count < MAX_FILES) { - // Remove newline - char *newline = strchr(line, '\n'); - if (newline) *newline = '\0'; - - if (strlen(line) < 3) continue; - - // Parse git status format: "XY filename" - char status = line[0]; - if (status == ' ') status = line[1]; // Check second column if first is space - - // Skip the status characters and space - char *filename = line + 3; - - // Store file info - viewer->files[viewer->file_count].status = status; - strncpy(viewer->files[viewer->file_count].filename, filename, MAX_FILENAME_LEN - 1); - viewer->files[viewer->file_count].filename[MAX_FILENAME_LEN - 1] = '\0'; - - viewer->file_count++; - } - - pclose(fp); - return viewer->file_count; + if (!viewer) + return 0; + + FILE *fp = popen("git status --porcelain 2>/dev/null", "r"); + if (!fp) + return 0; + + viewer->file_count = 0; + char line[512]; + + while (fgets(line, sizeof(line), fp) != NULL && + viewer->file_count < MAX_FILES) { + // Remove newline + char *newline = strchr(line, '\n'); + if (newline) + *newline = '\0'; + + if (strlen(line) < 3) + continue; + + // Parse git status format: "XY filename" + char status = line[0]; + if (status == ' ') + status = line[1]; // Check second column if first is space + + // Skip the status characters and space + char *filename = line + 3; + + // Store file info + viewer->files[viewer->file_count].status = status; + strncpy(viewer->files[viewer->file_count].filename, filename, + MAX_FILENAME_LEN - 1); + viewer->files[viewer->file_count].filename[MAX_FILENAME_LEN - 1] = '\0'; + + viewer->file_count++; + } + + pclose(fp); + return viewer->file_count; } /** * Check if a file is a new untracked file */ int is_new_file(const char *filename) { - char cmd[1024]; - snprintf(cmd, sizeof(cmd), "git ls-files --error-unmatch \"%s\" 2>/dev/null", filename); - - FILE *fp = popen(cmd, "r"); - if (!fp) return 1; // Assume new if we can't check - - char output[256]; - int is_tracked = (fgets(output, sizeof(output), fp) != NULL); - pclose(fp); - - return !is_tracked; // Return 1 if not tracked (new file) + char cmd[1024]; + snprintf(cmd, sizeof(cmd), "git ls-files --error-unmatch \"%s\" 2>/dev/null", + filename); + + FILE *fp = popen(cmd, "r"); + if (!fp) + return 1; // Assume new if we can't check + + char output[256]; + int is_tracked = (fgets(output, sizeof(output), fp) != NULL); + pclose(fp); + + return !is_tracked; // Return 1 if not tracked (new file) } /** * Load content of a new file and show all lines as additions */ int load_new_file_content(DiffViewer *viewer, const char *filename) { - if (!viewer || !filename) return 0; - - FILE *fp = fopen(filename, "r"); - if (!fp) return 0; - - viewer->diff_line_count = 0; - viewer->diff_scroll_offset = 0; - - // Add header line - DiffLine *header = &viewer->diff_lines[viewer->diff_line_count++]; - snprintf(header->line, sizeof(header->line), "@@ New file: %s @@", filename); - header->type = '@'; - header->line_number_old = 0; - header->line_number_new = 0; - - char line[1024]; - int line_number = 1; - - while (fgets(line, sizeof(line), fp) != NULL && viewer->diff_line_count < MAX_DIFF_LINES) { - // Remove newline - char *newline_pos = strchr(line, '\n'); - if (newline_pos) *newline_pos = '\0'; - - DiffLine *diff_line = &viewer->diff_lines[viewer->diff_line_count]; - - // Format as addition - snprintf(diff_line->line, sizeof(diff_line->line), "+%s", line); - diff_line->type = '+'; - diff_line->line_number_old = 0; - diff_line->line_number_new = line_number++; - - viewer->diff_line_count++; - } - - fclose(fp); - return viewer->diff_line_count; + if (!viewer || !filename) + return 0; + + FILE *fp = fopen(filename, "r"); + if (!fp) + return 0; + + viewer->diff_line_count = 0; + viewer->diff_scroll_offset = 0; + + // Add header line + DiffLine *header = &viewer->diff_lines[viewer->diff_line_count++]; + snprintf(header->line, sizeof(header->line), "@@ New file: %s @@", filename); + header->type = '@'; + header->line_number_old = 0; + header->line_number_new = 0; + + char line[1024]; + int line_number = 1; + + while (fgets(line, sizeof(line), fp) != NULL && + viewer->diff_line_count < MAX_DIFF_LINES) { + // Remove newline + char *newline_pos = strchr(line, '\n'); + if (newline_pos) + *newline_pos = '\0'; + + DiffLine *diff_line = &viewer->diff_lines[viewer->diff_line_count]; + + // Format as addition + snprintf(diff_line->line, sizeof(diff_line->line), "+%s", line); + diff_line->type = '+'; + diff_line->line_number_old = 0; + diff_line->line_number_new = line_number++; + + viewer->diff_line_count++; + } + + fclose(fp); + return viewer->diff_line_count; } /** * Load diff for a specific file */ int load_file_diff(DiffViewer *viewer, const char *filename) { - if (!viewer || !filename) return 0; - - // Check if this is a new untracked file - if (is_new_file(filename)) { - return load_new_file_content(viewer, filename); + if (!viewer || !filename) + return 0; + + // Check if this is a new untracked file + if (is_new_file(filename)) { + return load_new_file_content(viewer, filename); + } + + char cmd[1024]; + snprintf(cmd, sizeof(cmd), "git diff HEAD -- \"%s\" 2>/dev/null", filename); + + FILE *fp = popen(cmd, "r"); + if (!fp) + return 0; + + viewer->diff_line_count = 0; + viewer->diff_scroll_offset = 0; + + char line[1024]; + int old_line = 0, new_line = 0; + + while (fgets(line, sizeof(line), fp) != NULL && + viewer->diff_line_count < MAX_DIFF_LINES) { + // Remove newline + char *newline_pos = strchr(line, '\n'); + if (newline_pos) + *newline_pos = '\0'; + + DiffLine *diff_line = &viewer->diff_lines[viewer->diff_line_count]; + + // Parse diff line + if (line[0] == '@' && line[1] == '@') { + // Hunk header: @@-old_start,old_count +new_start,new_count@@ + sscanf(line, "@@-%d,%*d +%d,%*d@@", &old_line, &new_line); + old_line--; // Will be incremented before use + new_line--; + + strncpy(diff_line->line, line, sizeof(diff_line->line) - 1); + diff_line->line[sizeof(diff_line->line) - 1] = '\0'; + diff_line->type = '@'; + diff_line->line_number_old = old_line; + diff_line->line_number_new = new_line; + } else if (line[0] == '+') { + new_line++; + strncpy(diff_line->line, line, sizeof(diff_line->line) - 1); + diff_line->line[sizeof(diff_line->line) - 1] = '\0'; + diff_line->type = '+'; + diff_line->line_number_old = old_line; + diff_line->line_number_new = new_line; + } else if (line[0] == '-') { + old_line++; + strncpy(diff_line->line, line, sizeof(diff_line->line) - 1); + diff_line->line[sizeof(diff_line->line) - 1] = '\0'; + diff_line->type = '-'; + diff_line->line_number_old = old_line; + diff_line->line_number_new = new_line; + } else if (line[0] == ' ') { + old_line++; + new_line++; + strncpy(diff_line->line, line, sizeof(diff_line->line) - 1); + diff_line->line[sizeof(diff_line->line) - 1] = '\0'; + diff_line->type = ' '; + diff_line->line_number_old = old_line; + diff_line->line_number_new = new_line; + } else { + // Skip other lines (file headers, etc.) + continue; } - - char cmd[1024]; - snprintf(cmd, sizeof(cmd), "git diff HEAD -- \"%s\" 2>/dev/null", filename); - - FILE *fp = popen(cmd, "r"); - if (!fp) return 0; - - viewer->diff_line_count = 0; - viewer->diff_scroll_offset = 0; - - char line[1024]; - int old_line = 0, new_line = 0; - - while (fgets(line, sizeof(line), fp) != NULL && viewer->diff_line_count < MAX_DIFF_LINES) { - // Remove newline - char *newline_pos = strchr(line, '\n'); - if (newline_pos) *newline_pos = '\0'; - - DiffLine *diff_line = &viewer->diff_lines[viewer->diff_line_count]; - - // Parse diff line - if (line[0] == '@' && line[1] == '@') { - // Hunk header: @@-old_start,old_count +new_start,new_count@@ - sscanf(line, "@@-%d,%*d +%d,%*d@@", &old_line, &new_line); - old_line--; // Will be incremented before use - new_line--; - - strncpy(diff_line->line, line, sizeof(diff_line->line) - 1); - diff_line->line[sizeof(diff_line->line) - 1] = '\0'; - diff_line->type = '@'; - diff_line->line_number_old = old_line; - diff_line->line_number_new = new_line; - } else if (line[0] == '+') { - new_line++; - strncpy(diff_line->line, line, sizeof(diff_line->line) - 1); - diff_line->line[sizeof(diff_line->line) - 1] = '\0'; - diff_line->type = '+'; - diff_line->line_number_old = old_line; - diff_line->line_number_new = new_line; - } else if (line[0] == '-') { - old_line++; - strncpy(diff_line->line, line, sizeof(diff_line->line) - 1); - diff_line->line[sizeof(diff_line->line) - 1] = '\0'; - diff_line->type = '-'; - diff_line->line_number_old = old_line; - diff_line->line_number_new = new_line; - } else if (line[0] == ' ') { - old_line++; - new_line++; - strncpy(diff_line->line, line, sizeof(diff_line->line) - 1); - diff_line->line[sizeof(diff_line->line) - 1] = '\0'; - diff_line->type = ' '; - diff_line->line_number_old = old_line; - diff_line->line_number_new = new_line; - } else { - // Skip other lines (file headers, etc.) - continue; - } - - viewer->diff_line_count++; - } - - pclose(fp); - - // If no diff content but file exists, it might be a new file added to git - if (viewer->diff_line_count == 0) { - return load_new_file_content(viewer, filename); - } - - return viewer->diff_line_count; + + viewer->diff_line_count++; + } + + pclose(fp); + + // If no diff content but file exists, it might be a new file added to git + if (viewer->diff_line_count == 0) { + return load_new_file_content(viewer, filename); + } + + return viewer->diff_line_count; } /** * Render the diff viewer interface */ void render_diff_viewer(DiffViewer *viewer) { - if (!viewer) return; - - // Clear screen - printf("\033[2J\033[H"); - - // Title bar - printf(ANSI_COLOR_CYAN "Git Diff Viewer" ANSI_COLOR_RESET); + if (!viewer) + return; + + // Clear screen + printf("\033[2J\033[H"); + + // Title bar + printf(ANSI_COLOR_CYAN "Git Diff Viewer" ANSI_COLOR_RESET); + if (viewer->current_mode == MODE_FILE_LIST) { + printf(" - Use ↑/↓ to navigate files, Enter to view, q to quit\n"); + } else { + printf(" - Use ↑/↓ to scroll, ESC to return to file list, q to quit\n"); + } + printf("─%.0*s\n", viewer->terminal_width - 1, + "─────────────────────────────────────────────────────────────────────" + "───────────"); + + int start_row = 2; + int available_height = viewer->terminal_height - start_row - 1; + + // Render file list (left panel) + for (int i = 0; i < available_height && i < viewer->file_count; i++) { + printf("\033[%d;1H", start_row + i + 1); // Position cursor + + if (i == viewer->selected_file) { + if (viewer->current_mode == MODE_FILE_LIST) { + printf(ANSI_COLOR_CYAN "► " ANSI_COLOR_RESET); + } else { + printf(ANSI_COLOR_GREEN "► " ANSI_COLOR_RESET); + } + } else { + printf(" "); + } + + // Status indicator + char status = viewer->files[i].status; + if (status == 'M') { + printf(ANSI_COLOR_YELLOW "M" ANSI_COLOR_RESET); + } else if (status == 'A') { + printf(ANSI_COLOR_GREEN "A" ANSI_COLOR_RESET); + } else if (status == 'D') { + printf(ANSI_COLOR_RED "D" ANSI_COLOR_RESET); + } else { + printf("%c", status); + } + + printf(" "); + + // Filename (truncated to fit panel) + char truncated_name[256]; + int max_name_len = viewer->file_panel_width - 6; + if ((int)strlen(viewer->files[i].filename) > max_name_len) { + strncpy(truncated_name, viewer->files[i].filename, max_name_len - 3); + truncated_name[max_name_len - 3] = '\0'; + strcat(truncated_name, "..."); + } else { + strcpy(truncated_name, viewer->files[i].filename); + } + + printf("%-*s", max_name_len, truncated_name); + + // Vertical separator + printf("│"); + } + + // Render diff content (right panel) + if (viewer->current_mode == MODE_FILE_CONTENT && viewer->file_count > 0 && + viewer->selected_file < viewer->file_count) { + int diff_panel_start = viewer->file_panel_width + 1; + int diff_panel_width = viewer->terminal_width - diff_panel_start; + + for (int i = 0; i < available_height && + (i + viewer->diff_scroll_offset) < viewer->diff_line_count; + i++) { + + int line_idx = i + viewer->diff_scroll_offset; + DiffLine *line = &viewer->diff_lines[line_idx]; + + printf("\033[%d;%dH", start_row + i + 1, diff_panel_start + 1); + + // Color code based on line type + if (line->type == '+') { + printf(ANSI_COLOR_GREEN); + } else if (line->type == '-') { + printf(ANSI_COLOR_RED); + } else if (line->type == '@') { + printf(ANSI_COLOR_CYAN); + } + + // Truncate line to fit panel + char display_line[1024]; + int max_len = diff_panel_width - 1; + if ((int)strlen(line->line) > max_len) { + strncpy(display_line, line->line, max_len - 3); + display_line[max_len - 3] = '\0'; + strcat(display_line, "..."); + } else { + strcpy(display_line, line->line); + } + + printf("%-*s", max_len, display_line); + printf(ANSI_COLOR_RESET); + } + } else if (viewer->current_mode == MODE_FILE_LIST) { + // Show help text in the right panel when in file list mode + int diff_panel_start = viewer->file_panel_width + 1; + printf("\033[%d;%dH", start_row + 2, diff_panel_start + 3); + printf(ANSI_COLOR_YELLOW + "Select a file and press Enter to view its diff" ANSI_COLOR_RESET); + } + + // Status line at bottom + printf("\033[%d;1H", viewer->terminal_height); + if (viewer->file_count > 0) { if (viewer->current_mode == MODE_FILE_LIST) { - printf(" - Use ↑/↓ to navigate files, Enter to view, q to quit\n"); + printf("File %d/%d: %s [File List Mode]", viewer->selected_file + 1, + viewer->file_count, viewer->files[viewer->selected_file].filename); } else { - printf(" - Use ↑/↓ to scroll, ESC to return to file list, q to quit\n"); + printf("File %d/%d: %s [Content Mode - Line %d/%d]", + viewer->selected_file + 1, viewer->file_count, + viewer->files[viewer->selected_file].filename, + viewer->diff_scroll_offset + 1, + viewer->diff_line_count > 0 ? viewer->diff_line_count : 1); } - printf("─%.0*s\n", viewer->terminal_width - 1, "────────────────────────────────────────────────────────────────────────────────"); - - int start_row = 2; - int available_height = viewer->terminal_height - start_row - 1; - - // Render file list (left panel) - for (int i = 0; i < available_height && i < viewer->file_count; i++) { - printf("\033[%d;1H", start_row + i + 1); // Position cursor - - if (i == viewer->selected_file) { - if (viewer->current_mode == MODE_FILE_LIST) { - printf(ANSI_COLOR_CYAN "► " ANSI_COLOR_RESET); - } else { - printf(ANSI_COLOR_GREEN "► " ANSI_COLOR_RESET); - } - } else { - printf(" "); - } - - // Status indicator - char status = viewer->files[i].status; - if (status == 'M') { - printf(ANSI_COLOR_YELLOW "M" ANSI_COLOR_RESET); - } else if (status == 'A') { - printf(ANSI_COLOR_GREEN "A" ANSI_COLOR_RESET); - } else if (status == 'D') { - printf(ANSI_COLOR_RED "D" ANSI_COLOR_RESET); - } else { - printf("%c", status); - } - - printf(" "); - - // Filename (truncated to fit panel) - char truncated_name[256]; - int max_name_len = viewer->file_panel_width - 6; - if ((int)strlen(viewer->files[i].filename) > max_name_len) { - strncpy(truncated_name, viewer->files[i].filename, max_name_len - 3); - truncated_name[max_name_len - 3] = '\0'; - strcat(truncated_name, "..."); - } else { - strcpy(truncated_name, viewer->files[i].filename); - } - - printf("%-*s", max_name_len, truncated_name); - - // Vertical separator - printf("│"); - } - - // Render diff content (right panel) - if (viewer->current_mode == MODE_FILE_CONTENT && - viewer->file_count > 0 && viewer->selected_file < viewer->file_count) { - int diff_panel_start = viewer->file_panel_width + 1; - int diff_panel_width = viewer->terminal_width - diff_panel_start; - - for (int i = 0; i < available_height && - (i + viewer->diff_scroll_offset) < viewer->diff_line_count; i++) { - - int line_idx = i + viewer->diff_scroll_offset; - DiffLine *line = &viewer->diff_lines[line_idx]; - - printf("\033[%d;%dH", start_row + i + 1, diff_panel_start + 1); - - // Color code based on line type - if (line->type == '+') { - printf(ANSI_COLOR_GREEN); - } else if (line->type == '-') { - printf(ANSI_COLOR_RED); - } else if (line->type == '@') { - printf(ANSI_COLOR_CYAN); - } - - // Truncate line to fit panel - char display_line[1024]; - int max_len = diff_panel_width - 1; - if ((int)strlen(line->line) > max_len) { - strncpy(display_line, line->line, max_len - 3); - display_line[max_len - 3] = '\0'; - strcat(display_line, "..."); - } else { - strcpy(display_line, line->line); - } - - printf("%-*s", max_len, display_line); - printf(ANSI_COLOR_RESET); - } - } else if (viewer->current_mode == MODE_FILE_LIST) { - // Show help text in the right panel when in file list mode - int diff_panel_start = viewer->file_panel_width + 1; - printf("\033[%d;%dH", start_row + 2, diff_panel_start + 3); - printf(ANSI_COLOR_YELLOW "Select a file and press Enter to view its diff" ANSI_COLOR_RESET); - } - - // Status line at bottom - printf("\033[%d;1H", viewer->terminal_height); - if (viewer->file_count > 0) { - if (viewer->current_mode == MODE_FILE_LIST) { - printf("File %d/%d: %s [File List Mode]", - viewer->selected_file + 1, - viewer->file_count, - viewer->files[viewer->selected_file].filename); - } else { - printf("File %d/%d: %s [Content Mode - Line %d/%d]", - viewer->selected_file + 1, - viewer->file_count, - viewer->files[viewer->selected_file].filename, - viewer->diff_scroll_offset + 1, - viewer->diff_line_count > 0 ? viewer->diff_line_count : 1); - } - } else { - printf("No changed files found"); - } - - fflush(stdout); + } else { + printf("No changed files found"); + } + + fflush(stdout); } /** * Handle keyboard input for navigation */ int handle_diff_input(DiffViewer *viewer, char key) { - if (!viewer) return 0; - - int available_height = viewer->terminal_height - 3; - - switch (key) { - case 'q': - case 'Q': - return 0; // Exit - - case 27: // ESC - if (viewer->current_mode == MODE_FILE_CONTENT) { - viewer->current_mode = MODE_FILE_LIST; - } else { - return 0; // Exit if already in file list mode - } - break; - - case 'k': - case 65: // Up arrow - if (viewer->current_mode == MODE_FILE_LIST) { - // Navigate file list - if (viewer->selected_file > 0) { - viewer->selected_file--; - } - } else { - // Scroll diff content up - if (viewer->diff_scroll_offset > 0) { - viewer->diff_scroll_offset--; - } - } - break; - - case 'j': - case 66: // Down arrow - if (viewer->current_mode == MODE_FILE_LIST) { - // Navigate file list - if (viewer->selected_file < viewer->file_count - 1) { - viewer->selected_file++; - } - } else { - // Scroll diff content down - if (viewer->diff_line_count > available_height && - viewer->diff_scroll_offset < viewer->diff_line_count - available_height) { - viewer->diff_scroll_offset++; - } - } - break; - - case '\n': - case '\r': - if (viewer->current_mode == MODE_FILE_LIST && viewer->file_count > 0) { - // Enter file content mode and load diff - viewer->current_mode = MODE_FILE_CONTENT; - viewer->diff_scroll_offset = 0; // Reset scroll position - load_file_diff(viewer, viewer->files[viewer->selected_file].filename); - } - break; + if (!viewer) + return 0; + + int available_height = viewer->terminal_height - 3; + + switch (key) { + case 'q': + case 'Q': + return 0; // Exit + + case 27: // ESC + if (viewer->current_mode == MODE_FILE_CONTENT) { + viewer->current_mode = MODE_FILE_LIST; + } else { + return 0; // Exit if already in file list mode } - - return 1; // Continue + break; + + case 'k': + case 65: // Up arrow + if (viewer->current_mode == MODE_FILE_LIST) { + // Navigate file list + if (viewer->selected_file > 0) { + viewer->selected_file--; + } + } else { + // Scroll diff content up + if (viewer->diff_scroll_offset > 0) { + viewer->diff_scroll_offset--; + } + } + break; + + case 'j': + case 66: // Down arrow + if (viewer->current_mode == MODE_FILE_LIST) { + // Navigate file list + if (viewer->selected_file < viewer->file_count - 1) { + viewer->selected_file++; + } + } else { + // Scroll diff content down + if (viewer->diff_line_count > available_height && + viewer->diff_scroll_offset < + viewer->diff_line_count - available_height) { + viewer->diff_scroll_offset++; + } + } + break; + + case '\n': + case '\r': + if (viewer->current_mode == MODE_FILE_LIST && viewer->file_count > 0) { + // Enter file content mode and load diff + viewer->current_mode = MODE_FILE_CONTENT; + viewer->diff_scroll_offset = 0; // Reset scroll position + load_file_diff(viewer, viewer->files[viewer->selected_file].filename); + } + break; + } + + return 1; // Continue } /** * Set terminal to raw mode for interactive input */ void set_raw_mode(struct termios *orig_termios) { - tcgetattr(STDIN_FILENO, orig_termios); - - struct termios raw = *orig_termios; - raw.c_lflag &= ~(ICANON | ECHO); - raw.c_cc[VTIME] = 0; - raw.c_cc[VMIN] = 1; - - tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); + tcgetattr(STDIN_FILENO, orig_termios); + + struct termios raw = *orig_termios; + raw.c_lflag &= ~(ICANON | ECHO); + raw.c_cc[VTIME] = 0; + raw.c_cc[VMIN] = 1; + + tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); } /** * Restore terminal to original mode */ void restore_terminal_mode(struct termios *orig_termios) { - tcsetattr(STDIN_FILENO, TCSAFLUSH, orig_termios); + tcsetattr(STDIN_FILENO, TCSAFLUSH, orig_termios); } /** * Run the interactive diff viewer */ int run_diff_viewer(void) { - DiffViewer viewer; - struct termios orig_termios; - - if (!init_diff_viewer(&viewer)) { - printf("Failed to initialize diff viewer\n"); - return 1; - } - - if (get_changed_files(&viewer) == 0) { - printf("No changed files found\n"); - return 1; - } - - // Don't load initial file diff - start in file list mode - - set_raw_mode(&orig_termios); - - int running = 1; - while (running) { - render_diff_viewer(&viewer); - - char c = getchar(); - - // Handle escape sequences for arrow keys - if (c == 27) { - char seq[3]; - if (read(STDIN_FILENO, &seq[0], 1) == 1 && seq[0] == '[') { - if (read(STDIN_FILENO, &seq[1], 1) == 1) { - running = handle_diff_input(&viewer, seq[1]); - } - } else { - running = handle_diff_input(&viewer, c); - } - } else { - running = handle_diff_input(&viewer, c); + DiffViewer viewer; + struct termios orig_termios; + + if (!init_diff_viewer(&viewer)) { + printf("Failed to initialize diff viewer\n"); + return 1; + } + + if (get_changed_files(&viewer) == 0) { + printf("No changed files found\n"); + return 1; + } + + // Don't load initial file diff - start in file list mode + + set_raw_mode(&orig_termios); + + int running = 1; + while (running) { + render_diff_viewer(&viewer); + + char c = getchar(); + + // Handle escape sequences for arrow keys + if (c == 27) { + char seq[3]; + if (read(STDIN_FILENO, &seq[0], 1) == 1 && seq[0] == '[') { + if (read(STDIN_FILENO, &seq[1], 1) == 1) { + running = handle_diff_input(&viewer, seq[1]); } + } else { + running = handle_diff_input(&viewer, c); + } + } else { + running = handle_diff_input(&viewer, c); } - - restore_terminal_mode(&orig_termios); - printf("\033[2J\033[H"); // Clear screen - - cleanup_diff_viewer(&viewer); - return 0; + } + + restore_terminal_mode(&orig_termios); + printf("\033[2J\033[H"); // Clear screen + + cleanup_diff_viewer(&viewer); + return 0; } /** * Clean up diff viewer resources */ void cleanup_diff_viewer(DiffViewer *viewer) { - // Nothing to clean up for now, but good to have for future expansion - (void)viewer; -} \ No newline at end of file + // Nothing to clean up for now, but good to have for future expansion + (void)viewer; +}