- Lua 54.1%
- Rust 45.9%
Why: - New config option from the previous commit had no README mention. What: - Added a short note + example to the Undo/Redo Integration section, explaining why it exists (so the first undo past your first save has a real commit to land on) right next to the related caveat about unmatched pre-edit states. Impact: - Docs only. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|---|---|---|
| lua/localhistory | ||
| plugin | ||
| rust | ||
| tests | ||
| .gitignore | ||
| README.md | ||
localhistory.nvim
Local, Git-inspired per-file history for Neovim.
This repo contains:
lua/,plugin/: the Neovim pluginrust/: the Rust backend (localhistoryd)
Quickstart (Lua backend)
By default the plugin uses the Lua backend.
require("localhistory").setup()
Quickstart (Rust backend)
1) Build localhistoryd
rust.bin auto-detects rust/target/release/localhistoryd relative to
wherever this plugin itself is installed, so all you need to do is get that
binary built there. How depends on how you installed the plugin:
Installed via a plugin manager (from git): wire up its build/post-install hook to build the binary in place after clone/update:
-- lazy.nvim
{
"bentrinh/localhistory.nvim",
build = "cd rust && cargo build --release -p localhistoryd",
-- Without this, plugin/localhistory.lua auto-runs setup() with defaults
-- (Lua backend) before `config` below runs setup() again with your options.
-- Harmless (config below still wins), but redundant — skip it.
init = function()
vim.g.localhistory_auto_setup = false
end,
config = function()
require("localhistory").setup({ backend = "rust" })
end,
}
-- packer.nvim
use({
"bentrinh/localhistory.nvim",
run = "cd rust && cargo build --release -p localhistoryd",
})
" vim-plug
Plug 'bentrinh/localhistory.nvim', { 'do': 'cd rust && cargo build --release -p localhistoryd' }
The hook only runs on install/update, so after pulling a new version that
touches rust/, trigger your manager's build step again (e.g. :Lazy build localhistory.nvim, :PackerCompile after a change, or :PlugInstall!).
Manual clone (no plugin manager): from the repo root:
cd rust
cargo build --release -p localhistoryd
Either way, an alternative that puts localhistoryd on $PATH instead
(useful if you'd rather not rely on the auto-detected path):
cargo install --path rust/crates/localhistoryd --locked
2) Configure the Neovim plugin
require("localhistory").setup({
backend = "rust",
})
rust.bin only needs to be set explicitly if you installed the binary
somewhere the auto-detection won't find (e.g. via cargo install, where the
bare name "localhistoryd" resolves via $PATH):
require("localhistory").setup({
backend = "rust",
rust = { bin = "localhistoryd" },
})
If you'd rather disable auto-setup and configure explicitly:
vim.g.localhistory_auto_setup = false
require("localhistory").setup({ backend = "rust" })
Or, keeping auto-setup enabled, set this before the plugin loads:
vim.g.localhistory_config = {
backend = "rust",
}
Commands
:LocalHistoryToggle:LocalHistoryUndo:LocalHistoryRedo:LocalHistoryCheckout:LocalHistoryDiff:LocalHistoryDiffClose:LocalHistoryOpenLog(rust backend only, see Debugging the rust daemon)
Debugging the rust daemon
By default localhistoryd logs nothing. To see what it's doing (each request it
handles and the response it sends back), set a log level:
require("localhistory").setup({
backend = "rust",
rust = {
-- tracing's RUST_LOG syntax: "error" | "warn" | "info" | "debug" | "trace",
-- or a per-target filter like "localhistoryd=trace".
log_level = "debug",
},
})
Then :LocalHistoryOpenLog opens the log file (default:
storage_path/localhistoryd.log; override with rust.log_path). Each Neovim
session's daemon run is appended as its own --- localhistoryd session started ... --- block. Even with log_level unset, this file still captures
any panic/crash output the daemon prints, so it's worth checking first if the
rust backend seems stuck or unresponsive.
Browsing long histories
The sidebar renders history in pages (default: 200 commits) so huge histories stay fast. When older commits are hidden, a marker line shows how many remain:
~ 37 more commits - L: load more, A: show all
L— load the next page of older commitsA— render the entire history
Configure the page size (or disable pagination entirely):
require("localhistory").setup({
visualizer = {
page_size = 200, -- commits per page; 0 or nil = always render everything
},
})
The Rust CLI supports the same limit for debugging:
localhistoryd --db-path /tmp/localhistory.sqlite3 graph --filepath /abs/path/to/file --limit 200
Undo/Redo Integration
By default, localhistory.nvim does not override Neovim's native u / <C-r>.
If you want localhistory to follow native undo/redo navigation, enable the opt-in hook:
require("localhistory").setup({
hooks = {
native_undo_redo = {
enabled = true,
keys = { undo = "u", redo = "<C-r>" },
-- method = "autocmd", -- default
},
},
})
When enabled, localhistory observes native undo/redo and consolidates its current commit to the buffer content:
- If the current buffer content matches an existing localhistory commit, localhistory moves to that commit.
- If the content does not match any commit (unsaved intermediate undo states), localhistory does not move its pointer.
Since only saved states are ever commits, the very first native undo past your first edit-and-save normally has nothing to land on (the pre-edit state was never committed) and correctly does nothing. To avoid that, opening a file localhistory has never seen seeds a commit from its current on-disk content, so there's always a real commit for the first undo to reach:
require("localhistory").setup({
auto_commit_on_open = true, -- default; set false to only start tracking from the first save
})
CLI (Rust)
localhistoryd also provides a small CLI for debugging without Neovim.
Examples:
localhistoryd --db-path /tmp/localhistory.sqlite3 tree --filepath /abs/path/to/file
localhistoryd --db-path /tmp/localhistory.sqlite3 graph --filepath /abs/path/to/file
localhistoryd --db-path /tmp/localhistory.sqlite3 content --filepath /abs/path/to/file
localhistoryd --db-path /tmp/localhistory.sqlite3 undo --filepath /abs/path/to/file
Daemon:
localhistoryd --db-path /tmp/localhistory.sqlite3 serve --stdio