mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	fix(statuscolumn): misleading v:lnum for virtual lines #32912
Problem:  Virtual 'statuscolumn' lines are evaluated with a misleading v:(rel)num.
          Namely set to the line above for `virt_lines_above = true` lines, or even
          the last drawn line for a partial redraw.
Solution: Set `v:lnum` for the first evaluated row of a line, first above
          virtual line of a row and first non-virtual line of a row.
			
			
This commit is contained in:
		@@ -664,11 +664,15 @@ static void draw_lnum_col(win_T *wp, winlinevars_T *wlv)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Build and draw the 'statuscolumn' string for line "lnum" in window "wp".
 | 
			
		||||
static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int virtnum, int col_rows,
 | 
			
		||||
static void draw_statuscol(win_T *wp, winlinevars_T *wlv, int virtnum, int col_rows,
 | 
			
		||||
                           statuscol_T *stcp)
 | 
			
		||||
{
 | 
			
		||||
  // When called for the first non-filler row of line "lnum" set num v:vars
 | 
			
		||||
  linenr_T relnum = virtnum == 0 ? abs(get_cursor_rel_lnum(wp, lnum)) : -1;
 | 
			
		||||
  // Adjust lnum for filler lines belonging to the line above and set lnum v:vars for first
 | 
			
		||||
  // row, first non-filler line, and first filler line belonging to the current line.
 | 
			
		||||
  linenr_T lnum = wlv->lnum - ((wlv->n_virt_lines - wlv->filler_todo) < wlv->n_virt_below);
 | 
			
		||||
  linenr_T relnum = (virtnum == -wlv->filler_lines || virtnum == 0
 | 
			
		||||
                     || virtnum == (wlv->n_virt_below - wlv->filler_lines))
 | 
			
		||||
                    ? abs(get_cursor_rel_lnum(wp, lnum)) : -1;
 | 
			
		||||
 | 
			
		||||
  char buf[MAXPATHL];
 | 
			
		||||
  // When a buffer's line count has changed, make a best estimate for the full
 | 
			
		||||
@@ -1639,7 +1643,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b
 | 
			
		||||
      } else if (statuscol.draw) {
 | 
			
		||||
        // Draw 'statuscolumn' if it is set.
 | 
			
		||||
        const int v = (int)(ptr - line);
 | 
			
		||||
        draw_statuscol(wp, &wlv, lnum, wlv.row - startrow - wlv.filler_lines, col_rows, &statuscol);
 | 
			
		||||
        draw_statuscol(wp, &wlv, wlv.row - startrow - wlv.filler_lines, col_rows, &statuscol);
 | 
			
		||||
        if (wp->w_redr_statuscol) {
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -500,7 +500,7 @@ describe('statuscolumn', function()
 | 
			
		||||
      {8:buffer  0 5}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
 | 
			
		||||
      {8:wrapped 1 5}aaaaaaaa                                  |
 | 
			
		||||
      {8:virtual-2 5}virt_line                                 |
 | 
			
		||||
      {8:virtual-1 5}virt_line above                           |
 | 
			
		||||
      {8:virtual-1 6}virt_line above                           |
 | 
			
		||||
      {8:buffer  0 6}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
 | 
			
		||||
      {8:wrapped 1 6}aaaaaaaa                                  |
 | 
			
		||||
      {8:buffer  0 7}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
 | 
			
		||||
@@ -510,10 +510,26 @@ describe('statuscolumn', function()
 | 
			
		||||
      {8:wrapped 1 9}aaaaaaaa                                  |
 | 
			
		||||
                                                           |
 | 
			
		||||
    ]])
 | 
			
		||||
    -- Also test virt_lines at the end of buffer
 | 
			
		||||
    exec_lua([[
 | 
			
		||||
      vim.api.nvim_buf_set_extmark(0, ns, 15, 0, { virt_lines = {{{"END", ""}}} })
 | 
			
		||||
    -- Also correct v:lnum with a partial redraw
 | 
			
		||||
    exec_lua('vim.api.nvim_buf_set_extmark(0, ns, 4, 0, { virt_lines = {{{"virt_line", ""}}} })')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {8:buffer  0 4}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
 | 
			
		||||
      {8:wrapped 1 4}aaaaaaaa                                  |
 | 
			
		||||
      {8:buffer  0 5}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
 | 
			
		||||
      {8:wrapped 1 5}aaaaaaaa                                  |
 | 
			
		||||
      {8:virtual-3 5}virt_line                                 |
 | 
			
		||||
      {8:virtual-2 5}virt_line                                 |
 | 
			
		||||
      {8:virtual-1 6}virt_line above                           |
 | 
			
		||||
      {8:buffer  0 6}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
 | 
			
		||||
      {8:wrapped 1 6}aaaaaaaa                                  |
 | 
			
		||||
      {8:buffer  0 7}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
 | 
			
		||||
      {8:wrapped 1 7}aaaaaaaa                                  |
 | 
			
		||||
      {15:buffer  0 8}{100:^+--  1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
 | 
			
		||||
      {8:buffer  0 9}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{1:@@@}|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ]])
 | 
			
		||||
    -- Also test virt_lines at the end of buffer
 | 
			
		||||
    exec_lua('vim.api.nvim_buf_set_extmark(0, ns, 15, 0, { virt_lines = {{{"END", ""}}} })')
 | 
			
		||||
    feed('GkJzz')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {8:buffer  0 12}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user