mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	feat(float): implement footer
Problem: Now way to show text at the bottom part of floating window border (a.k.a. "footer"). Solution: Allows `footer` and `footer_pos` config fields similar to `title` and `title_pos`.
This commit is contained in:
		| @@ -3138,11 +3138,18 @@ nvim_open_win({buffer}, {enter}, {*config})                  *nvim_open_win()* | ||||
|                       specified by character: [ ["+", "MyCorner"], ["x", | ||||
|                       "MyBorder"] ]. | ||||
|  | ||||
|                   • title: Title (optional) in window border, String or list. | ||||
|                     List is [text, highlight] tuples. if is string the default | ||||
|                     highlight group is `FloatTitle`. | ||||
|                   • title_pos: Title position must set with title option. | ||||
|                     value can be of `left` `center` `right` default is left. | ||||
|                   • title: Title (optional) in window border, string or list. | ||||
|                     List should consist of `[text, highlight]` tuples. If | ||||
|                     string, the default highlight group is `FloatTitle`. | ||||
|                   • title_pos: Title position. Must be set with `title` | ||||
|                     option. Value can be one of "left", "center", or "right". | ||||
|                     Default is `"left"`. | ||||
|                   • footer: Footer (optional) in window border, string or | ||||
|                     list. List should consist of `[text, highlight]` tuples. | ||||
|                     If string, the default highlight group is `FloatTitle`. | ||||
|                   • footer_pos: Footer position. Must be set with `footer` | ||||
|                     option. Value can be one of "left", "center", or "right". | ||||
|                     Default is `"left"`. | ||||
|                   • noautocmd: If true then no buffer-related autocommand | ||||
|                     events such as |BufEnter|, |BufLeave| or |BufWinEnter| may | ||||
|                     fire from calling this function. | ||||
|   | ||||
| @@ -155,6 +155,9 @@ The following new APIs and features were added. | ||||
| • New RPC client type `msgpack-rpc` is added for `nvim_set_client_info` to | ||||
|   support fully MessagePack-RPC compliant clients. | ||||
|  | ||||
| • Floating windows can now show footer with new `footer` and `footer_pos` | ||||
|   config fields. | ||||
|  | ||||
| ============================================================================== | ||||
| CHANGED FEATURES                                                 *news-changed* | ||||
|  | ||||
|   | ||||
							
								
								
									
										17
									
								
								runtime/lua/vim/_meta/api.lua
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										17
									
								
								runtime/lua/vim/_meta/api.lua
									
									
									
										generated
									
									
									
								
							| @@ -1551,11 +1551,18 @@ function vim.api.nvim_open_term(buffer, opts) end | ||||
| ---                   specified by character: [ ["+", "MyCorner"], ["x", | ||||
| ---                   "MyBorder"] ]. | ||||
| --- | ||||
| ---               • title: Title (optional) in window border, String or list. | ||||
| ---                 List is [text, highlight] tuples. if is string the default | ||||
| ---                 highlight group is `FloatTitle`. | ||||
| ---               • title_pos: Title position must set with title option. | ||||
| ---                 value can be of `left` `center` `right` default is left. | ||||
| ---               • title: Title (optional) in window border, string or list. | ||||
| ---                 List should consist of `[text, highlight]` tuples. If | ||||
| ---                 string, the default highlight group is `FloatTitle`. | ||||
| ---               • title_pos: Title position. Must be set with `title` | ||||
| ---                 option. Value can be one of "left", "center", or "right". | ||||
| ---                 Default is `"left"`. | ||||
| ---               • footer: Footer (optional) in window border, string or | ||||
| ---                 list. List should consist of `[text, highlight]` tuples. | ||||
| ---                 If string, the default highlight group is `FloatTitle`. | ||||
| ---               • footer_pos: Footer position. Must be set with `footer` | ||||
| ---                 option. Value can be one of "left", "center", or "right". | ||||
| ---                 Default is `"left"`. | ||||
| ---               • noautocmd: If true then no buffer-related autocommand | ||||
| ---                 events such as `BufEnter`, `BufLeave` or `BufWinEnter` may | ||||
| ---                 fire from calling this function. | ||||
|   | ||||
							
								
								
									
										2
									
								
								runtime/lua/vim/_meta/api_keysets.lua
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								runtime/lua/vim/_meta/api_keysets.lua
									
									
									
										generated
									
									
									
								
							| @@ -108,6 +108,8 @@ error('Cannot require a meta file') | ||||
| --- @field border? any | ||||
| --- @field title? any | ||||
| --- @field title_pos? string | ||||
| --- @field footer? any | ||||
| --- @field footer_pos? string | ||||
| --- @field style? string | ||||
| --- @field noautocmd? boolean | ||||
|  | ||||
|   | ||||
| @@ -99,6 +99,8 @@ typedef struct { | ||||
|   Object border; | ||||
|   Object title; | ||||
|   String title_pos; | ||||
|   Object footer; | ||||
|   String footer_pos; | ||||
|   String style; | ||||
|   Boolean noautocmd; | ||||
| } Dict(float_config); | ||||
|   | ||||
| @@ -145,11 +145,18 @@ | ||||
| ///     By default, `FloatBorder` highlight is used, which links to `WinSeparator` | ||||
| ///     when not defined.  It could also be specified by character: | ||||
| ///       [ ["+", "MyCorner"], ["x", "MyBorder"] ]. | ||||
| ///   - title: Title (optional) in window border, String or list. | ||||
| ///     List is [text, highlight] tuples. if is string the default | ||||
| ///     highlight group is `FloatTitle`. | ||||
| ///   - title_pos: Title position must set with title option. | ||||
| ///     value can be of `left` `center` `right` default is left. | ||||
| ///   - title: Title (optional) in window border, string or list. | ||||
| ///     List should consist of `[text, highlight]` tuples. | ||||
| ///     If string, the default highlight group is `FloatTitle`. | ||||
| ///   - title_pos: Title position. Must be set with `title` option. | ||||
| ///     Value can be one of "left", "center", or "right". | ||||
| ///     Default is `"left"`. | ||||
| ///   - footer: Footer (optional) in window border, string or list. | ||||
| ///     List should consist of `[text, highlight]` tuples. | ||||
| ///     If string, the default highlight group is `FloatTitle`. | ||||
| ///   - footer_pos: Footer position. Must be set with `footer` option. | ||||
| ///     Value can be one of "left", "center", or "right". | ||||
| ///     Default is `"left"`. | ||||
| ///   - noautocmd: If true then no buffer-related autocommand events such as | ||||
| ///                  |BufEnter|, |BufLeave| or |BufWinEnter| may fire from | ||||
| ///                  calling this function. | ||||
| @@ -247,11 +254,19 @@ Dictionary config_put_bordertext(Dictionary config, FloatConfig *fconfig, | ||||
|   AlignTextPos align; | ||||
|   char *field_name; | ||||
|   char *field_pos_name; | ||||
|   if (bordertext_type == kBorderTextTitle) { | ||||
|   switch (bordertext_type) { | ||||
|   case kBorderTextTitle: | ||||
|     chunks = fconfig->title_chunks; | ||||
|     align = fconfig->title_pos; | ||||
|     field_name = "title"; | ||||
|     field_pos_name = "title_pos"; | ||||
|     break; | ||||
|   case kBorderTextFooter: | ||||
|     chunks = fconfig->footer_chunks; | ||||
|     align = fconfig->footer_pos; | ||||
|     field_name = "footer"; | ||||
|     field_pos_name = "footer_pos"; | ||||
|     break; | ||||
|   } | ||||
|  | ||||
|   Array bordertext = ARRAY_DICT_INIT; | ||||
| @@ -345,6 +360,9 @@ Dictionary nvim_win_get_config(Window window, Error *err) | ||||
|       if (config->title) { | ||||
|         rv = config_put_bordertext(rv, config, kBorderTextTitle); | ||||
|       } | ||||
|       if (config->footer) { | ||||
|         rv = config_put_bordertext(rv, config, kBorderTextFooter); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -410,10 +428,17 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, | ||||
|   bool *is_present; | ||||
|   VirtText *chunks; | ||||
|   int *width; | ||||
|   if (bordertext_type == kBorderTextTitle) { | ||||
|   switch (bordertext_type) { | ||||
|   case kBorderTextTitle: | ||||
|     is_present = &fconfig->title; | ||||
|     chunks = &fconfig->title_chunks; | ||||
|     width = &fconfig->title_width; | ||||
|     break; | ||||
|   case kBorderTextFooter: | ||||
|     is_present = &fconfig->footer; | ||||
|     chunks = &fconfig->footer_chunks; | ||||
|     width = &fconfig->footer_width; | ||||
|     break; | ||||
|   } | ||||
|  | ||||
|   if (bordertext.type == kObjectTypeString) { | ||||
| @@ -449,8 +474,13 @@ static bool parse_bordertext_pos(String bordertext_pos, BorderTextType bordertex | ||||
|                                  FloatConfig *fconfig, Error *err) | ||||
| { | ||||
|   AlignTextPos *align; | ||||
|   if (bordertext_type == kBorderTextTitle) { | ||||
|   switch (bordertext_type) { | ||||
|   case kBorderTextTitle: | ||||
|     align = &fconfig->title_pos; | ||||
|     break; | ||||
|   case kBorderTextFooter: | ||||
|     align = &fconfig->footer_pos; | ||||
|     break; | ||||
|   } | ||||
|  | ||||
|   if (bordertext_pos.size == 0) { | ||||
| @@ -467,8 +497,13 @@ static bool parse_bordertext_pos(String bordertext_pos, BorderTextType bordertex | ||||
|   } else if (strequal(pos, "right")) { | ||||
|     *align = kAlignRight; | ||||
|   } else { | ||||
|     if (bordertext_type == kBorderTextTitle) { | ||||
|     switch (bordertext_type) { | ||||
|     case kBorderTextTitle: | ||||
|       api_set_error(err, kErrorTypeValidation, "invalid title_pos value"); | ||||
|       break; | ||||
|     case kBorderTextFooter: | ||||
|       api_set_error(err, kErrorTypeValidation, "invalid footer_pos value"); | ||||
|       break; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| @@ -559,8 +594,9 @@ static void parse_border_style(Object style,  FloatConfig *fconfig, Error *err) | ||||
|     String str = style.data.string; | ||||
|     if (str.size == 0 || strequal(str.data, "none")) { | ||||
|       fconfig->border = false; | ||||
|       // title does not work with border equal none | ||||
|       // border text does not work with border equal none | ||||
|       fconfig->title = false; | ||||
|       fconfig->footer = false; | ||||
|       return; | ||||
|     } | ||||
|     for (size_t i = 0; defaults[i].name; i++) { | ||||
| @@ -750,6 +786,33 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig, | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (HAS_KEY_X(config, footer)) { | ||||
|     // footer only work with border | ||||
|     if (!HAS_KEY_X(config, border) && !fconfig->border) { | ||||
|       api_set_error(err, kErrorTypeException, "footer requires border to be set"); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (fconfig->footer) { | ||||
|       clear_virttext(&fconfig->footer_chunks); | ||||
|     } | ||||
|  | ||||
|     parse_bordertext(config->footer, kBorderTextFooter, fconfig, err); | ||||
|     if (ERROR_SET(err)) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     // handles unset 'footer_pos' same as empty string | ||||
|     if (!parse_bordertext_pos(config->footer_pos, kBorderTextFooter, fconfig, err)) { | ||||
|       return false; | ||||
|     } | ||||
|   } else { | ||||
|     if (HAS_KEY_X(config, footer_pos)) { | ||||
|       api_set_error(err, kErrorTypeException, "footer_pos requires footer to be set"); | ||||
|       return false; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (HAS_KEY_X(config, border)) { | ||||
|     parse_border_style(config->border, fconfig, err); | ||||
|     if (ERROR_SET(err)) { | ||||
|   | ||||
| @@ -938,6 +938,7 @@ typedef enum { | ||||
|  | ||||
| typedef enum { | ||||
|   kBorderTextTitle = 0, | ||||
|   kBorderTextFooter = 1, | ||||
| } BorderTextType; | ||||
|  | ||||
| typedef struct { | ||||
| @@ -952,14 +953,18 @@ typedef struct { | ||||
|   int zindex; | ||||
|   WinStyle style; | ||||
|   bool border; | ||||
|   bool title; | ||||
|   bool shadow; | ||||
|   schar_T border_chars[8]; | ||||
|   int border_hl_ids[8]; | ||||
|   int border_attr[8]; | ||||
|   bool title; | ||||
|   AlignTextPos title_pos; | ||||
|   VirtText title_chunks; | ||||
|   int title_width; | ||||
|   bool footer; | ||||
|   AlignTextPos footer_pos; | ||||
|   VirtText footer_chunks; | ||||
|   int footer_width; | ||||
|   bool noautocmd; | ||||
| } FloatConfig; | ||||
|  | ||||
|   | ||||
| @@ -782,10 +782,17 @@ static void win_redr_border(win_T *wp) | ||||
|     if (adj[3]) { | ||||
|       grid_put_schar(grid, irow + adj[0], 0, chars[6], attrs[6]); | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < icol; i++) { | ||||
|       int ic = (i == 0 && !adj[3] && chars[6][0]) ? 6 : 5; | ||||
|       grid_put_schar(grid, irow + adj[0], i + adj[3], chars[ic], attrs[ic]); | ||||
|     } | ||||
|  | ||||
|     if (wp->w_float_config.footer) { | ||||
|       int footer_col = win_get_bordertext_col(icol, wp->w_float_config.footer_width, | ||||
|                                               wp->w_float_config.footer_pos); | ||||
|       win_redr_bordertext(wp, grid, wp->w_float_config.footer_chunks, grid->rows - 1, footer_col); | ||||
|     } | ||||
|     if (adj[1]) { | ||||
|       grid_put_schar(grid, irow + adj[0], icol + adj[3], chars[4], attrs[4]); | ||||
|     } | ||||
|   | ||||
| @@ -5239,8 +5239,9 @@ static void win_free(win_T *wp, tabpage_T *tp) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // free the border title text | ||||
|   // free the border text | ||||
|   clear_virttext(&wp->w_float_config.title_chunks); | ||||
|   clear_virttext(&wp->w_float_config.footer_chunks); | ||||
|  | ||||
|   clear_matches(wp); | ||||
|  | ||||
|   | ||||
| @@ -1851,6 +1851,39 @@ describe('float window', function() | ||||
|       eq('center', title_pos) | ||||
|     end) | ||||
|  | ||||
|     it('validates footer footer_pos', function() | ||||
|       local buf = meths.create_buf(false,false) | ||||
|       eq("footer requires border to be set", | ||||
|          pcall_err(meths.open_win,buf, false, { | ||||
|           relative='editor', width=9, height=2, row=2, col=5, footer='Footer', | ||||
|          })) | ||||
|       eq("footer_pos requires footer to be set", | ||||
|          pcall_err(meths.open_win,buf, false, { | ||||
|           relative='editor', width=9, height=2, row=2, col=5, | ||||
|           border='single', footer_pos='left', | ||||
|          })) | ||||
|     end) | ||||
|  | ||||
|     it('validate footer_pos in nvim_win_get_config', function() | ||||
|       local footer_pos = exec_lua([[ | ||||
|         local bufnr = vim.api.nvim_create_buf(false, false) | ||||
|         local opts = { | ||||
|           relative = 'editor', | ||||
|           col = 2, | ||||
|           row = 5, | ||||
|           height = 2, | ||||
|           width = 9, | ||||
|           border = 'double', | ||||
|           footer = 'Test', | ||||
|           footer_pos = 'center' | ||||
|         } | ||||
|  | ||||
|         local win_id = vim.api.nvim_open_win(bufnr, true, opts) | ||||
|         return vim.api.nvim_win_get_config(win_id).footer_pos | ||||
|       ]]) | ||||
|  | ||||
|       eq('center', footer_pos) | ||||
|     end) | ||||
|  | ||||
|     it('border with title', function() | ||||
|       local buf = meths.create_buf(false, false) | ||||
| @@ -2033,6 +2066,368 @@ describe('float window', function() | ||||
|       end | ||||
|     end) | ||||
|  | ||||
|     it('border with footer', function() | ||||
|       local buf = meths.create_buf(false, false) | ||||
|       meths.buf_set_lines(buf, 0, -1, true, {' halloj! ', | ||||
|                                              ' BORDAA  '}) | ||||
|       local win = meths.open_win(buf, false, { | ||||
|         relative='editor', width=9, height=2, row=2, col=5, border="double", | ||||
|         footer = "Left",footer_pos = "left", | ||||
|       }) | ||||
|  | ||||
|       if multigrid then | ||||
|         screen:expect{grid=[[ | ||||
|         ## grid 1 | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [3:----------------------------------------]| | ||||
|         ## grid 2 | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|         ## grid 3 | ||||
|                                                   | | ||||
|         ## grid 4 | ||||
|           {5:╔═════════╗}| | ||||
|           {5:║}{1: halloj! }{5:║}| | ||||
|           {5:║}{1: BORDAA  }{5:║}| | ||||
|           {5:╚}{11:Left}{5:═════╝}| | ||||
|         ]], float_pos={ | ||||
|           [4] = { { id = 1001 }, "NW", 1, 2, 5, true } | ||||
|         }, win_viewport={ | ||||
|           [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; | ||||
|           [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; | ||||
|         }} | ||||
|       else | ||||
|         screen:expect{grid=[[ | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~    }{5:╔═════════╗}{0:                        }| | ||||
|           {0:~    }{5:║}{1: halloj! }{5:║}{0:                        }| | ||||
|           {0:~    }{5:║}{1: BORDAA  }{5:║}{0:                        }| | ||||
|           {0:~    }{5:╚}{11:Left}{5:═════╝}{0:                        }| | ||||
|                                                   | | ||||
|         ]]} | ||||
|       end | ||||
|  | ||||
|       meths.win_set_config(win, {footer= "Center",footer_pos="center"}) | ||||
|       if multigrid then | ||||
|         screen:expect{grid=[[ | ||||
|         ## grid 1 | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [3:----------------------------------------]| | ||||
|         ## grid 2 | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|         ## grid 3 | ||||
|                                                   | | ||||
|         ## grid 4 | ||||
|           {5:╔═════════╗}| | ||||
|           {5:║}{1: halloj! }{5:║}| | ||||
|           {5:║}{1: BORDAA  }{5:║}| | ||||
|           {5:╚═}{11:Center}{5:══╝}| | ||||
|         ]], float_pos={ | ||||
|           [4] = { { id = 1001 }, "NW", 1, 2, 5, true } | ||||
|         }, win_viewport={ | ||||
|           [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; | ||||
|           [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; | ||||
|         }} | ||||
|       else | ||||
|         screen:expect{grid=[[ | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~    }{5:╔═════════╗}{0:                        }| | ||||
|           {0:~    }{5:║}{1: halloj! }{5:║}{0:                        }| | ||||
|           {0:~    }{5:║}{1: BORDAA  }{5:║}{0:                        }| | ||||
|           {0:~    }{5:╚═}{11:Center}{5:══╝}{0:                        }| | ||||
|                                                   | | ||||
|         ]]} | ||||
|       end | ||||
|  | ||||
|       meths.win_set_config(win, {footer= "Right",footer_pos="right"}) | ||||
|       if multigrid then | ||||
|         screen:expect{grid=[[ | ||||
|         ## grid 1 | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [3:----------------------------------------]| | ||||
|         ## grid 2 | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|         ## grid 3 | ||||
|                                                   | | ||||
|         ## grid 4 | ||||
|           {5:╔═════════╗}| | ||||
|           {5:║}{1: halloj! }{5:║}| | ||||
|           {5:║}{1: BORDAA  }{5:║}| | ||||
|           {5:╚════}{11:Right}{5:╝}| | ||||
|         ]], float_pos={ | ||||
|           [4] = { { id = 1001 }, "NW", 1, 2, 5, true } | ||||
|         }, win_viewport={ | ||||
|           [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; | ||||
|           [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; | ||||
|         }} | ||||
|       else | ||||
|         screen:expect{grid=[[ | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~    }{5:╔═════════╗}{0:                        }| | ||||
|           {0:~    }{5:║}{1: halloj! }{5:║}{0:                        }| | ||||
|           {0:~    }{5:║}{1: BORDAA  }{5:║}{0:                        }| | ||||
|           {0:~    }{5:╚════}{11:Right}{5:╝}{0:                        }| | ||||
|                                                   | | ||||
|         ]]} | ||||
|       end | ||||
|  | ||||
|       meths.win_set_config(win, {footer= { {"🦄"},{"BB"}},footer_pos="right"}) | ||||
|       if multigrid then | ||||
|         screen:expect{grid=[[ | ||||
|         ## grid 1 | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [3:----------------------------------------]| | ||||
|         ## grid 2 | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|         ## grid 3 | ||||
|                                                   | | ||||
|         ## grid 4 | ||||
|           {5:╔═════════╗}| | ||||
|           {5:║}{1: halloj! }{5:║}| | ||||
|           {5:║}{1: BORDAA  }{5:║}| | ||||
|           {5:╚═════}🦄BB{5:╝}| | ||||
|         ]], float_pos={ | ||||
|           [4] = { { id = 1001 }, "NW", 1, 2, 5, true } | ||||
|         }, win_viewport={ | ||||
|           [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; | ||||
|           [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; | ||||
|         }} | ||||
|       else | ||||
|         screen:expect{grid=[[ | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~    }{5:╔═════════╗}{0:                        }| | ||||
|           {0:~    }{5:║}{1: halloj! }{5:║}{0:                        }| | ||||
|           {0:~    }{5:║}{1: BORDAA  }{5:║}{0:                        }| | ||||
|           {0:~    }{5:╚═════}🦄BB{5:╝}{0:                        }| | ||||
|                                                   | | ||||
|         ]]} | ||||
|       end | ||||
|     end) | ||||
|  | ||||
|     it('border with title and footer', function() | ||||
|       local buf = meths.create_buf(false, false) | ||||
|       meths.buf_set_lines(buf, 0, -1, true, {' halloj! ', | ||||
|                                              ' BORDAA  '}) | ||||
|       local win = meths.open_win(buf, false, { | ||||
|         relative='editor', width=9, height=2, row=2, col=5, border="double", | ||||
|         title = "Left", title_pos = "left", footer = "Right", footer_pos = "right", | ||||
|       }) | ||||
|  | ||||
|       if multigrid then | ||||
|         screen:expect{grid=[[ | ||||
|         ## grid 1 | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [3:----------------------------------------]| | ||||
|         ## grid 2 | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|         ## grid 3 | ||||
|                                                   | | ||||
|         ## grid 4 | ||||
|           {5:╔}{11:Left}{5:═════╗}| | ||||
|           {5:║}{1: halloj! }{5:║}| | ||||
|           {5:║}{1: BORDAA  }{5:║}| | ||||
|           {5:╚════}{11:Right}{5:╝}| | ||||
|         ]], float_pos={ | ||||
|           [4] = { { id = 1001 }, "NW", 1, 2, 5, true } | ||||
|         }, win_viewport={ | ||||
|           [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; | ||||
|           [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; | ||||
|         }} | ||||
|       else | ||||
|         screen:expect{grid=[[ | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~    }{5:╔}{11:Left}{5:═════╗}{0:                        }| | ||||
|           {0:~    }{5:║}{1: halloj! }{5:║}{0:                        }| | ||||
|           {0:~    }{5:║}{1: BORDAA  }{5:║}{0:                        }| | ||||
|           {0:~    }{5:╚════}{11:Right}{5:╝}{0:                        }| | ||||
|                                                   | | ||||
|         ]]} | ||||
|       end | ||||
|  | ||||
|       meths.win_set_config(win, {title= "Center",title_pos="center",footer= "Center",footer_pos="center"}) | ||||
|       if multigrid then | ||||
|         screen:expect{grid=[[ | ||||
|         ## grid 1 | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [3:----------------------------------------]| | ||||
|         ## grid 2 | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|         ## grid 3 | ||||
|                                                   | | ||||
|         ## grid 4 | ||||
|           {5:╔═}{11:Center}{5:══╗}| | ||||
|           {5:║}{1: halloj! }{5:║}| | ||||
|           {5:║}{1: BORDAA  }{5:║}| | ||||
|           {5:╚═}{11:Center}{5:══╝}| | ||||
|         ]], float_pos={ | ||||
|           [4] = { { id = 1001 }, "NW", 1, 2, 5, true } | ||||
|         }, win_viewport={ | ||||
|           [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; | ||||
|           [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; | ||||
|         }} | ||||
|       else | ||||
|         screen:expect{grid=[[ | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~    }{5:╔═}{11:Center}{5:══╗}{0:                        }| | ||||
|           {0:~    }{5:║}{1: halloj! }{5:║}{0:                        }| | ||||
|           {0:~    }{5:║}{1: BORDAA  }{5:║}{0:                        }| | ||||
|           {0:~    }{5:╚═}{11:Center}{5:══╝}{0:                        }| | ||||
|                                                   | | ||||
|         ]]} | ||||
|       end | ||||
|  | ||||
|       meths.win_set_config(win, {title= "Right",title_pos="right",footer= "Left",footer_pos="left"}) | ||||
|       if multigrid then | ||||
|         screen:expect{grid=[[ | ||||
|         ## grid 1 | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [3:----------------------------------------]| | ||||
|         ## grid 2 | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|         ## grid 3 | ||||
|                                                   | | ||||
|         ## grid 4 | ||||
|           {5:╔════}{11:Right}{5:╗}| | ||||
|           {5:║}{1: halloj! }{5:║}| | ||||
|           {5:║}{1: BORDAA  }{5:║}| | ||||
|           {5:╚}{11:Left}{5:═════╝}| | ||||
|         ]], float_pos={ | ||||
|           [4] = { { id = 1001 }, "NW", 1, 2, 5, true } | ||||
|         }, win_viewport={ | ||||
|           [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; | ||||
|           [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; | ||||
|         }} | ||||
|       else | ||||
|         screen:expect{grid=[[ | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~    }{5:╔════}{11:Right}{5:╗}{0:                        }| | ||||
|           {0:~    }{5:║}{1: halloj! }{5:║}{0:                        }| | ||||
|           {0:~    }{5:║}{1: BORDAA  }{5:║}{0:                        }| | ||||
|           {0:~    }{5:╚}{11:Left}{5:═════╝}{0:                        }| | ||||
|                                                   | | ||||
|         ]]} | ||||
|       end | ||||
|  | ||||
|       meths.win_set_config(win, {title= { {"🦄"},{"BB"}},title_pos="right",footer= { {"🦄"},{"BB"}},footer_pos="right"}) | ||||
|       if multigrid then | ||||
|         screen:expect{grid=[[ | ||||
|         ## grid 1 | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [2:----------------------------------------]| | ||||
|           [3:----------------------------------------]| | ||||
|         ## grid 2 | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|           {0:~                                       }| | ||||
|         ## grid 3 | ||||
|                                                   | | ||||
|         ## grid 4 | ||||
|           {5:╔═════}🦄BB{5:╗}| | ||||
|           {5:║}{1: halloj! }{5:║}| | ||||
|           {5:║}{1: BORDAA  }{5:║}| | ||||
|           {5:╚═════}🦄BB{5:╝}| | ||||
|         ]], float_pos={ | ||||
|           [4] = { { id = 1001 }, "NW", 1, 2, 5, true } | ||||
|         }, win_viewport={ | ||||
|           [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; | ||||
|           [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; | ||||
|         }} | ||||
|       else | ||||
|         screen:expect{grid=[[ | ||||
|           ^                                        | | ||||
|           {0:~                                       }| | ||||
|           {0:~    }{5:╔═════}🦄BB{5:╗}{0:                        }| | ||||
|           {0:~    }{5:║}{1: halloj! }{5:║}{0:                        }| | ||||
|           {0:~    }{5:║}{1: BORDAA  }{5:║}{0:                        }| | ||||
|           {0:~    }{5:╚═════}🦄BB{5:╝}{0:                        }| | ||||
|                                                   | | ||||
|         ]]} | ||||
|       end | ||||
|     end) | ||||
|  | ||||
|     it('terminates border on edge of viewport when window extends past viewport', function() | ||||
|       local buf = meths.create_buf(false, false) | ||||
|       meths.open_win(buf, false, {relative='editor', width=40, height=7, row=0, col=0, border="single", zindex=201}) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Evgeni Chasnovski
					Evgeni Chasnovski