feat: Add interactive line-by-line staging to ncurses diff viewer
Implement comprehensive interactive staging functionality that allows users to stage and unstage individual lines, similar to `git add -p` but with a visual interface. New features: - Split view mode showing unstaged changes (left) and staged changes (right) - Line-by-line staging: press Space on any diff line to stage/unstage it - Tab switching between unstaged and staged panes - Apply staged changes with 'a' key (runs `git apply --cached`) - Visual indicators for staged vs unstaged content with proper syntax highlighting - Interactive unstaging: switch to staged pane and press Space to unstage lines - Automatic refresh of git status after staging/unstaging operations - Proper git integration reading from both working directory and staging area Technical implementation: - Added `load_file_with_staging_info()` to load unstaged changes (staging vs working) - Added `rebuild_staged_view_from_git()` to load staged changes (HEAD vs staging) - Added `stage_hunk_by_line()` for individual line staging - Added `unstage_line_from_git()` for removing lines from staging area - Added `apply_staged_changes()` to apply staged content to git - Enhanced file content window with split view rendering - Added proper cursor management for both unstaged and staged panes This transforms the diff viewer into a full-featured interactive staging tool, allowing developers to create atomic commits with only specific lines rather than entire files. Keybindings: - Enter: Switch to split staging view - Tab: Switch between unstaged/staged panes - Space: Stage/unstage current line - 'a': Apply staged changes to git - 'c': Commit staged changes - 'r': Reset staged changes
This commit is contained in:
BIN
builtins.o
BIN
builtins.o
Binary file not shown.
@@ -1412,7 +1412,7 @@ char ***lsh_split_piped_line(char *line) {
|
||||
}
|
||||
|
||||
// First split by pipe character
|
||||
cmd_str = strtok_r(line, "|", &save_ptr);
|
||||
cmd_str = strtok_r(line, "|", &save_ptr);
|
||||
|
||||
while (cmd_str != NULL) {
|
||||
// Allocate space for this command
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@ typedef struct {
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
char status; // 'M' = modified, 'A' = added, 'D' = deleted
|
||||
int marked_for_commit; // 1 if marked for commit, 0 otherwise
|
||||
int has_staged_changes;
|
||||
} NCursesChangedFile;
|
||||
|
||||
typedef struct {
|
||||
@@ -40,6 +41,11 @@ typedef struct {
|
||||
char line[1024];
|
||||
char type; // '+' = addition, '-' = deletion, ' ' = context, '@' = hunk header
|
||||
int is_diff_line; // 1 if this is a diff line, 0 if original file line
|
||||
int hunk_id;
|
||||
int is_staged;
|
||||
int line_number_old;
|
||||
int line_number_new;
|
||||
int is_context;
|
||||
} NCursesFileLine;
|
||||
|
||||
typedef struct {
|
||||
@@ -138,6 +144,16 @@ typedef struct {
|
||||
int branch_commits_scroll_offset;
|
||||
int branch_commits_cursor_line;
|
||||
|
||||
int split_view_mode; // 0 = normal view, 1 = split staged/unstaged
|
||||
int staged_scroll_offset; // Scroll position for staged pane
|
||||
int active_pane; // 0 = unstaged, 1 = staged
|
||||
char current_file_path[512]; // Path of currently viewed file
|
||||
int total_hunks; // Total number of hunks in current file
|
||||
NCursesFileLine
|
||||
staged_lines[MAX_FULL_FILE_LINES]; // Separate storage for staged content
|
||||
int staged_line_count; // Number of lines in staged view
|
||||
int staged_cursor_line;
|
||||
|
||||
} NCursesDiffViewer;
|
||||
|
||||
/**
|
||||
@@ -331,4 +347,23 @@ int get_github_credentials(char *username, int username_len, char *token,
|
||||
int execute_git_with_auth(const char *base_cmd, const char *username,
|
||||
const char *token);
|
||||
|
||||
int stage_hunk_by_line(NCursesDiffViewer *viewer, int line_index);
|
||||
|
||||
int laod_file_with_staging_info(NCursesDiffViewer *viewer,
|
||||
const char *filename);
|
||||
|
||||
void rebuild_staged_view(NCursesDiffViewer *viewer);
|
||||
|
||||
int apply_staged_changes(NCursesDiffViewer *viewer);
|
||||
|
||||
int reset_staged_changes(NCursesDiffViewer *viewer);
|
||||
|
||||
int unstage_line_from_git(NCursesDiffViewer *viewer, int staged_line_index);
|
||||
|
||||
int commit_staged_changes_only(NCursesDiffViewer *viewer,
|
||||
const char *commit_title,
|
||||
const char *commit_message);
|
||||
|
||||
void rebuild_staged_view_from_git(NCursesDiffViewer *viewer);
|
||||
|
||||
#endif // NCURSES_DIFF_VIEWER_H
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user