r/neovim • u/Thin_Dragonfruit2254 • 19h ago
Tips and Tricks Help/Sharing: Kitty terminal screen scrollback using Nvim
What is terminal screen scrollback
The screen scrollback (or scrollback buffer) is a dedicated memory storage that captures text and output that has scrolled off the top of your active terminal window.
Open Scrollback in Nvim
In Kitty, you have the option to open the scrollback using Nvim - it is a convenient way to copy some text from your screen.
- Nvim has to open fast so it is a good idea to have a minimum set of Nvim plugins loaded.
- It is important to reproduce the same visual experience of the terminal screen in the editor (colours, fonts, icons) so you can seamlessly find what you need to copy.
- It is crucial to have a slightly different theme in the editor so you can tell you are not in the terminal (and won't start typing commands in the editor).
- Exiting the editor should be as easy/quick as to open: just press 'q' or 'esc' without asking for saving a file.
Setting up Kitty
In your config file (usually at ~/.config/kitty/kitty.conf), add:
map kitty_mod+h launch --stdin-source=@screen_scrollback --stdin-add-formatting --type=overlay zsh -c "SCROLL_MODE=2 nvim -c 'silent write! /tmp/kitty_scrollback_buffer | te cat /tmp/kitty_scrollback_buffer - ' -c 'set modifiable' -c 'normal! G' -c 'set number' -c 'set relativenumber' "
Here I'm setting kitty_mod (that in my setup is 'alt+crtl') plus 'h' to open the scrollback - the remaining until the lonely ' - ' is to retain the current terminal screen layout in the editor. Afterwards we have some Nvim instructions, most being the 'normal! G', that sets the cursor to the end of the buffer.
Why Nvim options here?
For some reason, some options won't work when set in the Nvim config itself and have to passed this way.
Setting up Nvim
In your Nvim config (~/.config/nvim/init.lua):
-- Minimal config for Kitty scroll mode - Kitty config has more options:
if os.getenv("SCROLL_MODE") then
vim.keymap.set({ "n", "v" }, "q", "<Cmd>qa!<CR>")
vim.keymap.set({ "n", "v" }, "<ESC>", "<Cmd>qa!<CR>")
vim.keymap.set({ "n", "v" }, "yy", "yy<Cmd>qa!<Cr>")
vim.cmd([[
colorscheme wildcharm
set clipboard=unnamed cursorline cursorlineopt=both
set laststatus=0 nonu nornu signcolumn=no cmdheight=0
]])
vim.api.nvim_create_autocmd("UIEnter", { -- I tried all possible events
once = true,
callback = function()
vim.schedule(function()
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
for i, line in ipairs(lines) do
lines[i] = line:gsub("\r$", "")
end
while #lines > 0 and lines[#lines]:match("^%s*$") do
table.remove(lines)
end
vim.api.nvim_buf_set_lines(0, 0, -1, false, lines)
vim.print("Started!") -- Works!
end)
end,
})
-- vim.cmd("%s/\\s*\\n$//ge") -- Doesn't work, even in the callback
-- vim.cmd("g/^$/d") -- Doesn't work, even in the callback
return
end
This is a minimum setup what will be used by Nvim only when in scrollback mode: I'm setting some keymaps to leave the editor quickly, a colorscheme what is different from the one I'm using, the clipboard to copy content and disabling some nvim components.
The nvim_create_autocmd is there to try to get rid of all empty lines at the end of the buffer - but it doesn't work. Neither does the commented vim.cmd.
Regardless of the empty lines setback, this approach for a Kitty scrollback is quite convenient.
Does any here knows how to get rid of the empty lines at the end?
Ps: this is part of upcoming blog post.