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:
Christian Brabandt
2026-03-09 18:26:41 +00:00
parent 727f6e2686
commit ffeb2339cb
5 changed files with 55 additions and 1 deletions
+43
View File
@@ -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