Repository navigation
Explicit repository, diff titles, window bars, single panes and downloads - #4
Merged
Merged
Conversation
The repository was found from the process's current directory whenever a git or jj command started. That directory follows the current window (`:lcd`, `:tcd`), so a diff could use the directory of the new diff tab, or of a window switched to while it loaded; jj diffs run from a subdirectory also read file contents from the wrong paths. `open(revset, opts)` now takes the directory to diff as `opts.cwd`, falling back to the current window's working directory (`:Difft` takes it when run, before the view opens). Every git, jj and difft command runs in that directory's repository root, the diff tab works in that directory (`:tcd`), and with `multiple_diffs` the same revset in another directory opens its own tab. The library's diff functions take the directory as an optional last argument (`cwd` in the asynchronous spec).
The header box of the side panel now starts with a title and a less
prominent subtitle, both derived from the diff:
- a commit diff: the title of its oldest commit, and "+N more" for the
commits after it;
- a staged or unstaged git diff, or the jj working copy: the kind of diff,
and when its files were read ("as of 9 Oct 16:30:04").
The library returns them as title, subtitle and snapshot_time. The title
wraps to the panel width, and when a resize changes its height the tree is
rebuilt below the box, keeping collapsed directories and the cursor row.
The box no longer shows the plugin name. The new highlight groups
DifftDiffTitle and DifftDiffSubtitle color the two parts.
A file that exists on one side only, added or deleted, is shown in one pane that takes the width of both. The other pane's window is closed and opened again, on its side, for the next file with both sides. The panes come back in the ratio they had, also one the user dragged, and resizes while one pane is shown leave that ratio alone. Focus moves to the remaining pane when the focused one closes, and <Tab> from the tree and remembered positions go to the pane that is shown.
The side panel gets a bar with the shown file's status (modified, added, deleted, renamed), right-aligned next to the panes. Each diff pane gets a bar with the file on its side: the file-type icon, the file name, its directory dimmed, and that side's line count (removed lines in the base pane, added lines in the head pane). A narrow pane gives up the directory first, then the count, then cuts the name; every cut uses an ellipsis. The bars share the panel's background and are underlined. The new highlight groups DifftBar, DifftBarNC and DifftBarMuted color them.
The side panel's header and the loading window drop their rounded boxes for the look of the bars: text with a one-cell margin and thin rules, drawn as underlined blank rows (highlight group DifftTreeRule). The loading window gets a bar on top with the share done, or a spinner while the number of files is unknown (DifftLoadingDone), above the range and the last message. DifftTreeTitle and DifftTreeDivider are removed, as nothing uses them any more.
A side panel narrowed by Neovim, for example in a window that opened small, grows back to its width when Neovim grows. A width the user gives the panel, narrower or wider, is kept through resizes; a double click on its border still resets it to the configured width.
The prebuilt library is downloaded from the GitHub repository the plugin was cloned from (its origin), so a fork gets its own releases, else from clabby/difftastic.nvim: the newest release at or before the installed plugin commit, or the latest release when the plugin is not a git clone. The stored version names the repository and the tag. A library from another repository, or one that no longer matches the installed plugin (e.g. after a plugin update), is downloaded again at startup. :DifftUpdate downloads the matching release again instead of the latest.
With download = true, difft is also downloaded from the latest release of jrosiek/difftastic, whose JSON output lists only the words that changed in comments, strings and text, into the library's directory. The library runs the downloaded difft, for jj too, and difft from PATH until it is there or when it cannot be downloaded. Without any difft, a diff stops with a message saying how to get one. A diff opened while a download it needs is still running waits for it in the loading window. :checkhealth difftastic-nvim shows the library and the difft in use, where they come from and their versions. Tests use a data directory of their own.
The side panel's buffer is named difftastic://<tab>/panel and the panes' difftastic://<tab>/base/<path> and difftastic://<tab>/head/<path>, following the shown file (the base pane names a renamed file's old path), so status lines show what a window holds instead of [Scratch]. The tab keeps two diff tabs showing the same file apart; renaming leaves no buffers behind, and the buffers stay unsaved scratch buffers.
A file difft fails on (e.g. crashes on its syntax) no longer fails the whole diff: for git it is compared again in difft's text mode, alone; jj runs difft once over all files, so there all files are compared again as text. jj only warns when its diff tool fails and still exits successfully; that warning now counts as a failure. A file compared as text shows "≡ line by line" on the left of the side panel's bar.
The subtitle of the diff's title and the secondary text in the bars (DifftDiffSubtitle, DifftBarMuted) are the text colour blended into the background instead of links to NonText, which some themes give the background colour itself, leaving that text invisible.
The background of changed text within a line is a fifth stronger, and the text is underlined in the added or removed colour half blended into the background (in the text's own colour where terminals draw no underline colours). The text keeps its syntax colour.
With an odd number of columns to share, the panes' split gave the extra column to the base pane after resizes and resets, but to the head pane on opening the view and on a double click on the split. Evening panes that were already even moved the split by a column. Every split now gives it to the base pane.
A range too long for its row in the side panel's header continues after its arrow on a second row, each side right-aligned; a side still too long for its row is cut at its start, keeping its end (e.g. ~227). Before, the range was cut at its end, often losing the head side.
The README's fork summary lists the diff's title and bars, single panes for added and deleted files, the downloads of a matching library and of a difft that marks only changed words in comments and text, and the line-by-line fallback for files difft fails on. The highlight tables describe DifftAdded and DifftRemoved as changed text within a line and DifftTreeRange as derived from Changed.
Neovim reports a window without a border as nothing, "none" or empty border parts, depending on its version; the loading window test now accepts each.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A diff now runs in an explicit repository, is titled after what it shows, and has bars that say which file is shown and how it changed. Added and deleted files take a single pane, changed text stands out more, and a file difft fails on no longer fails the whole diff. The plugin downloads a library matching its version and a difft with word-level JSON output.
Explicit repository directory
open(revset, opts)takesopts.cwd, a directory inside the repository to diff, so a caller (for example another process talking to Neovim over its socket) can name the repository instead of depending on the current window. Without it, the current window's working directory is used.:Diffttakes the directory when it is run, before the view opens, so:lcd/:tcdof the window it was run from are honoured even when the view opens after startup settles.jj diffnow runs from the repository root, so the paths it reports match the paths the file contents are read from.:tcd), leaving the tab it was opened from alone.multiple_diffs, the same revset in a different directory opens its own tab instead of switching to the other repository's.cwdin the asynchronous spec); without it, the process's directory at the time of the call is used.Diff title
+N morefor the commits after it;as of 9 Oct 16:30:04).DifftDiffTitle(links toTitle) andDifftDiffSubtitle(the text colour blended into the background).Bars on top of the panel and the panes
● modified,+ added,- deleted,➜ renamed), right-aligned next to the panes.…, and the bars never get wider than their window.DifftBar,DifftBarNCandDifftBarMuted.difftastic://<tab>/panel,difftastic://<tab>/base/<path>anddifftastic://<tab>/head/<path>, so status lines show what a window holds instead of[Scratch].One pane for added and deleted files
<Tab>from the tree and remembered positions go to the pane that is shown.Changed text
DifftDiffSubtitle,DifftBarMuted), readable with themes that giveNonTextthe background colour.Header and loading window
DifftTreeRule).tags/v5.8.2-stable~227 → tags/v5.8.2-stable) continues after its arrow on a second row; a side still too long for its row is cut at its start, keeping its end.DifftLoadingDone), or a spinner while the number of files is unknown, then the range, the last message and a rule.DifftTreeTitleandDifftTreeDividerare removed, as nothing uses them any more.Side panel width
Robustness
≡ line by linein the side panel's bar.Downloads
:DifftUpdatedownloads the matching release again instead of the latest.download = truefrom the latest release of jrosiek/difftastic, whose JSON output lists only the words that changed in comments, strings and text (JSON: list only changed words of changed comments, strings and text lines Wilfred/difftastic#1075), into the library's directory. The library runs the downloaded difft, for jj too, and difft fromPATHuntil it is there or when it cannot be downloaded.:checkhealth difftastic-nvimshows the library and the difft in use, where they come from and their versions, and whether nui.nvim is installed.Testing
..and...), staged, unstaged and jj diffs.PATH(git and jj), waiting for a download before a diff, and the health report. Tests use a data directory of their own.🤖 Generated with Claude Code