mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	feat(ui): overlay scrollbar on 'pumborder' #36273
Problem: When pumborder is set, the scrollbar still occupies a column on the screen, wasting a 1 column of space. Solution: Render the scrollbar on the right/left (rl mode) side of the border when pumborder is set.
This commit is contained in:
		| @@ -175,7 +175,6 @@ static const char *highlight_init_both[] = { | ||||
|   "default link PmenuKindSel     PmenuSel", | ||||
|   "default link PmenuSbar        Pmenu", | ||||
|   "default link PmenuBorder        Pmenu", | ||||
|   "default link PmenuShadow        FloatShadow", | ||||
|   "default link PmenuShadowThrough FloatShadowThrough", | ||||
|   "default link PreInsert        Added", | ||||
|   "default link ComplMatchIns    NONE", | ||||
| @@ -382,6 +381,7 @@ static const char *highlight_init_light[] = { | ||||
|   "OkMsg                guifg=NvimDarkGreen                                  ctermfg=2", | ||||
|   "Pmenu                                     guibg=NvimLightGrey3            cterm=reverse", | ||||
|   "PmenuThumb                                guibg=NvimLightGrey4", | ||||
|   "PmenuShadow                               guibg=NvimLightGrey4            ctermbg=0 blend=100", | ||||
|   "Question             guifg=NvimDarkCyan                                   ctermfg=6", | ||||
|   "QuickFixLine         guifg=NvimDarkCyan                                   ctermfg=6", | ||||
|   "RedrawDebugClear                          guibg=NvimLightYellow           ctermfg=15 ctermbg=3", | ||||
| @@ -467,6 +467,7 @@ static const char *highlight_init_dark[] = { | ||||
|   "OkMsg                guifg=NvimLightGreen                                ctermfg=10", | ||||
|   "Pmenu                                      guibg=NvimDarkGrey3           cterm=reverse", | ||||
|   "PmenuThumb                                 guibg=NvimDarkGrey4", | ||||
|   "PmenuShadow                                guibg=NvimDarkGrey4           ctermbg=0 blend=100", | ||||
|   "Question             guifg=NvimLightCyan                                 ctermfg=14", | ||||
|   "QuickFixLine         guifg=NvimLightCyan                                 ctermfg=14", | ||||
|   "RedrawDebugClear                           guibg=NvimDarkYellow          ctermfg=0 ctermbg=11", | ||||
|   | ||||
| @@ -599,18 +599,14 @@ void pum_redraw(void) | ||||
|       extra_space = true; | ||||
|     } | ||||
|   } | ||||
|   if (pum_scrollbar > 0) { | ||||
|     grid_width++; | ||||
|     if (pum_rl) { | ||||
|       col_off++; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   WinConfig fconfig = WIN_CONFIG_INIT; | ||||
|   int border_width = pum_border_width(); | ||||
|   int border_attr = 0; | ||||
|   schar_T border_char = 0; | ||||
|   schar_T fill_char = schar_from_ascii(' '); | ||||
|   bool has_border = border_width > 0; | ||||
|   // setup popup menu border if 'pumborder' option is set | ||||
|   if (border_width > 0) { | ||||
|     fconfig.border = true; | ||||
|     Error err = ERROR_INIT; | ||||
|     if (!parse_winborder(&fconfig, p_pumborder, &err)) { | ||||
|       if (ERROR_SET(&err)) { | ||||
| @@ -641,6 +637,17 @@ void pum_redraw(void) | ||||
|       fconfig.border_attr[i] = attr; | ||||
|     } | ||||
|     api_clear_error(&err); | ||||
|     if (pum_scrollbar) { | ||||
|       border_char = schar_from_str(fconfig.border_chars[3]); | ||||
|       border_attr = fconfig.border_attr[3]; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (pum_scrollbar > 0 && !fconfig.border) { | ||||
|     grid_width++; | ||||
|     if (pum_rl) { | ||||
|       col_off++; | ||||
|     } | ||||
|   } | ||||
|   grid_assign_handle(&pum_grid); | ||||
|  | ||||
| @@ -889,13 +896,10 @@ void pum_redraw(void) | ||||
|     } | ||||
|  | ||||
|     if (pum_scrollbar > 0) { | ||||
|       if (pum_rl) { | ||||
|         grid_line_puts(col_off - pum_width, " ", 1, | ||||
|                        i >= thumb_pos && i < thumb_pos + thumb_height ? attr_thumb : attr_scroll); | ||||
|       } else { | ||||
|         grid_line_puts(col_off + pum_width, " ", 1, | ||||
|                        i >= thumb_pos && i < thumb_pos + thumb_height ? attr_thumb : attr_scroll); | ||||
|       } | ||||
|       bool thumb = i >= thumb_pos && i < thumb_pos + thumb_height; | ||||
|       int scrollbar_col = col_off + (pum_rl ? -pum_width : pum_width); | ||||
|       grid_line_put_schar(scrollbar_col, (has_border && !thumb) ? border_char : fill_char, | ||||
|                           thumb ? attr_thumb : (has_border ? border_attr : attr_scroll)); | ||||
|     } | ||||
|     grid_line_flush(); | ||||
|     row++; | ||||
| @@ -954,7 +958,10 @@ static void pum_preview_set_text(buf_T *buf, char *info, linenr_T *lnum, int *ma | ||||
| static void pum_adjust_info_position(win_T *wp, int width) | ||||
| { | ||||
|   int border_width = pum_border_width(); | ||||
|   int col = pum_col + pum_width + pum_scrollbar + 1 + border_width; | ||||
|   int col = pum_col + pum_width + 1 + border_width; | ||||
|   if (border_width < 0) { | ||||
|     col += pum_scrollbar; | ||||
|   } | ||||
|   // TODO(glepnir): support config align border by using completepopup | ||||
|   // align menu | ||||
|   int right_extra = Columns - col; | ||||
|   | ||||
| @@ -1064,6 +1064,7 @@ describe('builtin popupmenu', function() | ||||
|         [113] = { background = Screen.colors.Yellow, foreground = Screen.colors.Black }, | ||||
|         [114] = { background = Screen.colors.Grey0, blend = 100 }, | ||||
|         [115] = { background = Screen.colors.Grey0, blend = 80 }, | ||||
|         [116] = { blend = 100, background = Screen.colors.NvimLightGrey4 }, | ||||
|         -- popup non-selected item | ||||
|         n = { background = Screen.colors.Plum1 }, | ||||
|         -- popup scrollbar knob | ||||
| @@ -8738,11 +8739,12 @@ describe('builtin popupmenu', function() | ||||
|       before_each(function() | ||||
|         screen:try_resize(30, 11) | ||||
|         exec([[ | ||||
|           let g:list = [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three", info: "3info"}] | ||||
|           funct Omni_test(findstart, base) | ||||
|             if a:findstart | ||||
|               return col(".") - 1 | ||||
|             endif | ||||
|             return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three", info: "3info"}] | ||||
|             return g:list | ||||
|           endfunc | ||||
|           hi link PmenuBorder FloatBorder | ||||
|           set omnifunc=Omni_test | ||||
| @@ -8992,9 +8994,9 @@ describe('builtin popupmenu', function() | ||||
|         end | ||||
|       end) | ||||
|  | ||||
|       it('pum border on cmdline', function() | ||||
|       it("'pumborder' on cmdline and scrollbar rendering", function() | ||||
|         command('set wildoptions=pum') | ||||
|         feed(':<TAB>') | ||||
|         feed(':t<TAB>') | ||||
|         if multigrid then | ||||
|           screen:expect({ | ||||
|             grid = [[ | ||||
| @@ -9005,18 +9007,18 @@ describe('builtin popupmenu', function() | ||||
|                                             | | ||||
|               {1:~                             }|*9 | ||||
|             ## grid 3 | ||||
|               :!^                            | | ||||
|               :t^                            | | ||||
|             ## grid 4 | ||||
|               ╭─────────────────╮| | ||||
|               │{12: !              }{c: }│| | ||||
|               │{n: #              }{12: }│| | ||||
|               │{n: &              }{12: }│| | ||||
|               │{n: <              }{12: }│| | ||||
|               │{n: =              }{12: }│| | ||||
|               │{n: >              }{12: }│| | ||||
|               │{n: @              }{12: }│| | ||||
|               │{n: Next           }{12: }│| | ||||
|               ╰─────────────────╯| | ||||
|               ╭────────────────╮| | ||||
|               │{12: t              }{c: }| | ||||
|               │{n: tNext          }│| | ||||
|               │{n: tab            }│| | ||||
|               │{n: tabNext        }│| | ||||
|               │{n: tabclose       }│| | ||||
|               │{n: tabdo          }│| | ||||
|               │{n: tabedit        }│| | ||||
|               │{n: tabfind        }│| | ||||
|               ╰────────────────╯| | ||||
|             ]], | ||||
|             win_pos = { | ||||
|               [2] = { | ||||
| @@ -9053,17 +9055,50 @@ describe('builtin popupmenu', function() | ||||
|           }) | ||||
|         else | ||||
|           screen:expect([[ | ||||
|             ╭─────────────────╮           | | ||||
|             │{12: !              }{c: }│{1:           }| | ||||
|             │{n: #              }{12: }│{1:           }| | ||||
|             │{n: &              }{12: }│{1:           }| | ||||
|             │{n: <              }{12: }│{1:           }| | ||||
|             │{n: =              }{12: }│{1:           }| | ||||
|             │{n: >              }{12: }│{1:           }| | ||||
|             │{n: @              }{12: }│{1:           }| | ||||
|             │{n: Next           }{12: }│{1:           }| | ||||
|             ╰─────────────────╯{1:           }| | ||||
|             :!^                            | | ||||
|             ╭────────────────╮            | | ||||
|             │{12: t              }{c: }{1:            }| | ||||
|             │{n: tNext          }│{1:            }| | ||||
|             │{n: tab            }│{1:            }| | ||||
|             │{n: tabNext        }│{1:            }| | ||||
|             │{n: tabclose       }│{1:            }| | ||||
|             │{n: tabdo          }│{1:            }| | ||||
|             │{n: tabedit        }│{1:            }| | ||||
|             │{n: tabfind        }│{1:            }| | ||||
|             ╰────────────────╯{1:            }| | ||||
|             :t^                            | | ||||
|           ]]) | ||||
|         end | ||||
|  | ||||
|         feed(('<C-N>'):rep(20)) | ||||
|         if not multigrid then | ||||
|           screen:expect([[ | ||||
|             ╭────────────────╮            | | ||||
|             │{n: tabs           }│{1:            }| | ||||
|             │{n: tag            }│{1:            }| | ||||
|             │{n: tags           }│{1:            }| | ||||
|             │{n: tcd            }{c: }{1:            }| | ||||
|             │{12: tchdir         }│{1:            }| | ||||
|             │{n: tcl            }│{1:            }| | ||||
|             │{n: tcldo          }│{1:            }| | ||||
|             │{n: tclfile        }│{1:            }| | ||||
|             ╰────────────────╯{1:            }| | ||||
|             :tchdir^                       | | ||||
|           ]]) | ||||
|         end | ||||
|         feed(('<C-P>'):rep(20)) | ||||
|         if not multigrid then | ||||
|           screen:expect([[ | ||||
|             ╭────────────────╮            | | ||||
|             │{12: t              }{c: }{1:            }| | ||||
|             │{n: tNext          }│{1:            }| | ||||
|             │{n: tab            }│{1:            }| | ||||
|             │{n: tabNext        }│{1:            }| | ||||
|             │{n: tabclose       }│{1:            }| | ||||
|             │{n: tabdo          }│{1:            }| | ||||
|             │{n: tabedit        }│{1:            }| | ||||
|             │{n: tabfind        }│{1:            }| | ||||
|             ╰────────────────╯{1:            }| | ||||
|             :t^                            | | ||||
|           ]]) | ||||
|         end | ||||
|       end) | ||||
| @@ -9084,9 +9119,9 @@ describe('builtin popupmenu', function() | ||||
|             ## grid 3 | ||||
|               {5:-- }{6:match 1 of 3}               | | ||||
|             ## grid 4 | ||||
|               ╭────────────────╮| | ||||
|               │{12:one            }{c: }│| | ||||
|               ╰────────────────╯| | ||||
|               ╭───────────────╮| | ||||
|               │{12:one            }{c: }| | ||||
|               ╰───────────────╯| | ||||
|             ]], | ||||
|             win_pos = { | ||||
|               [2] = { | ||||
| @@ -9124,9 +9159,9 @@ describe('builtin popupmenu', function() | ||||
|         else | ||||
|           screen:expect([[ | ||||
|             one^                           | | ||||
|             ╭────────────────╮{1:            }| | ||||
|             │{12:one            }{c: }│{1:            }| | ||||
|             ╰────────────────╯{1:            }| | ||||
|             ╭───────────────╮{1:             }| | ||||
|             │{12:one            }{c: }{1:             }| | ||||
|             ╰───────────────╯{1:             }| | ||||
|             {1:~                             }| | ||||
|             {3:[No Name] [+]                 }| | ||||
|             {5:-- }{6:match 1 of 3}               | | ||||
| @@ -9167,9 +9202,9 @@ describe('builtin popupmenu', function() | ||||
|               {n:1info}| | ||||
|             ## grid 5 | ||||
|               {12:one            }{114: }| | ||||
|               {n:two            }{115: }| | ||||
|               {n:three          }{115: }| | ||||
|               {114: }{115:               }| | ||||
|               {n:two            }{116: }| | ||||
|               {n:three          }{116: }| | ||||
|               {114: }{116:               }| | ||||
|             ]], | ||||
|             win_pos = { | ||||
|               [2] = { | ||||
| @@ -9225,9 +9260,9 @@ describe('builtin popupmenu', function() | ||||
|           screen:expect([[ | ||||
|             one^                           | | ||||
|             {12:one            }{114: }{n:1info}{1:         }| | ||||
|             {n:two            }{115: }{1:              }| | ||||
|             {n:three          }{115: }{1:              }| | ||||
|             {114: }{115:               }{1:              }| | ||||
|             {n:two            }{116: }{1:              }| | ||||
|             {n:three          }{116: }{1:              }| | ||||
|             {114: }{116:               }{1:              }| | ||||
|             {1:~                             }|*5 | ||||
|             {5:-- }{6:match 1 of 3}               | | ||||
|           ]]) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 glepnir
					glepnir