From cb0c4aea06f15faa403b30d60e7e854ab575c17f Mon Sep 17 00:00:00 2001 From: marcusDenslow Date: Fri, 24 Oct 2025 19:43:40 +0200 Subject: [PATCH] removing ai generated documentation. it served it's purpose to get the project up and running fast, but is not descriptive enough. focus going forwards is going to be on adding documentation --- include/builtins.h | 11 - include/common.h | 4 - include/data/aliases.h | 4 - include/data/bookmarks.h | 4 - include/data/favorite_cities.h | 4 - include/data/structured_data.h | 4 - include/git/git_integration.h | 77 ------- include/history/persistent_history.h | 4 - include/input/autocorrect.h | 29 --- include/input/line_reader.h | 38 ---- include/input/tab_complete.h | 13 -- include/search/filters.h | 42 ---- include/search/fzf_native.h | 37 ---- include/search/grep.h | 28 --- include/shell.h | 98 --------- include/ui/diff_viewer.h | 40 ---- include/ui/ncurses_diff_viewer.h | 172 ---------------- include/utils/countdown_timer.h | 36 ---- include/utils/timer.h | 25 --- shell | Bin 598760 -> 598632 bytes src/builtins.c | 107 ---------- src/data/aliases.c | 46 ----- src/data/bookmarks.c | 47 ----- src/data/favorite_cities.c | 38 ---- src/data/structured_data.c | 33 --- src/git/git_integration.c | 34 ---- src/history/persistent_history.c | 62 ------ src/input/autocorrect.c | 31 --- src/input/line_reader.c | 53 ----- src/input/tab_complete.c | 40 ---- src/main.c | 18 +- src/search/filters.c | 23 --- src/search/fzf_native.c | 50 ----- src/search/grep.c | 16 -- src/search/ripgrep.c | 51 ----- src/shell.c | 56 ------ src/system/ps_command.c | 16 -- src/ui/diff_viewer.c | 40 ---- src/ui/ncurses_diff_viewer.c | 288 --------------------------- src/ui/themes.c | 37 ---- src/utils/countdown_timer.c | 34 ---- src/utils/timer.c | 25 --- src/utils/weather.c | 9 - 43 files changed, 1 insertion(+), 1823 deletions(-) diff --git a/include/builtins.h b/include/builtins.h index 291e6f1..d548c30 100644 --- a/include/builtins.h +++ b/include/builtins.h @@ -1,7 +1,3 @@ -/** - * builtins.h - * Declarations for all built-in shell commands - */ #ifndef BUILTINS_H #define BUILTINS_H @@ -90,13 +86,6 @@ int lsh_num_builtins(void); extern char *builtin_str[]; extern int (*builtin_func[])(char **); -/** - * Extract a string value from a JSON object - * - * @param json The JSON string to parse - * @param key The key to find - * @return Allocated string containing the value (caller must free) - */ char *extract_json_string(const char *json, const char *key); #endif // BUILTINS_H diff --git a/include/common.h b/include/common.h index 47609b0..50ce985 100644 --- a/include/common.h +++ b/include/common.h @@ -1,7 +1,3 @@ -/** - * common.h - * Common includes, defines and macros used throughout the shell - */ #ifndef COMMON_H #define COMMON_H diff --git a/include/data/aliases.h b/include/data/aliases.h index eb435c3..045aa6f 100644 --- a/include/data/aliases.h +++ b/include/data/aliases.h @@ -1,7 +1,3 @@ -/** - * aliases.h - * Definitions for shell alias functionality - */ #ifndef ALIASES_H #define ALIASES_H diff --git a/include/data/bookmarks.h b/include/data/bookmarks.h index 715e5fe..39b6fd0 100644 --- a/include/data/bookmarks.h +++ b/include/data/bookmarks.h @@ -1,7 +1,3 @@ -/** - * bookmarks.h - * Functions for managing directory bookmarks - */ #ifndef BOOKMARKS_H #define BOOKMARKS_H diff --git a/include/data/favorite_cities.h b/include/data/favorite_cities.h index 1ff21d2..be01acb 100644 --- a/include/data/favorite_cities.h +++ b/include/data/favorite_cities.h @@ -1,7 +1,3 @@ -/** - * favorite_cities.h - * Functions for managing favorite cities for weather lookups - */ #ifndef FAVORITE_CITIES_H #define FAVORITE_CITIES_H diff --git a/include/data/structured_data.h b/include/data/structured_data.h index 15680f9..6067f77 100644 --- a/include/data/structured_data.h +++ b/include/data/structured_data.h @@ -1,7 +1,3 @@ -/** - * structured_data.h - * Definitions for structured data representation and manipulation - */ #ifndef STRUCTURED_DATA_H #define STRUCTURED_DATA_H diff --git a/include/git/git_integration.h b/include/git/git_integration.h index 619e842..9f505ce 100644 --- a/include/git/git_integration.h +++ b/include/git/git_integration.h @@ -1,26 +1,11 @@ -/** - * git_integration.h - * Functions for Git repository detection and information - */ #ifndef GIT_INTEGRATION_H #define GIT_INTEGRATION_H #include "common.h" -/** - * Initialize Git integration - */ void init_git_integration(void); -/** - * Check if the current directory is in a Git repository and get branch info - * - * @param branch_name Buffer to store branch name if found - * @param buffer_size Size of the branch_name buffer - * @param is_dirty Pointer to store dirty status flag (1 if repo has changes) - * @return 1 if in a Git repo, 0 otherwise - */ int get_git_branch(char *branch_name, size_t buffer_size, int *is_dirty); int get_last_commit(char *title, size_t title_size, char *hash, @@ -30,30 +15,10 @@ int get_recent_commit(char commits[][256], int count); int get_repo_url(char *url, size_t url_size); -/** - * Get the name of the Git repository - * - * @param repo_name Buffer to store repo name if found - * @param buffer_size Size of the repo_name buffer - * @return 1 if name was retrieved, 0 otherwise - */ int get_git_repo_name(char *repo_name, size_t buffer_size); -/** - * Get Git status for the current repository - * - * @return A string with the Git status or NULL if not in a repo - * (caller must free the returned string) - */ char *get_git_status(void); -/** - * Check if the current branch has diverged from its remote tracking branch - * - * @param commits_ahead Pointer to store number of commits ahead of remote - * @param commits_behind Pointer to store number of commits behind remote - * @return 1 if diverged (both ahead and behind > 0), 0 otherwise - */ int check_branch_divergence(int *commits_ahead, int *commits_behind); int create_git_stash(void); @@ -62,58 +27,16 @@ int create_git_stash_with_name(const char *stash_name); int get_git_stashes(char stashed[][512], int max_stashes); -/** - * Apply a git stash by index (keeps stash in list) - * - * @param stash_index Index of stash to apply (0 = most recent) - * @return 1 if stash was applied successfully, 0 otherwise - */ int apply_git_stash(int stash_index); -/** - * Pop a git stash by index (applies and removes stash from list) - * - * @param stash_index Index of stash to pop (0 = most recent) - * @return 1 if stash was popped successfully, 0 otherwise - */ int pop_git_stash(int stash_index); -/** - * Drop a git stash by index (removes stash without applying) - * - * @param stash_index Index of stash to drop (0 = most recent) - * @return 1 if stash was dropped successfully, 0 otherwise - */ int drop_git_stash(int stash_index); -/** - * Get detailed commit information including diff - * - * @param commit_hash The commit hash to get info for - * @param commit_info Buffer to store formatted commit info - * @param info_size Size of commit_info buffer - * @return 1 if successful, 0 otherwise - */ int get_commit_details(const char *commit_hash, char *commit_info, size_t info_size); -/** - * Get stash diff information - * - * @param stash_index Index of stash to get diff for - * @param stash_diff Buffer to store formatted stash diff - * @param diff_size Size of stash_diff buffer - * @return 1 if successful, 0 otherwise - */ int get_stash_diff(int stash_index, char *stash_diff, size_t diff_size); -/** - * Get commit history for a specific branch - * - * @param branch_name The branch name to get commits for - * @param commits Array to store commit information - * @param max_commits Maximum number of commits to retrieve - * @return Number of commits retrieved - */ int get_branch_commits(const char *branch_name, char commits[][2048], int max_commits); #endif // GIT_INTEGRATION_H diff --git a/include/history/persistent_history.h b/include/history/persistent_history.h index 00d1fd0..634eb60 100644 --- a/include/history/persistent_history.h +++ b/include/history/persistent_history.h @@ -1,7 +1,3 @@ -/** - * persistent_history.h - * Functions for persistent command history and frequency tracking - */ #ifndef PERSISTENT_HISTORY_H #define PERSISTENT_HISTORY_H diff --git a/include/input/autocorrect.h b/include/input/autocorrect.h index 9f31b7c..0b42256 100644 --- a/include/input/autocorrect.h +++ b/include/input/autocorrect.h @@ -1,7 +1,3 @@ -/** - * autocorrect.h - * Header for command auto-correction functionality - */ #ifndef AUTOCORRECT_H #define AUTOCORRECT_H @@ -10,41 +6,16 @@ #include "line_reader.h" #include -/** - * Calculate Levenshtein distance between two strings - * - * @param s1 First string - * @param s2 Second string - * @return Edit distance between the strings - */ int levenshtein_distance(const char *s1, const char *s2); -/** - * Helper function to find minimum of three integers - */ int min3(int a, int b, int c); -/** - * Initialize the autocorrect system - */ void init_autocorrect(void); -/** - * Shutdown the autocorrect system - */ void shutdown_autocorrect(void); -/** - * Check a command for possible corrections - * - * @param args Command arguments - * @return Corrected arguments array (must be freed by caller) or NULL if no correction - */ char **check_for_corrections(char **args); -/** - * Count the number of arguments in a NULL-terminated array - */ int count_args(char **args); #endif // AUTOCORRECT_H \ No newline at end of file diff --git a/include/input/line_reader.h b/include/input/line_reader.h index 6fcf768..46f7c43 100644 --- a/include/input/line_reader.h +++ b/include/input/line_reader.h @@ -1,59 +1,21 @@ -/** - * line_reader.h - * Functions for reading and parsing command lines - */ #ifndef LINE_READER_H #define LINE_READER_H #include "common.h" -/** - * Check if a command is valid - * - * @param cmd The command to check - * @return 1 if valid, 0 if not - */ int is_valid_command(const char *cmd); -/** - * Read a key from the terminal - * - * Handles special keys and escape sequences - */ int read_key(void); -/** - * Read a line of input from the user with tab completion - * - * @return The line read from stdin (must be freed by caller) - */ char *lsh_read_line(void); void generate_enhanced_prompt(char *prompt_buffer, size_t buffer_size); -/** - * Split a line into tokens - * - * @param line The line to split - * @return An array of tokens (must be freed by caller) - */ char **lsh_split_line(char *line); -/** - * Parse a token from a string, handling quoted strings - * - * @param str_ptr Pointer to the string to parse, will be updated - * @return The parsed token, or NULL if no more tokens - */ char *parse_token(char **str_ptr); -/** - * Split a line with pipes into separate command arrays - * - * @param line The line to split - * @return NULL-terminated array of NULL-terminated token arrays - */ char ***lsh_split_piped_line(char *line); #endif // LINE_READER_H diff --git a/include/input/tab_complete.h b/include/input/tab_complete.h index ea18e0c..013303e 100644 --- a/include/input/tab_complete.h +++ b/include/input/tab_complete.h @@ -1,16 +1,9 @@ -/** - * tab_complete.h - * Functions for tab completion and path suggestions - */ #ifndef TAB_COMPLETE_H #define TAB_COMPLETE_H #include "common.h" -/** - * Command context structure - */ typedef struct { int is_after_pipe; // Flag if cursor is right after a pipe int is_filter_command; // Flag if current command is a filter command @@ -38,9 +31,6 @@ typedef enum { ARG_TYPE_COMMAND, } ArgumentType; -/** - * Structure for command argument type information - */ typedef struct { char *command; // Command name ArgumentType arg_type; // Expected argument type @@ -50,9 +40,6 @@ typedef struct { // other matches } CommandArgInfo; -/** - * Structure for returning multiple suggestions - */ typedef struct { char **items; // Array of suggestion strings int count; // Number of suggestions diff --git a/include/search/filters.h b/include/search/filters.h index 84ac377..4e6b899 100644 --- a/include/search/filters.h +++ b/include/search/filters.h @@ -1,7 +1,3 @@ -/** - * filters.h - * Declarations for filter commands (where, sort-by, etc.) - */ // this is a test #ifndef FILTERS_H @@ -9,54 +5,16 @@ #include "structured_data.h" -/** - * Filter a table based on a condition (e.g., where size > 10kb) - * - * @param input The input table - * @param args Command arguments - * @return Filtered table or NULL on error - */ TableData *lsh_where(TableData *input, char **args); -/** - * Sort a table based on a column (e.g., sort-by size desc) - * - * @param input The input table - * @param args Command arguments - * @return Sorted table or NULL on error - */ TableData *lsh_sort_by(TableData *input, char **args); -/** - * Select specific columns from a table - * - * @param input The input table - * @param args Command arguments - * @return Table with selected columns or NULL on error - */ TableData *lsh_select(TableData *input, char **args); -/** - * Filter rows where a column contains a substring - * - * @param input The input table - * @param args Command arguments - * @return Filtered table or NULL on error - */ TableData *lsh_contains(TableData *input, char **args); -/** - * Limit the number of rows displayed - * - * @param input The input table - * @param args Command arguments - * @return Limited table or NULL on error - */ TableData *lsh_limit(TableData *input, char **args); -/** - * Case-insensitive substring search (strcasestr equivalent for Windows) - */ char *my_strcasestr(const char *haystack, const char *needle); // Export the filter arrays for the shell diff --git a/include/search/fzf_native.h b/include/search/fzf_native.h index d893acd..1abfbc1 100644 --- a/include/search/fzf_native.h +++ b/include/search/fzf_native.h @@ -1,7 +1,3 @@ -/** - * fzf_native.h - * Header for native fzf command-line fuzzy finder wrapper - */ #ifndef FZF_NATIVE_H #define FZF_NATIVE_H @@ -9,49 +5,16 @@ #include "builtins.h" #include "common.h" -/** - * Check if native fzf is installed on the system - * - * @return 1 if installed, 0 if not - */ int is_fzf_installed(void); -/** - * Display instructions for installing fzf - */ void show_fzf_install_instructions(void); -/** - * Run fzf with files from the current directory - * - * @param preview Enable preview window if 1 - * @param args Additional arguments for fzf - * @return Selected filename or NULL if canceled - */ char *run_native_fzf_files(int preview, char **args); -/** - * Run fzf with all files and directories from the current directory - * - * @param recursive Search recursively if 1 - * @param args Additional arguments for fzf - * @return Selected path or NULL if canceled - */ char *run_native_fzf_all(int recursive, char **args); -/** - * Run fzf with command history - * - * @return Selected command or NULL if canceled - */ char *run_native_fzf_history(void); -/** - * Command handler for the fzf command - * - * @param args Command arguments - * @return 1 to continue shell execution, 0 to exit shell - */ int lsh_fzf_native(char **args); #endif // FZF_NATIVE_H diff --git a/include/search/grep.h b/include/search/grep.h index 8f98789..cb26ebb 100644 --- a/include/search/grep.h +++ b/include/search/grep.h @@ -1,39 +1,11 @@ -/** - * grep.h - * Header for fast text searching in files with fuzzy matching capabilities - */ #ifndef GREP_H #define GREP_H #include "common.h" -/** - * Run grep with interactive interface - * - * Shows a split view with files on left, matches on right, and - * updates search results with each keystroke - */ void run_interactive_grep_session(void); -/** - * Command handler for the "grep" command - * - * Usage: grep [options] pattern [file/directory] - * Options: - * -n, --line-numbers Show line numbers - * -i, --ignore-case Ignore case distinctions - * -r, --recursive Search directories recursively - * -f, --fuzzy Use fuzzy matching instead of exact - * --file Specify files/directories to search (otherwise searches - * current dir) - * - * If called without arguments, opens an interactive grep UI with a split view - * that updates as you type. - * - * @param args Command arguments - * @return 1 to continue shell execution, 0 to exit shell - */ int lsh_grep(char **args); #endif // GREP_H diff --git a/include/shell.h b/include/shell.h index 36909c8..78d0e47 100644 --- a/include/shell.h +++ b/include/shell.h @@ -1,7 +1,3 @@ -/** - * shell.h - * Core shell functionality - */ #ifndef SHELL_H #define SHELL_H @@ -9,133 +5,39 @@ #include "common.h" #include "structured_data.h" -/** - * Display a welcome banner with BBQ sauce invention time - */ void display_welcome_banner(void); -/** - * Execute a command - * - * @param args Null-terminated array of command arguments - * @return 1 to continue the shell, 0 to exit - */ int lsh_execute(char **args); -/** - * Execute a pipeline of commands - * - * @param commands Null-terminated array of command arrays - * @return 1 to continue the shell, 0 to exit - */ int lsh_execute_piped(char ***commands); -/** - * Create a TableData structure from an ls command - * - * @param args Command arguments - * @return TableData pointer (must be freed by caller) or NULL on error - */ TableData* create_ls_table(char **args); -/** - * Parse input line into an array of commands (for pipelines) - * - * @param line Input command line - * @return Null-terminated array of command arrays - */ char*** lsh_split_commands(char *line); -/** - * Launch an external program - * - * @param args Null-terminated array of command arguments - * @return Always returns 1 (continue the shell) - */ int lsh_launch(char **args); -/** - * Main shell loop - */ void lsh_loop(void); -/** - * Free memory for a command array from lsh_split_commands - */ void free_commands(char ***commands); -/** - * Initialize the status bar at the bottom of the screen - * - * @param fd File descriptor for terminal (STDOUT_FILENO) - * @return 1 if successful, 0 on failure - */ int init_status_bar(int fd); -/** - * Temporarily hide the status bar before command execution - * - * @param fd File descriptor for terminal (STDOUT_FILENO) - */ void hide_status_bar(int fd); -/** - * Ensures there's space for the status bar by scrolling if needed - * - * @param fd File descriptor for terminal (STDOUT_FILENO) - */ void ensure_status_bar_space(int fd); -/** - * Check for terminal window resize and update status bar position - * - * @param fd File descriptor for terminal (STDOUT_FILENO) - */ void check_console_resize(int fd); -/** - * Update the status bar with Git information - * - * @param fd File descriptor for terminal (STDOUT_FILENO) - * @param git_info The Git information to display in the status bar - */ void update_status_bar(int fd, const char *git_info); -/** - * Get the name of the parent and current directories from a path - * - * @param cwd The current working directory path - * @param parent_dir_name Buffer to store the parent directory name - * @param current_dir_name Buffer to store the current directory name - * @param buf_size Size of the buffers - */ void get_path_display(const char *cwd, char *parent_dir_name, char *current_dir_name, size_t buf_size); -/** - * Initialize the terminal for raw mode - * - * @param orig_termios Original terminal settings to restore later - * @return File descriptor for terminal - */ int init_terminal(struct termios *orig_termios); -/** - * Restore terminal to original settings - * - * @param fd File descriptor for terminal - * @param orig_termios Original terminal settings - */ void restore_terminal(int fd, struct termios *orig_termios); -/** - * Get console dimensions - * - * @param fd File descriptor for terminal - * @param width Pointer to store width - * @param height Pointer to store height - * @return 1 on success, 0 on failure - */ int get_console_dimensions(int fd, int *width, int *height); #endif // SHELL_H \ No newline at end of file diff --git a/include/ui/diff_viewer.h b/include/ui/diff_viewer.h index a054834..458d630 100644 --- a/include/ui/diff_viewer.h +++ b/include/ui/diff_viewer.h @@ -1,7 +1,3 @@ -/** - * diff_viewer.h - * Interactive diff viewer for git changes - */ #ifndef DIFF_VIEWER_H #define DIFF_VIEWER_H @@ -43,64 +39,28 @@ typedef struct { ViewMode current_mode; } DiffViewer; -/** - * Initialize the diff viewer - */ int init_diff_viewer(DiffViewer *viewer); -/** - * Get list of changed files from git - */ int get_changed_files(DiffViewer *viewer); -/** - * Check if a file is a new untracked file - */ int is_new_file(const char *filename); -/** - * Load content of a new file and show all lines as additions - */ int load_new_file_content(DiffViewer *viewer, const char *filename); -/** - * Load diff for a specific file - */ int load_file_diff(DiffViewer *viewer, const char *filename); -/** - * Render the diff viewer interface - */ void render_diff_viewer(DiffViewer *viewer); -/** - * Handle keyboard input for navigation - */ int handle_diff_input(DiffViewer *viewer, char key); -/** - * Run the interactive diff viewer - */ int run_diff_viewer(void); -/** - * Clean up diff viewer resources - */ void cleanup_diff_viewer(DiffViewer *viewer); -/** - * Get terminal size - */ void get_terminal_size(int *width, int *height); -/** - * Set terminal to raw mode for interactive input - */ void set_raw_mode(struct termios *orig_termios); -/** - * Restore terminal to original mode - */ void restore_terminal_mode(struct termios *orig_termios); #endif // DIFF_VIEWER_H \ No newline at end of file diff --git a/include/ui/ncurses_diff_viewer.h b/include/ui/ncurses_diff_viewer.h index 1c7a2bd..3b66528 100644 --- a/include/ui/ncurses_diff_viewer.h +++ b/include/ui/ncurses_diff_viewer.h @@ -1,7 +1,3 @@ -/** - * ncurses_diff_viewer.h - * NCurses-based interactive diff viewer for git changes - */ #ifndef NCURSES_DIFF_VIEWER_H #define NCURSES_DIFF_VIEWER_H @@ -212,113 +208,50 @@ typedef struct { } NCursesDiffViewer; -/** - * Initialize the ncurses diff viewer - */ int init_ncurses_diff_viewer(NCursesDiffViewer *viewer); -/** - * Get list of changed files from git - */ int get_ncurses_changed_files(NCursesDiffViewer *viewer); -/** - * Load full file content with diff highlighting - */ int load_full_file_with_diff(NCursesDiffViewer *viewer, const char *filename); -/** - * Render the file list window - */ void render_file_list_window(NCursesDiffViewer *viewer); -/** - * Render the file content window - */ void render_file_content_window(NCursesDiffViewer *viewer); -/** - * Handle keyboard input for navigation - */ int handle_ncurses_diff_input(NCursesDiffViewer *viewer, int key); -/** - * Run the ncurses diff viewer - */ int run_ncurses_diff_viewer(void); -/** - * Clean up ncurses diff viewer resources - */ void cleanup_ncurses_diff_viewer(NCursesDiffViewer *viewer); -/** - * Create temporary file with current working version - */ int create_temp_file_with_changes(const char *filename, char *temp_path); -/** - * Create temporary file with git HEAD version - */ int create_temp_file_git_version(const char *filename, char *temp_path); -/** - * Get commit history - */ int get_commit_history(NCursesDiffViewer *viewer); -/** - * Toggle file marking for commit - */ void toggle_file_mark(NCursesDiffViewer *viewer, int file_index); -/** - * Mark all files for commit - */ void mark_all_files(NCursesDiffViewer *viewer); -/** - * Commit marked files with title and message - */ int commit_marked_files(NCursesDiffViewer *viewer, const char *commit_title, const char *commit_message); -/** - * Push specific commit - */ int push_commit(NCursesDiffViewer *viewer, int commit_index); -/** - * Pull commits from remote - */ int pull_commits(NCursesDiffViewer *viewer); -/** - * Render the commit list window - */ void render_commit_list_window(NCursesDiffViewer *viewer); -/** - * Get commit title and message input from user - */ int get_commit_title_input(char *title, int max_len, char *message, int max_message_len); -/** - * Draw a box with rounded corners - */ void draw_rounded_box(WINDOW *win); -/** - * Render the status bar - */ void render_status_bar(NCursesDiffViewer *viewer); void render_branch_list_window(NCursesDiffViewer *viewer); -/** - * Update sync status and check for new files - */ void update_sync_status(NCursesDiffViewer *viewer); int get_ncurses_git_stashes(NCursesDiffViewer *viewer); @@ -362,76 +295,34 @@ int get_stash_name_input(char *stash_name, int max_len); void render_stash_list_window(NCursesDiffViewer *viewer); -/** - * Load commit details for viewing - */ int load_commit_for_viewing(NCursesDiffViewer *viewer, const char *commit_hash); -/** - * Load stash details for viewing - */ int load_stash_for_viewing(NCursesDiffViewer *viewer, int stash_index); -/** - * Load commits for a specific branch for the hover preview - */ int load_branch_commits(NCursesDiffViewer *viewer, const char *branch_name); -/** - * Parse branch commits into navigable lines for branch view mode - */ int parse_branch_commits_to_lines(NCursesDiffViewer *viewer); -/** - * Start background fetch process - */ void start_background_fetch(NCursesDiffViewer *viewer); -/** - * Check if background fetch is complete and update UI accordingly - */ void check_background_fetch(NCursesDiffViewer *viewer); -/** - * Move cursor up/down while skipping empty lines - */ void move_cursor_smart(NCursesDiffViewer *viewer, int direction); -/** - * Move cursor up/down in unstaged pane with proper scrolling - */ void move_cursor_smart_unstaged(NCursesDiffViewer *viewer, int direction); -/** - * Move cursor up/down in staged pane with proper scrolling - */ void move_cursor_smart_staged(NCursesDiffViewer *viewer, int direction); -/** - * Helper function to wrap a long line into multiple display lines - */ int wrap_line_to_width(const char *input_line, char wrapped_lines[][1024], int max_lines, int width); -/** - * Render a single line with proper wrapping and coloring - */ int render_wrapped_line(WINDOW *win, const char *line, int start_y, int start_x, int width, int max_rows, int color_pair, int reverse); -/** - * Calculate how many display lines a wrapped line will take - */ int calculate_wrapped_line_height(const char *line, int width); -/** - * Load file preview showing the top of the file content - */ int load_file_preview(NCursesDiffViewer *viewer, const char *filename); -/** - * Update preview based on current mode and selection - */ void update_preview_for_current_selection(NCursesDiffViewer *viewer); int get_single_input(const char *title, const char *prompt, char *input, @@ -462,109 +353,46 @@ int commit_staged_changes_only(NCursesDiffViewer *viewer, void rebuild_staged_view_from_git(NCursesDiffViewer *viewer); -/** - * Initialize fuzzy search state - */ void init_fuzzy_search(NCursesDiffViewer *viewer); -/** - * Cleanup fuzzy search windows - */ void cleanup_fuzzy_search(NCursesDiffViewer *viewer); -/** - * Enter fuzzy search mode - */ void enter_fuzzy_search_mode(NCursesDiffViewer *viewer); -/** - * Exit fuzzy search mode - */ void exit_fuzzy_search_mode(NCursesDiffViewer *viewer); -/** - * Update fuzzy search filter based on current query - */ void update_fuzzy_filter(NCursesDiffViewer *viewer); -/** - * Render fuzzy search UI - */ void render_fuzzy_search(NCursesDiffViewer *viewer); -/** - * Render fuzzy search input field only - */ void render_fuzzy_input(NCursesDiffViewer *viewer); -/** - * Render fuzzy search file list content only - */ void render_fuzzy_list_content(NCursesDiffViewer *viewer); -/** - * Create fuzzy search windows with borders (one-time setup) - */ void create_fuzzy_windows_with_borders(NCursesDiffViewer *viewer); -/** - * Handle fuzzy search input - */ int handle_fuzzy_search_input(NCursesDiffViewer *viewer, int key); -/** - * Select file from fuzzy search results - */ void select_fuzzy_file(NCursesDiffViewer *viewer); -/** - * Initialize grep search state - */ void init_grep_search(NCursesDiffViewer *viewer); -/** - * Cleanup grep search windows - */ void cleanup_grep_search(NCursesDiffViewer *viewer); -/** - * Enter grep search mode for current view mode - */ void enter_grep_search_mode(NCursesDiffViewer *viewer); -/** - * Exit grep search mode - */ void exit_grep_search_mode(NCursesDiffViewer *viewer); -/** - * Update grep search filter based on current query and mode - */ void update_grep_filter(NCursesDiffViewer *viewer); -/** - * Render grep search UI - */ void render_grep_search(NCursesDiffViewer *viewer); -/** - * Handle grep search input - */ int handle_grep_search_input(NCursesDiffViewer *viewer, int key); -/** - * Select item from grep search results - */ void select_grep_item(NCursesDiffViewer *viewer); -/** - * Calculate grep match score for text content - */ int calculate_grep_score(const char *pattern, const char *text); -/** - * Extract branch name from stash info - */ void extract_branch_from_stash(const char *stash_info, char *branch_name, int max_len); diff --git a/include/utils/countdown_timer.h b/include/utils/countdown_timer.h index 6db1d2d..a2fb81e 100644 --- a/include/utils/countdown_timer.h +++ b/include/utils/countdown_timer.h @@ -1,57 +1,21 @@ -/** - * countdown_timer.h - * Header for focus timer functionality - */ #ifndef COUNTDOWN_TIMER_H #define COUNTDOWN_TIMER_H #include "common.h" -/** - * Start a new countdown timer - * - * @param seconds Total duration in seconds - * @param name Optional name for the timer session - * @return 1 if successful, 0 on failure - */ int start_countdown_timer(int seconds, const char *name); -/** - * Stop the current countdown timer - */ void stop_countdown_timer(); -/** - * Check if a timer is currently active - * - * @return TRUE if timer is active, FALSE otherwise - */ BOOL is_timer_active(); -/** - * Get the current timer display text - * - * @return Pointer to the display text string - */ const char *get_timer_display(); -/** - * Temporarily hide the timer display (used when running external programs) - */ void hide_timer_display(void); -/** - * Restore the timer display after it was hidden - */ void show_timer_display(void); -/** - * Command handler for the "timer" command - * - * @param args Command arguments - * @return 1 to continue shell, 0 to exit - */ int lsh_focus_timer(char **args); #endif // COUNTDOWN_TIMER_H diff --git a/include/utils/timer.h b/include/utils/timer.h index 412c851..7b1225f 100644 --- a/include/utils/timer.h +++ b/include/utils/timer.h @@ -1,38 +1,13 @@ -/** - * timer.h - * Header for command execution timer functionality - */ #ifndef TIMER_H #define TIMER_H #include "common.h" -/** - * Format a time interval in milliseconds to a readable string - * - * @param ms Time in milliseconds - * @param buffer Buffer to store formatted time - * @param buffer_size Size of the buffer - */ void format_time(double ms, char *buffer, size_t buffer_size); -/** - * Implementation of the timer command - * Usage: timer COMMAND [ARGS...] - * - * @param args Command arguments - * @return 1 to continue, 0 to exit - */ int lsh_timer(char **args); -/** - * Implementation of the time command (alias for timer) - * Usage: time COMMAND [ARGS...] - * - * @param args Command arguments - * @return 1 to continue, 0 to exit - */ int lsh_time(char **args); #endif // TIMER_H diff --git a/shell b/shell index d5b4193dc9e48e323219439c5085a22c8cd84258..d7dec2716f02419f22275398be03336d6e50f55a 100755 GIT binary patch delta 79244 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⁡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\n"); diff --git a/src/data/aliases.c b/src/data/aliases.c index 19b227f..c362c02 100644 --- a/src/data/aliases.c +++ b/src/data/aliases.c @@ -1,7 +1,3 @@ -/** - * aliases.c - * Implementation of shell alias functionality this is a test.. - */ #include "aliases.h" #include "builtins.h" @@ -17,9 +13,6 @@ int loading_aliases = 0; // Flag to prevent saving during loading // Path to the aliases file char aliases_file_path[PATH_MAX]; -/** - * Initialize the alias system - */ void init_aliases(void) { // Set initial capacity alias_capacity = 10; @@ -43,9 +36,6 @@ void init_aliases(void) { load_aliases(); } -/** - * Clean up the alias system - */ void cleanup_aliases(void) { if (!aliases) return; @@ -63,17 +53,11 @@ void cleanup_aliases(void) { alias_capacity = 0; } -/** - * Shutdown the alias system - */ void shutdown_aliases(void) { // Clean up (don't save here since we save immediately on changes) cleanup_aliases(); } -/** - * Load aliases from file - */ int load_aliases(void) { FILE *fp = fopen(aliases_file_path, "r"); if (!fp) { @@ -125,9 +109,6 @@ int load_aliases(void) { return 1; } -/** - * Save aliases to file - */ int save_aliases(void) { FILE *fp = fopen(aliases_file_path, "w"); if (!fp) { @@ -152,9 +133,6 @@ int save_aliases(void) { return 1; } -/** - * Add a new alias - */ int add_alias(const char *name, const char *command) { if (!name || !command) { return 0; @@ -199,9 +177,6 @@ int add_alias(const char *name, const char *command) { return 1; } -/** - * Remove an alias - */ int remove_alias(const char *name) { if (!name) { return 0; @@ -230,9 +205,6 @@ int remove_alias(const char *name) { return 0; // Alias not found } -/** - * Find an alias by name - */ AliasEntry *find_alias(const char *name) { for (int i = 0; i < alias_count; i++) { if (strcmp(aliases[i].name, name) == 0) { @@ -242,9 +214,6 @@ AliasEntry *find_alias(const char *name) { return NULL; } -/** - * Expand a command line by replacing aliases - */ char *expand_aliases(const char *command) { if (!command) { return NULL; @@ -293,9 +262,6 @@ char *expand_aliases(const char *command) { return result; } -/** - * Command handler for the "alias" command - */ int lsh_alias(char **args) { // No arguments - list all aliases if (args[1] == NULL) { @@ -396,9 +362,6 @@ int lsh_alias(char **args) { return 1; } -/** - * Command handler for the "unalias" command - */ int lsh_unalias(char **args) { if (args[1] == NULL) { printf("unalias: missing argument\n"); @@ -414,9 +377,6 @@ int lsh_unalias(char **args) { return 1; } -/** - * Command handler to show all aliases - */ int lsh_aliases(char **args) { for (int i = 0; i < alias_count; i++) { printf("alias %s='%s'\n", aliases[i].name, aliases[i].command); @@ -424,9 +384,6 @@ int lsh_aliases(char **args) { return 1; } -/** - * Get alias names for tab completion - */ char **get_alias_names(int *count) { if (alias_count == 0 || !count) { *count = 0; @@ -447,9 +404,6 @@ char **get_alias_names(int *count) { return names; } -/** - * Expand alias in args array - */ char **expand_alias(char **args) { if (!args || !args[0]) { return NULL; diff --git a/src/data/bookmarks.c b/src/data/bookmarks.c index 6a08fe2..3bc272c 100644 --- a/src/data/bookmarks.c +++ b/src/data/bookmarks.c @@ -1,8 +1,3 @@ -/** - * this is a test - * bookmarks.c - * Implementation of directory bookmarks functionality - */ #include "bookmarks.h" #include @@ -16,9 +11,6 @@ int bookmark_capacity = 0; // Path to the bookmarks file char bookmarks_file_path[PATH_MAX]; -/** - * Initialize the bookmark system - */ void init_bookmarks(void) { // Set initial capacity bookmark_capacity = 10; @@ -43,9 +35,6 @@ void init_bookmarks(void) { load_bookmarks(); } -/** - * Clean up the bookmark system - */ void cleanup_bookmarks(void) { if (!bookmarks) return; @@ -63,9 +52,6 @@ void cleanup_bookmarks(void) { bookmark_capacity = 0; } -/** - * Shutdown the bookmark system - */ void shutdown_bookmarks(void) { // Save bookmarks to file save_bookmarks(); @@ -74,9 +60,6 @@ void shutdown_bookmarks(void) { cleanup_bookmarks(); } -/** - * Load bookmarks from file - */ int load_bookmarks(void) { FILE *fp = fopen(bookmarks_file_path, "r"); if (!fp) { @@ -122,9 +105,6 @@ int load_bookmarks(void) { return 1; } -/** - * Save bookmarks to file - */ int save_bookmarks(void) { FILE *fp = fopen(bookmarks_file_path, "w"); if (!fp) { @@ -149,9 +129,6 @@ int save_bookmarks(void) { return 1; } -/** - * Add a new bookmark - */ int add_bookmark(const char *name, const char *path) { if (!name || !path) { return 0; @@ -187,9 +164,6 @@ int add_bookmark(const char *name, const char *path) { return 1; } -/** - * Remove a bookmark - */ int remove_bookmark(const char *name) { if (!name) { return 0; @@ -214,9 +188,6 @@ int remove_bookmark(const char *name) { return 0; // Bookmark not found } -/** - * Find a bookmark by name - */ BookmarkEntry *find_bookmark(const char *name) { for (int i = 0; i < bookmark_count; i++) { if (strcmp(bookmarks[i].name, name) == 0) { @@ -226,9 +197,6 @@ BookmarkEntry *find_bookmark(const char *name) { return NULL; } -/** - * Command handler for the "bookmark" command - */ int lsh_bookmark(char **args) { char cwd[PATH_MAX]; @@ -258,9 +226,6 @@ int lsh_bookmark(char **args) { return 1; } -/** - * Command handler for the "bookmarks" command - */ int lsh_bookmarks(char **args) { if (bookmark_count == 0) { printf("No bookmarks defined.\n"); @@ -323,9 +288,6 @@ int lsh_bookmarks(char **args) { return 1; } -/** - * Command handler for the "goto" command - */ int lsh_goto(char **args) { if (args[1] == NULL) { printf("Usage: goto \n"); @@ -346,9 +308,6 @@ int lsh_goto(char **args) { return 1; } -/** - * Command handler for the "unbookmark" command - */ int lsh_unbookmark(char **args) { if (args[1] == NULL) { printf("Usage: unbookmark \n"); @@ -365,9 +324,6 @@ int lsh_unbookmark(char **args) { return 1; } -/** - * Get bookmark names for tab completion - */ char **get_bookmark_names(int *count) { if (bookmark_count == 0 || !count) { *count = 0; @@ -388,9 +344,6 @@ char **get_bookmark_names(int *count) { return names; } -/** - * Find a matching bookmark by partial name - */ char *find_matching_bookmark(const char *partial_name) { if (!partial_name || strlen(partial_name) == 0) { return NULL; diff --git a/src/data/favorite_cities.c b/src/data/favorite_cities.c index cfbb84b..b666b63 100644 --- a/src/data/favorite_cities.c +++ b/src/data/favorite_cities.c @@ -1,7 +1,3 @@ -/** - * favorite_cities.c - * Implementation of favorite cities management for weather lookup - */ #include "favorite_cities.h" #include "builtins.h" @@ -15,9 +11,6 @@ int favorite_city_capacity = 0; // Path to the favorite cities file char favorite_cities_file_path[PATH_MAX]; -/** - * Initialize the favorite cities system - */ void init_favorite_cities(void) { // Set initial capacity favorite_city_capacity = 10; @@ -53,9 +46,6 @@ void init_favorite_cities(void) { } } -/** - * Clean up the favorite cities system - */ void cleanup_favorite_cities(void) { if (!favorite_cities) return; @@ -66,9 +56,6 @@ void cleanup_favorite_cities(void) { favorite_city_capacity = 0; } -/** - * Shutdown favorite cities system - save and cleanup - */ void shutdown_favorite_cities(void) { // Save to file first save_favorite_cities(); @@ -77,9 +64,6 @@ void shutdown_favorite_cities(void) { cleanup_favorite_cities(); } -/** - * Load favorite cities from file - */ int load_favorite_cities(void) { FILE *file = fopen(favorite_cities_file_path, "r"); if (!file) { @@ -115,9 +99,6 @@ int load_favorite_cities(void) { return 1; } -/** - * Save favorite cities to file - */ int save_favorite_cities(void) { FILE *file = fopen(favorite_cities_file_path, "w"); if (!file) { @@ -140,9 +121,6 @@ int save_favorite_cities(void) { return 1; } -/** - * Add a new favorite city - */ int add_favorite_city(const char *name) { if (!name) return 0; @@ -177,9 +155,6 @@ int add_favorite_city(const char *name) { return 1; } -/** - * Remove a favorite city - */ int remove_favorite_city(const char *name) { if (!name) return 0; @@ -199,9 +174,6 @@ int remove_favorite_city(const char *name) { return 0; // City not found } -/** - * Find a favorite city by name - */ CityEntry *find_favorite_city(const char *name) { if (!name) return NULL; @@ -215,9 +187,6 @@ CityEntry *find_favorite_city(const char *name) { return NULL; } -/** - * Get favorite city names for tab completion - */ char **get_favorite_city_names(int *count) { if (favorite_city_count == 0) { *count = 0; @@ -238,13 +207,6 @@ char **get_favorite_city_names(int *count) { return names; } -/** - * Command handler for the "cities" command - * Usage: - * cities add - * cities remove - * cities list - */ int lsh_cities(char **args) { if (args[1] == NULL) { // No subcommand - show usage diff --git a/src/data/structured_data.c b/src/data/structured_data.c index a092be9..f2ade48 100644 --- a/src/data/structured_data.c +++ b/src/data/structured_data.c @@ -1,16 +1,8 @@ -/** - * structured_data.c - * Implementation of structured data operations - * this is a comment - */ #include "structured_data.h" #include "builtins.h" // For set_color and reset_color functions #include -/** - * Create a new table with the given headers - */ TableData *create_table(char **headers, int header_count) { TableData *table = (TableData *)malloc(sizeof(TableData)); if (!table) { @@ -49,9 +41,6 @@ TableData *create_table(char **headers, int header_count) { return table; } -/** - * Add a row to a table - */ void add_table_row(TableData *table, DataValue *row) { if (!table || !row) return; @@ -72,9 +61,6 @@ void add_table_row(TableData *table, DataValue *row) { table->row_count++; } -/** - * Free all memory associated with a table - */ void free_table(TableData *table) { if (!table) return; @@ -98,9 +84,6 @@ void free_table(TableData *table) { free(table); } -/** - * Create a copy of a DataValue - */ DataValue copy_data_value(const DataValue *src) { DataValue dest; dest.type = src->type; @@ -123,9 +106,6 @@ DataValue copy_data_value(const DataValue *src) { return dest; } -/** - * Free a DataValue - */ void free_data_value(DataValue *value) { if (!value) return; @@ -137,9 +117,6 @@ void free_data_value(DataValue *value) { } } -/** - * Parse human-readable sizes (e.g., "10kb", "2.5MB") into bytes - */ long parse_size(const char *size_str) { char *unit; double size = strtod(size_str, &unit); @@ -180,9 +157,6 @@ long parse_size(const char *size_str) { return (long)size; // Default to just the number if no unit matches } -/** - * Extract size in bytes from a formatted size string (e.g., "10.5 KB") - */ long extract_size_bytes(const char *size_str) { double size_val = 0; char unit[8] = ""; @@ -204,9 +178,6 @@ long extract_size_bytes(const char *size_str) { return parse_size(size_str); } -/** - * Filter a table based on a condition - */ TableData *filter_table(TableData *input, char *field, char *op, char *value) { if (!input || !field || !op || !value) { return NULL; @@ -332,10 +303,6 @@ TableData *filter_table(TableData *input, char *field, char *op, char *value) { return result; } -/** - * Print a table to the console with nice formatting using Unicode box - * characters Linux version using ANSI escape sequences for colors - */ void print_table(TableData *table) { if (!table || table->row_count == 0) { printf("(empty table)\n"); diff --git a/src/git/git_integration.c b/src/git/git_integration.c index 81ca8c8..112a696 100644 --- a/src/git/git_integration.c +++ b/src/git/git_integration.c @@ -1,7 +1,3 @@ -/** - * git_integration.c - * Implementation of Git repository detection and information - */ #include "git_integration.h" #include @@ -9,16 +5,10 @@ #include #include -/** - * Initialize Git integration - */ void init_git_integration(void) { // No initialization needed for Linux } -/** - * Check if the current directory is in a Git repository and get branch info - */ int get_git_branch(char *branch_name, size_t buffer_size, int *is_dirty) { char git_dir[PATH_MAX] = ""; char cmd[PATH_MAX] = ""; @@ -75,9 +65,6 @@ int get_git_branch(char *branch_name, size_t buffer_size, int *is_dirty) { return status; } -/** - * Get the name of the Git repository - */ int get_git_repo_name(char *repo_name, size_t buffer_size) { if (!repo_name || buffer_size == 0) { return 0; @@ -115,9 +102,6 @@ int get_git_repo_name(char *repo_name, size_t buffer_size) { return 0; } -/** - * Get Git status for the current repository - */ char *get_git_status(void) { char branch_name[100] = ""; int is_dirty = 0; @@ -249,9 +233,6 @@ int get_repo_url(char *url, size_t url_size) { return 0; } -/** - * Check if the current branch has diverged from its remote tracking branch - */ int check_branch_divergence(int *commits_ahead, int *commits_behind) { if (!commits_ahead || !commits_behind) { return 0; @@ -394,9 +375,6 @@ int get_git_stashes(char stashes[][512], int max_stashes) { return count; } -/** - * Apply a git stash by index (keeps stash in list) - */ int apply_git_stash(int stash_index) { if (stash_index < 0) { return 0; @@ -410,9 +388,6 @@ int apply_git_stash(int stash_index) { return (result == 0) ? 1 : 0; } -/** - * Pop a git stash by index (applies and removes stash from list) - */ int pop_git_stash(int stash_index) { if (stash_index < 0) { return 0; @@ -426,9 +401,6 @@ int pop_git_stash(int stash_index) { return (result == 0) ? 1 : 0; } -/** - * Drop a git stash by index (removes stash without applying) - */ int drop_git_stash(int stash_index) { if (stash_index < 0) { return 0; @@ -442,9 +414,6 @@ int drop_git_stash(int stash_index) { return (result == 0) ? 1 : 0; } -/** - * Get detailed commit information including diff - */ int get_commit_details(const char *commit_hash, char *commit_info, size_t info_size) { if (!commit_hash || !commit_info || info_size == 0) { @@ -513,9 +482,6 @@ int get_commit_details(const char *commit_hash, char *commit_info, return 1; } -/** - * Get stash diff information - */ int get_stash_diff(int stash_index, char *stash_diff, size_t diff_size) { if (stash_index < 0 || !stash_diff || diff_size == 0) { return 0; diff --git a/src/history/persistent_history.c b/src/history/persistent_history.c index 05c94b0..e1462b1 100644 --- a/src/history/persistent_history.c +++ b/src/history/persistent_history.c @@ -1,7 +1,3 @@ -/** - * persistent_history.c - * Implementation of persistent command history and frequency tracking - */ #include "persistent_history.h" #include @@ -29,9 +25,6 @@ static int frequency_capacity = 0; static char history_file_path[PATH_MAX]; static char frequency_file_path[PATH_MAX]; -/** - * Initialize the persistent history system - */ void init_persistent_history(void) { // Allocate initial history capacity history_capacity = PERSISTENT_HISTORY_SIZE; @@ -85,10 +78,6 @@ void init_persistent_history(void) { load_frequencies_from_file(); } -/** - * Get the most recent command that starts with the given prefix - * returns NULL if no match found - */ char *get_most_recent_history_match(const char *prefix) { if (!prefix || !history_entries || strlen(prefix) == 0) { return NULL; @@ -122,9 +111,6 @@ char *get_most_recent_history_match(const char *prefix) { return NULL; } -/** - * Clean up persistent history resources - */ void cleanup_persistent_history(void) { if (history_entries) { for (int i = 0; i < history_size; i++) { @@ -148,18 +134,12 @@ void cleanup_persistent_history(void) { frequency_capacity = 0; } -/** - * Shutdown persistent history - */ void shutdown_persistent_history(void) { save_history_to_file(); save_frequencies_to_file(); cleanup_persistent_history(); } -/** - * Add a command to the persistent history - */ void add_to_history(const char *command) { if (!command || !*command || !history_entries) { return; // Skip empty commands @@ -192,9 +172,6 @@ void add_to_history(const char *command) { history_position = -1; } -/** - * Update command frequency statistics - */ void update_command_frequency(const char *command) { if (!command || !*command || !command_frequencies) { return; @@ -228,9 +205,6 @@ void update_command_frequency(const char *command) { frequency_count++; } -/** - * Save history to file - */ void save_history_to_file(void) { if (!history_entries || history_size == 0) { return; @@ -257,9 +231,6 @@ void save_history_to_file(void) { fclose(fp); } -/** - * Load history from file - */ void load_history_from_file(void) { FILE *fp = fopen(history_file_path, "r"); if (!fp) { @@ -296,9 +267,6 @@ void load_history_from_file(void) { fclose(fp); } -/** - * Save command frequencies to file - */ void save_frequencies_to_file(void) { if (!command_frequencies || frequency_count == 0) { return; @@ -325,9 +293,6 @@ void save_frequencies_to_file(void) { fclose(fp); } -/** - * Load command frequencies from file - */ void load_frequencies_from_file(void) { FILE *fp = fopen(frequency_file_path, "r"); if (!fp) { @@ -364,9 +329,6 @@ void load_frequencies_from_file(void) { fclose(fp); } -/** - * Get the history entry at the specified index - */ PersistentHistoryEntry *get_history_entry(int index) { if (index < 0 || index >= history_size) { return NULL; @@ -374,14 +336,8 @@ PersistentHistoryEntry *get_history_entry(int index) { return &history_entries[index]; } -/** - * Get the total number of history entries - */ int get_history_count(void) { return history_size; } -/** - * Find the best matching command based on frequency - */ char *find_best_frequency_match(const char *prefix) { if (!prefix || !*prefix || !command_frequencies) { return NULL; @@ -408,9 +364,6 @@ char *find_best_frequency_match(const char *prefix) { return NULL; } -/** - * Debug function to print frequency data - */ void debug_print_frequencies(void) { printf("Command Frequencies:\n"); for (int i = 0; i < frequency_count; i++) { @@ -419,9 +372,6 @@ void debug_print_frequencies(void) { } } -/** - * Case-insensitive substring search - */ char *_stristr(const char *haystack, const char *needle) { if (!haystack || !needle) return NULL; @@ -456,9 +406,6 @@ char *_stristr(const char *haystack, const char *needle) { return original; } -/** - * Get previous history entry for up-arrow key navigation - */ char *get_previous_history_entry(int *position) { if (!history_entries || history_size == 0) { return NULL; @@ -478,9 +425,6 @@ char *get_previous_history_entry(int *position) { return history_entries[*position].command; } -/** - * Get next history entry for down-arrow key navigation - */ char *get_next_history_entry(int *position) { if (!history_entries || history_size == 0 || *position < 0) { return NULL; @@ -498,9 +442,6 @@ char *get_next_history_entry(int *position) { } } -/** - * Get matching history entries for tab completion - */ char **get_matching_history_entries(const char *prefix) { if (!prefix || !history_entries) { return NULL; @@ -536,9 +477,6 @@ char **get_matching_history_entries(const char *prefix) { return result; } -/** - * Free matching entries array - */ void free_matching_entries(char **entries) { if (!entries) { return; diff --git a/src/input/autocorrect.c b/src/input/autocorrect.c index e878938..7bbeadf 100644 --- a/src/input/autocorrect.c +++ b/src/input/autocorrect.c @@ -1,17 +1,7 @@ -/** - * testing - * autocorrect.c - * Implementation of command auto-correction functionality - */ #include "autocorrect.h" #include "builtins.h" -/** - * Calculate Levenshtein distance between two strings - * Used to determine similarity between mistyped command and potential - * corrections - */ int levenshtein_distance(const char *s1, const char *s2) { int len1 = strlen(s1); int len2 = strlen(s2); @@ -61,9 +51,6 @@ int levenshtein_distance(const char *s1, const char *s2) { return result; } -/** - * Helper function to find minimum of three integers - */ int min3(int a, int b, int c) { int min = a; if (b < min) @@ -73,31 +60,16 @@ int min3(int a, int b, int c) { return min; } -/** - * Initialize the autocorrect system - */ void init_autocorrect(void) { // No initialization required currently } -/** - * Shutdown the autocorrect system - */ void shutdown_autocorrect(void) { // No cleanup required currently } -/** - * Check a command for possible corrections and suggest alternative - */ -/** - * Check a command for possible corrections and suggest alternative - */ -/** - * Check a command for possible corrections and suggest alternative - */ char **check_for_corrections(char **args) { if (!args || !args[0]) { return NULL; @@ -160,9 +132,6 @@ char **check_for_corrections(char **args) { return NULL; } -/** - * Count the number of arguments in a NULL-terminated array - */ int count_args(char **args) { int count = 0; while (args[count] != NULL) { diff --git a/src/input/line_reader.c b/src/input/line_reader.c index 7c9d07b..74c0888 100644 --- a/src/input/line_reader.c +++ b/src/input/line_reader.c @@ -1,7 +1,3 @@ -/** - * line_reader.c - * Implementation of line reading and parsing with context-aware suggestions - */ #include "line_reader.h" #include "aliases.h" @@ -49,12 +45,6 @@ static int has_history_suggestion = 0; #define NORMAL_COLOR "\033[0;36m" // Normal color for menu items #define RESET_COLOR "\033[0m" -/** - * Check if a command is valid - * - * @param cmd The command to check - * @return 1 if valid, 0 if not - */ int is_valid_command(const char *cmd) { if (!cmd || cmd[0] == '\0') { return 0; // Empty command is not valid @@ -177,11 +167,6 @@ int is_valid_command(const char *cmd) { return 0; // Command not found } -/** - * Read a key from the terminal - * - * Handles special keys and escape sequences - */ int read_key(void) { unsigned char c; int nread; @@ -261,9 +246,6 @@ int read_key(void) { return c; } -/** - * Update suggestions based on current input - */ void update_suggestions(const char *buffer, int position) { // Free previous suggestions if any if (suggestions) { @@ -372,9 +354,6 @@ void update_suggestions(const char *buffer, int position) { } } -/** - * Display a single inline suggestion (when not in menu mode) - */ void display_inline_suggestion(const char *prompt_buffer, const char *buffer, int position) { // Prioritize history suggestions when available, tab suggestions as fallback @@ -482,9 +461,6 @@ void display_inline_suggestion(const char *prompt_buffer, const char *buffer, } } -/** - * Function to clear the menu - */ void clear_menu() { if (max_menu_lines > 0) { // Save current cursor position @@ -514,9 +490,6 @@ void clear_menu() { } // this is a test -/** - * Function to display menu of suggestions - */ void display_menu(const char *prompt_buffer, const char *buffer, int position) { if (!has_suggestion || suggestion_count == 0) { @@ -612,9 +585,6 @@ void display_menu(const char *prompt_buffer, const char *buffer, int position) { fflush(stdout); } -/** - * Function to refresh the display - based on menu mode - */ void refresh_display(const char *prompt_buffer, const char *buffer, int position) { @@ -630,11 +600,6 @@ void refresh_display(const char *prompt_buffer, const char *buffer, } } -/** - * Read a line of input from the user - * - * @return The line read from stdin - */ char *lsh_read_line(void) { int bufsize = LSH_RL_BUFSIZE; int position = 0; @@ -1369,12 +1334,6 @@ char *lsh_read_line(void) { return buffer; } -/** - * Split a line into tokens - * - * @param line The line to split - * @return NULL-terminated array of tokens - */ char **lsh_split_line(char *line) { int bufsize = LSH_TOK_BUFSIZE; int position = 0; @@ -1406,12 +1365,6 @@ char **lsh_split_line(char *line) { return tokens; } -/** - * Parse a token from a string, handling quoted strings - * - * @param str_ptr Pointer to the string to parse, will be updated - * @return The parsed token, or NULL if no more tokens - */ char *parse_token(char **str_ptr) { char *str = *str_ptr; char *token_start; @@ -1460,12 +1413,6 @@ char *parse_token(char **str_ptr) { return strdup(token_start); } -/** - * Split a line with pipes into separate command arrays - * - * @param line The line to split - * @return NULL-terminated array of NULL-terminated token arrays - */ char ***lsh_split_piped_line(char *line) { int cmd_bufsize = LSH_TOK_BUFSIZE; int cmd_position = 0; diff --git a/src/input/tab_complete.c b/src/input/tab_complete.c index 8e42779..c5d7685 100644 --- a/src/input/tab_complete.c +++ b/src/input/tab_complete.c @@ -1,7 +1,3 @@ -/** - * tab_complete.c - * Linux implementation of tab completion - */ #include "tab_complete.h" #include "aliases.h" @@ -95,25 +91,15 @@ static CommandArgInfo command_arg_info[] = { // Global state static CommandContext current_context; -/** - * Initialize tab completion system - */ void init_tab_completion(void) { // Initialize context to defaults memset(¤t_context, 0, sizeof(CommandContext)); } -/** - * Shutdown tab completion system - */ void shutdown_tab_completion(void) { // Nothing to clean up for now } -/** - * Get the type of argument expected for a command and if strict matching is - * required - */ static ArgumentType get_argument_type(const char *cmd, int *strict_match) { if (!cmd || !*cmd) { if (strict_match) @@ -134,9 +120,6 @@ static ArgumentType get_argument_type(const char *cmd, int *strict_match) { return ARG_TYPE_ANY; } -/** - * Parse the command line to determine context - */ static void parse_command_context(const char *buffer) { // Reset the context memset(¤t_context, 0, sizeof(CommandContext)); @@ -189,9 +172,6 @@ static void parse_command_context(const char *buffer) { } } -/** - * Find all files/directories that match the beginning of path - */ static char *find_path_completions(const char *path) { if (!path || !*path) return NULL; @@ -294,9 +274,6 @@ static char *find_path_completions(const char *path) { return completion; } -/** - * Get the completion for a command - */ static char *complete_command(const char *prefix) { if (!prefix || !*prefix) return NULL; @@ -374,10 +351,6 @@ static char *complete_command(const char *prefix) { return result; } -/** - * Get all available suggestions for a specific argument type - * Returns a SuggestionList or NULL if no matches found - */ static SuggestionList *get_suggestions_by_type(ArgumentType arg_type, const char *token) { if (!token) @@ -855,10 +828,6 @@ case_label_file_dir: return suggestions; } -/** - * Try to complete the token as a specific argument type - * Returns the first match or NULL if no matches found - */ static char *complete_argument_by_type(ArgumentType arg_type, const char *token) { if (!token) @@ -880,9 +849,6 @@ static char *complete_argument_by_type(ArgumentType arg_type, return NULL; } -/** - * Free a suggestion list and all its items - */ void free_suggestion_list(SuggestionList *list) { if (!list) return; @@ -899,9 +865,6 @@ void free_suggestion_list(SuggestionList *list) { free(list); } -/** - * Get a list of suggestions for the current context - */ SuggestionList *get_suggestion_list(const char *buffer, const char *prefix) { if (!buffer) return NULL; @@ -994,9 +957,6 @@ SuggestionList *get_suggestion_list(const char *buffer, const char *prefix) { return suggestions; } -/** - * Get completion for the current context - */ char *get_tab_completion(const char *buffer) { if (!buffer) return NULL; diff --git a/src/main.c b/src/main.c index efc6a5c..555ce41 100644 --- a/src/main.c +++ b/src/main.c @@ -1,26 +1,10 @@ -/** - * main.c - * Entry point for the LSH shell program - */ - #include "common.h" #include "shell.h" #include -/** - * Main entry point - */ - int main(int argc, char **argv) { - // Set locale to support UTF-8 setlocale(LC_ALL, "en_US.UTF-8"); - - // Setup terminal for proper UTF-8 handling - // This is Linux equivalent of SetConsoleOutputCP(65001) - printf("\033%%G"); // Tell terminal to use UTF-8 - - // Start the shell loop + printf("\033%%G"); lsh_loop(); - return EXIT_SUCCESS; } diff --git a/src/search/filters.c b/src/search/filters.c index 74c5ccc..5ee7366 100644 --- a/src/search/filters.c +++ b/src/search/filters.c @@ -1,16 +1,9 @@ // this is another test -/** - * filters.c - * Implementation of filter commands (where, sort-by, etc.) - */ #include "filters.h" #include #include // For strcasecmp and strncasecmp -/** - * Filter a table based on a condition (e.g., where size > 10kb) - */ TableData *lsh_where(TableData *input, char **args) { if (!input || !args || !args[0]) { fprintf(stderr, "lsh: where: missing arguments\n"); @@ -64,9 +57,6 @@ TableData *lsh_where(TableData *input, char **args) { return filter_table(input, field, op, value); } -/** - * Sort a table based on a column (e.g., sort-by size desc) - */ TableData *lsh_sort_by(TableData *input, char **args) { if (!input || !args || !args[0]) { fprintf(stderr, "lsh: sort-by: missing arguments\n"); @@ -179,10 +169,6 @@ TableData *lsh_sort_by(TableData *input, char **args) { return result; } -/** - * Select specific columns from a table - * Supports both space-separated and comma-separated field names - */ TableData *lsh_select(TableData *input, char **args) { if (!input || !args || !args[0]) { fprintf(stderr, "lsh: select: missing arguments\n"); @@ -355,9 +341,6 @@ TableData *lsh_select(TableData *input, char **args) { return result; } -/** - * Case-insensitive substring search (strcasestr equivalent for Windows) - */ char *my_strcasestr(const char *haystack, const char *needle) { if (!haystack || !needle) return NULL; @@ -379,9 +362,6 @@ char *my_strcasestr(const char *haystack, const char *needle) { return NULL; } -/** - * Filter rows where a column contains a substring - */ TableData *lsh_contains(TableData *input, char **args) { if (!input || !args || !args[0] || !args[1]) { fprintf(stderr, "lsh: contains: missing arguments\n"); @@ -454,9 +434,6 @@ TableData *lsh_contains(TableData *input, char **args) { return result; } -/** - * Limit the number of rows displayed - */ TableData *lsh_limit(TableData *input, char **args) { if (!input || !args || !args[0]) { fprintf(stderr, "lsh: limit: missing arguments\n"); diff --git a/src/search/fzf_native.c b/src/search/fzf_native.c index d35e4a1..09293e1 100644 --- a/src/search/fzf_native.c +++ b/src/search/fzf_native.c @@ -1,7 +1,3 @@ -/** - * fzf_native halla - * Wrapper for the native fzf command-line fuzzy finder - */ // this is an addition #include "fzf_native.h" @@ -13,11 +9,6 @@ #include #include // For stat -/** - * Check if native fzf is installed on the system - * - * @return 1 if installed, 0 if not - */ int is_fzf_installed(void) { // Try to run fzf --version to check if it's installed FILE *fp = popen("fzf --version 2>/dev/null", "r"); @@ -35,9 +26,6 @@ int is_fzf_installed(void) { return has_output; } -/** - * Display instructions for installing fzf - */ void show_fzf_install_instructions(void) { printf("\nfzf is not installed on this system. To use this feature, install " "fzf:\n\n"); @@ -54,13 +42,6 @@ void show_fzf_install_instructions(void) { printf("After installation, restart your shell.\n"); } -/** - * Run fzf with files from the current directory - * - * @param preview Enable preview window if 1 - * @param args Additional arguments for fzf - * @return Selected filename or NULL if canceled - */ char *run_native_fzf_files(int preview, char **args) { // Check if fzf is installed if (!is_fzf_installed()) { @@ -151,13 +132,6 @@ char *run_native_fzf_files(int preview, char **args) { return selected; } -/** - * Run fzf with all files and directories from the current directory - * - * @param recursive Search recursively if 1 - * @param args Additional arguments for fzf - * @return Selected path or NULL if canceled - */ char *run_native_fzf_all(int recursive, char **args) { // Check if fzf is installed if (!is_fzf_installed()) { @@ -254,11 +228,6 @@ char *run_native_fzf_all(int recursive, char **args) { return selected; } -/** - * Run fzf with command history - * - * @return Selected command or NULL if canceled - */ char *run_native_fzf_history(void) { // Check if fzf is installed if (!is_fzf_installed()) { @@ -355,25 +324,12 @@ char *run_native_fzf_history(void) { return selected; } -/** - * Check if a specific editor is available - * - * @param editor Name of the editor executable - * @return 1 if available, 0 if not - */ int is_editor_available(const char *editor) { char command[256]; snprintf(command, sizeof(command), "%s --version >/dev/null 2>&1", editor); return (system(command) == 0); } -/** - * Open a file in the best available editor in the current terminal - * - * @param file_path Path to the file to open - * @param line_number Optional line number to jump to (0 to ignore) - * @return 1 if successful, 0 if failed - */ int open_in_best_editor(const char *file_path, int line_number) { char command[2048] = {0}; int success = 0; @@ -432,12 +388,6 @@ int open_in_best_editor(const char *file_path, int line_number) { } } -/** - * Command handler for the fzf command - * - * @param args Command arguments - * @return 1 to continue shell execution, 0 to exit shell - */ int lsh_fzf_native(char **args) { // Check if fzf is installed if (!is_fzf_installed()) { diff --git a/src/search/grep.c b/src/search/grep.c index 5733a04..0a535fa 100644 --- a/src/search/grep.c +++ b/src/search/grep.c @@ -1,7 +1,3 @@ -/** - * grep.c - * Custom implementation of text searching for Linux using Boyer-Moore algorithm - */ #include "grep.h" #include "builtins.h" @@ -327,9 +323,6 @@ int search_directory(const char *dir_path, const char *pattern, bool show_line_n return total_matches; } -/** - * Custom grep implementation using Boyer-Moore algorithm - */ int lsh_actual_grep(char **args) { if (args[1] == NULL) { printf("Usage: grep [options] pattern [file/directory]\n"); @@ -441,12 +434,6 @@ int lsh_actual_grep(char **args) { return 1; } -/** - * Run grep with interactive interface - * - * Shows a split view with files on left, matches on right, and - * updates search results with each keystroke - */ void run_interactive_grep_session(void) { // Save original terminal settings to restore later struct termios old_tio, new_tio; @@ -1127,9 +1114,6 @@ void run_interactive_grep_session(void) { printf(ANSI_CLEAR_SCREEN ANSI_CURSOR_HOME); } -/** - * Wrapper for grep - */ int lsh_grep(char **args) { // If no arguments provided, run interactive grep if (args[1] == NULL) { diff --git a/src/search/ripgrep.c b/src/search/ripgrep.c index 8967d5a..9632c96 100644 --- a/src/search/ripgrep.c +++ b/src/search/ripgrep.c @@ -1,7 +1,3 @@ -/** - * ripgrep.c - * Interactive wrapper for the ripgrep (rg) command-line search tool - */ #include "ripgrep.h" #include "common.h" @@ -15,11 +11,6 @@ #include // For access function #include // For terminal control -/** - * Check if ripgrep (rg) is installed on the system - * - * @return 1 if installed, 0 if not - */ int is_rg_installed(void) { // Try to run rg --version to check if it's installed FILE *fp = popen("rg --version 2>/dev/null", "r"); @@ -37,9 +28,6 @@ int is_rg_installed(void) { return has_output; } -/** - * Display instructions for installing ripgrep - */ void show_rg_install_instructions(void) { printf("\nripgrep (rg) is not installed on this system. To use this feature, " "install ripgrep:\n\n"); @@ -55,25 +43,12 @@ void show_rg_install_instructions(void) { printf("After installation, restart your shell.\n"); } -/** - * Check if a specific editor is available - * - * @param editor Name of the editor executable - * @return 1 if available, 0 if not - */ int is_editor_available_for_rg(const char *editor) { char command[256]; snprintf(command, sizeof(command), "%s --version >/dev/null 2>&1", editor); return (system(command) == 0); } -/** - * Open a file at a specific line in the best available editor - * - * @param file_path Path to the file to open - * @param line_number Line number to position cursor at - * @return 1 if successful, 0 if failed - */ int rg_open_in_editor(const char *file_path, int line_number) { char command[2048] = {0}; int success = 0; @@ -122,16 +97,6 @@ int rg_open_in_editor(const char *file_path, int line_number) { } } -/** - * Parse a ripgrep result line to extract file path and line number - * - * @param result_line The result line from ripgrep (format: - * file:line:column:text) - * @param file_path Buffer to store extracted file path - * @param file_path_size Size of file_path buffer - * @param line_number Pointer to store extracted line number - * @return 1 if parsing successful, 0 if failed - */ static int parse_rg_result(const char *result_line, char *file_path, size_t file_path_size, int *line_number) { // Ripgrep output format is: file:line:column:text @@ -162,12 +127,6 @@ static int parse_rg_result(const char *result_line, char *file_path, return 1; } -/** - * Run ripgrep with interactive filtering - * - * @param args Command arguments or NULL for interactive mode - * @return Selected filename/line or NULL if canceled - */ char *run_interactive_ripgrep(char **args) { // Check if ripgrep is installed if (!is_rg_installed()) { @@ -268,10 +227,6 @@ char *run_interactive_ripgrep(char **args) { return selected; } -/** - * Run ripgrep with interactive editing capabilities for a custom Neovim-like - * experience - */ void run_ripgrep_interactive_session(void) { // Check if ripgrep and fzf are installed if (!is_rg_installed()) { @@ -505,12 +460,6 @@ void run_ripgrep_interactive_session(void) { system("clear"); } -/** - * Command handler for the ripgrep command - * - * @param args Command arguments - * @return 1 to continue shell execution, 0 to exit shell - */ int lsh_ripgrep(char **args) { // Check if ripgrep is installed if (!is_rg_installed()) { diff --git a/src/shell.c b/src/shell.c index 6fd93d3..878d3a3 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1,7 +1,3 @@ -/** - * shell.c - * Implementation of core shell functionality - */ #include "shell.h" #include "aliases.h" // Added for alias support @@ -33,9 +29,6 @@ static int g_status_attributes = 12; // Red static int g_status_bar_enabled = 0; // Flag to track if status bar is enabled static struct termios g_orig_termios; // Original terminal settings -/** - * Initialize terminal for raw mode - */ int init_terminal(struct termios *orig_termios) { int fd = STDIN_FILENO; @@ -70,9 +63,6 @@ int init_terminal(struct termios *orig_termios) { return fd; } -/** - * Restore terminal to original settings - */ void restore_terminal(int fd, struct termios *orig_termios) { // Restore cursor and terminal settings printf("\033[?25h"); // Ensure cursor is visible @@ -83,9 +73,6 @@ void restore_terminal(int fd, struct termios *orig_termios) { } } -/** - * Get console dimensions - */ int get_console_dimensions(int fd, int *width, int *height) { struct winsize ws; @@ -100,9 +87,6 @@ int get_console_dimensions(int fd, int *width, int *height) { return 1; } -/** - * Temporarily hide the status bar before command execution - */ void hide_status_bar(int fd) { // Skip if status bar is not enabled if (!g_status_bar_enabled) @@ -125,10 +109,6 @@ void hide_status_bar(int fd) { fflush(stdout); } -/** - * This function scrolls the console buffer up one line to make room for the - * status bar when we're at the bottom of the screen. - */ void ensure_status_bar_space(int fd) { int width, height; if (!get_console_dimensions(fd, &width, &height)) { @@ -151,9 +131,6 @@ void ensure_status_bar_space(int fd) { fflush(stdout); } -/** - * Initialize the status bar at the bottom of the screen - */ int init_status_bar(int fd) { int width, height; if (!get_console_dimensions(fd, &width, &height)) { @@ -174,9 +151,6 @@ int init_status_bar(int fd) { return 1; } -/** - * Check for console window resize and update status bar position - */ void check_console_resize(int fd) { if (!g_status_bar_enabled) return; @@ -196,9 +170,6 @@ void check_console_resize(int fd) { } } -/** - * Update the status bar with Git information - */ void update_status_bar(int fd, const char *git_info) { if (!g_status_bar_enabled) return; @@ -264,9 +235,6 @@ void update_status_bar(int fd, const char *git_info) { fflush(stdout); } -/** - * Get the name of the parent and current directories from a path - */ void get_path_display(const char *cwd, char *parent_dir_name, char *current_dir_name, size_t buf_size) { @@ -330,9 +298,6 @@ void get_path_display(const char *cwd, char *parent_dir_name, } } -/** - * Create a TableData structure from an ls command - */ TableData* create_ls_table(char **args) { DIR *dir; struct dirent *entry; @@ -444,9 +409,6 @@ TableData* create_ls_table(char **args) { return table; } -/** - * Parse input line into an array of commands (for pipelines) - */ char*** lsh_split_commands(char *line) { char **cmd_groups = NULL; char *cmd_group, *saveptr0; @@ -644,9 +606,6 @@ char*** lsh_split_commands(char *line) { return commands; } -/** - * Launch an external program - */ int lsh_launch(char **args) { pid_t pid, wpid; int status; @@ -673,9 +632,6 @@ int lsh_launch(char **args) { return 1; } -/** - * Execute a command - */ int lsh_execute(char **args) { if (args[0] == NULL) { // An empty command was entered @@ -704,9 +660,6 @@ int lsh_execute(char **args) { return lsh_launch(args); } -/** - * Execute a pipeline of commands - */ int lsh_execute_piped(char ***commands) { // Count the number of commands in the pipeline int cmd_count = 0; @@ -833,9 +786,6 @@ int lsh_execute_piped(char ***commands) { return 1; } -/** - * Free memory for a command array from lsh_split_commands - */ void free_commands(char ***commands) { for (int i = 0; commands[i] != NULL; i++) { for (int j = 0; commands[i][j] != NULL; j++) { @@ -846,9 +796,6 @@ void free_commands(char ***commands) { free(commands); } -/** - * Display a welcome banner - */ void display_welcome_banner(void) { printf(ANSI_COLOR_CYAN); printf("╔════════════════════════════════════════════════════════════╗\n"); @@ -859,9 +806,6 @@ void display_welcome_banner(void) { printf(ANSI_COLOR_RESET); } -/** - * Main shell loop - */ void lsh_loop(void) { char *line; char **args; diff --git a/src/system/ps_command.c b/src/system/ps_command.c index bb37ef5..ff97b84 100644 --- a/src/system/ps_command.c +++ b/src/system/ps_command.c @@ -1,8 +1,3 @@ -/** - * ps_command.c - * Implementation of the 'ps' command for listing running processes - * Simple implementation for Linux - */ #include "builtins.h" #include "common.h" @@ -11,13 +6,6 @@ #include #include -/** - * Function to generate structured data for running processes - * This enables piping and filtering of process information - * - * @param args Command arguments - * @return TableData structure with process information - */ TableData* lsh_ps_structured(char **args) { // Define our table headers char *headers[] = {"PID", "Name", "Memory", "Threads"}; @@ -93,10 +81,6 @@ TableData* lsh_ps_structured(char **args) { return table; } -/** - * Implementation of the ps command to display process information - * Uses structured data to show processes in a formatted table - */ int lsh_ps_fancy(char **args) { // Create structured data table for processes TableData *table = lsh_ps_structured(args); diff --git a/src/ui/diff_viewer.c b/src/ui/diff_viewer.c index e842102..7ac1e8f 100644 --- a/src/ui/diff_viewer.c +++ b/src/ui/diff_viewer.c @@ -1,7 +1,3 @@ -/** - * diff_viewer.c - * Interactive diff viewer implementation - */ // thisis a test #include "diff_viewer.h" @@ -13,9 +9,6 @@ #include #include -/** - * Initialize the diff viewer - */ int init_diff_viewer(DiffViewer *viewer) { if (!viewer) return 0; @@ -32,9 +25,6 @@ int init_diff_viewer(DiffViewer *viewer) { return 1; } -/** - * Get terminal size - */ void get_terminal_size(int *width, int *height) { struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); @@ -42,9 +32,6 @@ void get_terminal_size(int *width, int *height) { *height = w.ws_row; } -/** - * Get list of changed files from git - */ int get_changed_files(DiffViewer *viewer) { if (!viewer) return 0; @@ -87,9 +74,6 @@ int get_changed_files(DiffViewer *viewer) { 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", @@ -106,9 +90,6 @@ int is_new_file(const char *filename) { 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; @@ -152,9 +133,6 @@ int load_new_file_content(DiffViewer *viewer, const char *filename) { 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; @@ -238,9 +216,6 @@ int load_file_diff(DiffViewer *viewer, const char *filename) { return viewer->diff_line_count; } -/** - * Render the diff viewer interface - */ void render_diff_viewer(DiffViewer *viewer) { if (!viewer) return; @@ -373,9 +348,6 @@ void render_diff_viewer(DiffViewer *viewer) { fflush(stdout); } -/** - * Handle keyboard input for navigation - */ int handle_diff_input(DiffViewer *viewer, char key) { if (!viewer) return 0; @@ -441,9 +413,6 @@ int handle_diff_input(DiffViewer *viewer, char key) { return 1; // Continue } -/** - * Set terminal to raw mode for interactive input - */ void set_raw_mode(struct termios *orig_termios) { tcgetattr(STDIN_FILENO, orig_termios); @@ -455,16 +424,10 @@ void set_raw_mode(struct termios *orig_termios) { tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); } -/** - * Restore terminal to original mode - */ void restore_terminal_mode(struct termios *orig_termios) { tcsetattr(STDIN_FILENO, TCSAFLUSH, orig_termios); } -/** - * Run the interactive diff viewer - */ int run_diff_viewer(void) { DiffViewer viewer; struct termios orig_termios; @@ -511,9 +474,6 @@ int run_diff_viewer(void) { 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; diff --git a/src/ui/ncurses_diff_viewer.c b/src/ui/ncurses_diff_viewer.c index aaabdd7..436e316 100644 --- a/src/ui/ncurses_diff_viewer.c +++ b/src/ui/ncurses_diff_viewer.c @@ -1,7 +1,3 @@ -/** - * ncurses_diff_viewer.c - * NCurses-based interactive diff viewer implementation - */ // this is a change // this is another change @@ -26,9 +22,6 @@ void handle_sigwinch(int sig) { terminal_resized = 1; } -/** - * Handle terminal resize by recreating all windows - */ void handle_terminal_resize(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -98,9 +91,6 @@ void handle_terminal_resize(NCursesDiffViewer *viewer) { terminal_resized = 0; } -/** - * Initialize the ncurses diff viewer - */ int init_ncurses_diff_viewer(NCursesDiffViewer *viewer) { if (!viewer) return 0; @@ -240,9 +230,6 @@ int init_ncurses_diff_viewer(NCursesDiffViewer *viewer) { return 1; } -/** - * Get list of changed files from git - */ int get_ncurses_changed_files(NCursesDiffViewer *viewer) { if (!viewer) return 0; @@ -285,9 +272,6 @@ int get_ncurses_changed_files(NCursesDiffViewer *viewer) { return viewer->file_count; } -/** - * Create temporary file with current working version - */ int create_temp_file_with_changes(const char *filename, char *temp_path) { snprintf(temp_path, 256, "/tmp/shell_diff_current_%d", getpid()); @@ -298,9 +282,6 @@ int create_temp_file_with_changes(const char *filename, char *temp_path) { return (system(cmd) == 0); } -/** - * Create temporary file with git HEAD version - */ int create_temp_file_git_version(const char *filename, char *temp_path) { snprintf(temp_path, 256, "/tmp/shell_diff_git_%d", getpid()); @@ -311,9 +292,6 @@ int create_temp_file_git_version(const char *filename, char *temp_path) { return (system(cmd) == 0); } -/** - * Check if a file is a new untracked file - */ int is_ncurses_new_file(const char *filename) { char cmd[1024]; snprintf(cmd, sizeof(cmd), "git ls-files --error-unmatch \"%s\" 2>/dev/null", @@ -330,9 +308,6 @@ int is_ncurses_new_file(const char *filename) { return !is_tracked; // Return 1 if not tracked (new file) } -/** - * Load file with staging information - */ int load_file_with_staging_info(NCursesDiffViewer *viewer, const char *filename) { @@ -484,9 +459,6 @@ int load_file_with_staging_info(NCursesDiffViewer *viewer, return viewer->file_line_count; } -/** - * Stage/unstage a single line by line index - */ // this is a change // this is another change @@ -547,9 +519,6 @@ int stage_hunk_by_line(NCursesDiffViewer *viewer, int line_index) { return 1; } -/** - * Rebuild staged view with proper git patch format for individual lines - */ void rebuild_staged_view(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -682,9 +651,6 @@ void rebuild_staged_view(NCursesDiffViewer *viewer) { } } -/** - * Rebuild staged view from what's actually staged in git - */ void rebuild_staged_view_from_git(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -794,9 +760,6 @@ void rebuild_staged_view_from_git(NCursesDiffViewer *viewer) { pclose(diff_fp); } -/** - * Apply staged changes using git - */ int apply_staged_changes(NCursesDiffViewer *viewer) { if (!viewer || viewer->staged_line_count == 0) @@ -844,9 +807,6 @@ int apply_staged_changes(NCursesDiffViewer *viewer) { return (result == 0); } -/** - * Unstage a specific line from the staged pane - */ int unstage_line_from_git(NCursesDiffViewer *viewer, int staged_line_index) { if (!viewer || staged_line_index < 0 || @@ -884,9 +844,6 @@ int unstage_line_from_git(NCursesDiffViewer *viewer, int staged_line_index) { return 0; } -/** - * Reset staged changes - */ int reset_staged_changes(NCursesDiffViewer *viewer) { if (!viewer) @@ -902,9 +859,6 @@ int reset_staged_changes(NCursesDiffViewer *viewer) { return 1; } -/** - * Draw a box with rounded corners - */ void draw_rounded_box(WINDOW *win) { if (!win) return; @@ -931,9 +885,6 @@ void draw_rounded_box(WINDOW *win) { mvwaddch(win, height - 1, width - 1, ACS_LRCORNER); } -/** - * Get commit history - */ int get_commit_history(NCursesDiffViewer *viewer) { if (!viewer) return 0; @@ -1056,9 +1007,6 @@ int get_commit_history(NCursesDiffViewer *viewer) { return viewer->commit_count; } -/** - * Toggle file marking for commit - */ void toggle_file_mark(NCursesDiffViewer *viewer, int file_index) { if (!viewer || file_index < 0 || file_index >= viewer->file_count) return; @@ -1067,9 +1015,6 @@ void toggle_file_mark(NCursesDiffViewer *viewer, int file_index) { !viewer->files[file_index].marked_for_commit; } -/** - * Mark all files for commit (or unmark if all are already marked) - */ void mark_all_files(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -1089,10 +1034,6 @@ void mark_all_files(NCursesDiffViewer *viewer) { } } -/** - * Show confirmation dialog for diverged branch - * Returns 1 for force push, 0 for cancel - */ int show_diverged_branch_dialog(int commits_ahead, int commits_behind) { // Save current screen WINDOW *saved_screen = dupwin(stdscr); @@ -1157,10 +1098,6 @@ int show_diverged_branch_dialog(int commits_ahead, int commits_behind) { return result; } -/** - * Show confirmation dialog requiring user to type "yes" - * Returns 1 if confirmed, 0 if cancelled - */ int show_reset_confirmation_dialog(void) { // Save current screen WINDOW *saved_screen = dupwin(stdscr); @@ -1253,9 +1190,6 @@ int show_reset_confirmation_dialog(void) { return 0; } -/** - * Get commit title and message input from user - */ int get_commit_title_input(char *title, int max_len, char *message, int max_message_len) { @@ -1560,9 +1494,6 @@ int get_commit_title_input(char *title, int max_len, char *message, return strlen(title) > 0 ? 1 : 0; } -/** - * Commit marked files with title and message - */ int commit_marked_files(NCursesDiffViewer *viewer, const char *commit_title, const char *commit_message) { if (!viewer || !commit_title || strlen(commit_title) == 0) @@ -1634,9 +1565,6 @@ int commit_marked_files(NCursesDiffViewer *viewer, const char *commit_title, return 0; } -/** - * Reset commit (soft) - undo commit but keep changes - */ int reset_commit_soft(NCursesDiffViewer *viewer, int commit_index) { if (!viewer || commit_index < 0 || commit_index >= viewer->commit_count) return 0; @@ -1668,9 +1596,6 @@ int reset_commit_soft(NCursesDiffViewer *viewer, int commit_index) { return 0; } -/** - * Reset commit (hard) - undo commit and discard changes - */ int reset_commit_hard(NCursesDiffViewer *viewer, int commit_index) { if (!viewer || commit_index < 0 || commit_index >= viewer->commit_count) return 0; @@ -1712,9 +1637,6 @@ int reset_commit_hard(NCursesDiffViewer *viewer, int commit_index) { return 0; } -/** - * Amend the most recent commit - */ int amend_commit(NCursesDiffViewer *viewer) { if (!viewer || viewer->commit_count == 0) return 0; @@ -2205,9 +2127,6 @@ int execute_git_with_auth(const char *base_cmd, const char *username, return result; } -/** - * Push specific commit - */ int push_commit(NCursesDiffViewer *viewer, int commit_index) { if (!viewer || commit_index < 0 || commit_index >= viewer->commit_count) return 0; @@ -2427,9 +2346,6 @@ int push_commit(NCursesDiffViewer *viewer, int commit_index) { return 0; } -/** - * Pull commits from remote - */ int pull_commits(NCursesDiffViewer *viewer) { if (!viewer) return 0; @@ -2471,9 +2387,6 @@ int pull_commits(NCursesDiffViewer *viewer) { return 0; } -/** - * Render the file list window - */ void render_file_list_window(NCursesDiffViewer *viewer) { if (!viewer || !viewer->file_list_win) return; @@ -2614,9 +2527,6 @@ void render_file_list_window(NCursesDiffViewer *viewer) { wrefresh(viewer->file_list_win); } -/** - * Render the commit list window - */ void render_commit_list_window(NCursesDiffViewer *viewer) { if (!viewer || !viewer->commit_list_win) @@ -2730,9 +2640,6 @@ void render_commit_list_window(NCursesDiffViewer *viewer) { wrefresh(viewer->commit_list_win); } -/** - * Render the file content window with split staging view - */ void render_file_content_window(NCursesDiffViewer *viewer) { if (!viewer || !viewer->file_content_win) return; @@ -2966,9 +2873,6 @@ void render_file_content_window(NCursesDiffViewer *viewer) { wrefresh(viewer->file_content_win); } -/** - * Render the status bar - */ void render_status_bar(NCursesDiffViewer *viewer) { if (!viewer || !viewer->status_bar_win) return; @@ -3148,9 +3052,6 @@ void render_status_bar(NCursesDiffViewer *viewer) { refresh(); } -/** - * Update sync status and check for new files - */ void update_sync_status(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -3464,9 +3365,6 @@ int commit_staged_changes_only(NCursesDiffViewer *viewer, return 0; } -/** - * Handle keyboard input for navigation - */ int handle_ncurses_diff_input(NCursesDiffViewer *viewer, int key) { if (!viewer) return 0; @@ -4749,9 +4647,6 @@ int handle_ncurses_diff_input(NCursesDiffViewer *viewer, int key) { return 1; // Continue } -/** - * Run the ncurses diff viewer - */ int run_ncurses_diff_viewer(void) { NCursesDiffViewer viewer; @@ -4882,13 +4777,7 @@ int run_ncurses_diff_viewer(void) { return 0; } -/** - * Get list of git stashes - */ -/** - * Get list of git branches - */ int get_ncurses_git_branches(NCursesDiffViewer *viewer) { if (!viewer) @@ -4999,9 +4888,6 @@ int get_ncurses_git_branches(NCursesDiffViewer *viewer) { return 1; } -/** - * Get branch name input from user for new branch creation - */ int get_branch_name_input(char *branch_name, int max_len) { if (!branch_name || max_len <= 0) return 0; @@ -5086,9 +4972,6 @@ cleanup: return result; } -/** - * Create a new git branch - */ int create_git_branch(const char *branch_name) { if (!branch_name || strlen(branch_name) == 0) return 0; @@ -5112,9 +4995,6 @@ int create_git_branch(const char *branch_name) { return (system(cmd) == 0); } -/** - * Get new branch name input from user for branch renaming - */ int get_rename_branch_input(const char *current_name, char *new_name, int max_len) { if (!current_name || !new_name || max_len <= 0) @@ -5205,9 +5085,6 @@ cleanup_rename: return result; } -/** - * Rename a git branch - */ int rename_git_branch(const char *old_name, const char *new_name) { if (!old_name || !new_name || strlen(old_name) == 0 || strlen(new_name) == 0) return 0; @@ -5219,9 +5096,6 @@ int rename_git_branch(const char *old_name, const char *new_name) { return (system(cmd) == 0); } -/** - * Show delete branch confirmation dialog - */ int show_delete_branch_dialog(const char *branch_name) { if (!branch_name) return DELETE_CANCEL; @@ -5302,9 +5176,6 @@ int show_delete_branch_dialog(const char *branch_name) { } } -/** - * Show universal error popup - */ void show_error_popup(const char *error_message) { if (!error_message) return; @@ -5341,9 +5212,6 @@ void show_error_popup(const char *error_message) { refresh(); } -/** - * Get available git remotes - */ int get_git_remotes(char remotes[][256], int max_remotes) { FILE *fp = popen("git remote 2>/dev/null", "r"); if (!fp) @@ -5370,9 +5238,6 @@ int get_git_remotes(char remotes[][256], int max_remotes) { return count; } -/** - * Show upstream selection dialog - */ int show_upstream_selection_dialog(const char *branch_name, char *upstream_result, int max_len) { if (!branch_name || !upstream_result) @@ -5498,9 +5363,6 @@ int show_upstream_selection_dialog(const char *branch_name, return 0; } -/** - * Get current git branch name - */ int get_current_branch_name(char *branch_name, int max_len) { if (!branch_name) return 0; @@ -5523,9 +5385,6 @@ int get_current_branch_name(char *branch_name, int max_len) { return 0; } -/** - * Check if a branch has an upstream - */ int branch_has_upstream(const char *branch_name) { if (!branch_name) return 0; @@ -5537,9 +5396,6 @@ int branch_has_upstream(const char *branch_name) { return (system(cmd) == 0); } -/** - * Delete git branch based on option - */ int delete_git_branch(const char *branch_name, DeleteBranchOption option) { if (!branch_name || option == DELETE_CANCEL) return 0; @@ -5607,9 +5463,6 @@ int get_ncurses_git_stashes(NCursesDiffViewer *viewer) { return viewer->stash_count; } -/** - * Get stash name input from user - */ int get_stash_name_input(char *stash_name, int max_len) { if (!stash_name) return 0; @@ -5761,9 +5614,6 @@ int get_stash_name_input(char *stash_name, int max_len) { return strlen(stash_name) > 0 ? 1 : 0; } -/** - * Create a new git stash - */ int create_ncurses_git_stash(NCursesDiffViewer *viewer) { if (!viewer) return 0; @@ -5797,9 +5647,6 @@ int create_ncurses_git_stash(NCursesDiffViewer *viewer) { return result; } -/** - * Render the stash list window - */ void render_stash_list_window(NCursesDiffViewer *viewer) { if (!viewer || !viewer->stash_list_win) return; @@ -6169,9 +6016,6 @@ void render_branch_list_window(NCursesDiffViewer *viewer) { wrefresh(viewer->branch_list_win); } -/** - * Parse and load content lines from text with diff highlighting - */ int parse_content_lines(NCursesDiffViewer *viewer, const char *content) { if (!viewer || !content) { return 0; @@ -6250,9 +6094,6 @@ int parse_content_lines(NCursesDiffViewer *viewer, const char *content) { return viewer->file_line_count; } -/** - * Load commit details for viewing - */ int load_commit_for_viewing(NCursesDiffViewer *viewer, const char *commit_hash) { if (!viewer || !commit_hash) { @@ -6274,9 +6115,6 @@ int load_commit_for_viewing(NCursesDiffViewer *viewer, return 0; } -/** - * Load stash details for viewing - */ int load_stash_for_viewing(NCursesDiffViewer *viewer, int stash_index) { if (!viewer || stash_index < 0) { return 0; @@ -6297,9 +6135,6 @@ int load_stash_for_viewing(NCursesDiffViewer *viewer, int stash_index) { return 0; } -/** - * Load commits for a specific branch for the hover preview - */ int load_branch_commits(NCursesDiffViewer *viewer, const char *branch_name) { if (!viewer || !branch_name) { return 0; @@ -6322,9 +6157,6 @@ int load_branch_commits(NCursesDiffViewer *viewer, const char *branch_name) { return viewer->branch_commit_count; } -/** - * Parse branch commits into navigable lines for branch view mode - */ int parse_branch_commits_to_lines(NCursesDiffViewer *viewer) { if (!viewer || viewer->branch_commit_count == 0) { return 0; @@ -6394,9 +6226,6 @@ int parse_branch_commits_to_lines(NCursesDiffViewer *viewer) { return viewer->file_line_count; } -/** - * Start background fetch process - */ void start_background_fetch(NCursesDiffViewer *viewer) { if (!viewer || viewer->fetch_in_progress || viewer->critical_operation_in_progress) { @@ -6417,9 +6246,6 @@ void start_background_fetch(NCursesDiffViewer *viewer) { } } -/** - * Check if background fetch is complete and update UI accordingly - */ void check_background_fetch(NCursesDiffViewer *viewer) { if (!viewer || !viewer->fetch_in_progress) { return; @@ -6497,9 +6323,6 @@ void check_background_fetch(NCursesDiffViewer *viewer) { } } -/** - * Update preview based on current mode and selection - */ void update_preview_for_current_selection(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -6565,9 +6388,6 @@ void update_preview_for_current_selection(NCursesDiffViewer *viewer) { } } -/** - * Load file preview showing the top of the file content - */ int load_file_preview(NCursesDiffViewer *viewer, const char *filename) { if (!viewer || !filename) return 0; @@ -6620,10 +6440,6 @@ int load_file_preview(NCursesDiffViewer *viewer, const char *filename) { return 1; } -/** - * Helper function to wrap a long line into multiple display lines - * Returns the number of wrapped lines created - */ int wrap_line_to_width(const char *input_line, char wrapped_lines[][1024], int max_lines, int width) { int input_len = strlen(input_line); @@ -6655,10 +6471,6 @@ int wrap_line_to_width(const char *input_line, char wrapped_lines[][1024], return line_count; } -/** - * Render a single line with proper wrapping and coloring - * Returns the number of display rows used - */ int render_wrapped_line(WINDOW *win, const char *line, int start_y, int start_x, int width, int max_rows, int color_pair, int reverse) { char wrapped_lines[10] @@ -6689,9 +6501,6 @@ int render_wrapped_line(WINDOW *win, const char *line, int start_y, int start_x, return rows_used; } -/** - * Calculate how many display lines a wrapped line will take - */ int calculate_wrapped_line_height(const char *line, int width) { int line_len = strlen(line); if (line_len <= width) { @@ -6700,10 +6509,6 @@ int calculate_wrapped_line_height(const char *line, int width) { return (line_len + width - 1) / width; // Ceiling division } -/** - * Move cursor up/down while skipping empty lines - * direction: -1 for up, 1 for down - */ void move_cursor_smart(NCursesDiffViewer *viewer, int direction) { if (!viewer || viewer->file_line_count == 0) { return; @@ -6783,10 +6588,6 @@ void move_cursor_smart(NCursesDiffViewer *viewer, int direction) { } } -/** - * Move cursor up/down in unstaged pane with proper scrolling - * direction: -1 for up, 1 for down - */ void move_cursor_smart_unstaged(NCursesDiffViewer *viewer, int direction) { if (!viewer || viewer->file_line_count == 0) { return; @@ -6895,10 +6696,6 @@ void move_cursor_smart_unstaged(NCursesDiffViewer *viewer, int direction) { } } -/** - * Move cursor up/down in staged pane with proper scrolling - * direction: -1 for up, 1 for down - */ void move_cursor_smart_staged(NCursesDiffViewer *viewer, int direction) { if (!viewer || viewer->staged_line_count == 0) { return; @@ -6985,9 +6782,6 @@ void move_cursor_smart_staged(NCursesDiffViewer *viewer, int direction) { } } -/** - * Clean up ncurses diff viewer resources - */ void cleanup_ncurses_diff_viewer(NCursesDiffViewer *viewer) { if (viewer) { // Clean up any background fetch process @@ -7024,9 +6818,6 @@ void cleanup_ncurses_diff_viewer(NCursesDiffViewer *viewer) { endwin(); } -/** - * Initialize fuzzy search state - */ void init_fuzzy_search(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -7050,9 +6841,6 @@ void init_fuzzy_search(NCursesDiffViewer *viewer) { viewer->fuzzy_last_filtered_count = -1; } -/** - * Cleanup fuzzy search windows - */ void cleanup_fuzzy_search(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -7067,10 +6855,6 @@ void cleanup_fuzzy_search(NCursesDiffViewer *viewer) { } } -/** - * Calculate fuzzy match score - higher score is better match - * Returns 0 if no match, positive score if match - */ int calculate_fuzzy_score(const char *pattern, const char *filename) { if (!pattern || !filename) return 0; @@ -7149,9 +6933,6 @@ int calculate_fuzzy_score(const char *pattern, const char *filename) { return score; } -/** - * Compare function for sorting scored files (higher scores first) - */ int compare_scored_files(const void *a, const void *b) { const struct { int file_index; @@ -7165,9 +6946,6 @@ int compare_scored_files(const void *a, const void *b) { file_a->score; // Descending order (higher scores first) } -/** - * Update fuzzy search filter based on current query - */ void update_fuzzy_filter(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -7196,9 +6974,6 @@ void update_fuzzy_filter(NCursesDiffViewer *viewer) { } } -/** - * Enter fuzzy search mode - */ void enter_fuzzy_search_mode(NCursesDiffViewer *viewer) { if (!viewer || viewer->current_mode != NCURSES_MODE_FILE_LIST) return; @@ -7234,9 +7009,6 @@ void enter_fuzzy_search_mode(NCursesDiffViewer *viewer) { viewer->fuzzy_needs_full_redraw = 1; } -/** - * Exit fuzzy search mode - */ void exit_fuzzy_search_mode(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -7249,9 +7021,6 @@ void exit_fuzzy_search_mode(NCursesDiffViewer *viewer) { refresh(); } -/** - * Render fuzzy search input field only - */ void render_fuzzy_input(NCursesDiffViewer *viewer) { if (!viewer->fuzzy_input_win) return; @@ -7275,9 +7044,6 @@ void render_fuzzy_input(NCursesDiffViewer *viewer) { wrefresh(viewer->fuzzy_input_win); } -/** - * Render fuzzy search file list content only (no borders) - */ void render_fuzzy_list_content(NCursesDiffViewer *viewer) { if (!viewer->fuzzy_list_win) return; @@ -7329,9 +7095,6 @@ void render_fuzzy_list_content(NCursesDiffViewer *viewer) { wrefresh(viewer->fuzzy_list_win); } -/** - * Create fuzzy search windows with borders (one-time setup) - */ void create_fuzzy_windows_with_borders(NCursesDiffViewer *viewer) { if (!viewer->fuzzy_input_win || !viewer->fuzzy_list_win) return; @@ -7348,9 +7111,6 @@ void create_fuzzy_windows_with_borders(NCursesDiffViewer *viewer) { wrefresh(viewer->fuzzy_list_win); } -/** - * Main fuzzy search render function with granular updates - */ void render_fuzzy_search(NCursesDiffViewer *viewer) { if (!viewer || !viewer->fuzzy_search_active) return; @@ -7393,9 +7153,6 @@ void render_fuzzy_search(NCursesDiffViewer *viewer) { viewer->fuzzy_last_filtered_count = viewer->fuzzy_filtered_count; } -/** - * Handle fuzzy search input - */ int handle_fuzzy_search_input(NCursesDiffViewer *viewer, int key) { if (!viewer || !viewer->fuzzy_search_active) return 0; @@ -7458,9 +7215,6 @@ int handle_fuzzy_search_input(NCursesDiffViewer *viewer, int key) { } } -/** - * Select file from fuzzy search results - */ void select_fuzzy_file(NCursesDiffViewer *viewer) { if (!viewer || viewer->fuzzy_filtered_count == 0) return; @@ -7506,9 +7260,6 @@ void select_fuzzy_file(NCursesDiffViewer *viewer) { } } -/** - * Initialize grep search state - */ void init_grep_search(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -7533,9 +7284,6 @@ void init_grep_search(NCursesDiffViewer *viewer) { viewer->grep_last_filtered_count = -1; } -/** - * Cleanup grep search windows - */ void cleanup_grep_search(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -7550,9 +7298,6 @@ void cleanup_grep_search(NCursesDiffViewer *viewer) { } } -/** - * Extract branch name from stash info - */ void extract_branch_from_stash(const char *stash_info, char *branch_name, int max_len) { if (!stash_info || !branch_name || max_len <= 0) @@ -7583,9 +7328,6 @@ void extract_branch_from_stash(const char *stash_info, char *branch_name, } } -/** - * Calculate grep match score for text content - */ int calculate_grep_score(const char *pattern, const char *text) { if (!pattern || !text) return 0; @@ -7648,9 +7390,6 @@ int calculate_grep_score(const char *pattern, const char *text) { return score; } -/** - * Compare function for sorting grep scored items - */ int compare_grep_scored_items(const void *a, const void *b) { const struct { int item_index; @@ -7663,9 +7402,6 @@ int compare_grep_scored_items(const void *a, const void *b) { return item_b->score - item_a->score; // Descending order } -/** - * Update grep search filter based on current query and mode - */ void update_grep_filter(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -7758,9 +7494,6 @@ void update_grep_filter(NCursesDiffViewer *viewer) { } } -/** - * Enter grep search mode for current view mode - */ void enter_grep_search_mode(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -7795,9 +7528,6 @@ void enter_grep_search_mode(NCursesDiffViewer *viewer) { viewer->grep_needs_full_redraw = 1; } -/** - * Exit grep search mode - */ void exit_grep_search_mode(NCursesDiffViewer *viewer) { if (!viewer) return; @@ -7810,9 +7540,6 @@ void exit_grep_search_mode(NCursesDiffViewer *viewer) { refresh(); } -/** - * Render grep search input field only - */ void render_grep_input(NCursesDiffViewer *viewer) { if (!viewer->grep_input_win) return; @@ -7836,9 +7563,6 @@ void render_grep_input(NCursesDiffViewer *viewer) { wrefresh(viewer->grep_input_win); } -/** - * Render grep search list content only (no borders) - */ void render_grep_list_content(NCursesDiffViewer *viewer) { if (!viewer->grep_list_win) return; @@ -7980,9 +7704,6 @@ void render_grep_list_content(NCursesDiffViewer *viewer) { wrefresh(viewer->grep_list_win); } -/** - * Create grep search windows with borders (one-time setup) - */ void create_grep_windows_with_borders(NCursesDiffViewer *viewer) { if (!viewer->grep_input_win || !viewer->grep_list_win) return; @@ -8015,9 +7736,6 @@ void create_grep_windows_with_borders(NCursesDiffViewer *viewer) { wrefresh(viewer->grep_list_win); } -/** - * Main grep search render function with granular updates - */ void render_grep_search(NCursesDiffViewer *viewer) { if (!viewer || !viewer->grep_search_active) return; @@ -8060,9 +7778,6 @@ void render_grep_search(NCursesDiffViewer *viewer) { viewer->grep_last_filtered_count = viewer->grep_filtered_count; } -/** - * Handle grep search input - */ int handle_grep_search_input(NCursesDiffViewer *viewer, int key) { if (!viewer || !viewer->grep_search_active) return 0; @@ -8125,9 +7840,6 @@ int handle_grep_search_input(NCursesDiffViewer *viewer, int key) { } } -/** - * Select item from grep search results - */ void select_grep_item(NCursesDiffViewer *viewer) { if (!viewer || viewer->grep_filtered_count == 0) return; diff --git a/src/ui/themes.c b/src/ui/themes.c index 696f7d3..9faa1bc 100644 --- a/src/ui/themes.c +++ b/src/ui/themes.c @@ -1,7 +1,3 @@ -/** - * themes.c - * Implementation of theme system for shell appearance - */ #include "themes.h" #include @@ -195,9 +191,6 @@ static ShellTheme catppuccin_mocha_theme = { // Path to the theme configuration file char theme_config_path[PATH_MAX]; -/** - * Initialize the theme system - */ void init_theme_system(void) { // Determine theme config file location in user's home directory char *home_dir = getenv("HOME"); @@ -230,12 +223,6 @@ void init_theme_system(void) { } } -/** - * Load a specific theme by name - * - * @param theme_name Name of the theme to load - * @return 1 if successful, 0 if theme not found - */ int load_theme(const char *theme_name) { if (strcmp(theme_name, "default") == 0) { memcpy(¤t_theme, &default_theme, sizeof(ShellTheme)); @@ -253,10 +240,6 @@ int load_theme(const char *theme_name) { return 0; } -/** - * Apply the current theme settings - * Called whenever theme-dependent UI elements need to be updated - */ void apply_current_theme(void) { // When called, the shell can update any on-screen elements that depend on // theme colors. This function would be called when changing themes or at startup. @@ -289,16 +272,8 @@ void apply_current_theme(void) { } } -/** - * Get pointer to the current theme - * - * @return Pointer to the current theme structure - */ const ShellTheme *get_current_theme(void) { return ¤t_theme; } -/** - * List all available themes - */ void list_available_themes(void) { printf("Available themes:\n"); printf(" default - Standard shell colors\n"); @@ -317,9 +292,6 @@ void list_available_themes(void) { } } -/** - * Initialize themes at shell startup - */ void init_themes(void) { // Call the theme system initialization init_theme_system(); @@ -328,9 +300,6 @@ void init_themes(void) { apply_current_theme(); } -/** - * Shutdown theme system - */ void shutdown_themes(void) { // Reset terminal color to default printf(ANSI_COLOR_RESET); @@ -338,12 +307,6 @@ void shutdown_themes(void) { // Currently, no other cleanup is needed for the theme system } -/** - * Command handler for the "theme" command - * - * @param args Command arguments - * @return 1 to continue shell execution, 0 to exit shell - */ int lsh_theme(char **args) { if (args[1] == NULL) { // No arguments, show usage info and current theme diff --git a/src/utils/countdown_timer.c b/src/utils/countdown_timer.c index ada4c07..8f56213 100644 --- a/src/utils/countdown_timer.c +++ b/src/utils/countdown_timer.c @@ -1,7 +1,3 @@ -/** - * countdown_timer.c - * Implementation of a focus timer that integrates with the shell status bar - */ #include "countdown_timer.h" #include "common.h" @@ -28,9 +24,6 @@ static struct { // programs } timer_state = {FALSE, 0, "", "", 0, FALSE, FALSE}; -/** - * Update timer display text based on remaining time - */ static void update_timer_display(void) { if (!timer_state.is_active) { strcpy(timer_state.display_text, ""); @@ -66,9 +59,6 @@ static void update_timer_display(void) { } } -/** - * Timer thread function - */ static void *timer_thread_func(void *param) { while (!timer_state.should_exit) { // Update timer display @@ -94,9 +84,6 @@ static void *timer_thread_func(void *param) { return NULL; } -/** - * Start a new countdown timer - */ int start_countdown_timer(int seconds, const char *name) { // Stop any existing timer if (timer_state.is_active) { @@ -136,9 +123,6 @@ int start_countdown_timer(int seconds, const char *name) { return 1; } -/** - * Stop the current countdown timer - */ void stop_countdown_timer() { if (!timer_state.is_active) { return; @@ -165,14 +149,8 @@ void stop_countdown_timer() { timer_state.session_name[0] = '\0'; } -/** - * Check if a timer is currently active - */ BOOL is_timer_active() { return timer_state.is_active; } -/** - * Get the current timer display text - */ const char *get_timer_display() { if (timer_state.is_temporarily_hidden || !timer_state.is_active) { return ""; @@ -180,19 +158,10 @@ const char *get_timer_display() { return timer_state.display_text; } -/** - * Temporarily hide the timer display - */ void hide_timer_display(void) { timer_state.is_temporarily_hidden = TRUE; } -/** - * Restore the timer display after it was hidden - */ void show_timer_display(void) { timer_state.is_temporarily_hidden = FALSE; } -/** - * Parse time string in format "XhYmZs" to seconds - */ static int parse_time_string(const char *time_str) { if (!time_str || !*time_str) { return 0; @@ -252,9 +221,6 @@ static int parse_time_string(const char *time_str) { return total_seconds; } -/** - * Command handler for the focus timer command - */ int lsh_focus_timer(char **args) { if (!args[1]) { // No arguments - show help diff --git a/src/utils/timer.c b/src/utils/timer.c index 93d8f4a..97c5d71 100644 --- a/src/utils/timer.c +++ b/src/utils/timer.c @@ -1,20 +1,9 @@ -/** - * timer.c - * Implements a command to measure execution time of other commands - */ #include "builtins.h" #include "common.h" #include "shell.h" #include -/** - * Format a time interval in milliseconds to a readable string - * - * @param ms Time in milliseconds - * @param buffer Buffer to store formatted time - * @param buffer_size Size of the buffer - */ void format_time(double ms, char *buffer, size_t buffer_size) { if (ms < 1.0) { // Microseconds @@ -33,13 +22,6 @@ void format_time(double ms, char *buffer, size_t buffer_size) { } } -/** - * Implementation of the timer command - * Usage: timer COMMAND [ARGS...] - * - * @param args Command arguments - * @return 1 to continue, 0 to exit - */ int lsh_timer(char **args) { if (!args[1]) { printf("timer: usage: timer COMMAND [ARGS...]\n"); @@ -87,11 +69,4 @@ int lsh_timer(char **args) { return result; } -/** - * Implementation of the time command (alias for timer) - * Usage: time COMMAND [ARGS...] - * - * @param args Command arguments - * @return 1 to continue, 0 to exit - */ int lsh_time(char **args) { return lsh_timer(args); } \ No newline at end of file diff --git a/src/utils/weather.c b/src/utils/weather.c index fcc9caa..588e60b 100644 --- a/src/utils/weather.c +++ b/src/utils/weather.c @@ -1,8 +1,3 @@ -/** - * weather.c - * Implementation of weather information fetching and display for Linux - * Uses wttr.in service to display weather with its rich UI - */ #include "weather.h" #include "favorite_cities.h" @@ -13,10 +8,6 @@ // this is a test // this is another test -/** - * Command handler for the "weather" command - * Executes curl to get weather from wttr.in with full UI - */ int lsh_weather(char **args) { char command[256]; char location[128] = ""; // Default empty location