Skip to content

feat: add toggleable raw diff view with color support#112

Draft
rm-hull wants to merge 17 commits into
mainfrom
feat/diff-view
Draft

feat: add toggleable raw diff view with color support#112
rm-hull wants to merge 17 commits into
mainfrom
feat/diff-view

Conversation

@rm-hull
Copy link
Copy Markdown
Owner

@rm-hull rm-hull commented May 24, 2026

Add Raw Diff view to TUI. Allow users to inspect staged changes with original git colors before/during commit summary generation.

Key Changes

  • Git Client: Implemented DiffWithColor using a PTY (pseudo-terminal) to trick git into emitting ANSI color codes.
  • UI Model:
    • Added showDiffView state.
    • Implemented CTRL+D toggle between commit view and diff view.
    • Added diffColorMsg to handle asynchronous diff loading.
  • Diff View: Created diffViewModel using bubbles/viewport for scrollable, colored diff output.

User Flow

graph TD
    A[Commit View] -- "CTRL+D" --> B{Diff Loaded?}
    B -- No --> C[Fetch Colored Diff]
    C --> D[Diff View]
    B -- Yes --> D
    D -- "CTRL+D / ESC" --> A
Loading

Technical Implementation Detail

git diff normally strips colors when output is piped. To preserve them, the app now spawns git inside a PTY, forcing git to believe it's talking to a real terminal, thus preserving ANSI color codes for the TUI.

rm-hull added 3 commits May 24, 2026 22:34
Migrated the diff view logic from the main model into a dedicated
`diffViewModel` struct to improve separation of concerns and
maintainability
of the Bubble Tea model.

- Introduced `showDiffView` state.
- Encapsulated UI rendering and message handling for the diff view.
- Simplified the main `Model` update and view logic by delegating to the
  new component.
Apply strikethrough to the CTRL+K keybinding in the help text to
visually indicate the action is currently unavailable or disabled.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 24, 2026

TestsPassed ✅SkippedFailed
JUnit Test Report56 ran56 passed0 skipped0 failed
TestResult
JUnit Test Report
com/rm-hull/git-commit-summary/internal/config.TestLoad/Defaults✅ passed
com/rm-hull/git-commit-summary/internal/config.TestLoad/WithEnvironmentVariables✅ passed
com/rm-hull/git-commit-summary/internal/config.TestLoad✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/handle_empty_quoted_strings✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/empty_file,_add_new_properties✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/existing_file,_update_properties✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/doesnt_overwrite_values_if_new_value_is_the_same✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/existing_file,_add_new_and_update_existing✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/preserve_comments_and_other_lines✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/handle_mixed_quoting_styles✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/empty_props,_no_changes✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/properties_with_special_characters✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties✅ passed
com/rm-hull/git-commit-summary/internal/git.TestClient_prepareCommitMessage/Single_line_message_with_skipCI✅ passed
com/rm-hull/git-commit-summary/internal/git.TestClient_prepareCommitMessage/Multi-line_message_with_skipCI✅ passed
com/rm-hull/git-commit-summary/internal/git.TestClient_prepareCommitMessage/Single_line_message_without_skipCI✅ passed
com/rm-hull/git-commit-summary/internal/git.TestClient_prepareCommitMessage/Multi-line_message_without_skipCI✅ passed
com/rm-hull/git-commit-summary/internal/git.TestClient_prepareCommitMessage/Empty_message_with_skipCI✅ passed
com/rm-hull/git-commit-summary/internal/git.TestClient_prepareCommitMessage✅ passed
com/rm-hull/git-commit-summary/internal/llm_provider.TestNewProvider/GoogleProvider✅ passed
com/rm-hull/git-commit-summary/internal/llm_provider.TestNewProvider/OpenAIProvider✅ passed
com/rm-hull/git-commit-summary/internal/llm_provider.TestNewProvider/UnknownProvider✅ passed
com/rm-hull/git-commit-summary/internal/llm_provider.TestNewProvider✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/NewHistory✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Add_and_Value✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Undo✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Redo✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Undo_at_beginning✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Redo_at_end✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Add_truncates_future_history✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Multiple_Undos_and_Redos✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/tea.KeyMsg_-_CtrlC_in_showSpinner_state✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/tea.KeyMsg_-_CtrlC_in_other_states✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/gitCheckMsg_-_empty_(no_staged_changes)✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/gitCheckMsg_-_non-empty_(staged_changes)✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/gitDiffMsg_with_hint✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/llmResultMsg_-_with_user_message✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/llmResultMsg_-_without_user_message✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/commitMsg✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/regenerateMsg_-_initializes_promptView_with_current_hint✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/userResponseMsg_-_updates_m.hint✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/cancelRegenPromptMsg_-_re-enables_help_text✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/errMsg✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/abortMsg✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/spinner.Update_for_showSpinner_state✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/commitView.Update_for_showCommitView_state✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/promptView.Update_for_showRegeneratePrompt_state✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/llmResultMsg_-_YOLO_mode✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/llmResultMsg_-_YOLO_mode_-_empty_summary✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update✅ passed
com/rm-hull/git-commit-summary/internal/version.TestCheckLatestReturnsLatestWhenNewer✅ passed
com/rm-hull/git-commit-summary/internal/version.TestCheckLatestReturnsEmptyWhenUpToDate✅ passed
com/rm-hull/git-commit-summary/internal/version.TestCheckLatestReturnsEmptyForDevel✅ passed
com/rm-hull/git-commit-summary/internal/version.TestCheckLatestWithRevSuffix✅ passed
com/rm-hull/git-commit-summary/internal/version.TestCheckLatestWithRevSuffixAndUpToDate✅ passed

gemini-code-assist[bot]

This comment was marked as outdated.

@coveralls
Copy link
Copy Markdown

coveralls commented May 24, 2026

Coverage Report for CI Build 26846112045

Coverage decreased (-1.7%) to 32.269%

Details

  • Coverage decreased (-1.7%) from the base build.
  • Patch coverage: 105 uncovered changes across 4 files (22 of 127 lines covered, 17.32%).
  • 3 coverage regressions across 2 files.

Uncovered Changes

File Changed Covered %
internal/git/client.go 45 0 0.0%
internal/ui/diff_view.go 45 11 24.44%
internal/ui/model.go 30 10 33.33%
internal/ui/commit_view.go 7 1 14.29%

Coverage Regressions

3 previously-covered lines in 2 files lost coverage.

File Lines Losing Coverage Coverage
internal/ui/model.go 2 60.87%
internal/ui/commit_view.go 1 23.79%

Coverage Stats

Coverage Status
Relevant Lines: 1221
Covered Lines: 394
Line Coverage: 32.27%
Coverage Strength: 0.35 hits per line

💛 - Coveralls

@rm-hull rm-hull changed the title Feat/diff view feat: add toggleable raw diff view with color support May 24, 2026
rm-hull and others added 11 commits May 24, 2026 23:35
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
- Consolidate duplicate diff argument construction into `diffArgs`
helper
- Update `diff_view` UI to mark removed shortcuts as strikethrough
- Update `diffArgs` to accept an exclusion flag for better control.
- Enhance error handling in `DiffWithColor` for `io.Copy` and
`cmd.Wait`.
- Simplify `repeatCount` calculation in `diffViewModel` using `max`.
Cache the `lipgloss.Style` in the `diffViewModel` struct instead of
re-instantiating it on every view update to improve rendering
efficiency.
- Inline `viewport` initialization in `commitViewModel`.
- Update `diffViewModel` help text to include new keybindings:
    - **CTRL+K**: Clear
    - **CTRL+P**: Editor (swapped from Preview)
…t/diff-view

* 'main' of github.com:rm-hull/git-commit-summary:
  fix: streamline summary generation with persistent hints (#116)
  fix: re-enable help text when cancelling regeneration (#115)
  chore: migrate to Charm v2 ecosystem (#114)
  chore: update download stats [skip ci]
  chore: go get -u && go mod tidy (#113)
Consolidate `Diff` and `DiffWithColor` into a single, parameterized
`Diff` method to reduce code duplication and simplify the `GitClient`
interface.

- Updated `GitClient` interface to support color and exclusion flags.
- Simplified `Model` diff retrieval by calling the unified `Diff`
method.
- Cleaned up redundant UI code.
- Replace tabs with spaces in diff output for consistent formatting.
- Refactor state transitions to use custom message types for
  `showDiffView` and `cancelDiffView`.
- Clean up `Update` logic in the main model for better maintainability.
Moved `diffColorMsg` from `diff_view.go` to the main `model.go` struct
to centralize state management and allow access across different UI
components.
Removed `width` and `height` from the `Model` struct as they are no
longer being utilized within the UI logic.
@rm-hull
Copy link
Copy Markdown
Owner Author

rm-hull commented May 25, 2026

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a raw diff view accessible via CTRL+D and integrates PTY support to provide colored git diffs. Key changes include refactoring the GitClient interface, implementing a new diffViewModel, and updating the UI state machine to handle diff transitions. Feedback highlights a potential syscall.EIO error when reading from PTY on Linux, a missing window resize handler for the new view, and the accidental removal of the undo hint from the help text. Additionally, a correction was suggested for the mock git client in tests to properly track arguments.

Comment thread internal/git/client.go
Comment on lines +85 to +87
if _, err := io.Copy(&buf, ptmx); err != nil {
return "", errors.Wrap(err, "reading git diff output failed")
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

On Linux systems, reading from a PTY master file descriptor often returns a syscall.EIO error when the child process (in this case, git) terminates. This will cause io.Copy to return an error even if the command executed successfully and all output was captured. You should check for this specific error and treat it as an EOF if the command otherwise succeeded.

Comment thread internal/ui/commit_view.go
Comment thread internal/ui/model.go
Comment thread internal/ui/model_test.go
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@rm-hull rm-hull marked this pull request as draft May 25, 2026 20:17
rm-hull added 2 commits May 26, 2026 08:54
Update `TestModel_Update` to include the required boolean flags for the
`Diff` method call to match the updated internal API signature.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants