mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	fix(terminal): adjust marks when deleting scrollback lines (#36294)
This also fixes inconsistent scrolling behavior on terminal output when cursor is in the middle of the buffer and the scrollback is full.
This commit is contained in:
		| @@ -581,7 +581,13 @@ do | |||||||
|       if string.match(args.data.sequence, '^\027]133;A') then |       if string.match(args.data.sequence, '^\027]133;A') then | ||||||
|         local lnum = args.data.cursor[1] ---@type integer |         local lnum = args.data.cursor[1] ---@type integer | ||||||
|         if lnum >= 1 then |         if lnum >= 1 then | ||||||
|           vim.api.nvim_buf_set_extmark(args.buf, nvim_terminal_prompt_ns, lnum - 1, 0, {}) |           vim.api.nvim_buf_set_extmark( | ||||||
|  |             args.buf, | ||||||
|  |             nvim_terminal_prompt_ns, | ||||||
|  |             lnum - 1, | ||||||
|  |             0, | ||||||
|  |             { right_gravity = false } | ||||||
|  |           ) | ||||||
|         end |         end | ||||||
|       end |       end | ||||||
|     end, |     end, | ||||||
|   | |||||||
| @@ -429,7 +429,7 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ | |||||||
|     // changed range, and move any in the remainder of the buffer. |     // changed range, and move any in the remainder of the buffer. | ||||||
|     linenr_T adjust = end > start ? MAXLNUM : 0; |     linenr_T adjust = end > start ? MAXLNUM : 0; | ||||||
|     mark_adjust_buf(buf, (linenr_T)start, (linenr_T)(end - 1), adjust, (linenr_T)extra, |     mark_adjust_buf(buf, (linenr_T)start, (linenr_T)(end - 1), adjust, (linenr_T)extra, | ||||||
|                     true, true, kExtmarkNOOP); |                     true, kMarkAdjustApi, kExtmarkNOOP); | ||||||
|  |  | ||||||
|     extmark_splice(buf, (int)start - 1, 0, (int)(end - start), 0, |     extmark_splice(buf, (int)start - 1, 0, (int)(end - start), 0, | ||||||
|                    deleted_bytes, (int)new_len, 0, inserted_bytes, |                    deleted_bytes, (int)new_len, 0, inserted_bytes, | ||||||
| @@ -662,7 +662,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In | |||||||
|     // Do not adjust any cursors. need to use column-aware logic (below) |     // Do not adjust any cursors. need to use column-aware logic (below) | ||||||
|     linenr_T adjust = end_row >= start_row ? MAXLNUM : 0; |     linenr_T adjust = end_row >= start_row ? MAXLNUM : 0; | ||||||
|     mark_adjust_buf(buf, (linenr_T)start_row, (linenr_T)end_row - 1, adjust, (linenr_T)extra, |     mark_adjust_buf(buf, (linenr_T)start_row, (linenr_T)end_row - 1, adjust, (linenr_T)extra, | ||||||
|                     true, true, kExtmarkNOOP); |                     true, kMarkAdjustApi, kExtmarkNOOP); | ||||||
|  |  | ||||||
|     extmark_splice(buf, (int)start_row - 1, (colnr_T)start_col, |     extmark_splice(buf, (int)start_row - 1, (colnr_T)start_col, | ||||||
|                    (int)(end_row - start_row), col_extent, old_byte, |                    (int)(end_row - start_row), col_extent, old_byte, | ||||||
|   | |||||||
| @@ -1180,7 +1180,7 @@ void ex_changes(exarg_T *eap) | |||||||
| void mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T amount_after, | void mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T amount_after, | ||||||
|                  ExtmarkOp op) |                  ExtmarkOp op) | ||||||
| { | { | ||||||
|   mark_adjust_buf(curbuf, line1, line2, amount, amount_after, true, false, op); |   mark_adjust_buf(curbuf, line1, line2, amount, amount_after, true, kMarkAdjustNormal, op); | ||||||
| } | } | ||||||
|  |  | ||||||
| // mark_adjust_nofold() does the same as mark_adjust() but without adjusting | // mark_adjust_nofold() does the same as mark_adjust() but without adjusting | ||||||
| @@ -1191,11 +1191,11 @@ void mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T amoun | |||||||
| void mark_adjust_nofold(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T amount_after, | void mark_adjust_nofold(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T amount_after, | ||||||
|                         ExtmarkOp op) |                         ExtmarkOp op) | ||||||
| { | { | ||||||
|   mark_adjust_buf(curbuf, line1, line2, amount, amount_after, false, false, op); |   mark_adjust_buf(curbuf, line1, line2, amount, amount_after, false, kMarkAdjustNormal, op); | ||||||
| } | } | ||||||
|  |  | ||||||
| void mark_adjust_buf(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount, | void mark_adjust_buf(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount, | ||||||
|                      linenr_T amount_after, bool adjust_folds, bool by_api, ExtmarkOp op) |                      linenr_T amount_after, bool adjust_folds, MarkAdjustMode mode, ExtmarkOp op) | ||||||
| { | { | ||||||
|   int fnum = buf->b_fnum; |   int fnum = buf->b_fnum; | ||||||
|   linenr_T *lp; |   linenr_T *lp; | ||||||
| @@ -1205,6 +1205,9 @@ void mark_adjust_buf(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount | |||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   bool by_api = mode == kMarkAdjustApi; | ||||||
|  |   bool by_term = mode == kMarkAdjustTerm; | ||||||
|  |  | ||||||
|   if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) { |   if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) { | ||||||
|     // named marks, lower case and upper case |     // named marks, lower case and upper case | ||||||
|     for (int i = 0; i < NMARKS; i++) { |     for (int i = 0; i < NMARKS; i++) { | ||||||
| @@ -1305,7 +1308,7 @@ void mark_adjust_buf(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount | |||||||
|  |  | ||||||
|       // topline and cursor position for windows with the same buffer |       // topline and cursor position for windows with the same buffer | ||||||
|       // other than the current window |       // other than the current window | ||||||
|       if (win != curwin || by_api) { |       if (by_api || (by_term ? win->w_cursor.lnum < buf->b_ml.ml_line_count : win != curwin)) { | ||||||
|         if (win->w_topline >= line1 && win->w_topline <= line2) { |         if (win->w_topline >= line1 && win->w_topline <= line2) { | ||||||
|           if (amount == MAXLNUM) {                  // topline is deleted |           if (amount == MAXLNUM) {                  // topline is deleted | ||||||
|             if (by_api && amount_after > line1 - line2 - 1) { |             if (by_api && amount_after > line1 - line2 - 1) { | ||||||
| @@ -1327,7 +1330,7 @@ void mark_adjust_buf(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount | |||||||
|           win->w_topfill = 0; |           win->w_topfill = 0; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       if (win != curwin && !by_api) { |       if (!by_api && (by_term ? win->w_cursor.lnum < buf->b_ml.ml_line_count : win != curwin)) { | ||||||
|         if (win->w_cursor.lnum >= line1 && win->w_cursor.lnum <= line2) { |         if (win->w_cursor.lnum >= line1 && win->w_cursor.lnum <= line2) { | ||||||
|           if (amount == MAXLNUM) {         // line with cursor is deleted |           if (amount == MAXLNUM) {         // line with cursor is deleted | ||||||
|             if (line1 <= 1) { |             if (line1 <= 1) { | ||||||
|   | |||||||
| @@ -39,6 +39,13 @@ typedef enum { | |||||||
|   kMarkAllNoResolve,  ///< Return all types of marks but don't resolve fnum (global marks). |   kMarkAllNoResolve,  ///< Return all types of marks but don't resolve fnum (global marks). | ||||||
| } MarkGet; | } MarkGet; | ||||||
|  |  | ||||||
|  | /// Options when adjusting marks | ||||||
|  | typedef enum { | ||||||
|  |   kMarkAdjustNormal,  ///< Normal mode commands, etc. | ||||||
|  |   kMarkAdjustApi,     ///< Changing lines from the API | ||||||
|  |   kMarkAdjustTerm,    ///< Terminal scrollback | ||||||
|  | } MarkAdjustMode; | ||||||
|  |  | ||||||
| /// Number of possible numbered global marks | /// Number of possible numbered global marks | ||||||
| #define EXTRA_MARKS     ('9' - '0' + 1) | #define EXTRA_MARKS     ('9' - '0' + 1) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -74,6 +74,7 @@ | |||||||
| #include "nvim/macros_defs.h" | #include "nvim/macros_defs.h" | ||||||
| #include "nvim/main.h" | #include "nvim/main.h" | ||||||
| #include "nvim/map_defs.h" | #include "nvim/map_defs.h" | ||||||
|  | #include "nvim/mark.h" | ||||||
| #include "nvim/mbyte.h" | #include "nvim/mbyte.h" | ||||||
| #include "nvim/memline.h" | #include "nvim/memline.h" | ||||||
| #include "nvim/memory.h" | #include "nvim/memory.h" | ||||||
| @@ -159,10 +160,11 @@ struct terminal { | |||||||
|   // window height has increased) and must be deleted from the terminal buffer |   // window height has increased) and must be deleted from the terminal buffer | ||||||
|   int sb_pending; |   int sb_pending; | ||||||
|   size_t sb_deleted;                // Lines deleted from sb_buffer. |   size_t sb_deleted;                // Lines deleted from sb_buffer. | ||||||
|  |   size_t sb_deleted_last;           // Value of sb_deleted on last refresh_scrollback() | ||||||
|  |  | ||||||
|   char *title;     // VTermStringFragment buffer |   char *title;     // VTermStringFragment buffer | ||||||
|   size_t title_len;    // number of rows pushed to sb_buffer |   size_t title_len; | ||||||
|   size_t title_size;   // sb_buffer size |   size_t title_size; | ||||||
|  |  | ||||||
|   // buf_T instance that acts as a "drawing surface" for libvterm |   // buf_T instance that acts as a "drawing surface" for libvterm | ||||||
|   // we can't store a direct reference to the buffer because the |   // we can't store a direct reference to the buffer because the | ||||||
| @@ -2220,6 +2222,8 @@ static void adjust_scrollback(Terminal *term, buf_T *buf) | |||||||
|       term->sb_current--; |       term->sb_current--; | ||||||
|       xfree(term->sb_buffer[term->sb_current]); |       xfree(term->sb_buffer[term->sb_current]); | ||||||
|     } |     } | ||||||
|  |     mark_adjust_buf(buf, 1, (linenr_T)diff, MAXLNUM, -(linenr_T)diff, true, | ||||||
|  |                     kMarkAdjustTerm, kExtmarkUndo); | ||||||
|     deleted_lines_buf(buf, 1, (linenr_T)diff); |     deleted_lines_buf(buf, 1, (linenr_T)diff); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -2235,6 +2239,11 @@ static void adjust_scrollback(Terminal *term, buf_T *buf) | |||||||
| // Refresh the scrollback of an invalidated terminal. | // Refresh the scrollback of an invalidated terminal. | ||||||
| static void refresh_scrollback(Terminal *term, buf_T *buf) | static void refresh_scrollback(Terminal *term, buf_T *buf) | ||||||
| { | { | ||||||
|  |   linenr_T deleted = (linenr_T)(term->sb_deleted - term->sb_deleted_last); | ||||||
|  |   deleted = MIN(deleted, buf->b_ml.ml_line_count); | ||||||
|  |   mark_adjust_buf(buf, 1, deleted, MAXLNUM, -deleted, true, kMarkAdjustTerm, kExtmarkUndo); | ||||||
|  |   term->sb_deleted_last = term->sb_deleted; | ||||||
|  |  | ||||||
|   int width, height; |   int width, height; | ||||||
|   vterm_get_size(term->vt, &height, &width); |   vterm_get_size(term->vt, &height, &width); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -227,6 +227,15 @@ describe(':terminal mouse', function() | |||||||
|       it('will forward mouse clicks to the program with the correct even if set nu', function() |       it('will forward mouse clicks to the program with the correct even if set nu', function() | ||||||
|         skip(is_os('win')) |         skip(is_os('win')) | ||||||
|         command('set number') |         command('set number') | ||||||
|  |         screen:expect([[ | ||||||
|  |           {121: 11 }line28                                        | | ||||||
|  |           {121: 12 }line29                                        | | ||||||
|  |           {121: 13 }line30                                        | | ||||||
|  |           {121: 14 }mouse enabled                                 | | ||||||
|  |           {121: 15 }rows: 6, cols: 46                             | | ||||||
|  |           {121: 16 }^                                              | | ||||||
|  |           {5:-- TERMINAL --}                                    | | ||||||
|  |         ]]) | ||||||
|         -- When the display area such as a number is clicked, it returns to the |         -- When the display area such as a number is clicked, it returns to the | ||||||
|         -- normal mode. |         -- normal mode. | ||||||
|         feed('<LeftMouse><3,0>') |         feed('<LeftMouse><3,0>') | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ local tt = require('test.functional.testterm') | |||||||
|  |  | ||||||
| local clear, eq = n.clear, t.eq | local clear, eq = n.clear, t.eq | ||||||
| local feed, testprg = n.feed, n.testprg | local feed, testprg = n.feed, n.testprg | ||||||
|  | local fn = n.fn | ||||||
| local eval = n.eval | local eval = n.eval | ||||||
| local command = n.command | local command = n.command | ||||||
| local poke_eventloop = n.poke_eventloop | local poke_eventloop = n.poke_eventloop | ||||||
| @@ -25,6 +26,18 @@ describe(':terminal scrollback', function() | |||||||
|     screen = tt.setup_screen(nil, nil, 30) |     screen = tt.setup_screen(nil, nil, 30) | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|  |   local function feed_new_lines_and_wait(count) | ||||||
|  |     local lines = {} | ||||||
|  |     for i = 1, count do | ||||||
|  |       table.insert(lines, 'new_line' .. tostring(i)) | ||||||
|  |     end | ||||||
|  |     table.insert(lines, '') | ||||||
|  |     feed_data(lines) | ||||||
|  |     retry(nil, 1000, function() | ||||||
|  |       eq({ 'new_line' .. tostring(count), '' }, api.nvim_buf_get_lines(0, -3, -1, true)) | ||||||
|  |     end) | ||||||
|  |   end | ||||||
|  |  | ||||||
|   describe('when the limit is exceeded', function() |   describe('when the limit is exceeded', function() | ||||||
|     before_each(function() |     before_each(function() | ||||||
|       local lines = {} |       local lines = {} | ||||||
| @@ -56,6 +69,108 @@ describe(':terminal scrollback', function() | |||||||
|                                       | |                                       | | ||||||
|       ]]) |       ]]) | ||||||
|     end) |     end) | ||||||
|  |  | ||||||
|  |     describe('and cursor on non-last row in screen', function() | ||||||
|  |       before_each(function() | ||||||
|  |         feed([[<C-\><C-N>M$]]) | ||||||
|  |         fn.setpos("'m", { 0, 13, 4, 0 }) | ||||||
|  |         local ns = api.nvim_create_namespace('test') | ||||||
|  |         api.nvim_buf_set_extmark(0, ns, 12, 0, { end_col = 6, hl_group = 'ErrorMsg' }) | ||||||
|  |         screen:expect([[ | ||||||
|  |           line26                        | | ||||||
|  |           line27                        | | ||||||
|  |           {101:line2^8}                        | | ||||||
|  |           line29                        | | ||||||
|  |           line30                        | | ||||||
|  |                                         |*2 | ||||||
|  |         ]]) | ||||||
|  |       end) | ||||||
|  |  | ||||||
|  |       it("when outputting fewer than 'scrollback' lines", function() | ||||||
|  |         feed_new_lines_and_wait(6) | ||||||
|  |         screen:expect([[ | ||||||
|  |           line26                        | | ||||||
|  |           line27                        | | ||||||
|  |           {101:line2^8}                        | | ||||||
|  |           line29                        | | ||||||
|  |           line30                        | | ||||||
|  |           new_line1                     | | ||||||
|  |                                         | | ||||||
|  |         ]]) | ||||||
|  |         eq({ 0, 7, 4, 0 }, fn.getpos("'m")) | ||||||
|  |         eq({ 0, 7, 6, 0 }, fn.getpos('.')) | ||||||
|  |       end) | ||||||
|  |  | ||||||
|  |       it("when outputting more than 'scrollback' lines", function() | ||||||
|  |         feed_new_lines_and_wait(11) | ||||||
|  |         screen:expect([[ | ||||||
|  |           line27                        | | ||||||
|  |           {101:line2^8}                        | | ||||||
|  |           line29                        | | ||||||
|  |           line30                        | | ||||||
|  |           new_line1                     | | ||||||
|  |           new_line2                     | | ||||||
|  |                                         | | ||||||
|  |         ]]) | ||||||
|  |         eq({ 0, 2, 4, 0 }, fn.getpos("'m")) | ||||||
|  |         eq({ 0, 2, 6, 0 }, fn.getpos('.')) | ||||||
|  |       end) | ||||||
|  |  | ||||||
|  |       it('when outputting more lines than whole buffer', function() | ||||||
|  |         feed_new_lines_and_wait(20) | ||||||
|  |         screen:expect([[ | ||||||
|  |           ^new_line6                     | | ||||||
|  |           new_line7                     | | ||||||
|  |           new_line8                     | | ||||||
|  |           new_line9                     | | ||||||
|  |           new_line10                    | | ||||||
|  |           new_line11                    | | ||||||
|  |                                         | | ||||||
|  |         ]]) | ||||||
|  |         eq({ 0, 0, 0, 0 }, fn.getpos("'m")) | ||||||
|  |         eq({ 0, 1, 1, 0 }, fn.getpos('.')) | ||||||
|  |       end) | ||||||
|  |     end) | ||||||
|  |  | ||||||
|  |     describe('and cursor on scrollback row #12651', function() | ||||||
|  |       before_each(function() | ||||||
|  |         feed([[<C-\><C-N>Hk$]]) | ||||||
|  |         fn.setpos("'m", { 0, 10, 4, 0 }) | ||||||
|  |         local ns = api.nvim_create_namespace('test') | ||||||
|  |         api.nvim_buf_set_extmark(0, ns, 9, 0, { end_col = 6, hl_group = 'ErrorMsg' }) | ||||||
|  |         screen:expect([[ | ||||||
|  |           {101:line2^5}                        | | ||||||
|  |           line26                        | | ||||||
|  |           line27                        | | ||||||
|  |           line28                        | | ||||||
|  |           line29                        | | ||||||
|  |           line30                        | | ||||||
|  |                                         | | ||||||
|  |         ]]) | ||||||
|  |       end) | ||||||
|  |  | ||||||
|  |       it("when outputting fewer than 'scrollback' lines", function() | ||||||
|  |         feed_new_lines_and_wait(6) | ||||||
|  |         screen:expect_unchanged() | ||||||
|  |         eq({ 0, 4, 4, 0 }, fn.getpos("'m")) | ||||||
|  |         eq({ 0, 4, 6, 0 }, fn.getpos('.')) | ||||||
|  |       end) | ||||||
|  |  | ||||||
|  |       it("when outputting more than 'scrollback' lines", function() | ||||||
|  |         feed_new_lines_and_wait(11) | ||||||
|  |         screen:expect([[ | ||||||
|  |           ^line27                        | | ||||||
|  |           line28                        | | ||||||
|  |           line29                        | | ||||||
|  |           line30                        | | ||||||
|  |           new_line1                     | | ||||||
|  |           new_line2                     | | ||||||
|  |                                         | | ||||||
|  |         ]]) | ||||||
|  |         eq({ 0, 0, 0, 0 }, fn.getpos("'m")) | ||||||
|  |         eq({ 0, 1, 1, 0 }, fn.getpos('.')) | ||||||
|  |       end) | ||||||
|  |     end) | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|   describe('with cursor at last row', function() |   describe('with cursor at last row', function() | ||||||
| @@ -70,6 +185,43 @@ describe(':terminal scrollback', function() | |||||||
|         ^                              | |         ^                              | | ||||||
|         {5:-- TERMINAL --}                | |         {5:-- TERMINAL --}                | | ||||||
|       ]]) |       ]]) | ||||||
|  |       fn.setpos("'m", { 0, 3, 4, 0 }) | ||||||
|  |       local ns = api.nvim_create_namespace('test') | ||||||
|  |       api.nvim_buf_set_extmark(0, ns, 2, 0, { end_col = 5, hl_group = 'ErrorMsg' }) | ||||||
|  |       screen:expect([[ | ||||||
|  |         tty ready                     | | ||||||
|  |         line1                         | | ||||||
|  |         {101:line2}                         | | ||||||
|  |         line3                         | | ||||||
|  |         line4                         | | ||||||
|  |         ^                              | | ||||||
|  |         {5:-- TERMINAL --}                | | ||||||
|  |       ]]) | ||||||
|  |     end) | ||||||
|  |  | ||||||
|  |     it("when outputting more than 'scrollback' lines in Normal mode", function() | ||||||
|  |       feed([[<C-\><C-N>]]) | ||||||
|  |       feed_new_lines_and_wait(11) | ||||||
|  |       screen:expect([[ | ||||||
|  |         new_line7                     | | ||||||
|  |         new_line8                     | | ||||||
|  |         new_line9                     | | ||||||
|  |         new_line10                    | | ||||||
|  |         new_line11                    | | ||||||
|  |         ^                              | | ||||||
|  |                                       | | ||||||
|  |       ]]) | ||||||
|  |       feed('gg') | ||||||
|  |       screen:expect([[ | ||||||
|  |         ^line1                         | | ||||||
|  |         {101:line2}                         | | ||||||
|  |         line3                         | | ||||||
|  |         line4                         | | ||||||
|  |         new_line1                     | | ||||||
|  |         new_line2                     | | ||||||
|  |                                       | | ||||||
|  |       ]]) | ||||||
|  |       eq({ 0, 2, 4, 0 }, fn.getpos("'m")) | ||||||
|     end) |     end) | ||||||
|  |  | ||||||
|     describe('and 1 line is printed', function() |     describe('and 1 line is printed', function() | ||||||
| @@ -80,7 +232,7 @@ describe(':terminal scrollback', function() | |||||||
|       it('will hide the top line', function() |       it('will hide the top line', function() | ||||||
|         screen:expect([[ |         screen:expect([[ | ||||||
|           line1                         | |           line1                         | | ||||||
|           line2                         | |           {101:line2}                         | | ||||||
|           line3                         | |           line3                         | | ||||||
|           line4                         | |           line4                         | | ||||||
|           line5                         | |           line5                         | | ||||||
| @@ -88,32 +240,34 @@ describe(':terminal scrollback', function() | |||||||
|           {5:-- TERMINAL --}                | |           {5:-- TERMINAL --}                | | ||||||
|         ]]) |         ]]) | ||||||
|         eq(7, api.nvim_buf_line_count(0)) |         eq(7, api.nvim_buf_line_count(0)) | ||||||
|  |         eq({ 0, 3, 4, 0 }, fn.getpos("'m")) | ||||||
|       end) |       end) | ||||||
|  |  | ||||||
|       describe('and then 3 more lines are printed', function() |       describe('and then 3 more lines are printed', function() | ||||||
|         before_each(function() |         before_each(function() | ||||||
|           feed_data({ 'line6', 'line7', 'line8' }) |           feed_data({ 'line6', 'line7', 'line8', '' }) | ||||||
|         end) |         end) | ||||||
|  |  | ||||||
|         it('will hide the top 4 lines', function() |         it('will hide the top 4 lines', function() | ||||||
|           screen:expect([[ |           screen:expect([[ | ||||||
|             line3                         | |  | ||||||
|             line4                         | |             line4                         | | ||||||
|             line5                         | |             line5                         | | ||||||
|             line6                         | |             line6                         | | ||||||
|             line7                         | |             line7                         | | ||||||
|             line8^                         | |             line8                         | | ||||||
|  |             ^                              | | ||||||
|             {5:-- TERMINAL --}                | |             {5:-- TERMINAL --}                | | ||||||
|           ]]) |           ]]) | ||||||
|  |           eq({ 0, 3, 4, 0 }, fn.getpos("'m")) | ||||||
|  |  | ||||||
|           feed('<c-\\><c-n>6k') |           feed('<c-\\><c-n>6k') | ||||||
|           screen:expect([[ |           screen:expect([[ | ||||||
|             ^line2                         | |             ^line3                         | | ||||||
|             line3                         | |  | ||||||
|             line4                         | |             line4                         | | ||||||
|             line5                         | |             line5                         | | ||||||
|             line6                         | |             line6                         | | ||||||
|             line7                         | |             line7                         | | ||||||
|  |             line8                         | | ||||||
|                                           | |                                           | | ||||||
|           ]]) |           ]]) | ||||||
|  |  | ||||||
| @@ -121,7 +275,7 @@ describe(':terminal scrollback', function() | |||||||
|           screen:expect([[ |           screen:expect([[ | ||||||
|             ^tty ready                     | |             ^tty ready                     | | ||||||
|             line1                         | |             line1                         | | ||||||
|             line2                         | |             {101:line2}                         | | ||||||
|             line3                         | |             line3                         | | ||||||
|             line4                         | |             line4                         | | ||||||
|             line5                         | |             line5                         | | ||||||
| @@ -130,12 +284,12 @@ describe(':terminal scrollback', function() | |||||||
|  |  | ||||||
|           feed('G') |           feed('G') | ||||||
|           screen:expect([[ |           screen:expect([[ | ||||||
|             line3                         | |  | ||||||
|             line4                         | |             line4                         | | ||||||
|             line5                         | |             line5                         | | ||||||
|             line6                         | |             line6                         | | ||||||
|             line7                         | |             line7                         | | ||||||
|             ^line8                         | |             line8                         | | ||||||
|  |             ^                              | | ||||||
|                                           | |                                           | | ||||||
|           ]]) |           ]]) | ||||||
|         end) |         end) | ||||||
| @@ -147,13 +301,14 @@ describe(':terminal scrollback', function() | |||||||
|         feed([[<C-\><C-N>]]) |         feed([[<C-\><C-N>]]) | ||||||
|         screen:try_resize(screen._width - 2, screen._height - 1) |         screen:try_resize(screen._width - 2, screen._height - 1) | ||||||
|         screen:expect([[ |         screen:expect([[ | ||||||
|           line2                       | |           {101:line2}                       | | ||||||
|           line3                       | |           line3                       | | ||||||
|           line4                       | |           line4                       | | ||||||
|           rows: 5, cols: 28           | |           rows: 5, cols: 28           | | ||||||
|           ^                            | |           ^                            | | ||||||
|                                       | |                                       | | ||||||
|         ]]) |         ]]) | ||||||
|  |         eq({ 0, 3, 4, 0 }, fn.getpos("'m")) | ||||||
|       end |       end | ||||||
|  |  | ||||||
|       it('will hide top line', will_hide_top_line) |       it('will hide top line', will_hide_top_line) | ||||||
| @@ -172,13 +327,21 @@ describe(':terminal scrollback', function() | |||||||
|                                       | |                                       | | ||||||
|           ]]) |           ]]) | ||||||
|           eq(8, api.nvim_buf_line_count(0)) |           eq(8, api.nvim_buf_line_count(0)) | ||||||
|           feed([[3k]]) |           eq({ 0, 3, 4, 0 }, fn.getpos("'m")) | ||||||
|  |           feed('3k') | ||||||
|           screen:expect([[ |           screen:expect([[ | ||||||
|             ^line4                     | |             ^line4                     | | ||||||
|             rows: 5, cols: 28         | |             rows: 5, cols: 28         | | ||||||
|             rows: 3, cols: 26         | |             rows: 3, cols: 26         | | ||||||
|                                       | |                                       | | ||||||
|           ]]) |           ]]) | ||||||
|  |           feed('gg') | ||||||
|  |           screen:expect([[ | ||||||
|  |             ^tty ready                 | | ||||||
|  |             line1                     | | ||||||
|  |             {101:line2}                     | | ||||||
|  |                                       | | ||||||
|  |           ]]) | ||||||
|         end) |         end) | ||||||
|       end) |       end) | ||||||
|     end) |     end) | ||||||
| @@ -255,6 +418,18 @@ describe(':terminal scrollback', function() | |||||||
|         ^                              | |         ^                              | | ||||||
|         {5:-- TERMINAL --}                | |         {5:-- TERMINAL --}                | | ||||||
|       ]]) |       ]]) | ||||||
|  |       fn.setpos("'m", { 0, 3, 4, 0 }) | ||||||
|  |       local ns = api.nvim_create_namespace('test') | ||||||
|  |       api.nvim_buf_set_extmark(0, ns, 2, 0, { end_col = 5, hl_group = 'ErrorMsg' }) | ||||||
|  |       screen:expect([[ | ||||||
|  |         tty ready                     | | ||||||
|  |         line1                         | | ||||||
|  |         {101:line2}                         | | ||||||
|  |         line3                         | | ||||||
|  |         line4                         | | ||||||
|  |         ^                              | | ||||||
|  |         {5:-- TERMINAL --}                | | ||||||
|  |       ]]) | ||||||
|       screen:try_resize(screen._width, screen._height - 3) |       screen:try_resize(screen._width, screen._height - 3) | ||||||
|       screen:expect([[ |       screen:expect([[ | ||||||
|         line4                         | |         line4                         | | ||||||
| @@ -281,6 +456,7 @@ describe(':terminal scrollback', function() | |||||||
|           ^                              | |           ^                              | | ||||||
|           {5:-- TERMINAL --}                | |           {5:-- TERMINAL --}                | | ||||||
|         ]]) |         ]]) | ||||||
|  |         eq({ 0, 3, 4, 0 }, fn.getpos("'m")) | ||||||
|       end |       end | ||||||
|  |  | ||||||
|       it('will pop 1 line and then push it back', pop_then_push) |       it('will pop 1 line and then push it back', pop_then_push) | ||||||
| @@ -294,7 +470,7 @@ describe(':terminal scrollback', function() | |||||||
|  |  | ||||||
|         local function pop3_then_push1() |         local function pop3_then_push1() | ||||||
|           screen:expect([[ |           screen:expect([[ | ||||||
|             line2                         | |             {101:line2}                         | | ||||||
|             line3                         | |             line3                         | | ||||||
|             line4                         | |             line4                         | | ||||||
|             rows: 3, cols: 30             | |             rows: 3, cols: 30             | | ||||||
| @@ -304,11 +480,12 @@ describe(':terminal scrollback', function() | |||||||
|             {5:-- TERMINAL --}                | |             {5:-- TERMINAL --}                | | ||||||
|           ]]) |           ]]) | ||||||
|           eq(9, api.nvim_buf_line_count(0)) |           eq(9, api.nvim_buf_line_count(0)) | ||||||
|  |           eq({ 0, 3, 4, 0 }, fn.getpos("'m")) | ||||||
|           feed('<c-\\><c-n>gg') |           feed('<c-\\><c-n>gg') | ||||||
|           screen:expect([[ |           screen:expect([[ | ||||||
|             ^tty ready                     | |             ^tty ready                     | | ||||||
|             line1                         | |             line1                         | | ||||||
|             line2                         | |             {101:line2}                         | | ||||||
|             line3                         | |             line3                         | | ||||||
|             line4                         | |             line4                         | | ||||||
|             rows: 3, cols: 30             | |             rows: 3, cols: 30             | | ||||||
| @@ -330,7 +507,7 @@ describe(':terminal scrollback', function() | |||||||
|             screen:expect([[ |             screen:expect([[ | ||||||
|               tty ready                     | |               tty ready                     | | ||||||
|               line1                         | |               line1                         | | ||||||
|               line2                         | |               {101:line2}                         | | ||||||
|               line3                         | |               line3                         | | ||||||
|               line4                         | |               line4                         | | ||||||
|               rows: 3, cols: 30             | |               rows: 3, cols: 30             | | ||||||
| @@ -344,6 +521,7 @@ describe(':terminal scrollback', function() | |||||||
|             -- since there's an empty line after the cursor, the buffer line |             -- since there's an empty line after the cursor, the buffer line | ||||||
|             -- count equals the terminal screen height |             -- count equals the terminal screen height | ||||||
|             eq(11, api.nvim_buf_line_count(0)) |             eq(11, api.nvim_buf_line_count(0)) | ||||||
|  |             eq({ 0, 3, 4, 0 }, fn.getpos("'m")) | ||||||
|           end) |           end) | ||||||
|         end) |         end) | ||||||
|       end) |       end) | ||||||
| @@ -484,22 +662,36 @@ describe("'scrollback' option", function() | |||||||
|     table.insert(lines, '') |     table.insert(lines, '') | ||||||
|     feed_data(lines) |     feed_data(lines) | ||||||
|     screen:expect([[ |     screen:expect([[ | ||||||
|         line26                        | |       line26                        | | ||||||
|         line27                        | |       line27                        | | ||||||
|         line28                        | |       line28                        | | ||||||
|         line29                        | |       line29                        | | ||||||
|         line30                        | |       line30                        | | ||||||
|         ^                              | |       ^                              | | ||||||
|         {5:-- TERMINAL --}                | |       {5:-- TERMINAL --}                | | ||||||
|       ]]) |     ]]) | ||||||
|  |     local ns = api.nvim_create_namespace('test') | ||||||
|     local term_height = 6 -- Actual terminal screen height, not the scrollback |     local term_height = 6 -- Actual terminal screen height, not the scrollback | ||||||
|     -- Initial |     -- Initial | ||||||
|     local scrollback = api.nvim_get_option_value('scrollback', {}) |     local scrollback = api.nvim_get_option_value('scrollback', {}) | ||||||
|     eq(scrollback + term_height, eval('line("$")')) |     eq(scrollback + term_height, fn.line('$')) | ||||||
|  |     n.fn.setpos("'m", { 0, scrollback + 1, 4, 0 }) | ||||||
|  |     api.nvim_buf_set_extmark(0, ns, scrollback, 0, { end_col = 6, hl_group = 'ErrorMsg' }) | ||||||
|  |     screen:expect([[ | ||||||
|  |       {101:line26}                        | | ||||||
|  |       line27                        | | ||||||
|  |       line28                        | | ||||||
|  |       line29                        | | ||||||
|  |       line30                        | | ||||||
|  |       ^                              | | ||||||
|  |       {5:-- TERMINAL --}                | | ||||||
|  |     ]]) | ||||||
|     -- Reduction |     -- Reduction | ||||||
|     scrollback = scrollback - 2 |     scrollback = scrollback - 2 | ||||||
|     api.nvim_set_option_value('scrollback', scrollback, {}) |     api.nvim_set_option_value('scrollback', scrollback, {}) | ||||||
|     eq(scrollback + term_height, eval('line("$")')) |     eq(scrollback + term_height, fn.line('$')) | ||||||
|  |     screen:expect_unchanged() | ||||||
|  |     eq({ 0, scrollback + 1, 4, 0 }, n.fn.getpos("'m")) | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|   it('defaults to 10000 in :terminal buffers', function() |   it('defaults to 10000 in :terminal buffers', function() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 zeertzjq
					zeertzjq