urxvt has the ability to select text using just the keyboard. By hitting a key you enter into something akin to Vim's normal mode (where you can move the cursor with your keyboard and select text using v). I found this to be a great productivity boost and would be great if kitty supported it as well.
You can open the contents of the kitty screen/scrollback buffer in any arbitrary program
you like, including vimpager. https://sw.kovidgoyal.net/kitty/conf.html#shortcut-kitty.Browse scrollback buffer in less
vimpager doesn't really allow for vim-like selection (or at the very least I can't figure out if it does).
But I was able to do so with neovim and its pager mode. For future reference:
scrollback_pager nvim -c 'set ft=man' -
It isn't as fast as urxvt (since it needs to launch a program), nor are pretty (urxvt just "uncages" the cursor), but it will will do for now.
Still think it would be a great feature to support natively.
To me the ability to use dedicated programs is far superior to using some kind of builtin mode. In your own example, you can take advantage of all the power of vim, which no dedicated mode is ever going to match.
I haven't used urxvt but I highly doubt it supports the level of sophistication in searching/cursor movement/etc. that vim does.
It does not, of course. But that wouldn't be the point, the point would be speed. Opening anything (except for many less) is gonna take several hundreds of millis.
really? vim opens on my system in 27 milliseconds
time vim -u NONE -c exit
0.02s user 0.01s system 96% cpu 0.027 total
yeah I just figured out that I was missing -u NONE. Which makes sense, my plugins are gonna slow things down. Ok, this should be enough. Thanks!
Unfortunately with -u NONE you get ANSI color codes breaking everything up. I can't find a way to get rid of those without loading packages and slowing down startup. Any suggestions on how to proceed?
This has my vote for a feature request: AFAIK there aren't any good options when it comes to pagers that allow native selection and are fast enough on startup.
I seriously doubt that loading the package to parse ansi color codes could materially affect startup times. But even if it did, use the pipe function in kitty to pipe plain text without ansi codes instead. Then you can use -u NONE
I've been using scrollback_pager vim -u NONE so far and it works fine except for the ANSI codes mentioned earlier, but I don't think you can enable raw text with this option. So I tried using map f1 pipe @ansi overlay less +G -R as in the docs but it does nothing without any errors. I've tried adding @screen and @text as well with no luck.
Additionally, using this method the cursor always starts on the beginning of scroll-back instead of at the last prompt, you have to type three keys to get out :q!, and using text editors as pagers generally doesn't work very well.
that stack exchange post is just a bunch of hand waving about how vim wont work well in some terminals as a pager. It works fine in kitty. And the example command using pipe works fine for me. You are probably confused by the fact that on running it the screen does not change, since it basically shows you the screne contents but inside less.
and it is trivial to pass commands to vim on startup if you need the cursor to go to the bottom. One of the many advantages of using something as powerful as vim as apager.
I can understand your position on not including a copy mode implementation in kitty. Different people would want different things and it would either evolve into creeping featurism or leave some people dissatisfied.
However, in order to say that it’s trivial to implement using an external program in a scrollback_pager or pipe command, kitty should pass to that program at least the following:
INPUT_LINE_NUMBER in scrollback_pagerThe external program can then implement its own ideas of cursor motion, selection, and confirmation or cancellation. It will also have to solve the problem of copying the selection to the clipboard and having it persist beyond its own termination — possibly by spawning nohup xclip.
I think it would be pretty easy to extend Window.show_scrollback to pass cursor position analogously to INPUT_LINE_NUMBER. I must ask, however, why is that implemented as text substitution? I’d probably choose carefully named environment variables.
Also, scrollback_pager looks very similar to pipe @ansi overlay; would it be a good idea to extend pipe so that it would be able to replace scrollback_pager completely?
On Sat, Nov 24, 2018 at 12:19:56PM -0800, Yuri Khan wrote:
I can understand your position on not including a copy mode implementation in kitty. Different people would want different things and it would either evolve into creeping featurism or leave some people dissatisfied.
However, in order to say that it’s trivial to implement using an external program in a
scrollback_pagerorpipecommand, kitty should pass to that program at least the following:
- [x] Scrollback buffer text (optionally with formatting) — via stdin
- [x] Scroll position —
INPUT_LINE_NUMBERinscrollback_pager- [ ] Cursor position, so that the external program would be able to start out with the screen laid out exactly the same way as it was
Cursor position can be queried via escape codes, but sure, it is trivial
to add as an env var along with the scroll position for pipe
The external program can then implement its own ideas of cursor motion, selection, and confirmation or cancellation. It will also have to solve the problem of copying the selection to the clipboard and having it persist beyond its own termination — possibly by spawning
nohup xclip.
There is no such problem, it can use the OSC 52 escape code to have
kitty do the copying for it.
I think it would be pretty easy to extend
Window.show_scrollbackto pass cursor position analogously toINPUT_LINE_NUMBER. I must ask, however, why is that implemented as text substitution? I’d probably choose carefully named environment variables.
Because scrollback_pager is meant to work with external programs not designed for
it, like less. less needs it as a command line argument, not an env var.
Also,
scrollback_pagerlooks very similar topipe @ansi overlay; would it be a good idea to extendpipeso that it would be able to replacescrollback_pagercompletely?
No scrollback_pager will remain for legacy compat and to make the simple
use case of browsing history in a pager straightforward.
Cursor position can be queried via escape codes
Hm, is that right? I assumed the commands run by scrollback_pager and pipe start out in a new window, with its own cursor position (initially at 0, 0).
The external program […] will also have to solve the problem of copying the selection to the clipboard and having it persist beyond its own termination — possibly by spawning
nohup xclip.There is no such problem, it can use the OSC 52 escape code to have kitty do the copying for it.
Assuming the clipboard_control setting allows it. And there are reasons to block both reading and writing the clipboard. While allowing reading exposes the user to information disclosure, allowing writing sets up denial of service: a malicious program can repeatedly set the clipboard to a random value, thereby preventing its normal use.
Or are these windows exempt from clipboard_control protection?
why is that implemented as text substitution? I’d probably choose carefully named environment variables.
Because scrollback_pager is meant to work with external programs not designed for it, like less. less needs it as a command line argument, not an env var.
Environment variables would work if scrollback_pager and pipe started their external programs via shell, or by using shell explicitly:
scrollback_pager $SHELL -c "less -RS +$KITTY_TOP_LINE"
On Sun, Nov 25, 2018 at 12:42:13AM -0800, Yuri Khan wrote:
Cursor position can be queried via escape codes
Hm, is that right? I assumed the commands run by
scrollback_pagerandpipestart out in a new window, with its own cursor position (initially at 0, 0).
The cursor is the overlay window can simply be psitioned atthe same
position as the origin window to start with.
The external program […] will also have to solve the problem of copying the selection to the clipboard and having it persist beyond its own termination — possibly by spawning
nohup xclip.There is no such problem, it can use the OSC 52 escape code to have kitty do the copying for it.
Assuming the
clipboard_controlsetting allows it. And there are reasons to block both reading and writing the clipboard. While allowing reading exposes the user to information disclosure, allowing writing sets up denial of service: a malicious program can repeatedly set the clipboard to a random value, thereby preventing its normal use.Or are these windows exempt from
clipboard_controlprotection?
No they are not, I really dont see what on earth a DoS attack against a
local clipboard would achieve. And any program can write to the
clipboard, at any time, so if you dont trust the programs running on
your machine, turning off write in clipboard-control is meaningless.
why is that implemented as text substitution? I’d probably choose carefully named environment variables.
Because scrollback_pager is meant to work with external programs not designed for it, like less. less needs it as a command line argument, not an env var.
Environment variables would work if
scrollback_pagerandpipestarted their external programs via shell, or by using shell explicitly:scrollback_pager $SHELL -c "less -RS +$KITTY_TOP_LINE"
Sure, but the point is to make them simple to use. You are essentially
proposing wrapping the external program in a mini shell program. Why
bother?
Oh and incidentally, pipe is not a replacement for show_scrollback. That is because currently show_scrollback takes lines with hard line-breaks at screen boundaries as input, while pipe takes lines with hard linebreaks only at actual line boundaries at input. In other words pipe takes geometry independent data while show_scrollback is mostly designed for use only in overlays which have the same geometry as the underlying window. This also means that it is not really possible to pass in scroll position/cursor position to pipe since they dont correspond to the input.
And I just committed some changes to pipe to make all we have discussed possible.
There's also vim -u NORC instead of NONE which provides some more features while still having a fast startup.
-u {vimrc} [...]
When {vimrc} is equal to "NORC" (all uppercase), this has the
same effect as "NONE", but plugins and syntax highlighting are
not skipped.
--noplugin Skip loading plugins. Resets the 'loadplugins' option.
Note that the -u argument may also disable loading plugins:
argument load vimrc files load plugins
(nothing) yes yes
-u NONE no no
-u NORC no yes
--noplugin yes no
I have implemented a keyboard-driven screen grabber for Kitty as a kitten.
@pjrt @RosalesJ @yurikhan @lithammer
Sorry to ping you directly like this but I'm stuck and could use your help if you have been successful here.
I'm trying to use neovim (or vim if I have to) as a scrollback pager in kitty. I tried a few things with various amounts of luck:
# Works but ANSI escape sequences clutter the actual text
scrollback_pager vim -
# Does not work; screen just flashes
scrollback_pager nvim
# Does not work; screen just flashes
scrollback_pager nvim -c 'set ft=man'
# Works but loses text coloring
map kitty_mod+h launch --stdin-source=@screen_scrollback --stdin-add-formatting --type=overlay vim -c "normal G" -c "set nonumber nolist" -
If you can answer:
Thanks!
Sorry @Asheq this was a while ago so idk if what I said said still applies.
I just ended up going back to urxvt.
Unfortunately I'm using the default pager (i.e. less). But searching for "scrollback_pager nvim" here on GitHub reveals quite a few elaborate setups. Maybe try one of those? Otherwise it might be a good idea to raise an issue over at Neovim.
I do not use a scrollback pager. If I need to read something a few pages back, I just scroll (which I have bound to Shift+PgUp/PgDn). If I need to copy something (which is the topic of this issue), I use the kitten I’ve linked to in my previous comment.
Before I wrote that kitten, I tried adapting vim for the purpose. I was similarly discontent with the loss of color, so I looked at _AnsiEsc_ and _Improved AnsiEsc_. When I found out that _Improved_ means it handles 16 colors, I said “FFFFUUUUUUUUUU” and dropped the whole idea. I don’t even like vim; why would I use it for scrollback pager if it does not make 24-bit color support ridiculously easy?
And, lastly, yes, my kitten retains full color, by working directly with Kitty’s representation of colored text and not trying to shoehorn that into a mechanism designed primarily for programming language syntax highlighting.
Sorry @Asheq this was a while ago so idk if what I said said still applies.
I just ended up going back to urxvt.
Thanks @pjrt. I'm curious: do you use vim as a scrollback pager in urxvt? Or does urxvt have some sort of built-in pseudo-vim mode?
Unfortunately I'm using the default pager (i.e.
less). But searching for "scrollback_pager nvim" here on GitHub reveals quite a few elaborate setups. Maybe try one of those? Otherwise it might be a good idea to raise an issue over at Neovim.
Thanks @lithammer. I tried a couple of those examples and am still getting a flash. I'll try more thoroughly later when I get a chance and raise an issue in neovim if need be.
I noticed an example that executes the vim command ":set ft=terminal", which made me realize that it would make a lot of sense to call into neovim's built-in terminal for a task like this since it would understand ANSI escape codes (without using a "hack" like the AnsiEsc vim plugin).
@Asheq yeah. there is a plugin in urxvt called keyboard-select which allows u to unhatch the cursor from the command line and move it up and down like VIM.
With this u can highlight and scroll up and down. And even search in the terminal.
I do not use a scrollback pager. If I need to read something a few pages back, I just scroll (which I have bound to Shift+PgUp/PgDn). If I need to copy something (which is the topic of this issue), I use the kitten I’ve linked to in my previous comment.
Before I wrote that kitten, I tried adapting vim for the purpose. I was similarly discontent with the loss of color, so I looked at _AnsiEsc_ and _Improved AnsiEsc_. When I found out that _Improved_ means it handles 16 colors, I said “FFFFUUUUUUUUUU” and dropped the whole idea. I don’t even like vim; why would I use it for scrollback pager if it does not make 24-bit color support ridiculously easy?
And, lastly, yes, my kitten retains full color, by working directly with Kitty’s representation of colored text and not trying to shoehorn that into a mechanism designed primarily for programming language syntax highlighting.
@yurikhan Thanks! I'll try the kitten that you wrote. However, I have a highly-customized vim that I would really like to use because it would be impossible to replicate that experience down to every key-stroke in something else.
I haven't tried it, but the AnsiEsc plugin sounds a bit like a hack. I think the ideal solution should somehow make use of the built-in vim/neovim terminal that already understands ANSI escape codes. Not sure how to do it yet; I might have to open an issue in the vim/neovim repos.
I don’t even like vim
I'm curious: what editor do you use instead?
I'm curious: what editor do you use instead?
Why, Emacs, of course.
@pjrt @yurikhan @lithammer
If you are curious, I got it working using neovim with text formatting/coloring intact. I have a long, complicated command and am still working on perfecting it, but here it is so far:
scrollback_pager /usr/local/bin/nvim -c "set nonumber nolist showtabline=0 foldcolumn=0" -c "autocmd TermOpen * normal G" -c "silent write /tmp/kitty_scrollback_buffer | te cat /tmp/kitty_scrollback_buffer - "
I needed to provide the full path to the nvim binary. The built-in neovim terminal handles the ANSI escape codes.

This worked for me with vim 8.2 (I think you need at least 8.1):
scrollback_pager vim - -c 'w! /tmp/kitty_scrollback' -c 'term ++curwin cat /tmp/kitty_scrollback'
@Asheq, that's awesome! Just wondering how could we automatically delete the existing /tmp/kitty_scrollback_buffer file before opening?
Error detected while processing command line:
E13: File exists (add ! to override)
Press ENTER or type command to continue
on second open attempt. What I'm doing now is a manual rm /tmp/kitty_scrollback_buffer. Before I open the scrollback pager.
@suessflorian: You can do it with one of these:
scrollback_pager vim - -c 'set nonumber' -c 'w! /tmp/kitty_scrollback' -c 'term ++curwin sh -c "head -c-1 /tmp/kitty_scrollback; rm /tmp/kitty_scrollback"'
scrollback_pager nvim -c "set nonumber nolist showtabline=0 foldcolumn=0 laststatus=0" -c "autocmd TermOpen * normal G" -c "silent write! /tmp/kitty_scrollback_buffer | te head -c-1 /tmp/kitty_scrollback_buffer; rm /tmp/kitty_scrollback_buffer; cat"
It's the commands from @Asheq and @i-tub modified to delete the file, and to suppress the blank line which was at the end. To fix the error you got, it would have been enough to just add ! after write, but these commands additionally deletes the file right after it has been read, so your backlog doesn't remain lying around in /tmp.
If anyone is wondering how to copy from this vim pager and keep the clipboard contents after exiting vim, you can use https://github.com/chromium/hterm/blob/master/etc/osc52.vim. Just run the source and vmap commands from the top of that file.
@Asheq Thanks for this scrollback_pager command. How do you switch to the pager mode?
Update: I found it. Add the following setting to kitty.conf
map f6 show_scrollback
I tried a few of the nvim suggestions on this page but most of them didn't work for one reason or another. Here's my tweaks to Asheq's config:
scrollback_pager /usr/local/bin/nvim -u NONE -c "set nonumber nolist showtabline=0 foldcolumn=0" -c "autocmd TermOpen * normal G" -c "map q :qa!<CR>" -c "set clipboard+=unnamedplus" -c "silent write! /tmp/kitty_scrollback_buffer | te cat /tmp/kitty_scrollback_buffer - "
command explained:
scrollback_pager /usr/local/bin/nvim
this is the original invocation of nvim, using the full path because Asheq mentioned it explicitly
-u NONE
Added this -u NONE to stop nvim from loading any of my plugins/config, one of them was throwing an error halting the entire process from rendering my scrollback
-c "set nonumber nolist showtabline=0 foldcolumn=0"
This is from the original, it strips out various vim things so your scrollback buffer looks as close as possible to what your terminal looked like a moment ago before invoking the pager
-c "autocmd TermOpen * normal G"
I don't actually know what this does! haha, the embedded terminal features of nvim are still outside of my understanding.
-c "map q :qa!<CR>"
Added this mapping so I can hit q and have it quit the pager, just like in less. I definitely do not need vim's macro-mapping when i'm scrollin up through terminal output.
-c "set clipboard+=unnamedplus"
nvim, as installed by homebrew on osx supports the osx clipboard by default. it's kept in the + register, but if you set this config then all yanks/pastes will automatically sync to your osx clipboard.
-c "silent write! /tmp/kitty_scrollback_buffer | te cat /tmp/kitty_scrollback_buffer - "
I don't really know what this does, but i had to change write to write! so that it was possible to enter the scrollback buffer more than once a day, lol. I don't know what the second half does at all.
Now I can enter nvim to navigate the scrollback, see all the colors and stuff, yank as normal, and hit q to simply pop out just like in other pagers!
Thank you @cpdean !
-c "autocmd TermOpen * normal G"
I don't actually know what this does! haha, the embedded terminal features of nvim are still outside of my understanding.
This will run G command (go to last line) when the terminal jobs starts. The te in te cat /tmp/... command is a shorter way of running terminal cat /tmp/... which starts a terminal job.
Most helpful comment
I have implemented a keyboard-driven screen grabber for Kitty as a kitten.