Skip to content

Git Log: bottom-docked history tool window (JetBrains-style) #3

Description

@dG9hc3Q

Summary

Add a Git Log tool window, docked like JetBrains' "Git" tool window:
a bottom-docked panel with the commit-graph list on the left and a
selected-commit detail view on the right. It sits alongside the existing
Rhyme Search bottom panel and is toggled from the bottom tool-window stripe.

Motivation

Rhymr already has VCS baked into the editor — change bars in the gutter
(editor::vcs_gutter + git::ops::line_changes), a branch segment in the
status bar, and commit/push/pull/fetch actions (git/dialog.rs,
app.git-*). There is no way to see history: what changed, when, and by
whom. For a lyric IDE where version control is a headline feature, a
browsable log is the missing piece.

Reference — JetBrains Git Log

  • Left: reverse-chronological commit list with the branch/merge graph
    rail, columns for subject, author, date; branch/tag ref labels on the
    relevant rows; a "load more" tail (paged, not the whole history at once).
  • Right (or below): selected commit's metadata (full hash, author,
    committer, date, full message) and its list of changed files.
  • Double-click a changed file -> diff of that file at that commit.
  • Filter/search bar: by branch, by author, by message substring.

Scope the first version to the left list + commit detail + changed-file
list. Per-file diff view and the filter bar can be a fast follow.

UI / docking

  • New bottom-docked panel, same mechanism as Rhyme Search: a child of the
    vertical Paned in app/layout.rs, hidden until toggled.
  • app/chrome.rs::bottom_stripe currently hardcodes a single "Rhyme
    Search" toggle — generalise it to host multiple bottom tool-window
    buttons ("Rhyme Search", "Git"), or add a second stripe entry. Only one
    bottom panel visible at a time (JetBrains behaviour), or allow the
    Paned to show whichever was last toggled.
  • Follow the rhyme/search.rs::RhymeSearch widget shape:
    get_widget() / is_collapsed() / set_expanded() / connect_toggle().
  • Wire an app.git-log gio action + accel in app/menu.rs (JetBrains uses
    Alt+9 for the Git tool window; pick something consistent with the
    existing accel scheme), and a "Git Log" item in the Git menu.
  • Styling: classic/boxy, --radius-* = 0, driven from SCSS
    (assets/scss/…, new stem registered in CSS_FILES in both
    src/css.rs and build.rs). Graph rail colours come from the theme
    palette in src/css.rs (PALETTE, (name, dark, light)), not hardcoded.
  • Icons via crate::app::icons::img (there are vcs/git-* NetIcons in
    the bundled set already).

Data layer — git/ops.rs

Add history reads to GitController (git2 revwalk), keeping the existing
error-handling and threading conventions in that module:

  • fn log(&self, start: LogStart, limit: usize, skip: usize) -> Result<Vec<CommitSummary>, _>
    — paged; LogStart = current HEAD / a branch / all refs.
  • struct CommitSummary { id, short_id, summary, author_name, author_email, time, parent_ids } — enough to render a row and draw the graph edges.
  • fn commit_detail(&self, id) -> Result<CommitDetail, _> — full message,
    author + committer, and the changed-file list (git2::Diff of the
    commit against its first parent; handle the root commit).
  • fn ref_labels(&self) -> Result<HashMap<Oid, Vec<RefLabel>>, _> — local
    branches, remote branches, tags, for the ref chips.
  • (fast follow) fn file_diff_at(&self, id, path) -> Result<…, _> for the
    double-click diff.

One representation for a commit — don't add a parallel model next to
whatever line_changes / file_statuses already use.

Behaviour

  • All git reads run off the GTK main thread; results marshalled back to
    the UI (CLAUDE.md non-negotiable — no blocking work on the main thread).
  • Load the first page (~100 commits) on first open; append pages on scroll
    to bottom / "Load more".
  • Refresh on demand (toolbar button in the panel) and after any in-app
    commit/pull/fetch (hook into the same WorkspaceController refresh path
    that updates the branch label and gutter).
  • Selecting a commit populates the detail pane; empty state when nothing
    selected.
  • When the workspace isn't a git repo, the panel shows an inert "Not a git
    repository" placeholder (mirror how the status-bar branch segment / gutter
    handle that).
  • Graph rendering: a GtkDrawingArea column (or per-row drawn cell)
    painting parent edges — start simple (single-lane for linear history,
    widen lanes for merges); it doesn't need to be pixel-perfect with
    JetBrains on day one.

Out of scope (separate follow-ups)

  • Committing / amending / reverting / cherry-pick / branch checkout from
    the log (context-menu actions).
  • Interactive rebase.
  • Blame.
  • Diff viewer polish beyond a plain per-file textual diff.

Acceptance criteria

  • Bottom-docked "Git" panel, toggled from the bottom stripe + an
    app.git-log action/accel + a Git-menu entry.
  • Commit list: subject / author / date, ref-label chips, paged loading.
  • Commit detail pane: full hash, author, committer, date, full
    message, changed-file list.
  • History reads added to GitController via git2 revwalk, one commit
    model, typed to the module's existing error style.
  • All git reads off the main thread; panel refreshes after in-app
    commit/pull/fetch.
  • Non-repo and empty-selection states handled.
  • SCSS stem registered in css.rs + build.rs; graph/theme colours
    from the src/css.rs palette; icons via icons::img.
  • cargo fmt + cargo clippy clean; syllable regression suite
    unaffected.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions