-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: Ability to select text with the keyboard (vim-like) #719
Comments
You can open the contents of the kitty screen/scrollback buffer in any arbitrary program |
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:
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 |
really? vim opens on my system in 27 milliseconds
|
yeah I just figured out that I was missing |
Unfortunately with 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 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 |
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
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 I think it would be pretty easy to extend Also, |
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_pager` or `pipe` command, kitty should pass to that program at least the following:
* [x] Scrollback buffer text (optionally with formatting) — via stdin
* [x] Scroll position — `INPUT_LINE_NUMBER` in `scrollback_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_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.
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_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?
No scrollback_pager will remain for legacy compat and to make the simple
use case of browsing history in a pager straightforward.
|
Hm, is that right? I assumed the commands run by
Assuming the Or are these windows exempt from
Environment variables would work if
|
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_pager` and `pipe` start 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_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?
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_pager` and `pipe` started 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. |
Also make some data such as scroll position, cursor position and screen geometry available via an env var when piping. See #719
And I just committed some changes to pipe to make all we have discussed possible. |
There's also
|
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. |
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. |
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 With this u can highlight and scroll up and down. And even search in the terminal. |
@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'm curious: what editor do you use instead? |
Why, Emacs, of course. |
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:
I needed to provide the full path to the |
See #5945. |
I agree that offloading this to a separate program is probably the right move from a design perspective. The problem is that at least for what I want, that separate program doesn't quite exist. Most pagers, like less, most, moar, vimpager, etc. don't have any way to select and copy text. But an editor like vim is difficult to use as a pager, see below. The best solution I've found is the one in #719 (comment). But it is in the middle of a very long thread (and in fact Github hides the original post when you initial open this issue). However, it is far from trivial. At the very least I think it is worth mentioning this solution in the documentation, so it is more visible (maybe along with some other options for configuration scrollback pagers) and maybe including a similar script as part of the kitty distribution? It still isn't perfect though. In particular I still have a couple of issues with it:
|
If you don't like using neovim, write one, it should be a project of a few days for a motivated Or wait until I get around to writing my less replacement. |
I forgot to mention in my original reply that the pager script should be given executable permission. chmod +x ~/.config/kitty/pager.sh
I had considered posting it independently in GitHub Discussion, but decided it wasn't of sufficient quality to warrant a separate topic. This script is a workaround at best.
As long as it works, I don't care much. Until there is a "documented behavior".
I actually use it under macOS. At least it works in my environment.
This has been explicitly solved by an uncompleted escape sequence, which is of course an imperfect solution. |
nvimpager allows you to select text and copy to clipboard, provided you always use the pager mode with |
You don't even need to use a nvimpager. You can use nvim directly. It can read from stdin and has scrolling bindings. Maybe with |
I do like using neovim. The problem is that using it as a pager for this is, perhaps surprisingly, rather difficult to get right. Unless you don't care about colors or other formatting :).
To get something basic maybe. To get something that is featureful and works, well, I think it would probably be more than that. I did look at kitty_grab, my main complaint is it doesn't support search. Maybe I could make a PR to add that, although honestly I'm more interested in getting a better solution for nvim. Just so we are on the same page, I'm not advocating for adding native support for keyboard navigation. The biggest thing I'd like is for better (i.e. more organized and findable) documentation on solutions for this. And maybe a little bit of griping that there isn't quite something that does everything I want.
Yeah... unfortunately I think there probably needs to be a change in nvim for solution that is less of a workaround.
Oh, I wondered what that was for, and didn't put it in my version of the script. But that seems like another hacky workaround.
But that doesn't preserve ANSI colors. |
On Tue, Jan 31, 2023 at 11:05:13PM -0800, Thayne McCombs wrote:
> If you don't like using neovim
I do like using neovim. The problem is that using it as a pager for this is, perhaps surprisingly, rather difficult to get right. Unless you don't care about colors or other formatting :).
Although I dont use it myself, the solution provided by @page-down does
preserve colors as far as I know.
> it should be a project of a few days for a motivated individual
To get something basic maybe. To get something that is featureful and works, well, I think it would probably be more than that. I did look at kitty_grab, my main complaint is it doesn't support search. Maybe I could make a PR to add that, although honestly I'm more interested in getting a better solution for nvim.
Nah, it wont take more than a few days, a week tops, you will see when I write a
native pager for kitty :) Of course, I will be cheating by using a bunch
of infrastructure already in kitty for it.
Just so we are on the same page, I'm not advocating for adding native support for keyboard navigation. The biggest thing I'd like is for better (i.e. more organized and findable) documentation on solutions for this. And maybe a little bit of griping that there isn't quite something that does everything I want.
You are most welcome to send PRs improving the docs.
|
@page-down Any clue what's happening? EDIT: It seems that this is caused by removing the I guess the biggest caveat to this approach is that there will be a flicker and cursor jump when you first initiate the pager, which is a bit disorienting. I don't think there's a way around this other than patching nvim itself. |
I'm having success using github.com/lunixbochs/vtclean to strip control characters from stdin. It works better than all the substitution commands I've seen. This is my set-up: scrollback_pager sh -c 'vtclean | nvim -c "normal G"' I tried some alternatives to preserve colours using nvim's terminal, but none of them worked properly, so I gave up on that. |
The `scrollback_pager` script was taken from kovidgoyal/kitty#719 comment: <kovidgoyal/kitty#719 (comment)> * Change font size * Remove some window options
The `scrollback_pager` script was taken from kovidgoyal/kitty#719 comment: <kovidgoyal/kitty#719 (comment)> * Change font size * Remove some window options
By pressing ctrl+shift+h, use the vim key to navigate and copy past the content. Source: kovidgoyal/kitty#719 (comment)
Nice, that works, I just had to replace EDIT: after some time with this solution it started feeling like too much of a downgrade to lose the colors. Some comments here show solutions using Vim's terminal and some mention that there are plugins that allow keeping the colors. The latter seemed like a more "natural" way to go, so I tried the Baleia plugin and it's been working really well so far. It can be installed in Neovim with Lazy like this: {
'm00qek/baleia.nvim',
config = function()
require('baleia').setup({})
end
}, and then in Kitty you use it like this: scrollback_pager $SHELL -c 'nvim -c "lua local baleia = require(\"baleia\").setup({}); baleia.once(0)" -c "map <silent> q :qa!<CR>"' |
Here is my solution for original Vim. It works for X and Wayland, but involves a lot more settings, plugins and workarounds. I have tested this for some time and it works great. When the buffer is very long you will see some scrolling, since Vim's terminal buffer does not support pasting without moving the cursor. .config/kitty/kitty.conf scrollback_pager sh -c 'vim --not-a-term -u ~/.vim/kitty_scrollback.vim +"terminal ++curwin tail -n 10000 "<(tail -n 10000 | sed -e "s/$\x1b'']8;;file:[^\]*[\]//g" ) +"PreserveCursorPosition INPUT_LINE_NUMBER CURSOR_LINE CURSOR_COLUMN"' .vim/kitty_scrollback.vim set encoding=utf-8
set nocompatible
call plug#begin('~/.vim/plugged')
Plug 'pineapplegiant/spaceduck'
Plug 'jasonccox/vim-wayland-clipboard'
call plug#end()
colorscheme spaceduck
set nonu
set nornu
set termguicolors
set background=dark
set noshowmode
set noruler
set laststatus=0
set noshowcmd
set termwinscroll=10000
nnoremap q <Cmd>quitall!<CR>
nnoremap i <Cmd>quitall!<CR>
vnoremap y "+y
nnoremap y "+y
command -bar -nargs=+ PreserveCursorPosition call s:PreserveCursorPosition(<f-args>)
function s:PreserveCursorPosition(topline, curline, curcol)
let input_line_nr = str2nr(a:topline)
let cursor_line = str2nr(a:curline)
let cursor_column = str2nr(a:curcol)
let last_line = line('$')
sleep 100m
call cursor(max([0, input_line_nr - 1]) + cursor_line, cursor_column)
endfunction If you use another plugin manager than vim-plug, you should change those lines. Same goes for the colortheme. |
…. Ameowzing! Linking the repo to kovidgoyal/kitty#719
~/.config/kitty/kitty.conf:
~/.config/nvim/kitty+page.lua: local setup = function()
local nlines = vim.fn.getenv('INPUT_LINE_NUMBER')
local cur_line = vim.fn.getenv('CURSOR_LINE')
local cur_column = vim.fn.getenv('CURSOR_COLUMN')
vim.opt.encoding='utf-8'
vim.opt.clipboard = 'unnamed'
vim.opt.compatible = false
vim.opt.number = false
vim.opt.relativenumber = false
vim.opt.termguicolors = true
vim.opt.showmode = false
vim.opt.ruler = false
vim.opt.laststatus = 0
vim.opt.showcmd = false
vim.opt.scrollback = 1000
local term_buf = vim.api.nvim_create_buf(true, false);
local term_io = vim.api.nvim_open_term(term_buf, {})
vim.api.nvim_buf_set_keymap(term_buf, 'n', 'q', '<Cmd>q<CR>', { })
local group = vim.api.nvim_create_augroup('kitty+page', {})
vim.api.nvim_create_autocmd('VimEnter', {
group = group,
pattern = '*',
once = true,
callback = function(ev)
local current_win = vim.fn.win_getid()
for _, line in ipairs(vim.api.nvim_buf_get_lines(ev.buf, 0, -1, false)) do
vim.api.nvim_chan_send(term_io, line)
vim.api.nvim_chan_send(term_io, '\r\n')
end
term_io = false
vim.api.nvim_create_autocmd('ModeChanged', {
group = group,
pattern = "([nN]:[^vV])|([vV]:[^nN])",
command = 'stopinsert'
})
vim.api.nvim_win_set_buf(current_win, term_buf)
if nlines ~= vim.NIL and cur_line ~= vim.NIL and cur_column ~= vim.NIL then
vim.api.nvim_win_set_cursor(current_win, {vim.fn.max({1, nlines}) + cur_line, cur_column - 1})
else
vim.api.nvim_input([[<C-\><C-n>G]])
end
vim.api.nvim_buf_delete(ev.buf, { force = true } )
end
})
end
setup()
|
After exploring multitudes of solutions, spending my time with it patiently, I can't help but think that an external pager is just an awkward, dead-end solution riddled with unresolvable issues and compromises. Here's an argument by @xJonathanLEI from a Zellij issue centering around the same dillema that I find myself completely agreeing with:
(I understand that the color issue does not apply to To add another point, there will be an inevitable nasty flicker when you transition between the terminal and the pager process, which I also find jarring and disorienting. There's no way to actually resolve this issue due to the very nature of the pipeline, which is why I think it's a dead-end solution. I understand the appeal of delegating the editor/pager functionality to a separate process, because this relieves the maintainer from the burden of having to re-implement one. But basically everything I've tried so far feels second-class compared to a built-in vi-mode solution, which is really unfortunate. |
I just released ✨ Features
|
Thanks @galaxia4Eva -- works great for me! |
@ibash here's an updated version that takes kitty input into account: https://gist.github.com/galaxia4Eva/9e91c4f275554b4bd844b6feece16b3d files: |
This is my modified attempt derived from https://gist.github.com/galaxia4Eva/9e91c4f275554b4bd844b6feece16b3d with /home/YOUR_USER/.config/nvim/lua/kitty+page.lua: return function(INPUT_LINE_NUMBER)
vim.opt.encoding='utf-8'
-- Prevent auto-centering on click
vim.opt.scrolloff = 0
vim.opt.compatible = false
vim.opt.number = false
vim.opt.relativenumber = false
vim.opt.termguicolors = true
vim.opt.showmode = false
vim.opt.ruler = false
vim.opt.signcolumn=no
vim.opt.showtabline=0
vim.opt.laststatus = 0
vim.o.cmdheight = 0
vim.opt.showcmd = false
vim.opt.scrollback = 100000
vim.opt.clipboard:append('unnamedplus')
local term_buf = vim.api.nvim_create_buf(true, false)
local term_io = vim.api.nvim_open_term(term_buf, {})
-- Map 'q' to first yank the visual selection (if any), which makes the copy selection work, and then quit.
vim.api.nvim_buf_set_keymap(term_buf, 'v', 'q', 'y<Cmd>qa!<CR>', { })
-- Regular quit mapping for normal mode
vim.api.nvim_buf_set_keymap(term_buf, 'n', 'q', '<Cmd>qa!<CR>', { })
local group = vim.api.nvim_create_augroup('kitty+page', {clear = true})
local setCursor = function()
local max_line_nr = vim.api.nvim_buf_line_count(term_buf)
local input_line_nr = math.max(1, math.min(tonumber(INPUT_LINE_NUMBER), max_line_nr))
-- It seems that both the view (view.topline) and the cursor (nvim_win_set_cursor) must be set
-- for scrolling and cursor positioning to work reliably with terminal buffers.
vim.fn.winrestview({topline = input_line_nr})
vim.api.nvim_win_set_cursor(0, {input_line_nr, 0})
end
vim.api.nvim_create_autocmd('ModeChanged', {
group = group,
buffer = term_buf,
callback = function()
local mode = vim.fn.mode()
if mode == 't' then
vim.cmd.stopinsert()
vim.schedule(setCursor)
end
end,
})
vim.api.nvim_create_autocmd('VimEnter', {
group = group,
pattern = '*',
once = true,
callback = function(ev)
local current_win = vim.fn.win_getid()
-- Instead of sending lines individually, concatenate them.
local main_lines = vim.api.nvim_buf_get_lines(ev.buf, 0, -2, false)
local content = table.concat(main_lines, '\r\n')
vim.api.nvim_chan_send(term_io, content .. '\r\n')
-- Process the last line separately (without trailing \r\n)
local last_line = vim.api.nvim_buf_get_lines(ev.buf, -2, -1, false)[1]
if last_line then
vim.api.nvim_chan_send(term_io, last_line)
end
vim.api.nvim_win_set_buf(current_win, term_buf)
vim.api.nvim_buf_delete(ev.buf, { force = true } )
-- Use vim.defer_fn to make sure the terminal has time to process the content and the buffer is ready.
vim.defer_fn(setCursor, 10)
end
})
end
On my
|
Could you please tell me what's the float window? |
@laishulu Thanks! Take a look at the README on https://github.com/mikesmithgh/kitty-scrollback.nvim. The floating window is just a floating window in Neovim. kitty-scrollback.nvim opens Kitty's scrollback buffer in Neovim. Once kitty-scrollback.nvim is open, if you yank text or attempt to enter insert mode, the floating window will show up. |
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 usingv
). I found this to be a great productivity boost and would be great ifkitty
supported it as well.The text was updated successfully, but these errors were encountered: