mirror of
https://github.com/vim/vim.git
synced 2026-05-28 00:21:37 +02:00
patch 9.2.0127: line('w0') and line('w$') return wrong values in a terminal
Problem: In a terminal window, line('w0') and line('w$') return wrong
values instead of the first and last visible line number,
because a terminal buffer does not go through the normal
redraw path that updates w_topline and w_botline (ubaldot).
Solution: Before computing w0 and w$, sync the terminal contents to the
buffer by calling may_move_terminal_to_buffer() so that
w_topline and w_botline are correctly updated.
fixes: #19585
closes: #19615
supported by AI claude.
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
@@ -6945,6 +6945,10 @@ var2fpos(
|
||||
pos.col = 0;
|
||||
if (name[1] == '0') // "w0": first visible line
|
||||
{
|
||||
#ifdef FEAT_TERMINAL
|
||||
if (bt_terminal(curwin->w_buffer))
|
||||
may_move_terminal_to_buffer(curwin->w_buffer->b_term, TRUE);
|
||||
#endif
|
||||
update_topline();
|
||||
// In silent Ex mode topline is zero, but that's not a valid line
|
||||
// number; use one instead.
|
||||
@@ -6953,6 +6957,10 @@ var2fpos(
|
||||
}
|
||||
else if (name[1] == '$') // "w$": last visible line
|
||||
{
|
||||
#ifdef FEAT_TERMINAL
|
||||
if (bt_terminal(curwin->w_buffer))
|
||||
may_move_terminal_to_buffer(curwin->w_buffer->b_term, TRUE);
|
||||
#endif
|
||||
validate_botline();
|
||||
// In silent Ex mode botline is zero, return zero then.
|
||||
pos.lnum = curwin->w_botline > 0 ? curwin->w_botline - 1 : 0;
|
||||
|
||||
@@ -13,6 +13,7 @@ int term_job_running_not_none(term_T *term);
|
||||
int term_none_open(term_T *term);
|
||||
int term_confirm_stop(buf_T *buf);
|
||||
int term_try_stop_job(buf_T *buf);
|
||||
void may_move_terminal_to_buffer(term_T *term, int redraw);
|
||||
int term_check_timers(int next_due_arg, proftime_T *now);
|
||||
int term_in_normal_mode(void);
|
||||
void term_enter_job_mode(void);
|
||||
|
||||
+1
-1
@@ -2172,7 +2172,7 @@ for_all_windows_and_curwin(win_T **wp, int *did_curwin)
|
||||
* Terminal-Normal mode.
|
||||
* When "redraw" is TRUE redraw the windows that show the terminal.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
may_move_terminal_to_buffer(term_T *term, int redraw)
|
||||
{
|
||||
if (term->tl_vterm == NULL)
|
||||
|
||||
@@ -1162,4 +1162,47 @@ func Test_terminal_max_combining_chars()
|
||||
exe buf . "bwipe!"
|
||||
endfunc
|
||||
|
||||
func Test_term_getpos()
|
||||
CheckRunVimInTerminal
|
||||
CheckUnix
|
||||
CheckExecutable seq
|
||||
defer delete('XTest_getpos_result')
|
||||
|
||||
let lines =<< trim EOL
|
||||
term ++curwin sh
|
||||
EOL
|
||||
call writefile(lines, 'XTest_getpos', 'D')
|
||||
let buf = RunVimInTerminal('-S XTest_getpos', {'rows': 15})
|
||||
call term_sendkeys(buf, "for i in `seq 1 30`; do echo line$i; done\<cr>")
|
||||
|
||||
call WaitForAssert({-> assert_match("line18", term_getline(buf, 1))})
|
||||
call WaitForAssert({-> assert_match("line30", term_getline(buf, 13))})
|
||||
|
||||
call term_sendkeys(buf, "\<c-w>:let g:job_w0 = line('w0')\<cr>")
|
||||
call term_sendkeys(buf, "\<c-w>:let g:job_wdollar = line('w$')\<cr>")
|
||||
call term_sendkeys(buf, "\<c-w>:call writefile([string(g:job_w0), string(g:job_wdollar)], 'XTest_getpos_result')\<cr>")
|
||||
call WaitForAssert({-> assert_true(filereadable('XTest_getpos_result'))})
|
||||
call WaitForAssert({-> assert_equal(2, len(readfile('XTest_getpos_result')))})
|
||||
let job_result = readfile('XTest_getpos_result')
|
||||
" 15 - 1: statusline - 1: prompt line
|
||||
call assert_equal(13, str2nr(job_result[1]) - str2nr(job_result[0]))
|
||||
call assert_true(str2nr(job_result[0]) > 1)
|
||||
call delete('XTest_getpos_result')
|
||||
|
||||
" switch to Terminal-Normal mode and record w0/w$
|
||||
call term_sendkeys(buf, "\<c-w>N")
|
||||
call term_sendkeys(buf, ":let g:w0 = line('w0')\<cr>")
|
||||
call term_sendkeys(buf, ":let g:wdollar = line('w$')\<cr>")
|
||||
call term_sendkeys(buf, ":call writefile([string(g:w0), string(g:wdollar)], 'XTest_getpos_result')\<cr>")
|
||||
|
||||
call WaitForAssert({-> assert_true(filereadable('XTest_getpos_result'))})
|
||||
call WaitForAssert({-> assert_equal(2, len(readfile('XTest_getpos_result')))})
|
||||
let result = readfile('XTest_getpos_result')
|
||||
" 15 - 1: statusline - 1: for prompt line
|
||||
call assert_equal(13, str2nr(result[1]) - str2nr(result[0]))
|
||||
call assert_true(str2nr(result[0]) > 1)
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
127,
|
||||
/**/
|
||||
126,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user