Add support for custom pagers, e.g. *Delta*
This PR resolves #97, to support custom pagers. I made it configurable and tested it with Delta.
For Delta, an example config is:
log_pager = { 'delta', '--width', '117' }
I used baleia to colorize text with ANSI escape sequences.
It's recommended to set disable_context_highlighting = true, otherwise when the cursor is in the hunk, we lose background highlighting.
To set a Delta theme, set the environment variables e.g.
vim.env.BAT_THEME = 'Catppuccin Latte'
vim.env.DELTA_FEATURES = '+catppuccin-latte'
Very cool work - I didn't think it would be this straightforward.
Do you have a recommended set of flags to use with delta to provide a good output? This is... a bit rough around the edges.
Hm I'm not sure where the strange colors come from. These minimal settings should hopefully work:
I set these options:
disable_context_highlighting = true,log_pager = { 'delta', '--width', '117' },
In Git settings:
[delta]
side-by-side = true
See if that makes it display properly.
Ok I made a minimal config that's 100% reproducible with Docker. Maybe it's cause you didn't install Bat.
Create this Dockerfile:
# syntax = docker/dockerfile:1.2
FROM alpine:3.21.0
# Install packages
RUN apk add \
bat \
delta \
git \
neovim
Build and run it:
$ docker build --tag nvim_image .
$ docker container run --detach --rm --interactive --name nvim_container --mount 'type=bind,source=/tmp/nvim/,target=/tmp/nvim/' nvim_image
$ docker container exec --interactive --tty --workdir /tmp/nvim/ nvim_container /bin/sh -l
Create /tmp/nvim/init.lua with the contents:
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = 'https://github.com/folke/lazy.nvim.git'
local out = vim.fn.system({ 'git', 'clone', '--filter=blob:none', '--branch=stable', lazyrepo, lazypath })
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ 'Failed to clone lazy.nvim:\n', 'ErrorMsg' },
{ out, 'WarningMsg' },
{ '\nPress any key to exit...' },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
vim.g.mapleader = ' '
vim.g.maplocalleader = '\\'
vim.env.DELTA_FEATURES = '+side-by-side'
-- Setup lazy.nvim
require('lazy').setup({
spec = {
{
dir = '/tmp/nvim/neogit/',
dependencies = {
'nvim-lua/plenary.nvim',
'sindrets/diffview.nvim',
'm00qek/baleia.nvim',
'nvim-telescope/telescope.nvim',
},
opts = {
disable_context_highlighting = true,
graph_style = 'kitty',
log_pager = { 'delta', '--width', '120' },
commit_editor = {
staged_diff_split_kind = 'vsplit_left',
},
},
},
{
'm00qek/baleia.nvim',
version = '*',
config = function() vim.g.baleia = require('baleia').setup({}) end,
},
},
})
vim.cmd('Neogit cwd=/tmp/nvim/neogit/')
In the container run:
$ git clone -b feat/custom-pager --single-branch https://github.com/stevenxxiu/neogit.git
$ nvim -u init.lua
Any luck on getting this to show properly on your end? I hope my Docker example helps. I can provide a screenshot if needed.
The docker example is 10/10, but it still looks off to me. Could you show me a screenshot of how it looks for you?
Hi,
I am trying your repository @stevenxxiu (thanks for the pull request!).
It works great with "side-by-side", but without it, I have ^[[0K at the end of lines.
@misaflo I'm guessing baleia doesn't handle this ANSI control sequence. I removed that part of the line now.
@CKolkey I finally figured the issue out. Turns out for baleia, I used version = "*" in init.lua, so the latest commit wasn't fetched. I'm guessing you did the same.
The following should work now.
Create this Dockerfile. I realize now less is enough. bat isn't required.
# syntax = docker/dockerfile:1.2
FROM alpine:3.21.0
# Install packages
RUN apk add \
less \
delta \
git \
neovim
Build and run it:
$ docker build --tag nvim_image .
$ docker container run --detach --rm --interactive --name nvim_container --mount 'type=bind,source=/tmp/nvim/,target=/tmp/nvim/' nvim_image
$ docker container exec --interactive --tty --workdir /tmp/nvim/ nvim_container /bin/sh -l
Create /tmp/nvim/init.lua with the contents:
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"
vim.env.DELTA_FEATURES = "+side-by-side"
-- Setup lazy.nvim
require("lazy").setup({
spec = {
{
dir = "/tmp/nvim/neogit/",
dependencies = {
"nvim-lua/plenary.nvim",
"sindrets/diffview.nvim",
"m00qek/baleia.nvim",
"nvim-telescope/telescope.nvim",
},
opts = {
disable_context_highlighting = true,
graph_style = "kitty",
log_pager = { "delta", "--width", "119" },
commit_editor = {
staged_diff_split_kind = "vsplit_left",
},
},
},
{
"m00qek/baleia.nvim",
config = function()
vim.g.baleia = require("baleia").setup({})
end,
},
},
})
vim.cmd("Neogit cwd=/tmp/nvim/neogit/")
In the container run:
$ git clone -b feat/custom-pager --single-branch https://github.com/stevenxxiu/neogit.git
$ nvim -u init.lua
@misaflo I'm guessing baleia doesn't handle this ANSI control sequence. I removed that part of the line now.
It fixes the issue, but introduces an other: it highlights (greeen or red) an extra line, where there is no diff.
Ok I took a more detailed look. Now it shouldn't affect the next line, but it won't color the rest of the line's background either, like it should in the terminal. That requires baleia to properly support this ANSI escape sequence.
Oh and here's some screenshots from the Docker config above:
Side by side:
Not side by side:
I rebased and got unit tests to pass.
I'll try to do a good review soon as I can. I have some newborns (twin boys) at home right now so bear with me ;)
Congrats on having 2 twin boys! Take your time.
This is a great work! Looking forward to the merger.
When is this going to get merged?
@CKolkey have you had time yet? This still works fine. I rebased pretty much every time there was an update on master.
@stevenxxiu if this is merged, it will be a replacement for Diffview, right?
@tienlonghungson Not entirely. I use both. diffview lets me copy text easily from the previous commit's files. This is more a visual tool.
@stevenxxiu thank you very much for your work here. I've gotten it working perfectly with no rendering issues for previous commit diffs. When I do neogit diff and select unstaged for unstaged commits however, it still uses diffview.nvim
But if i just use :Neogit and look at the unstaged files, it uses delta.
Do you know how to make it use delta for unstaged diffs inside the diff menu?
Do you know how to make it use delta for unstaged diffs inside the diff menu?
For me that's a way to go explore the diff more deeply, so I prefer using diffview for that.
@CKolkey any shot to get this merged? would really like to use it.
@stevenxxiu has done a great job and the PR looks quite clean
Hi @stevenxxiu, I encountered an issue: when my cursor is outside the changes block, everything displays correctly. But once I move the cursor into it, the background color for the "Diff" disappears. Syntax highlighting still works, but I can no longer see which line has changed. Could this be a problem with my configuration?
@Daydreamer-riri I'm not sure. I don't have this issue with my config. Perhaps create some minimal init.lua that reproduces the issue.
When I'm using LazyVim's default configuration, only the cursor line is highlighted correctly — and even then, only the foreground color appears as expected, while the background color is off. Could this be related to the highlight group settings?
@Daydreamer-riri I can only look into this issue if you give me a minimal init.lua, with only neogit and any dependencies in it, including from this PR.
Sorry, I didn’t enable disable_context_highlighting — I missed the note about it in the documentation. Everything works fine now.
Do I see it correctly that staging particular sections of the diff does no longer work with this?
What I mean is, when I (within a hunk) Select a specific line using Visual (Line) mode, and I hit s, the whole file gets staged.
Tested with my normal setup as well as with this minimal docker example
What I mean is, when I (within a hunk) Select a specific line using Visual (Line) mode, and I hit
s, the whole file gets staged.
That's right. I don't see a way to implement this, as I have to parse the output of the pager.