mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	feat(api): add nvim_win_text_height (#24236)
It uses the same code as "scroll_delta" of "win_viewport" UI event to calculate text height, but is more flexible.
This commit is contained in:
		| @@ -130,9 +130,9 @@ set(NVIM_VERSION_PATCH 0) | |||||||
| set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers | set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers | ||||||
|  |  | ||||||
| # API level | # API level | ||||||
| set(NVIM_API_LEVEL 11)        # Bump this after any API change. | set(NVIM_API_LEVEL 12)        # Bump this after any API change. | ||||||
| set(NVIM_API_LEVEL_COMPAT 0)  # Adjust this after a _breaking_ API change. | set(NVIM_API_LEVEL_COMPAT 0)  # Adjust this after a _breaking_ API change. | ||||||
| set(NVIM_API_PRERELEASE false) | set(NVIM_API_PRERELEASE true) | ||||||
|  |  | ||||||
| # Build-type: RelWithDebInfo | # Build-type: RelWithDebInfo | ||||||
| # /Og means something different in MSVC | # /Og means something different in MSVC | ||||||
|   | |||||||
| @@ -2961,6 +2961,38 @@ nvim_win_set_width({window}, {width})                   *nvim_win_set_width()* | |||||||
|       • {window}  Window handle, or 0 for current window |       • {window}  Window handle, or 0 for current window | ||||||
|       • {width}   Width as a count of columns |       • {width}   Width as a count of columns | ||||||
|  |  | ||||||
|  | nvim_win_text_height({window}, {*opts})               *nvim_win_text_height()* | ||||||
|  |     Computes the number of screen lines occupied by a range of text in a given | ||||||
|  |     window. Works for off-screen text and takes folds into account. | ||||||
|  |  | ||||||
|  |     Diff filler or virtual lines above a line are counted as a part of that | ||||||
|  |     line, unless the line is on "start_row" and "start_vcol" is specified. | ||||||
|  |  | ||||||
|  |     Diff filler or virtual lines below the last buffer line are counted in the | ||||||
|  |     result when "end_row" is omitted. | ||||||
|  |  | ||||||
|  |     Line indexing is similar to |nvim_buf_get_text()|. | ||||||
|  |  | ||||||
|  |     Parameters: ~ | ||||||
|  |       • {window}  Window handle, or 0 for current window. | ||||||
|  |       • {opts}    Optional parameters: | ||||||
|  |                   • start_row: Starting line index, 0-based inclusive. When | ||||||
|  |                     omitted start at the very top. | ||||||
|  |                   • end_row: Ending line index, 0-based inclusive. When | ||||||
|  |                     omitted end at the very bottom. | ||||||
|  |                   • start_vcol: Starting virtual column index on "start_row", | ||||||
|  |                     0-based inclusive, rounded down to full screen lines. When | ||||||
|  |                     omitted include the whole line. | ||||||
|  |                   • end_vcol: Ending virtual column index on "end_row", | ||||||
|  |                     0-based exclusive, rounded up to full screen lines. When | ||||||
|  |                     omitted include the whole line. | ||||||
|  |  | ||||||
|  |     Return: ~ | ||||||
|  |         The number of screen lines that the range of text occupy. | ||||||
|  |  | ||||||
|  |     See also: ~ | ||||||
|  |       • |virtcol()| for text width. | ||||||
|  |  | ||||||
|  |  | ||||||
| ============================================================================== | ============================================================================== | ||||||
| Win_Config Functions                                          *api-win_config* | Win_Config Functions                                          *api-win_config* | ||||||
|   | |||||||
| @@ -99,6 +99,9 @@ The following new APIs and features were added. | |||||||
|  |  | ||||||
| • |vim.system()| for running system commands. | • |vim.system()| for running system commands. | ||||||
|  |  | ||||||
|  | • Added |nvim_win_text_height()| to get the number of screen lines occupied by | ||||||
|  |   a range of text in a given window. | ||||||
|  |  | ||||||
| • |nvim_set_keymap()| and |nvim_del_keymap()| now support abbreviations. | • |nvim_set_keymap()| and |nvim_del_keymap()| now support abbreviations. | ||||||
|  |  | ||||||
| • Implemented LSP inlay hints: |vim.lsp.inlay_hint()| | • Implemented LSP inlay hints: |vim.lsp.inlay_hint()| | ||||||
|   | |||||||
| @@ -1334,27 +1334,6 @@ static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra) | |||||||
|   invalidate_botline(); |   invalidate_botline(); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Normalizes 0-based indexes to buffer line numbers |  | ||||||
| static int64_t normalize_index(buf_T *buf, int64_t index, bool end_exclusive, bool *oob) |  | ||||||
| { |  | ||||||
|   assert(buf->b_ml.ml_line_count > 0); |  | ||||||
|   int64_t max_index = buf->b_ml.ml_line_count + (int)end_exclusive - 1; |  | ||||||
|   // Fix if < 0 |  | ||||||
|   index = index < 0 ? max_index + index + 1 : index; |  | ||||||
|  |  | ||||||
|   // Check for oob |  | ||||||
|   if (index > max_index) { |  | ||||||
|     *oob = true; |  | ||||||
|     index = max_index; |  | ||||||
|   } else if (index < 0) { |  | ||||||
|     *oob = true; |  | ||||||
|     index = 0; |  | ||||||
|   } |  | ||||||
|   // Convert the index to a vim line number |  | ||||||
|   index++; |  | ||||||
|   return index; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Initialise a string array either: | /// Initialise a string array either: | ||||||
| /// - on the Lua stack (as a table) (if lstate is not NULL) | /// - on the Lua stack (as a table) (if lstate is not NULL) | ||||||
| /// - as an API array object (if lstate is NULL). | /// - as an API array object (if lstate is NULL). | ||||||
|   | |||||||
| @@ -171,6 +171,13 @@ typedef struct { | |||||||
|   Object link; |   Object link; | ||||||
| } Dict(get_highlight); | } Dict(get_highlight); | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |   Object start_row; | ||||||
|  |   Object end_row; | ||||||
|  |   Object start_vcol; | ||||||
|  |   Object end_vcol; | ||||||
|  | } Dict(win_text_height); | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|   Object buffer; |   Object buffer; | ||||||
|   Object event; |   Object event; | ||||||
|   | |||||||
| @@ -478,6 +478,27 @@ Array string_to_array(const String input, bool crlf) | |||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// Normalizes 0-based indexes to buffer line numbers. | ||||||
|  | int64_t normalize_index(buf_T *buf, int64_t index, bool end_exclusive, bool *oob) | ||||||
|  | { | ||||||
|  |   assert(buf->b_ml.ml_line_count > 0); | ||||||
|  |   int64_t max_index = buf->b_ml.ml_line_count + (int)end_exclusive - 1; | ||||||
|  |   // A negative index counts from the bottom. | ||||||
|  |   index = index < 0 ? max_index + index + 1 : index; | ||||||
|  |  | ||||||
|  |   // Check for oob and clamp. | ||||||
|  |   if (index > max_index) { | ||||||
|  |     *oob = true; | ||||||
|  |     index = max_index; | ||||||
|  |   } else if (index < 0) { | ||||||
|  |     *oob = true; | ||||||
|  |     index = 0; | ||||||
|  |   } | ||||||
|  |   // Convert the index to a 1-based line number. | ||||||
|  |   index++; | ||||||
|  |   return index; | ||||||
|  | } | ||||||
|  |  | ||||||
| /// Returns a substring of a buffer line | /// Returns a substring of a buffer line | ||||||
| /// | /// | ||||||
| /// @param buf          Buffer handle | /// @param buf          Buffer handle | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
|  |  | ||||||
| #include "nvim/api/private/defs.h" | #include "nvim/api/private/defs.h" | ||||||
| #include "nvim/api/private/helpers.h" | #include "nvim/api/private/helpers.h" | ||||||
|  | #include "nvim/api/private/validate.h" | ||||||
| #include "nvim/api/window.h" | #include "nvim/api/window.h" | ||||||
| #include "nvim/ascii.h" | #include "nvim/ascii.h" | ||||||
| #include "nvim/buffer_defs.h" | #include "nvim/buffer_defs.h" | ||||||
| @@ -20,6 +21,7 @@ | |||||||
| #include "nvim/lua/executor.h" | #include "nvim/lua/executor.h" | ||||||
| #include "nvim/memline_defs.h" | #include "nvim/memline_defs.h" | ||||||
| #include "nvim/move.h" | #include "nvim/move.h" | ||||||
|  | #include "nvim/plines.h" | ||||||
| #include "nvim/pos.h" | #include "nvim/pos.h" | ||||||
| #include "nvim/types.h" | #include "nvim/types.h" | ||||||
| #include "nvim/window.h" | #include "nvim/window.h" | ||||||
| @@ -462,3 +464,104 @@ void nvim_win_set_hl_ns(Window window, Integer ns_id, Error *err) | |||||||
|   win->w_hl_needs_update = true; |   win->w_hl_needs_update = true; | ||||||
|   redraw_later(win, UPD_NOT_VALID); |   redraw_later(win, UPD_NOT_VALID); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// Computes the number of screen lines occupied by a range of text in a given window. | ||||||
|  | /// Works for off-screen text and takes folds into account. | ||||||
|  | /// | ||||||
|  | /// Diff filler or virtual lines above a line are counted as a part of that line, | ||||||
|  | /// unless the line is on "start_row" and "start_vcol" is specified. | ||||||
|  | /// | ||||||
|  | /// Diff filler or virtual lines below the last buffer line are counted in the result | ||||||
|  | /// when "end_row" is omitted. | ||||||
|  | /// | ||||||
|  | /// Line indexing is similar to |nvim_buf_get_text()|. | ||||||
|  | /// | ||||||
|  | /// @param window  Window handle, or 0 for current window. | ||||||
|  | /// @param opts    Optional parameters: | ||||||
|  | ///                - start_row: Starting line index, 0-based inclusive. | ||||||
|  | ///                             When omitted start at the very top. | ||||||
|  | ///                - end_row: Ending line index, 0-based inclusive. | ||||||
|  | ///                           When omitted end at the very bottom. | ||||||
|  | ///                - start_vcol: Starting virtual column index on "start_row", | ||||||
|  | ///                              0-based inclusive, rounded down to full screen lines. | ||||||
|  | ///                              When omitted include the whole line. | ||||||
|  | ///                - end_vcol: Ending virtual column index on "end_row", | ||||||
|  | ///                            0-based exclusive, rounded up to full screen lines. | ||||||
|  | ///                            When omitted include the whole line. | ||||||
|  | /// @return  The number of screen lines that the range of text occupy. | ||||||
|  | /// | ||||||
|  | /// @see |virtcol()| for text width. | ||||||
|  | Object nvim_win_text_height(Window window, Dict(win_text_height) *opts, Error *err) | ||||||
|  |   FUNC_API_SINCE(12) | ||||||
|  | { | ||||||
|  |   win_T *const win = find_window_by_handle(window, err); | ||||||
|  |   if (!win) { | ||||||
|  |     return NIL; | ||||||
|  |   } | ||||||
|  |   buf_T *const buf = win->w_buffer; | ||||||
|  |   const linenr_T line_count = buf->b_ml.ml_line_count; | ||||||
|  |  | ||||||
|  |   linenr_T start_lnum = 1; | ||||||
|  |   linenr_T end_lnum = line_count; | ||||||
|  |   int64_t start_vcol = -1; | ||||||
|  |   int64_t end_vcol = -1; | ||||||
|  |  | ||||||
|  |   bool oob = false; | ||||||
|  |  | ||||||
|  |   if (HAS_KEY(opts->start_row)) { | ||||||
|  |     VALIDATE_T("start_row", kObjectTypeInteger, opts->start_row.type, { | ||||||
|  |       return NIL; | ||||||
|  |     }); | ||||||
|  |     start_lnum = (linenr_T)normalize_index(buf, opts->start_row.data.integer, false, &oob); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (HAS_KEY(opts->end_row)) { | ||||||
|  |     VALIDATE_T("end_row", kObjectTypeInteger, opts->end_row.type, { | ||||||
|  |       return NIL; | ||||||
|  |     }); | ||||||
|  |     end_lnum = (linenr_T)normalize_index(buf, opts->end_row.data.integer, false, &oob); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   VALIDATE(!oob, "%s", "Line index out of bounds", { | ||||||
|  |     return NIL; | ||||||
|  |   }); | ||||||
|  |   VALIDATE((start_lnum <= end_lnum), "%s", "'start_row' is higher than 'end_row'", { | ||||||
|  |     return NIL; | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   if (HAS_KEY(opts->start_vcol)) { | ||||||
|  |     VALIDATE(HAS_KEY(opts->start_row), "%s", "'start_vcol' specified without 'start_row'", { | ||||||
|  |       return NIL; | ||||||
|  |     }); | ||||||
|  |     VALIDATE_T("start_vcol", kObjectTypeInteger, opts->start_vcol.type, { | ||||||
|  |       return NIL; | ||||||
|  |     }); | ||||||
|  |     start_vcol = opts->start_vcol.data.integer; | ||||||
|  |     VALIDATE_RANGE((start_vcol >= 0 && start_vcol <= MAXCOL), "start_vcol", { | ||||||
|  |       return NIL; | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (HAS_KEY(opts->end_vcol)) { | ||||||
|  |     VALIDATE(HAS_KEY(opts->end_row), "%s", "'end_vcol' specified without 'end_row'", { | ||||||
|  |       return NIL; | ||||||
|  |     }); | ||||||
|  |     VALIDATE_T("end_vcol", kObjectTypeInteger, opts->end_vcol.type, { | ||||||
|  |       return NIL; | ||||||
|  |     }); | ||||||
|  |     end_vcol = opts->end_vcol.data.integer; | ||||||
|  |     VALIDATE_RANGE((end_vcol >= 0 && end_vcol <= MAXCOL), "end_vcol", { | ||||||
|  |       return NIL; | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (start_lnum == end_lnum && start_vcol >= 0 && end_vcol >= 0) { | ||||||
|  |     VALIDATE((start_vcol <= end_vcol), "%s", "'start_vcol' is higher than 'end_vcol'", { | ||||||
|  |       return NIL; | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const int64_t res = win_text_height(win, start_lnum, start_vcol, end_lnum, end_vcol) | ||||||
|  |                       + (HAS_KEY(opts->end_row) ? 0 : win_get_fill(win, line_count + 1)); | ||||||
|  |   return INTEGER_OBJ(res); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| #ifndef NVIM_API_WINDOW_H | #ifndef NVIM_API_WINDOW_H | ||||||
| #define NVIM_API_WINDOW_H | #define NVIM_API_WINDOW_H | ||||||
|  |  | ||||||
|  | #include "nvim/api/keysets.h" | ||||||
| #include "nvim/api/private/defs.h" | #include "nvim/api/private/defs.h" | ||||||
|  |  | ||||||
| #ifdef INCLUDE_GENERATED_DECLARATIONS | #ifdef INCLUDE_GENERATED_DECLARATIONS | ||||||
|   | |||||||
| @@ -600,14 +600,14 @@ static int win_nolbr_chartabsize(chartabsize_T *cts, int *headp) | |||||||
|  |  | ||||||
| /// Get the number of screen lines a range of text will take in window "wp". | /// Get the number of screen lines a range of text will take in window "wp". | ||||||
| /// | /// | ||||||
| /// @param start_lnum  first line number | /// @param start_lnum  Starting line number, 1-based inclusive. | ||||||
| /// @param start_vcol  >= 0: virtual column on "start_lnum" where counting starts, | /// @param start_vcol  >= 0: Starting virtual column index on "start_lnum", | ||||||
| ///                          rounded down to full screen lines | ///                          0-based inclusive, rounded down to full screen lines. | ||||||
| ///                    < 0:  count a full "start_lnum", including filler lines above | ///                    < 0:  Count a full "start_lnum", including filler lines above. | ||||||
| /// @param end_lnum    last line number | /// @param end_lnum    Ending line number, 1-based inclusive. | ||||||
| /// @param end_vcol    >= 0: virtual column on "end_lnum" where counting ends, | /// @param end_vcol    >= 0: Ending virtual column index on "end_lnum", | ||||||
| ///                          rounded up to full screen lines | ///                          0-based exclusive, rounded up to full screen lines. | ||||||
| ///                    < 0:  count a full "end_lnum", not including fillers lines below | ///                    < 0:  Count a full "end_lnum", not including fillers lines below. | ||||||
| int64_t win_text_height(win_T *const wp, const linenr_T start_lnum, const int64_t start_vcol, | int64_t win_text_height(win_T *const wp, const linenr_T start_lnum, const int64_t start_vcol, | ||||||
|                         const linenr_T end_lnum, const int64_t end_vcol) |                         const linenr_T end_lnum, const int64_t end_vcol) | ||||||
| { | { | ||||||
| @@ -620,39 +620,39 @@ int64_t win_text_height(win_T *const wp, const linenr_T start_lnum, const int64_ | |||||||
|     width2 = MAX(width2, 0); |     width2 = MAX(width2, 0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   int64_t size = 0; |   int64_t height_sum = 0; | ||||||
|   int64_t height_nofill = 0; |   int64_t height_cur_nofill = 0; | ||||||
|   linenr_T lnum = start_lnum; |   linenr_T lnum = start_lnum; | ||||||
|  |  | ||||||
|   if (start_vcol >= 0) { |   if (start_vcol >= 0) { | ||||||
|     linenr_T lnum_next = lnum; |     linenr_T lnum_next = lnum; | ||||||
|     const bool folded = hasFoldingWin(wp, lnum, &lnum, &lnum_next, true, NULL); |     const bool folded = hasFoldingWin(wp, lnum, &lnum, &lnum_next, true, NULL); | ||||||
|     height_nofill = folded ? 1 : plines_win_nofill(wp, lnum, false); |     height_cur_nofill = folded ? 1 : plines_win_nofill(wp, lnum, false); | ||||||
|     size += height_nofill; |     height_sum += height_cur_nofill; | ||||||
|     const int64_t row_off = (start_vcol < width1 || width2 <= 0) |     const int64_t row_off = (start_vcol < width1 || width2 <= 0) | ||||||
|                             ? 0 |                             ? 0 | ||||||
|                             : 1 + (start_vcol - width1) / width2; |                             : 1 + (start_vcol - width1) / width2; | ||||||
|     size -= MIN(row_off, height_nofill); |     height_sum -= MIN(row_off, height_cur_nofill); | ||||||
|     lnum = lnum_next + 1; |     lnum = lnum_next + 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   while (lnum <= end_lnum) { |   while (lnum <= end_lnum) { | ||||||
|     linenr_T lnum_next = lnum; |     linenr_T lnum_next = lnum; | ||||||
|     const bool folded = hasFoldingWin(wp, lnum, &lnum, &lnum_next, true, NULL); |     const bool folded = hasFoldingWin(wp, lnum, &lnum, &lnum_next, true, NULL); | ||||||
|     height_nofill = folded ? 1 : plines_win_nofill(wp, lnum, false); |     height_cur_nofill = folded ? 1 : plines_win_nofill(wp, lnum, false); | ||||||
|     size += win_get_fill(wp, lnum) + height_nofill; |     height_sum += win_get_fill(wp, lnum) + height_cur_nofill; | ||||||
|     lnum = lnum_next + 1; |     lnum = lnum_next + 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (end_vcol >= 0) { |   if (end_vcol >= 0) { | ||||||
|     size -= height_nofill; |     height_sum -= height_cur_nofill; | ||||||
|     const int64_t row_off = end_vcol == 0 |     const int64_t row_off = end_vcol == 0 | ||||||
|                             ? 0 |                             ? 0 | ||||||
|                             : (end_vcol <= width1 || width2 <= 0) |                             : (end_vcol <= width1 || width2 <= 0) | ||||||
|                               ? 1 |                               ? 1 | ||||||
|                               : 1 + (end_vcol - width1 + width2 - 1) / width2; |                               : 1 + (end_vcol - width1 + width2 - 1) / width2; | ||||||
|     size += MIN(row_off, height_nofill); |     height_sum += MIN(row_off, height_cur_nofill); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   return size; |   return height_sum; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -595,6 +595,217 @@ describe('API/win', function() | |||||||
|     end) |     end) | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|  |   describe('text_height', function() | ||||||
|  |     it('validation', function() | ||||||
|  |       local X = meths.get_vvar('maxcol') | ||||||
|  |       insert([[ | ||||||
|  |         aaa | ||||||
|  |         bbb | ||||||
|  |         ccc | ||||||
|  |         ddd | ||||||
|  |         eee]]) | ||||||
|  |       eq("Invalid window id: 23", | ||||||
|  |          pcall_err(meths.win_text_height, 23, {})) | ||||||
|  |       eq("Line index out of bounds", | ||||||
|  |          pcall_err(curwinmeths.text_height, { start_row = 5 })) | ||||||
|  |       eq("Line index out of bounds", | ||||||
|  |          pcall_err(curwinmeths.text_height, { start_row = -6 })) | ||||||
|  |       eq("Line index out of bounds", | ||||||
|  |          pcall_err(curwinmeths.text_height, { end_row = 5 })) | ||||||
|  |       eq("Line index out of bounds", | ||||||
|  |          pcall_err(curwinmeths.text_height, { end_row = -6 })) | ||||||
|  |       eq("'start_row' is higher than 'end_row'", | ||||||
|  |          pcall_err(curwinmeths.text_height, { start_row = 3, end_row = 1 })) | ||||||
|  |       eq("'start_vcol' specified without 'start_row'", | ||||||
|  |          pcall_err(curwinmeths.text_height, { end_row = 2, start_vcol = 0 })) | ||||||
|  |       eq("'end_vcol' specified without 'end_row'", | ||||||
|  |          pcall_err(curwinmeths.text_height, { start_row = 2, end_vcol = 0 })) | ||||||
|  |       eq("Invalid 'start_vcol': out of range", | ||||||
|  |          pcall_err(curwinmeths.text_height, { start_row = 2, start_vcol = -1 })) | ||||||
|  |       eq("Invalid 'start_vcol': out of range", | ||||||
|  |          pcall_err(curwinmeths.text_height, { start_row = 2, start_vcol = X + 1 })) | ||||||
|  |       eq("Invalid 'end_vcol': out of range", | ||||||
|  |          pcall_err(curwinmeths.text_height, { end_row = 2, end_vcol = -1 })) | ||||||
|  |       eq("Invalid 'end_vcol': out of range", | ||||||
|  |          pcall_err(curwinmeths.text_height, { end_row = 2, end_vcol = X + 1 })) | ||||||
|  |       eq("'start_vcol' is higher than 'end_vcol'", | ||||||
|  |          pcall_err(curwinmeths.text_height, { start_row = 2, end_row = 2, start_vcol = 10, end_vcol = 5 })) | ||||||
|  |     end) | ||||||
|  |  | ||||||
|  |     it('with two diff windows', function() | ||||||
|  |       local X = meths.get_vvar('maxcol') | ||||||
|  |       local screen = Screen.new(45, 22) | ||||||
|  |       screen:set_default_attr_ids({ | ||||||
|  |         [0] = {foreground = Screen.colors.Blue1, bold = true}; | ||||||
|  |         [1] = {foreground = Screen.colors.Blue4, background = Screen.colors.Grey}; | ||||||
|  |         [2] = {foreground = Screen.colors.Brown}; | ||||||
|  |         [3] = {foreground = Screen.colors.Blue1, background = Screen.colors.LightCyan1, bold = true}; | ||||||
|  |         [4] = {background = Screen.colors.LightBlue}; | ||||||
|  |         [5] = {foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey}; | ||||||
|  |         [6] = {background = Screen.colors.Plum1}; | ||||||
|  |         [7] = {background = Screen.colors.Red, bold = true}; | ||||||
|  |         [8] = {reverse = true}; | ||||||
|  |         [9] = {bold = true, reverse = true}; | ||||||
|  |       }) | ||||||
|  |       screen:attach() | ||||||
|  |       exec([[ | ||||||
|  |         set diffopt+=context:2 number | ||||||
|  |         let expr = 'printf("%08d", v:val) .. repeat("!", v:val)' | ||||||
|  |         call setline(1, map(range(1, 20) + range(25, 45), expr)) | ||||||
|  |         vnew | ||||||
|  |         call setline(1, map(range(3, 20) + range(28, 50), expr)) | ||||||
|  |         windo diffthis | ||||||
|  |       ]]) | ||||||
|  |       feed('24gg') | ||||||
|  |       screen:expect{grid=[[ | ||||||
|  |         {1:  }{2:    }{3:----------------}│{1:  }{2:  1 }{4:00000001!       }| | ||||||
|  |         {1:  }{2:    }{3:----------------}│{1:  }{2:  2 }{4:00000002!!      }| | ||||||
|  |         {1:  }{2:  1 }00000003!!!     │{1:  }{2:  3 }00000003!!!     | | ||||||
|  |         {1:  }{2:  2 }00000004!!!!    │{1:  }{2:  4 }00000004!!!!    | | ||||||
|  |         {1:+ }{2:  3 }{5:+-- 14 lines: 00}│{1:+ }{2:  5 }{5:+-- 14 lines: 00}| | ||||||
|  |         {1:  }{2: 17 }00000019!!!!!!!!│{1:  }{2: 19 }00000019!!!!!!!!| | ||||||
|  |         {1:  }{2: 18 }00000020!!!!!!!!│{1:  }{2: 20 }00000020!!!!!!!!| | ||||||
|  |         {1:  }{2:    }{3:----------------}│{1:  }{2: 21 }{4:00000025!!!!!!!!}| | ||||||
|  |         {1:  }{2:    }{3:----------------}│{1:  }{2: 22 }{4:00000026!!!!!!!!}| | ||||||
|  |         {1:  }{2:    }{3:----------------}│{1:  }{2: 23 }{4:00000027!!!!!!!!}| | ||||||
|  |         {1:  }{2: 19 }00000028!!!!!!!!│{1:  }{2: 24 }^00000028!!!!!!!!| | ||||||
|  |         {1:  }{2: 20 }00000029!!!!!!!!│{1:  }{2: 25 }00000029!!!!!!!!| | ||||||
|  |         {1:+ }{2: 21 }{5:+-- 14 lines: 00}│{1:+ }{2: 26 }{5:+-- 14 lines: 00}| | ||||||
|  |         {1:  }{2: 35 }00000044!!!!!!!!│{1:  }{2: 40 }00000044!!!!!!!!| | ||||||
|  |         {1:  }{2: 36 }00000045!!!!!!!!│{1:  }{2: 41 }00000045!!!!!!!!| | ||||||
|  |         {1:  }{2: 37 }{4:00000046!!!!!!!!}│{1:  }{2:    }{3:----------------}| | ||||||
|  |         {1:  }{2: 38 }{4:00000047!!!!!!!!}│{1:  }{2:    }{3:----------------}| | ||||||
|  |         {1:  }{2: 39 }{4:00000048!!!!!!!!}│{1:  }{2:    }{3:----------------}| | ||||||
|  |         {1:  }{2: 40 }{4:00000049!!!!!!!!}│{1:  }{2:    }{3:----------------}| | ||||||
|  |         {1:  }{2: 41 }{4:00000050!!!!!!!!}│{1:  }{2:    }{3:----------------}| | ||||||
|  |         {8:[No Name] [+]          }{9:[No Name] [+]         }| | ||||||
|  |                                                      | | ||||||
|  |       ]]} | ||||||
|  |       screen:try_resize(45, 3) | ||||||
|  |       screen:expect{grid=[[ | ||||||
|  |         {1:  }{2: 19 }00000028!!!!!!!!│{1:  }{2: 24 }^00000028!!!!!!!!| | ||||||
|  |         {8:[No Name] [+]          }{9:[No Name] [+]         }| | ||||||
|  |                                                      | | ||||||
|  |       ]]} | ||||||
|  |       eq(20, meths.win_text_height(1000, {})) | ||||||
|  |       eq(20, meths.win_text_height(1001, {})) | ||||||
|  |       eq(20, meths.win_text_height(1000, { start_row = 0 })) | ||||||
|  |       eq(20, meths.win_text_height(1001, { start_row = 0 })) | ||||||
|  |       eq(15, meths.win_text_height(1000, { end_row = -1 })) | ||||||
|  |       eq(20, meths.win_text_height(1001, { end_row = -1 })) | ||||||
|  |       eq(15, meths.win_text_height(1000, { end_row = 40 })) | ||||||
|  |       eq(20, meths.win_text_height(1001, { end_row = 40 })) | ||||||
|  |       eq(10, meths.win_text_height(1000, { start_row = 23 })) | ||||||
|  |       eq(13, meths.win_text_height(1001, { start_row = 18 })) | ||||||
|  |       eq(11, meths.win_text_height(1000, { end_row = 23 })) | ||||||
|  |       eq(11, meths.win_text_height(1001, { end_row = 18 })) | ||||||
|  |       eq(11, meths.win_text_height(1000, { start_row = 3, end_row = 39 })) | ||||||
|  |       eq(11, meths.win_text_height(1001, { start_row = 1, end_row = 34 })) | ||||||
|  |       eq(9, meths.win_text_height(1000, { start_row = 4, end_row = 38 })) | ||||||
|  |       eq(9, meths.win_text_height(1001, { start_row = 2, end_row = 33 })) | ||||||
|  |       eq(9, meths.win_text_height(1000, { start_row = 5, end_row = 37 })) | ||||||
|  |       eq(9, meths.win_text_height(1001, { start_row = 3, end_row = 32 })) | ||||||
|  |       eq(9, meths.win_text_height(1000, { start_row = 17, end_row = 25 })) | ||||||
|  |       eq(9, meths.win_text_height(1001, { start_row = 15, end_row = 20 })) | ||||||
|  |       eq(7, meths.win_text_height(1000, { start_row = 18, end_row = 24 })) | ||||||
|  |       eq(7, meths.win_text_height(1001, { start_row = 16, end_row = 19 })) | ||||||
|  |       eq(6, meths.win_text_height(1000, { start_row = -1 })) | ||||||
|  |       eq(5, meths.win_text_height(1000, { start_row = -1, start_vcol = X })) | ||||||
|  |       eq(0, meths.win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1 })) | ||||||
|  |       eq(0, meths.win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1, end_vcol = X })) | ||||||
|  |       eq(1, meths.win_text_height(1000, { start_row = -1, start_vcol = 0, end_row = -1, end_vcol = X })) | ||||||
|  |       eq(3, meths.win_text_height(1001, { end_row = 0 })) | ||||||
|  |       eq(2, meths.win_text_height(1001, { end_row = 0, end_vcol = 0 })) | ||||||
|  |       eq(2, meths.win_text_height(1001, { start_row = 0, end_row = 0, end_vcol = 0 })) | ||||||
|  |       eq(0, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = 0 })) | ||||||
|  |       eq(1, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = X })) | ||||||
|  |       eq(11, meths.win_text_height(1001, { end_row = 18 })) | ||||||
|  |       eq(9, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18 })) | ||||||
|  |       eq(10, meths.win_text_height(1001, { end_row = 18, end_vcol = 0 })) | ||||||
|  |       eq(8, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18, end_vcol = 0 })) | ||||||
|  |     end) | ||||||
|  |  | ||||||
|  |     it('with wrapped lines', function() | ||||||
|  |       local X = meths.get_vvar('maxcol') | ||||||
|  |       local screen = Screen.new(45, 22) | ||||||
|  |       screen:set_default_attr_ids({ | ||||||
|  |         [0] = {foreground = Screen.colors.Blue1, bold = true}; | ||||||
|  |         [1] = {foreground = Screen.colors.Brown}; | ||||||
|  |         [2] = {background = Screen.colors.Yellow}; | ||||||
|  |       }) | ||||||
|  |       screen:attach() | ||||||
|  |       exec([[ | ||||||
|  |         set number cpoptions+=n | ||||||
|  |         call setline(1, repeat([repeat('foobar-', 36)], 3)) | ||||||
|  |       ]]) | ||||||
|  |       local ns = meths.create_namespace('') | ||||||
|  |       meths.buf_set_extmark(0, ns, 1, 100, { virt_text = {{('?'):rep(15), 'Search'}}, virt_text_pos = 'inline' }) | ||||||
|  |       meths.buf_set_extmark(0, ns, 2, 200, { virt_text = {{('!'):rep(75), 'Search'}}, virt_text_pos = 'inline' }) | ||||||
|  |       screen:expect{grid=[[ | ||||||
|  |         {1:  1 }^foobar-foobar-foobar-foobar-foobar-foobar| | ||||||
|  |         -foobar-foobar-foobar-foobar-foobar-foobar-fo| | ||||||
|  |         obar-foobar-foobar-foobar-foobar-foobar-fooba| | ||||||
|  |         r-foobar-foobar-foobar-foobar-foobar-foobar-f| | ||||||
|  |         oobar-foobar-foobar-foobar-foobar-foobar-foob| | ||||||
|  |         ar-foobar-foobar-foobar-foobar-              | | ||||||
|  |         {1:  2 }foobar-foobar-foobar-foobar-foobar-foobar| | ||||||
|  |         -foobar-foobar-foobar-foobar-foobar-foobar-fo| | ||||||
|  |         obar-foobar-fo{2:???????????????}obar-foobar-foob| | ||||||
|  |         ar-foobar-foobar-foobar-foobar-foobar-foobar-| | ||||||
|  |         foobar-foobar-foobar-foobar-foobar-foobar-foo| | ||||||
|  |         bar-foobar-foobar-foobar-foobar-foobar-foobar| | ||||||
|  |         -                                            | | ||||||
|  |         {1:  3 }foobar-foobar-foobar-foobar-foobar-foobar| | ||||||
|  |         -foobar-foobar-foobar-foobar-foobar-foobar-fo| | ||||||
|  |         obar-foobar-foobar-foobar-foobar-foobar-fooba| | ||||||
|  |         r-foobar-foobar-foobar-foobar-foobar-foobar-f| | ||||||
|  |         oobar-foobar-foobar-foob{2:!!!!!!!!!!!!!!!!!!!!!}| | ||||||
|  |         {2:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}| | ||||||
|  |         {2:!!!!!!!!!}ar-foobar-foobar-foobar-foobar-fooba| | ||||||
|  |         r-foobar-foobar-                             | | ||||||
|  |                                                      | | ||||||
|  |       ]]} | ||||||
|  |       screen:try_resize(45, 2) | ||||||
|  |       screen:expect{grid=[[ | ||||||
|  |         {1:  1 }^foobar-foobar-foobar-foobar-foobar-foobar| | ||||||
|  |                                                      | | ||||||
|  |       ]]} | ||||||
|  |       eq(21, meths.win_text_height(0, {})) | ||||||
|  |       eq(6, meths.win_text_height(0, { start_row = 0, end_row = 0 })) | ||||||
|  |       eq(7, meths.win_text_height(0, { start_row = 1, end_row = 1 })) | ||||||
|  |       eq(8, meths.win_text_height(0, { start_row = 2, end_row = 2 })) | ||||||
|  |       eq(1, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 41 })) | ||||||
|  |       eq(2, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 42 })) | ||||||
|  |       eq(2, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 86 })) | ||||||
|  |       eq(3, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 87 })) | ||||||
|  |       eq(6, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 266 })) | ||||||
|  |       eq(7, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 267 })) | ||||||
|  |       eq(7, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 311 })) | ||||||
|  |       eq(7, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 312 })) | ||||||
|  |       eq(7, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = X })) | ||||||
|  |       eq(7, meths.win_text_height(0, { start_row = 1, start_vcol = 40, end_row = 1, end_vcol = X })) | ||||||
|  |       eq(6, meths.win_text_height(0, { start_row = 1, start_vcol = 41, end_row = 1, end_vcol = X })) | ||||||
|  |       eq(6, meths.win_text_height(0, { start_row = 1, start_vcol = 85, end_row = 1, end_vcol = X })) | ||||||
|  |       eq(5, meths.win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = X })) | ||||||
|  |       eq(2, meths.win_text_height(0, { start_row = 1, start_vcol = 265, end_row = 1, end_vcol = X })) | ||||||
|  |       eq(1, meths.win_text_height(0, { start_row = 1, start_vcol = 266, end_row = 1, end_vcol = X })) | ||||||
|  |       eq(1, meths.win_text_height(0, { start_row = 1, start_vcol = 310, end_row = 1, end_vcol = X })) | ||||||
|  |       eq(0, meths.win_text_height(0, { start_row = 1, start_vcol = 311, end_row = 1, end_vcol = X })) | ||||||
|  |       eq(18, meths.win_text_height(0, { start_row = 0, start_vcol = 131 })) | ||||||
|  |       eq(19, meths.win_text_height(0, { start_row = 0, start_vcol = 130 })) | ||||||
|  |       eq(20, meths.win_text_height(0, { end_row = 2, end_vcol = 311 })) | ||||||
|  |       eq(21, meths.win_text_height(0, { end_row = 2, end_vcol = 312 })) | ||||||
|  |       eq(17, meths.win_text_height(0, { start_row = 0, start_vcol = 131, end_row = 2, end_vcol = 311 })) | ||||||
|  |       eq(19, meths.win_text_height(0, { start_row = 0, start_vcol = 130, end_row = 2, end_vcol = 312 })) | ||||||
|  |       eq(16, meths.win_text_height(0, { start_row = 0, start_vcol = 221 })) | ||||||
|  |       eq(17, meths.win_text_height(0, { start_row = 0, start_vcol = 220 })) | ||||||
|  |       eq(14, meths.win_text_height(0, { end_row = 2, end_vcol = 41 })) | ||||||
|  |       eq(15, meths.win_text_height(0, { end_row = 2, end_vcol = 42 })) | ||||||
|  |       eq(9, meths.win_text_height(0, { start_row = 0, start_vcol = 221, end_row = 2, end_vcol = 41 })) | ||||||
|  |       eq(11, meths.win_text_height(0, { start_row = 0, start_vcol = 220, end_row = 2, end_vcol = 42 })) | ||||||
|  |     end) | ||||||
|  |   end) | ||||||
|  |  | ||||||
|   describe('open_win', function() |   describe('open_win', function() | ||||||
|     it('noautocmd option works', function() |     it('noautocmd option works', function() | ||||||
|       command('autocmd BufEnter,BufLeave,BufWinEnter * let g:fired = 1') |       command('autocmd BufEnter,BufLeave,BufWinEnter * let g:fired = 1') | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 zeertzjq
					zeertzjq