Skip to content
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

Closed
pjrt opened this issue Jul 11, 2018 · 95 comments
Closed

Feature Request: Ability to select text with the keyboard (vim-like) #719

pjrt opened this issue Jul 11, 2018 · 95 comments

Comments

@pjrt
Copy link

pjrt commented Jul 11, 2018

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.

@kovidgoyal
Copy link
Owner

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

@pjrt
Copy link
Author

pjrt commented Jul 11, 2018

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.

@kovidgoyal
Copy link
Owner

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.

@pjrt
Copy link
Author

pjrt commented Jul 12, 2018

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.

@kovidgoyal
Copy link
Owner

kovidgoyal commented Jul 12, 2018

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

@pjrt
Copy link
Author

pjrt commented Jul 12, 2018

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!

@RosalesJ
Copy link

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.

@kovidgoyal
Copy link
Owner

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

@RosalesJ
Copy link

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.

@kovidgoyal
Copy link
Owner

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.

@yurikhan
Copy link
Contributor

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:

  • Scrollback buffer text (optionally with formatting) — via stdin
  • 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

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.

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?

@kovidgoyal
Copy link
Owner

kovidgoyal commented Nov 25, 2018 via email

@yurikhan
Copy link
Contributor

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"

@kovidgoyal
Copy link
Owner

kovidgoyal commented Nov 25, 2018 via email

@kovidgoyal
Copy link
Owner

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.

kovidgoyal added a commit that referenced this issue Nov 26, 2018
Also make some data such as scroll position, cursor position and screen
geometry available via an env var when piping. See #719
@kovidgoyal
Copy link
Owner

And I just committed some changes to pipe to make all we have discussed possible.

@lithammer
Copy link

lithammer commented Nov 26, 2018

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

@yurikhan
Copy link
Contributor

yurikhan commented Dec 9, 2018

I have implemented a keyboard-driven screen grabber for Kitty as a kitten.

@Asheq
Copy link

Asheq commented Jan 31, 2020

@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:

  • How does your scrollback pager setup look?
  • Have you been able to use neovim as a scrollback pager? I would prefer to use it over vim
  • Have you been able to retain the text coloring? May be via the vim AnsiEsc plugin? Is this plugin reliable?

Thanks!

@pjrt
Copy link
Author

pjrt commented Jan 31, 2020

Sorry @Asheq this was a while ago so idk if what I said said still applies.

I just ended up going back to urxvt.

@lithammer
Copy link

lithammer commented Jan 31, 2020

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.

@yurikhan
Copy link
Contributor

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.

@Asheq
Copy link

Asheq commented Jan 31, 2020

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?

@Asheq
Copy link

Asheq commented Jan 31, 2020

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).

@pjrt
Copy link
Author

pjrt commented Jan 31, 2020

@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.

@Asheq
Copy link

Asheq commented Jan 31, 2020

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?

@yurikhan
Copy link
Contributor

yurikhan commented Feb 1, 2020

I'm curious: what editor do you use instead?

Why, Emacs, of course.

@Asheq
Copy link

Asheq commented Feb 3, 2020

@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.

example

@raffaem
Copy link

raffaem commented Jan 30, 2023

oh, I think you are right. I think I confused it with the (also annoying) "[Process exited 0]" at the end of output in :terminal.

See #5945.

@tmccombs
Copy link

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:

  1. It exploits undocumented and probably unintentional behavior of neovim, specifically that file descriptor 63 isn't closed. See :terminal closes file descriptors under 25 neovim/neovim#16764. Relatedly using /dev/fd/63 only works on linux.
  2. After the terminal finishes, it adds a "[Process exited 0]" message to the end

@kovidgoyal
Copy link
Owner

If you don't like using neovim, write one, it should be a project of a few days for a motivated
individual. Or use one someone has written already like https://github.com/yurikhan/kitty_grab

Or wait until I get around to writing my less replacement.

@page-down
Copy link
Contributor

... but when I exit vim it output "Press Enter or Esc to exit" ...

I forgot to mention in my original reply that the pager script should be given executable permission.
This message will not appear.

chmod +x ~/.config/kitty/pager.sh

... worth mentioning this solution in the documentation ...

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.

@tmccombs

... I still have a couple of issues with it:

  1. ... exploits undocumented and probably unintentional behavior of neovim ...

As long as it works, I don't care much. Until there is a "documented behavior".

... Relatedly using /dev/fd/63 only works on linux.

I actually use it under macOS. At least it works in my environment.

  1. ... it adds a "[Process exited 0]" message ...

This has been explicitly solved by an uncompleted escape sequence, which is of course an imperfect solution.
The neovim terminal is ended immediately, so there is no harm.

@ghost
Copy link

ghost commented Jan 31, 2023

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.

nvimpager allows you to select text and copy to clipboard, provided you always use the pager mode with -p

@raffaem
Copy link

raffaem commented Jan 31, 2023

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 -u NONE if you don't need the plugins.

@tmccombs
Copy link

tmccombs commented Feb 1, 2023

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 :).

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.

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.

This script is a workaround at best.

Yeah... unfortunately I think there probably needs to be a change in nvim for solution that is less of a workaround.

This has been explicitly solved by an uncompleted escape sequence, which is of course an imperfect solution.

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.

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 -u NONE if you don't need the plugins.

But that doesn't preserve ANSI colors.

@kovidgoyal
Copy link
Owner

kovidgoyal commented Feb 1, 2023 via email

@musjj
Copy link

musjj commented Apr 24, 2023

@page-down
I'm having a weird problem with your script: only a portion of the scrollback gets outputted, ending with a [Process exited 0] midway. But I can't reproduce this consistently, sometimes it happens, sometimes it doesn't. The location of the cutoff is also inconsistent when it happens.

Any clue what's happening?

EDIT: It seems that this is caused by removing the sleep 0.01 command, I guess that's essential.

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.

@oyarsa
Copy link

oyarsa commented Apr 26, 2023

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.

rafamadriz added a commit to rafamadriz/dotfiles that referenced this issue Apr 30, 2023
The `scrollback_pager` script was taken from kovidgoyal/kitty#719 comment:
<kovidgoyal/kitty#719 (comment)>

* Change font size
* Remove some window options
rafamadriz added a commit to rafamadriz/dotfiles that referenced this issue Apr 30, 2023
The `scrollback_pager` script was taken from kovidgoyal/kitty#719 comment:
<kovidgoyal/kitty#719 (comment)>

* Change font size
* Remove some window options
th-herve added a commit to th-herve/dotfiles that referenced this issue May 29, 2023
    By pressing ctrl+shift+h, use the vim key to navigate and copy past
    the content.

    Source: kovidgoyal/kitty#719 (comment)
@rafalglowacz
Copy link

rafalglowacz commented Jun 17, 2023

scrollback_pager sh -c 'vtclean | nvim -c "normal G"'

Nice, that works, I just had to replace vtclean with its full path.

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>"'

@jclsn
Copy link

jclsn commented Jul 6, 2023

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.

mikesmithgh added a commit to mikesmithgh/kitty-scrollback.nvim that referenced this issue Aug 30, 2023
@galaxia4Eva
Copy link

~/.config/kitty/kitty.conf:

# ...
scrollback_pager nvim -u ~/.config/nvim/kitty+page.lua -R -M -
# ...

~/.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()

@musjj
Copy link

musjj commented Sep 18, 2023

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:

Now that this old thread is dug out... Tbh this is still one of main things that deter me from daily driving with Zellij. I understand that it's the maintainer's decision to not implement something like tmux's copy mode, and I respect that. However, apart from the extra keystroke, the actual main downside for me is the context switch that comes with this approach.
With something like tmux's copy mode, you act on what's on your screen, with all the text positioning and colors in place. Once the buffer is sent to the editor, the positioning can change (due to bufferlines and stuff), and the colors are most definitely lost. There's some mental effort to refocus on where you wanted to work on before entering this mode. And it's another context switch after you finish copying and exit the editor.

(I understand that the color issue does not apply to kitty)

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.

@mikesmithgh
Copy link
Contributor

I just released v1.0.0 of kitty-scrollback.nvim. If you have any feedback, issues, or suggestions feel free to open an issue. I'm interested to get feedback if the setup easy or if there are any unclear/confusing steps. This requires Neovim nightly (v0.10) and Kitty v0.29.

kitty-scrollback.nvim

Features

  • 😻 Navigate Kitty's scrollback buffer with Neovim
  • 🐱 Copy contents from Neovim to system clipboard
  • 😺 Send contents from Neovim to Kitty shell
  • 🙀 Execute shell command from Neovim to Kitty shell

@ibash
Copy link

ibash commented Sep 21, 2023

Thanks @galaxia4Eva -- works great for me!

@galaxia4Eva
Copy link

galaxia4Eva commented Sep 22, 2023

@ibash here's an updated version that takes kitty input into account:

https://gist.github.com/galaxia4Eva/9e91c4f275554b4bd844b6feece16b3d

files:
~/.config/kitty/kitty.conf
~/.config/nvim/lua/kitty+page.lua

@insilications
Copy link

This is my modified attempt derived from https://gist.github.com/galaxia4Eva/9e91c4f275554b4bd844b6feece16b3d with vim.defer_fn(setCursor, 10) to make sure the terminal has time to process the content and the buffer is ready. https://gist.github.com/insilications/9ec404b74771add0a431e06b00f39679

/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 kitty.conf:

scrollback_pager nvim -u NONE -R -M -c 'lua require("kitty+page")(INPUT_LINE_NUMBER)' -

@laishulu
Copy link

laishulu commented Dec 9, 2024

I just released v1.0.0 of kitty-scrollback.nvim. If you have any feedback, issues, or suggestions feel free to open an issue. I'm interested to get feedback if the setup easy or if there are any unclear/confusing steps. This requires Neovim nightly (v0.10) and Kitty v0.29.

kitty-scrollback.nvim kitty-scrollback.nvim

Features

* 😻 Navigate Kitty's scrollback buffer with Neovim

* 🐱 Copy contents from Neovim to system clipboard

* 😺 Send contents from Neovim to Kitty shell

* 🙀 Execute shell command from Neovim to Kitty shell

Could you please tell me what's the float window?
It's really sexy.
I want it, but don't have a clue how it is achieved.

@mikesmithgh
Copy link
Contributor

Could you please tell me what's the float window? It's really sexy. I want it, but don't have a clue how it is achieved.

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests