[vim/vim] Provide the possibility to not scroll to the bottom in the terminal buffer (Issue #11518)

35 views
Skip to first unread message

jclsn

unread,
Nov 7, 2022, 9:31:43 AM11/7/22
to vim/vim, Subscribed

Is your feature request about something that is currently impossible or hard to do? Please describe the problem.
I am trying to write a plugin that displays the output from a terminal buffer in a popup. Unfortunately the terminal scrolls to the bottom before you can display it in a popup. I want it not to scroll though and let the cursor stay at the top. I've tried some hacks with an exit_cb callback function which waits for 100 milliseconds and then calls cursor(1, 1). This is a bit hacky and the terminal buffer still has to scroll all the way down until the cursor can be placed at the top.

Is there a way to just paste the content of the terminal buffer without scrolling?

Describe the solution you'd like
I am imagining a flag popupb_create or probably term_startt that inhibits the scrolling.

Describe alternatives you've considered
Maybe there is an easy way to accomplish what I need without even using a terminal buffer, but I couldn't come up with one.

Additional context
Here is my plugin https://github.com/jclsn/glow.vim/blob/master/plugin/glow.vim

A similar plugin exists for Neovim and I wanted to rewrite it for Vim.


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11518@github.com>

bfrg

unread,
Nov 7, 2022, 10:37:13 AM11/7/22
to vim/vim, Subscribed

Somehow related to #8822. I think, the tricky part here is that the terminal buffer is displayed in a popup window.

Minimal example:

vim9script

writefile(range(100), '/tmp/file')
const ptybuf = term_start('cat /tmp/file', {hidden: true})
const winid = popup_create(ptybuf, {
    minheight: 20,
    maxheight: 20,
    minwidth: 80,
    maxwidth: 80,
    border: []
})


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11518/1305791153@github.com>

jclsn

unread,
Nov 7, 2022, 10:49:54 AM11/7/22
to vim/vim, Subscribed

Yes, it was probably not intended to do that. I couldn't find another way to get it to work though


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11518/1305810081@github.com>

bfrg

unread,
Nov 7, 2022, 11:20:01 AM11/7/22
to vim/vim, Subscribed

One way to keep Vim from scrolling the terminal output in the popup is by calling popup_create() in the exit_cb of term_start():

vim9script

writefile(range(100), '/tmp/file')
var ptybuf: number

ptybuf = term_start('cat /tmp/file'
, {
    hidden: true,
    exit_cb: (_, _) => popup_create(ptybuf, {
        minheight: 20,
        maxheight: 20,
        minwidth: 80,
        maxwidth: 80,
        close: 'button',
        border: []
    })
})

However, now the problem is that the popup can't be scrolled, neither with the mouse nor with a popup-filter. Notice how the popup isn't focused anymore, unlike in the example above.

Here's a minimal example with a popup-filter that accomplishes scrolling using firstline:

vim9script

writefile(range(100), '/tmp/file')
var ptybuf: number

def Filter(winid: number, key: string): bool
    if key == 'q'
        popup_close(winid)
    elseif key == 'g'
        popup_setoptions(winid, {firstline: 1})
    elseif key == 'G'
        const height = popup_getpos(winid).core_height
        const nlines = line('$', winid)
        const newline = nlines >= height ? nlines - height + 1 : 1
        popup_setoptions(winid, {firstline: newline})
    elseif key == 'j' || key == 'e'
        const line: number = popup_getoptions(winid).firstline
        const newline: number = line < line('$', winid) ? (line + 1) : line('$', winid)
        popup_setoptions(winid, {firstline: newline})
    elseif key == 'k' || key == 'y'
        const line: number = popup_getoptions(winid).firstline
        const newline: number = (line - 1) > 0 ? (line - 1) : 1
        popup_setoptions(winid, {firstline: newline})
    endif
    return true
enddef

ptybuf = term_start('cat /tmp/file'
, {
    hidden: true,
    exit_cb: (_, _) => popup_create(ptybuf, {
        minheight: 20,
        maxheight: 20,
        minwidth: 80,
        maxwidth: 80,
        border: [],
        firstline: 1,
        filtermode: 'n',
        mappings: false,
        filter: Filter
    })
})

The filter provides the following keys:

  • q -- close the popup window (works)
  • G -- scroll to bottom (works)
  • g -- scroll to top (doesn't work correctly, only after a timeout, or when pressing gg)
  • j -- scroll up one line (doesn't work)
  • k -- scroll down one line (doesn't work)

I've also tried to use win_execute(winid, "normal! \<c-e>") instead of using firstline but that doesn't work either.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11518/1305854604@github.com>

jclsn

unread,
Nov 7, 2022, 2:34:16 PM11/7/22
to vim/vim, Subscribed

@bfrg It is still scrolling for me if I take a really long markdown file. There is not really a difference actually


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11518/1306091468@github.com>

jclsn

unread,
Nov 7, 2022, 2:50:40 PM11/7/22
to vim/vim, Subscribed

@bfrg Yes, this actually pops up great. For me the scrolling also works flawlessly without the filter. Probably because I use glow and not cat.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11518/1306106944@github.com>

Bram Moolenaar

unread,
Nov 12, 2022, 2:19:43 PM11/12/22
to vim/vim, Subscribed


> I am trying to write a plugin that displays the output from a terminal
> buffer in a popup. Unfortunately the terminal scrolls to the bottom
> before you can display it in a popup. I want it not to scroll though
> and let the cursor stay at the top. I've tried some hacks with an
> ``exit_cb`` callback function which waits for 100 milliseconds and
> then calls ``cursor(1, 1)``. This is a bit hacky and the terminal

> buffer still has to scroll all the way down until the cursor can be
> placed at the top.
>
> Is there a way to just paste the content of the terminal buffer
> without scrolling?

Why are you using a terminal buffer? If you just want to grab the
output of a shell command there are several other ways.
For example, use job_start() and write the output to a buffer:
"out_io": "buffer"

> **Describe the solution you'd like**

> I am imagining a flag ``popupb_create`` or probably ``term_startt``
> that inhibits the scrolling.

The terminal buffer has very specific behavior, aimed at interacting
with the terminal. Blocking scrolling sounds like a great way to
introduce new problems, that will then require users to read that they
are doing it wrong. I rather avoid adding options that cause trouble.

> **Describe alternatives you've considered**

> Maybe there is an easy way to accomplish what I need without even
> using a terminal buffer, but I couldn't come up with one.

If you say what you are trying to do then maybe someone has an idea.


--
hundred-and-one symptoms of being an internet addict:
49. You never have to deal with busy signals when calling your ISP...because
you never log off.

/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11518/1312554487@github.com>

bfrg

unread,
Nov 15, 2022, 11:18:03 AM11/15/22
to vim/vim, Subscribed

Why are you using a terminal buffer? If you just want to grab the output of a shell command there are several other ways.
For example, use job_start() and write the output to a buffer: "out_io": "buffer"

I'm not the author but I had a discussion with him in the #vim channel last week.

He needs the terminal buffer because he also wants to capture the colors of the output. That's the whole point of his plugin. But the colored output is lost when using job_start(), unless the command provides some --color=always option, or alternatively, using the pty option in job_start(). In either case he will have to parse the terminal escape codes manually and convert them to text-properties (or similar) to get the same effect. This is quite cumbersome.

I think there are use cases when writing to a terminal buffer is more useful, even if there's no interaction with the terminal through stdin.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11518/1315545968@github.com>

jclsn

unread,
Nov 15, 2022, 11:22:12 AM11/15/22
to vim/vim, Subscribed

@brammool Yeah, I also think that using a terminal buffer is probably not the best solution. I'd appreciate one that works better, but I did not know how. @bfrg Tried working something out without it and it did not work. I am not proficient enough in Vimscript to find a better solution. For now it works great apart from the cursor not being at the top after the buffer opened.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11518/1315552250@github.com>

jclsn

unread,
Nov 29, 2022, 3:20:48 PM11/29/22
to vim/vim, Subscribed

@brammool So I have two use cases for this now. You said that there was a way to do this with background jobs? How?

What is crucial for me is that all the terminal output is pasted into Vim with the right color codes etc. It has to look exactly as in the terminal.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11518/1331247842@github.com>

7to...@gmail.com

unread,
Nov 29, 2022, 4:44:45 PM11/29/22
to vim_dev
On Tuesday, November 29, 2022 at 9:20:48 PM UTC+1 jclsn wrote:

@brammool So I have two use cases for this now. You said that there was a way to do this with background jobs? How?

What is crucial for me is that all the terminal output is pasted into Vim with the right color codes etc. It has to look exactly as in the terminal.

Is there a way to copy a line of a terminal buffer with all coloring into another (terminal) buffer? If not - would it be difficult to implement? The goal is to keep the other (terminal) buffer in Terminal-Normal mode so that its cursor can stay at the top all the time. This is still just a workaround but maybe someone can come up with something better using this idea.

Tom M

Message ID: <vim/vim/issues/11518/1331247842@github.com>

Reply all
Reply to author
Forward
0 new messages