Mercurial > vim
comparison src/terminal.c @ 13878:a590029f16a0 v8.0.1810
patch 8.0.1810: buffer of a terminal only updated in Terminal-Normal mode
commit https://github.com/vim/vim/commit/56bc8e299cdae1b4606897749ef54a0161381a4a
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu May 10 18:05:56 2018 +0200
patch 8.0.1810: buffer of a terminal only updated in Terminal-Normal mode
Problem: Buffer of a terminal only updated in Terminal-Normal mode.
Solution: Copy the terminal window content to the buffer when in
Terminal-Job mode.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 10 May 2018 18:15:06 +0200 |
parents | de8455bd2d05 |
children | bbf5bdba4a80 |
comparison
equal
deleted
inserted
replaced
13877:aee4384c0938 | 13878:a590029f16a0 |
---|---|
41 * - Win32: Redirecting input does not work, half of Test_terminal_redir_file() | 41 * - Win32: Redirecting input does not work, half of Test_terminal_redir_file() |
42 * is disabled. | 42 * is disabled. |
43 * - Win32: Redirecting output works but includes escape sequences. | 43 * - Win32: Redirecting output works but includes escape sequences. |
44 * - Win32: Make terminal used for :!cmd in the GUI work better. Allow for | 44 * - Win32: Make terminal used for :!cmd in the GUI work better. Allow for |
45 * redirection. | 45 * redirection. |
46 * - Copy text in the vterm to the Vim buffer once in a while, so that | |
47 * completion works. | |
48 * - When the job only outputs lines, we could handle resizing the terminal | 46 * - When the job only outputs lines, we could handle resizing the terminal |
49 * better: store lines separated by line breaks, instead of screen lines, | 47 * better: store lines separated by line breaks, instead of screen lines, |
50 * then when the window is resized redraw those lines. | 48 * then when the window is resized redraw those lines. |
51 * - Redrawing is slow with Athena and Motif. (Ramel Eshed) | 49 * - Redrawing is slow with Athena and Motif. (Ramel Eshed) |
52 * - For the GUI fill termios with default values, perhaps like pangoterm: | 50 * - For the GUI fill termios with default values, perhaps like pangoterm: |
129 char_u *tl_status_text; /* NULL or allocated */ | 127 char_u *tl_status_text; /* NULL or allocated */ |
130 | 128 |
131 /* Range of screen rows to update. Zero based. */ | 129 /* Range of screen rows to update. Zero based. */ |
132 int tl_dirty_row_start; /* MAX_ROW if nothing dirty */ | 130 int tl_dirty_row_start; /* MAX_ROW if nothing dirty */ |
133 int tl_dirty_row_end; /* row below last one to update */ | 131 int tl_dirty_row_end; /* row below last one to update */ |
134 | 132 int tl_dirty_snapshot; /* text updated after making snapshot */ |
133 #ifdef FEAT_TIMERS | |
134 int tl_timer_set; | |
135 proftime_T tl_timer_due; | |
136 #endif | |
135 int tl_postponed_scroll; /* to be scrolled up */ | 137 int tl_postponed_scroll; /* to be scrolled up */ |
136 | 138 |
137 garray_T tl_scrollback; | 139 garray_T tl_scrollback; |
138 int tl_scrollback_scrolled; | 140 int tl_scrollback_scrolled; |
139 cellattr_T tl_default_color; | 141 cellattr_T tl_default_color; |
1440 } | 1442 } |
1441 return FALSE; | 1443 return FALSE; |
1442 } | 1444 } |
1443 | 1445 |
1444 /* | 1446 /* |
1447 * Remove the terminal contents from the scrollback and the buffer. | |
1448 * Used before adding a new scrollback line or updating the buffer for lines | |
1449 * displayed in the terminal. | |
1450 */ | |
1451 static void | |
1452 cleanup_scrollback(term_T *term) | |
1453 { | |
1454 sb_line_T *line; | |
1455 garray_T *gap; | |
1456 | |
1457 gap = &term->tl_scrollback; | |
1458 while (curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled | |
1459 && gap->ga_len > 0) | |
1460 { | |
1461 ml_delete(curbuf->b_ml.ml_line_count, FALSE); | |
1462 line = (sb_line_T *)gap->ga_data + gap->ga_len - 1; | |
1463 vim_free(line->sb_cells); | |
1464 --gap->ga_len; | |
1465 } | |
1466 check_cursor(); | |
1467 } | |
1468 | |
1469 /* | |
1445 * Add the current lines of the terminal to scrollback and to the buffer. | 1470 * Add the current lines of the terminal to scrollback and to the buffer. |
1446 * Called after the job has ended and when switching to Terminal-Normal mode. | 1471 * Called after the job has ended and when switching to Terminal-Normal mode. |
1447 */ | 1472 */ |
1448 static void | 1473 static void |
1449 move_terminal_to_buffer(term_T *term) | 1474 move_terminal_to_buffer(term_T *term) |
1457 cellattr_T *p; | 1482 cellattr_T *p; |
1458 VTermScreen *screen; | 1483 VTermScreen *screen; |
1459 | 1484 |
1460 if (term->tl_vterm == NULL) | 1485 if (term->tl_vterm == NULL) |
1461 return; | 1486 return; |
1487 | |
1488 /* Nothing to do if the buffer already has the lines and nothing was | |
1489 * changed. */ | |
1490 if (!term->tl_dirty_snapshot | |
1491 && curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled) | |
1492 return; | |
1493 | |
1494 ch_log(term->tl_job == NULL ? NULL : term->tl_job->jv_channel, | |
1495 "Adding terminal window snapshot to buffer"); | |
1496 | |
1497 /* First remove the lines that were appended before, they might be | |
1498 * outdated. */ | |
1499 cleanup_scrollback(term); | |
1500 | |
1462 screen = vterm_obtain_screen(term->tl_vterm); | 1501 screen = vterm_obtain_screen(term->tl_vterm); |
1463 fill_attr = new_fill_attr = term->tl_default_color; | 1502 fill_attr = new_fill_attr = term->tl_default_color; |
1464 | |
1465 for (pos.row = 0; pos.row < term->tl_rows; ++pos.row) | 1503 for (pos.row = 0; pos.row < term->tl_rows; ++pos.row) |
1466 { | 1504 { |
1467 len = 0; | 1505 len = 0; |
1468 for (pos.col = 0; pos.col < term->tl_cols; ++pos.col) | 1506 for (pos.col = 0; pos.col < term->tl_cols; ++pos.col) |
1469 if (vterm_screen_get_cell(screen, pos, &cell) != 0 | 1507 if (vterm_screen_get_cell(screen, pos, &cell) != 0 |
1546 else | 1584 else |
1547 vim_free(p); | 1585 vim_free(p); |
1548 } | 1586 } |
1549 } | 1587 } |
1550 | 1588 |
1589 term->tl_dirty_snapshot = FALSE; | |
1590 #ifdef FEAT_TIMERS | |
1591 term->tl_timer_set = FALSE; | |
1592 #endif | |
1593 | |
1551 /* Obtain the current background color. */ | 1594 /* Obtain the current background color. */ |
1552 vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm), | 1595 vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm), |
1553 &term->tl_default_color.fg, &term->tl_default_color.bg); | 1596 &term->tl_default_color.fg, &term->tl_default_color.bg); |
1554 | 1597 |
1555 FOR_ALL_WINDOWS(wp) | 1598 FOR_ALL_WINDOWS(wp) |
1569 redraw_win_later(wp, NOT_VALID); | 1612 redraw_win_later(wp, NOT_VALID); |
1570 } | 1613 } |
1571 } | 1614 } |
1572 } | 1615 } |
1573 | 1616 |
1617 #if defined(FEAT_TIMERS) || defined(PROTO) | |
1618 /* | |
1619 * Check if any terminal timer expired. If so, copy text from the terminal to | |
1620 * the buffer. | |
1621 * Return the time until the next timer will expire. | |
1622 */ | |
1623 int | |
1624 term_check_timers(int next_due_arg, proftime_T *now) | |
1625 { | |
1626 term_T *term; | |
1627 int next_due = next_due_arg; | |
1628 | |
1629 for (term = first_term; term != NULL; term = term->tl_next) | |
1630 { | |
1631 if (term->tl_timer_set && !term->tl_normal_mode) | |
1632 { | |
1633 long this_due = proftime_time_left(&term->tl_timer_due, now); | |
1634 | |
1635 if (this_due <= 1) | |
1636 { | |
1637 term->tl_timer_set = FALSE; | |
1638 move_terminal_to_buffer(term); | |
1639 } | |
1640 else if (next_due == -1 || next_due > this_due) | |
1641 next_due = this_due; | |
1642 } | |
1643 } | |
1644 | |
1645 return next_due; | |
1646 } | |
1647 #endif | |
1648 | |
1574 static void | 1649 static void |
1575 set_terminal_mode(term_T *term, int normal_mode) | 1650 set_terminal_mode(term_T *term, int normal_mode) |
1576 { | 1651 { |
1577 term->tl_normal_mode = normal_mode; | 1652 term->tl_normal_mode = normal_mode; |
1578 VIM_CLEAR(term->tl_status_text); | 1653 VIM_CLEAR(term->tl_status_text); |
1636 */ | 1711 */ |
1637 void | 1712 void |
1638 term_enter_job_mode() | 1713 term_enter_job_mode() |
1639 { | 1714 { |
1640 term_T *term = curbuf->b_term; | 1715 term_T *term = curbuf->b_term; |
1641 sb_line_T *line; | |
1642 garray_T *gap; | |
1643 | |
1644 /* Remove the terminal contents from the scrollback and the buffer. */ | |
1645 gap = &term->tl_scrollback; | |
1646 while (curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled | |
1647 && gap->ga_len > 0) | |
1648 { | |
1649 ml_delete(curbuf->b_ml.ml_line_count, FALSE); | |
1650 line = (sb_line_T *)gap->ga_data + gap->ga_len - 1; | |
1651 vim_free(line->sb_cells); | |
1652 --gap->ga_len; | |
1653 } | |
1654 check_cursor(); | |
1655 | 1716 |
1656 set_terminal_mode(term, FALSE); | 1717 set_terminal_mode(term, FALSE); |
1657 | 1718 |
1658 if (term->tl_channel_closed) | 1719 if (term->tl_channel_closed) |
1659 cleanup_vterm(term); | 1720 cleanup_vterm(term); |
2172 | 2233 |
2173 theend: | 2234 theend: |
2174 in_terminal_loop = NULL; | 2235 in_terminal_loop = NULL; |
2175 if (restore_cursor) | 2236 if (restore_cursor) |
2176 prepare_restore_cursor_props(); | 2237 prepare_restore_cursor_props(); |
2238 | |
2239 /* Move a snapshot of the screen contents to the buffer, so that completion | |
2240 * works in other buffers. */ | |
2241 if (curbuf->b_term != NULL) | |
2242 move_terminal_to_buffer(curbuf->b_term); | |
2243 | |
2177 return ret; | 2244 return ret; |
2178 } | 2245 } |
2179 | 2246 |
2180 /* | 2247 /* |
2181 * Called when a job has finished. | 2248 * Called when a job has finished. |
2388 return get_cterm_attr_idx(attr, fg, bg); | 2455 return get_cterm_attr_idx(attr, fg, bg); |
2389 } | 2456 } |
2390 return 0; | 2457 return 0; |
2391 } | 2458 } |
2392 | 2459 |
2460 static void | |
2461 set_dirty_snapshot(term_T *term) | |
2462 { | |
2463 term->tl_dirty_snapshot = TRUE; | |
2464 #ifdef FEAT_TIMERS | |
2465 if (!term->tl_normal_mode) | |
2466 { | |
2467 /* Update the snapshot after 100 msec of not getting updates. */ | |
2468 profile_setlimit(100L, &term->tl_timer_due); | |
2469 term->tl_timer_set = TRUE; | |
2470 } | |
2471 #endif | |
2472 } | |
2473 | |
2393 static int | 2474 static int |
2394 handle_damage(VTermRect rect, void *user) | 2475 handle_damage(VTermRect rect, void *user) |
2395 { | 2476 { |
2396 term_T *term = (term_T *)user; | 2477 term_T *term = (term_T *)user; |
2397 | 2478 |
2398 term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, rect.start_row); | 2479 term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, rect.start_row); |
2399 term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_row); | 2480 term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_row); |
2481 set_dirty_snapshot(term); | |
2400 redraw_buf_later(term->tl_buffer, SOME_VALID); | 2482 redraw_buf_later(term->tl_buffer, SOME_VALID); |
2401 return 1; | 2483 return 1; |
2402 } | 2484 } |
2403 | 2485 |
2404 static void | 2486 static void |
2441 term_scroll_up(term, dest.start_row, count); | 2523 term_scroll_up(term, dest.start_row, count); |
2442 } | 2524 } |
2443 | 2525 |
2444 term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, dest.start_row); | 2526 term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, dest.start_row); |
2445 term->tl_dirty_row_end = MIN(term->tl_dirty_row_end, dest.end_row); | 2527 term->tl_dirty_row_end = MIN(term->tl_dirty_row_end, dest.end_row); |
2528 set_dirty_snapshot(term); | |
2446 | 2529 |
2447 /* Note sure if the scrolling will work correctly, let's do a complete | 2530 /* Note sure if the scrolling will work correctly, let's do a complete |
2448 * redraw later. */ | 2531 * redraw later. */ |
2449 redraw_buf_later(term->tl_buffer, NOT_VALID); | 2532 redraw_buf_later(term->tl_buffer, NOT_VALID); |
2450 return 1; | 2533 return 1; |
2591 */ | 2674 */ |
2592 static int | 2675 static int |
2593 handle_pushline(int cols, const VTermScreenCell *cells, void *user) | 2676 handle_pushline(int cols, const VTermScreenCell *cells, void *user) |
2594 { | 2677 { |
2595 term_T *term = (term_T *)user; | 2678 term_T *term = (term_T *)user; |
2679 | |
2680 /* First remove the lines that were appended before, the pushed line goes | |
2681 * above it. */ | |
2682 cleanup_scrollback(term); | |
2596 | 2683 |
2597 /* If the number of lines that are stored goes over 'termscrollback' then | 2684 /* If the number of lines that are stored goes over 'termscrollback' then |
2598 * delete the first 10%. */ | 2685 * delete the first 10%. */ |
2599 if (term->tl_scrollback.ga_len >= term->tl_buffer->b_p_twsl) | 2686 if (term->tl_scrollback.ga_len >= term->tl_buffer->b_p_twsl) |
2600 { | 2687 { |