Skip to content

Commit 498c256

Browse files
committed
patch 8.0.1722: cannot specify a minimal size for a terminal window
Problem: Cannot specify a minimal size for a terminal window. Solution: Support the "rows*cols" format for 'winsize'.
1 parent a7eef3d commit 498c256

File tree

5 files changed

+152
-55
lines changed

5 files changed

+152
-55
lines changed

runtime/doc/options.txt

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7960,15 +7960,23 @@ A jump table for the options with a short description can be found at |Q_op|.
79607960
'termsize' 'tms' string (default "")
79617961
local to window
79627962
{not in Vi}
7963-
Size of the |terminal| window. Format: {rows}x{columns}.
7963+
Size of the |terminal| window. Format: {rows}x{columns} or
7964+
{rows}*{columns}.
79647965
- When empty the terminal gets the size from the window.
7965-
- When set (e.g., "24x80") the terminal size is not adjusted to the
7966-
window size. If the window is smaller only the top-left part is
7967-
displayed.
7968-
When rows is zero then use the height of the window.
7969-
When columns is zero then use the width of the window.
7970-
For example: "30x0" uses 30 rows with the current window width.
7971-
Using "0x0" is the same as empty.
7966+
- When set with a "x" (e.g., "24x80") the terminal size is not
7967+
adjusted to the window size. If the window is smaller only the
7968+
top-left part is displayed.
7969+
- When set with a "*" (e.g., "10*50") the terminal size follows the
7970+
window size, but will not be smaller than the specified rows and/or
7971+
columns.
7972+
- When rows is zero then use the height of the window.
7973+
- When columns is zero then use the width of the window.
7974+
- Using "0x0" or "0*0" is the same as empty.
7975+
7976+
Examples:
7977+
"30x0" uses 30 rows and the current window width.
7978+
"20*0" uses at least 20 rows and the current window width.
7979+
"0*40" uses the current window height and at least 40 columns.
79727980
Note that the command running in the terminal window may still change
79737981
the size of the terminal. In that case the Vim window will be
79747982
adjusted to that size, if possible.

src/option.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7464,7 +7464,9 @@ did_set_string_option(
74647464
if (*curwin->w_p_tms != NUL)
74657465
{
74667466
p = skipdigits(curwin->w_p_tms);
7467-
if (p == curwin->w_p_tms || *p != 'x' || *skipdigits(p + 1) != NUL)
7467+
if (p == curwin->w_p_tms
7468+
|| (*p != 'x' && *p != '*')
7469+
|| *skipdigits(p + 1) != NUL)
74687470
errmsg = e_invarg;
74697471
}
74707472
}

src/terminal.c

Lines changed: 64 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,20 @@
4242
* redirection. Probably in call to channel_set_pipes().
4343
* - Win32: Redirecting output does not work, Test_terminal_redir_file()
4444
* is disabled.
45-
* - Copy text in the vterm to the Vim buffer once in a while, so that
46-
* completion works.
4745
* - When starting terminal window with shell in terminal, then using :gui to
4846
* switch to GUI, shell stops working. Scrollback seems wrong, command
4947
* running in shell is still running.
50-
* - in GUI vertical split causes problems. Cursor is flickering. (Hirohito
51-
* Higashi, 2017 Sep 19)
52-
* - after resizing windows overlap. (Boris Staletic, #2164)
53-
* - cursor blinks in terminal on widows with a timer. (xtal8, #2142)
54-
* - Termdebug does not work when Vim build with mzscheme. gdb hangs.
55-
* - After executing a shell command the status line isn't redraw.
56-
* - add test for giving error for invalid 'termsize' value.
57-
* - support minimal size when 'termsize' is "rows*cols".
58-
* - support minimal size when 'termsize' is empty?
5948
* - GUI: when using tabs, focus in terminal, click on tab does not work.
49+
* - Copy text in the vterm to the Vim buffer once in a while, so that
50+
* completion works.
6051
* - Redrawing is slow with Athena and Motif. Also other GUI? (Ramel Eshed)
6152
* - For the GUI fill termios with default values, perhaps like pangoterm:
6253
* http://bazaar.launchpad.net/~leonerd/pangoterm/trunk/view/head:/main.c#L134
6354
* - When 'encoding' is not utf-8, or the job is using another encoding, setup
6455
* conversions.
56+
* - Termdebug does not work when Vim build with mzscheme: gdb hangs just after
57+
* "run". Everything else works, including communication channel. Not
58+
* initializing mzscheme avoid the problem, thus it's not some #ifdef.
6559
*/
6660

6761
#include "vim.h"
@@ -133,9 +127,6 @@ struct terminal_S {
133127
/* last known vterm size */
134128
int tl_rows;
135129
int tl_cols;
136-
/* vterm size does not follow window size */
137-
int tl_rows_fixed;
138-
int tl_cols_fixed;
139130

140131
char_u *tl_title; /* NULL or allocated */
141132
char_u *tl_status_text; /* NULL or allocated */
@@ -207,9 +198,38 @@ static int desired_cursor_blink = -1;
207198
* 1. Generic code for all systems.
208199
*/
209200

201+
/*
202+
* Parse 'termsize' and set "rows" and "cols" for the terminal size in the
203+
* current window.
204+
* Sets "rows" and/or "cols" to zero when it should follow the window size.
205+
* Return TRUE if the size is the minimum size: "24*80".
206+
*/
207+
static int
208+
parse_termsize(win_T *wp, int *rows, int *cols)
209+
{
210+
int minsize = FALSE;
211+
212+
*rows = 0;
213+
*cols = 0;
214+
215+
if (*wp->w_p_tms != NUL)
216+
{
217+
char_u *p = vim_strchr(wp->w_p_tms, 'x');
218+
219+
/* Syntax of value was already checked when it's set. */
220+
if (p == NULL)
221+
{
222+
minsize = TRUE;
223+
p = vim_strchr(wp->w_p_tms, '*');
224+
}
225+
*rows = atoi((char *)wp->w_p_tms);
226+
*cols = atoi((char *)p + 1);
227+
}
228+
return minsize;
229+
}
230+
210231
/*
211232
* Determine the terminal size from 'termsize' and the current window.
212-
* Assumes term->tl_rows and term->tl_cols are zero.
213233
*/
214234
static void
215235
set_term_and_win_size(term_T *term)
@@ -224,27 +244,21 @@ set_term_and_win_size(term_T *term)
224244
return;
225245
}
226246
#endif
227-
if (*curwin->w_p_tms != NUL)
247+
if (parse_termsize(curwin, &term->tl_rows, &term->tl_cols))
228248
{
229-
char_u *p = vim_strchr(curwin->w_p_tms, 'x') + 1;
230-
231-
term->tl_rows = atoi((char *)curwin->w_p_tms);
232-
term->tl_cols = atoi((char *)p);
249+
if (term->tl_rows != 0)
250+
term->tl_rows = MAX(term->tl_rows, curwin->w_height);
251+
if (term->tl_cols != 0)
252+
term->tl_cols = MAX(term->tl_cols, curwin->w_width);
233253
}
234254
if (term->tl_rows == 0)
235255
term->tl_rows = curwin->w_height;
236256
else
237-
{
238257
win_setheight_win(term->tl_rows, curwin);
239-
term->tl_rows_fixed = TRUE;
240-
}
241258
if (term->tl_cols == 0)
242259
term->tl_cols = curwin->w_width;
243260
else
244-
{
245261
win_setwidth_win(term->tl_cols, curwin);
246-
term->tl_cols_fixed = TRUE;
247-
}
248262
}
249263

250264
/*
@@ -2853,6 +2867,10 @@ term_update_window(win_T *wp)
28532867
VTermScreen *screen;
28542868
VTermState *state;
28552869
VTermPos pos;
2870+
int rows, cols;
2871+
int newrows, newcols;
2872+
int minsize;
2873+
win_T *twp;
28562874

28572875
if (term == NULL || term->tl_vterm == NULL || term->tl_normal_mode)
28582876
return FAIL;
@@ -2871,31 +2889,32 @@ term_update_window(win_T *wp)
28712889
* If the window was resized a redraw will be triggered and we get here.
28722890
* Adjust the size of the vterm unless 'termsize' specifies a fixed size.
28732891
*/
2874-
if ((!term->tl_rows_fixed && term->tl_rows != wp->w_height)
2875-
|| (!term->tl_cols_fixed && term->tl_cols != wp->w_width))
2876-
{
2877-
int rows = term->tl_rows_fixed ? term->tl_rows : wp->w_height;
2878-
int cols = term->tl_cols_fixed ? term->tl_cols : wp->w_width;
2879-
win_T *twp;
2892+
minsize = parse_termsize(wp, &rows, &cols);
28802893

2881-
FOR_ALL_WINDOWS(twp)
2894+
newrows = 99999;
2895+
newcols = 99999;
2896+
FOR_ALL_WINDOWS(twp)
2897+
{
2898+
/* When more than one window shows the same terminal, use the
2899+
* smallest size. */
2900+
if (twp->w_buffer == term->tl_buffer)
28822901
{
2883-
/* When more than one window shows the same terminal, use the
2884-
* smallest size. */
2885-
if (twp->w_buffer == term->tl_buffer)
2886-
{
2887-
if (!term->tl_rows_fixed && rows > twp->w_height)
2888-
rows = twp->w_height;
2889-
if (!term->tl_cols_fixed && cols > twp->w_width)
2890-
cols = twp->w_width;
2891-
}
2902+
newrows = MIN(newrows, twp->w_height);
2903+
newcols = MIN(newcols, twp->w_width);
28922904
}
2905+
}
2906+
newrows = rows == 0 ? newrows : minsize ? MAX(rows, newrows) : rows;
2907+
newcols = cols == 0 ? newcols : minsize ? MAX(cols, newcols) : cols;
2908+
2909+
if (term->tl_rows != newrows || term->tl_cols != newcols)
2910+
{
2911+
28932912

28942913
term->tl_vterm_size_changed = TRUE;
2895-
vterm_set_size(vterm, rows, cols);
2914+
vterm_set_size(vterm, newrows, newcols);
28962915
ch_log(term->tl_job->jv_channel, "Resizing terminal to %d lines",
2897-
rows);
2898-
term_report_winsize(term, rows, cols);
2916+
newrows);
2917+
term_report_winsize(term, newrows, newcols);
28992918
}
29002919

29012920
/* The cursor may have been moved when resizing. */

src/testdir/test_terminal.vim

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1357,7 +1357,7 @@ func Test_terminal_ansicolors_func()
13571357
exe buf . 'bwipe'
13581358
endfunc
13591359

1360-
func Test_terminal_termsize_option()
1360+
func Test_terminal_termsize_option_fixed()
13611361
if !CanRunVimInTerminal()
13621362
return
13631363
endif
@@ -1389,3 +1389,69 @@ func Test_terminal_termsize_option()
13891389

13901390
set termsize=
13911391
endfunc
1392+
1393+
func Test_terminal_termsize_option_zero()
1394+
set termsize=0x0
1395+
let buf = Run_shell_in_terminal({})
1396+
let win = bufwinid(buf)
1397+
call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
1398+
call Stop_shell_in_terminal(buf)
1399+
call term_wait(buf)
1400+
exe buf . 'bwipe'
1401+
1402+
set termsize=7x0
1403+
let buf = Run_shell_in_terminal({})
1404+
let win = bufwinid(buf)
1405+
call assert_equal([7, winwidth(win)], term_getsize(buf))
1406+
call Stop_shell_in_terminal(buf)
1407+
call term_wait(buf)
1408+
exe buf . 'bwipe'
1409+
1410+
set termsize=0x33
1411+
let buf = Run_shell_in_terminal({})
1412+
let win = bufwinid(buf)
1413+
call assert_equal([winheight(win), 33], term_getsize(buf))
1414+
call Stop_shell_in_terminal(buf)
1415+
call term_wait(buf)
1416+
exe buf . 'bwipe'
1417+
1418+
set termsize=
1419+
endfunc
1420+
1421+
func Test_terminal_termsize_mininmum()
1422+
set termsize=10*50
1423+
vsplit
1424+
let buf = Run_shell_in_terminal({})
1425+
let win = bufwinid(buf)
1426+
call assert_inrange(10, 1000, winheight(win))
1427+
call assert_inrange(50, 1000, winwidth(win))
1428+
call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
1429+
1430+
resize 15
1431+
vertical resize 60
1432+
redraw
1433+
call assert_equal([15, 60], term_getsize(buf))
1434+
call assert_equal(15, winheight(win))
1435+
call assert_equal(60, winwidth(win))
1436+
1437+
resize 7
1438+
vertical resize 30
1439+
redraw
1440+
call assert_equal([10, 50], term_getsize(buf))
1441+
call assert_equal(7, winheight(win))
1442+
call assert_equal(30, winwidth(win))
1443+
1444+
call Stop_shell_in_terminal(buf)
1445+
call term_wait(buf)
1446+
exe buf . 'bwipe'
1447+
1448+
set termsize=0*0
1449+
let buf = Run_shell_in_terminal({})
1450+
let win = bufwinid(buf)
1451+
call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
1452+
call Stop_shell_in_terminal(buf)
1453+
call term_wait(buf)
1454+
exe buf . 'bwipe'
1455+
1456+
set termsize=
1457+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,8 @@ static char *(features[]) =
762762

763763
static int included_patches[] =
764764
{ /* Add new patch number below this line */
765+
/**/
766+
1722,
765767
/**/
766768
1721,
767769
/**/

0 commit comments

Comments
 (0)