1" Tests for window cmd (:wincmd, :split, :vsplit, :resize and etc...)
2
3source check.vim
4
5func Test_window_cmd_ls0_with_split()
6  set ls=0
7  set splitbelow
8  split
9  quit
10  call assert_equal(0, &lines - &cmdheight - winheight(0))
11  new | only!
12  "
13  set splitbelow&vim
14  botright split
15  quit
16  call assert_equal(0, &lines - &cmdheight - winheight(0))
17  new | only!
18  set ls&vim
19endfunc
20
21func Test_window_cmd_cmdwin_with_vsp()
22  CheckFeature cmdwin
23
24  let efmt = 'Expected 0 but got %d (in ls=%d, %s window)'
25  for v in range(0, 2)
26    exec "set ls=" . v
27    vsplit
28    call feedkeys("q:\<CR>")
29    let ac = &lines - (&cmdheight + winheight(0) + !!v)
30    let emsg = printf(efmt, ac, v, 'left')
31    call assert_equal(0, ac, emsg)
32    wincmd w
33    let ac = &lines - (&cmdheight + winheight(0) + !!v)
34    let emsg = printf(efmt, ac, v, 'right')
35    call assert_equal(0, ac, emsg)
36    new | only!
37  endfor
38  set ls&vim
39endfunc
40
41" Test for jumping to windows
42func Test_window_jump()
43  new
44  " jumping to a window with a count greater than the max windows
45  exe "normal 4\<C-W>w"
46  call assert_equal(2, winnr())
47  only
48endfunc
49
50func Test_window_cmd_wincmd_gf()
51  let fname = 'test_gf.txt'
52  let swp_fname = '.' . fname . '.swp'
53  call writefile([], fname)
54  call writefile([], swp_fname)
55  function s:swap_exists()
56    let v:swapchoice = s:swap_choice
57  endfunc
58  " Remove the catch-all that runtest.vim adds
59  au! SwapExists
60  augroup test_window_cmd_wincmd_gf
61    autocmd!
62    exec "autocmd SwapExists " . fname . " call s:swap_exists()"
63  augroup END
64
65  call setline(1, fname)
66  " (E)dit anyway
67  let s:swap_choice = 'e'
68  wincmd gf
69  call assert_equal(2, tabpagenr())
70  call assert_equal(fname, bufname("%"))
71  quit!
72
73  " (Q)uit
74  let s:swap_choice = 'q'
75  wincmd gf
76  call assert_equal(1, tabpagenr())
77  call assert_notequal(fname, bufname("%"))
78  new | only!
79
80  call delete(fname)
81  call delete(swp_fname)
82  augroup! test_window_cmd_wincmd_gf
83endfunc
84
85func Test_window_quit()
86  e Xa
87  split Xb
88  call assert_equal(2, '$'->winnr())
89  call assert_equal('Xb', bufname(winbufnr(1)))
90  call assert_equal('Xa', bufname(winbufnr(2)))
91
92  wincmd q
93  call assert_equal(1, winnr('$'))
94  call assert_equal('Xa', bufname(winbufnr(1)))
95
96  bw Xa Xb
97endfunc
98
99func Test_window_horizontal_split()
100  call assert_equal(1, winnr('$'))
101  3wincmd s
102  call assert_equal(2, winnr('$'))
103  call assert_equal(3, winheight(0))
104  call assert_equal(winwidth(1), 2->winwidth())
105
106  call assert_fails('botright topleft wincmd s', 'E442:')
107  bw
108endfunc
109
110func Test_window_vertical_split()
111  call assert_equal(1, winnr('$'))
112  3wincmd v
113  call assert_equal(2, winnr('$'))
114  call assert_equal(3, winwidth(0))
115  call assert_equal(winheight(1), winheight(2))
116
117  call assert_fails('botright topleft wincmd v', 'E442:')
118  bw
119endfunc
120
121" Test the ":wincmd ^" and "<C-W>^" commands.
122func Test_window_split_edit_alternate()
123
124  " Test for failure when the alternate buffer/file no longer exists.
125  edit Xfoo | %bw
126  call assert_fails(':wincmd ^', 'E23:')
127
128  " Test for the expected behavior when we have two named buffers.
129  edit Xfoo | edit Xbar
130  wincmd ^
131  call assert_equal('Xfoo', bufname(winbufnr(1)))
132  call assert_equal('Xbar', bufname(winbufnr(2)))
133  only
134
135  " Test for the expected behavior when the alternate buffer is not named.
136  enew | let l:nr1 = bufnr('%')
137  edit Xfoo | let l:nr2 = bufnr('%')
138  wincmd ^
139  call assert_equal(l:nr1, winbufnr(1))
140  call assert_equal(l:nr2, winbufnr(2))
141  only
142
143  " FIXME: this currently fails on AppVeyor, but passes locally
144  if !has('win32')
145    " Test the Normal mode command.
146    call feedkeys("\<C-W>\<C-^>", 'tx')
147    call assert_equal(l:nr2, winbufnr(1))
148    call assert_equal(l:nr1, winbufnr(2))
149  endif
150
151  %bw!
152endfunc
153
154" Test the ":[count]wincmd ^" and "[count]<C-W>^" commands.
155func Test_window_split_edit_bufnr()
156
157  %bwipeout
158  let l:nr = bufnr('%') + 1
159  call assert_fails(':execute "normal! ' . l:nr . '\<C-W>\<C-^>"', 'E92:')
160  call assert_fails(':' . l:nr . 'wincmd ^', 'E16:')
161  call assert_fails(':0wincmd ^', 'E16:')
162
163  edit Xfoo | edit Xbar | edit Xbaz
164  let l:foo_nr = bufnr('Xfoo')
165  let l:bar_nr = bufnr('Xbar')
166  let l:baz_nr = bufnr('Xbaz')
167
168  " FIXME: this currently fails on AppVeyor, but passes locally
169  if !has('win32')
170    call feedkeys(l:foo_nr . "\<C-W>\<C-^>", 'tx')
171    call assert_equal('Xfoo', bufname(winbufnr(1)))
172    call assert_equal('Xbaz', bufname(winbufnr(2)))
173    only
174
175    call feedkeys(l:bar_nr . "\<C-W>\<C-^>", 'tx')
176    call assert_equal('Xbar', bufname(winbufnr(1)))
177    call assert_equal('Xfoo', bufname(winbufnr(2)))
178    only
179
180    execute l:baz_nr . 'wincmd ^'
181    call assert_equal('Xbaz', bufname(winbufnr(1)))
182    call assert_equal('Xbar', bufname(winbufnr(2)))
183  endif
184
185  %bw!
186endfunc
187
188func Test_window_split_no_room()
189  " N horizontal windows need >= 2*N + 1 lines:
190  " - 1 line + 1 status line in each window
191  " - 1 Ex command line
192  "
193  " 2*N + 1 <= &lines
194  " N <= (lines - 1)/2
195  "
196  " Beyond that number of windows, E36: Not enough room is expected.
197  let hor_win_count = (&lines - 1)/2
198  let hor_split_count = hor_win_count - 1
199  for s in range(1, hor_split_count) | split | endfor
200  call assert_fails('split', 'E36:')
201
202  " N vertical windows need >= 2*(N - 1) + 1 columns:
203  " - 1 column + 1 separator for each window (except last window)
204  " - 1 column for the last window which does not have separator
205  "
206  " 2*(N - 1) + 1 <= &columns
207  " 2*N - 1 <= &columns
208  " N <= (&columns + 1)/2
209  let ver_win_count = (&columns + 1)/2
210  let ver_split_count = ver_win_count - 1
211  for s in range(1, ver_split_count) | vsplit | endfor
212  call assert_fails('vsplit', 'E36:')
213
214  %bw!
215endfunc
216
217func Test_window_exchange()
218  e Xa
219
220  " Nothing happens with window exchange when there is 1 window
221  wincmd x
222  call assert_equal(1, winnr('$'))
223
224  split Xb
225  split Xc
226
227  call assert_equal('Xc', bufname(winbufnr(1)))
228  call assert_equal('Xb', bufname(winbufnr(2)))
229  call assert_equal('Xa', bufname(winbufnr(3)))
230
231  " Exchange current window 1 with window 3
232  3wincmd x
233  call assert_equal('Xa', bufname(winbufnr(1)))
234  call assert_equal('Xb', bufname(winbufnr(2)))
235  call assert_equal('Xc', bufname(winbufnr(3)))
236
237  " Exchange window with next when at the top window
238  wincmd x
239  call assert_equal('Xb', bufname(winbufnr(1)))
240  call assert_equal('Xa', bufname(winbufnr(2)))
241  call assert_equal('Xc', bufname(winbufnr(3)))
242
243  " Exchange window with next when at the middle window
244  wincmd j
245  wincmd x
246  call assert_equal('Xb', bufname(winbufnr(1)))
247  call assert_equal('Xc', bufname(winbufnr(2)))
248  call assert_equal('Xa', bufname(winbufnr(3)))
249
250  " Exchange window with next when at the bottom window.
251  " When there is no next window, it exchanges with the previous window.
252  wincmd j
253  wincmd x
254  call assert_equal('Xb', bufname(winbufnr(1)))
255  call assert_equal('Xa', bufname(winbufnr(2)))
256  call assert_equal('Xc', bufname(winbufnr(3)))
257
258  bw Xa Xb Xc
259endfunc
260
261func Test_window_rotate()
262  e Xa
263  split Xb
264  split Xc
265  call assert_equal('Xc', bufname(winbufnr(1)))
266  call assert_equal('Xb', bufname(winbufnr(2)))
267  call assert_equal('Xa', bufname(winbufnr(3)))
268
269  " Rotate downwards
270  wincmd r
271  call assert_equal('Xa', bufname(winbufnr(1)))
272  call assert_equal('Xc', bufname(winbufnr(2)))
273  call assert_equal('Xb', bufname(winbufnr(3)))
274
275  2wincmd r
276  call assert_equal('Xc', bufname(winbufnr(1)))
277  call assert_equal('Xb', bufname(winbufnr(2)))
278  call assert_equal('Xa', bufname(winbufnr(3)))
279
280  " Rotate upwards
281  wincmd R
282  call assert_equal('Xb', bufname(winbufnr(1)))
283  call assert_equal('Xa', bufname(winbufnr(2)))
284  call assert_equal('Xc', bufname(winbufnr(3)))
285
286  2wincmd R
287  call assert_equal('Xc', bufname(winbufnr(1)))
288  call assert_equal('Xb', bufname(winbufnr(2)))
289  call assert_equal('Xa', bufname(winbufnr(3)))
290
291  bot vsplit
292  call assert_fails('wincmd R', 'E443:')
293
294  bw Xa Xb Xc
295endfunc
296
297func Test_window_height()
298  e Xa
299  split Xb
300
301  let [wh1, wh2] = [winheight(1), winheight(2)]
302  " Active window (1) should have the same height or 1 more
303  " than the other window.
304  call assert_inrange(wh2, wh2 + 1, wh1)
305
306  wincmd -
307  call assert_equal(wh1 - 1, winheight(1))
308  call assert_equal(wh2 + 1, winheight(2))
309
310  wincmd +
311  call assert_equal(wh1, winheight(1))
312  call assert_equal(wh2, 2->winheight())
313
314  2wincmd _
315  call assert_equal(2, winheight(1))
316  call assert_equal(wh1 + wh2 - 2, winheight(2))
317
318  wincmd =
319  call assert_equal(wh1, winheight(1))
320  call assert_equal(wh2, winheight(2))
321
322  2wincmd _
323  set winfixheight
324  split Xc
325  let [wh1, wh2, wh3] = [winheight(1), winheight(2), winheight(3)]
326  call assert_equal(2, winheight(2))
327  call assert_inrange(wh3, wh3 + 1, wh1)
328  3wincmd +
329  call assert_equal(2,       winheight(2))
330  call assert_equal(wh1 + 3, winheight(1))
331  call assert_equal(wh3 - 3, winheight(3))
332  wincmd =
333  call assert_equal(2,   winheight(2))
334  call assert_equal(wh1, winheight(1))
335  call assert_equal(wh3, winheight(3))
336
337  wincmd j
338  set winfixheight&
339
340  wincmd =
341  let [wh1, wh2, wh3] = [winheight(1), winheight(2), winheight(3)]
342  " Current window (2) should have the same height or 1 more
343  " than the other windows.
344  call assert_inrange(wh1, wh1 + 1, wh2)
345  call assert_inrange(wh3, wh3 + 1, wh2)
346
347  bw Xa Xb Xc
348endfunc
349
350func Test_window_width()
351  e Xa
352  vsplit Xb
353
354  let [ww1, ww2] = [winwidth(1), winwidth(2)]
355  " Active window (1) should have the same width or 1 more
356  " than the other window.
357  call assert_inrange(ww2, ww2 + 1, ww1)
358
359  wincmd <
360  call assert_equal(ww1 - 1, winwidth(1))
361  call assert_equal(ww2 + 1, winwidth(2))
362
363  wincmd >
364  call assert_equal(ww1, winwidth(1))
365  call assert_equal(ww2, winwidth(2))
366
367  2wincmd |
368  call assert_equal(2, winwidth(1))
369  call assert_equal(ww1 + ww2 - 2, winwidth(2))
370
371  wincmd =
372  call assert_equal(ww1, winwidth(1))
373  call assert_equal(ww2, winwidth(2))
374
375  2wincmd |
376  set winfixwidth
377  vsplit Xc
378  let [ww1, ww2, ww3] = [winwidth(1), winwidth(2), winwidth(3)]
379  call assert_equal(2, winwidth(2))
380  call assert_inrange(ww3, ww3 + 1, ww1)
381  3wincmd >
382  call assert_equal(2,       winwidth(2))
383  call assert_equal(ww1 + 3, winwidth(1))
384  call assert_equal(ww3 - 3, winwidth(3))
385  wincmd =
386  call assert_equal(2,   winwidth(2))
387  call assert_equal(ww1, winwidth(1))
388  call assert_equal(ww3, winwidth(3))
389
390  wincmd l
391  set winfixwidth&
392
393  wincmd =
394  let [ww1, ww2, ww3] = [winwidth(1), winwidth(2), winwidth(3)]
395  " Current window (2) should have the same width or 1 more
396  " than the other windows.
397  call assert_inrange(ww1, ww1 + 1, ww2)
398  call assert_inrange(ww3, ww3 + 1, ww2)
399
400  bw Xa Xb Xc
401endfunc
402
403func Test_equalalways_on_close()
404  set equalalways
405  vsplit
406  windo split
407  split
408  wincmd J
409  " now we have a frame top-left with two windows, a frame top-right with two
410  " windows and a frame at the bottom, full-width.
411  let height_1 = winheight(1)
412  let height_2 = winheight(2)
413  let height_3 = winheight(3)
414  let height_4 = winheight(4)
415  " closing the bottom window causes all windows to be resized.
416  close
417  call assert_notequal(height_1, winheight(1))
418  call assert_notequal(height_2, winheight(2))
419  call assert_notequal(height_3, winheight(3))
420  call assert_notequal(height_4, winheight(4))
421  call assert_equal(winheight(1), winheight(3))
422  call assert_equal(winheight(2), winheight(4))
423
424  1wincmd w
425  split
426  4wincmd w
427  resize + 5
428  " left column has three windows, equalized heights.
429  " right column has two windows, top one a bit higher
430  let height_1 = winheight(1)
431  let height_2 = winheight(2)
432  let height_4 = winheight(4)
433  let height_5 = winheight(5)
434  3wincmd w
435  " closing window in left column equalizes heights in left column but not in
436  " the right column
437  close
438  call assert_notequal(height_1, winheight(1))
439  call assert_notequal(height_2, winheight(2))
440  call assert_equal(height_4, winheight(3))
441  call assert_equal(height_5, winheight(4))
442
443  only
444  set equalalways&
445endfunc
446
447func Test_win_screenpos()
448  CheckFeature quickfix
449
450  call assert_equal(1, winnr('$'))
451  split
452  vsplit
453  10wincmd _
454  30wincmd |
455  call assert_equal([1, 1], win_screenpos(1))
456  call assert_equal([1, 32], win_screenpos(2))
457  call assert_equal([12, 1], win_screenpos(3))
458  call assert_equal([0, 0], win_screenpos(4))
459  call assert_fails('let l = win_screenpos([])', 'E745:')
460  only
461endfunc
462
463func Test_window_jump_tag()
464  CheckFeature quickfix
465
466  help
467  /iccf
468  call assert_match('^|iccf|',  getline('.'))
469  call assert_equal(2, winnr('$'))
470  2wincmd }
471  call assert_equal(3, winnr('$'))
472  call assert_match('^|iccf|',  getline('.'))
473  wincmd k
474  call assert_match('\*iccf\*',  getline('.'))
475  call assert_equal(2, winheight(0))
476
477  wincmd z
478  set previewheight=4
479  help
480  /bugs
481  wincmd }
482  wincmd k
483  call assert_match('\*bugs\*',  getline('.'))
484  call assert_equal(4, winheight(0))
485  set previewheight&
486
487  %bw!
488endfunc
489
490func Test_window_newtab()
491  e Xa
492
493  call assert_equal(1, tabpagenr('$'))
494  call assert_equal("\nAlready only one window", execute('wincmd T'))
495
496  split Xb
497  split Xc
498
499  wincmd T
500  call assert_equal(2, tabpagenr('$'))
501  call assert_equal(['Xb', 'Xa'], map(tabpagebuflist(1), 'bufname(v:val)'))
502  call assert_equal(['Xc'      ], map(2->tabpagebuflist(), 'bufname(v:val)'))
503  call assert_equal(['Xc'      ], map(tabpagebuflist(), 'bufname(v:val)'))
504
505  %bw!
506endfunc
507
508func Test_next_split_all()
509  " This was causing an illegal memory access.
510  n x
511  norm axxx
512  split
513  split
514  s/x
515  s/x
516  all
517  bwipe!
518endfunc
519
520" Tests for adjusting window and contents
521func GetScreenStr(row)
522   let str = ""
523   for c in range(1,3)
524       let str .= nr2char(screenchar(a:row, c))
525   endfor
526   return str
527endfunc
528
529func Test_window_contents()
530  enew! | only | new
531  call setline(1, range(1,256))
532
533  exe "norm! \<C-W>t\<C-W>=1Gzt\<C-W>w\<C-W>+"
534  redraw
535  let s3 = GetScreenStr(1)
536  wincmd p
537  call assert_equal(1, line("w0"))
538  call assert_equal('1  ', s3)
539
540  exe "norm! \<C-W>t\<C-W>=50Gzt\<C-W>w\<C-W>+"
541  redraw
542  let s3 = GetScreenStr(1)
543  wincmd p
544  call assert_equal(50, line("w0"))
545  call assert_equal('50 ', s3)
546
547  exe "norm! \<C-W>t\<C-W>=59Gzt\<C-W>w\<C-W>+"
548  redraw
549  let s3 = GetScreenStr(1)
550  wincmd p
551  call assert_equal(59, line("w0"))
552  call assert_equal('59 ', s3)
553
554  %d
555  call setline(1, ['one', 'two', 'three'])
556  call assert_equal(1, line('w0'))
557  call assert_equal(3, line('w$'))
558
559  bwipeout!
560  call test_garbagecollect_now()
561endfunc
562
563func Test_window_colon_command()
564  " This was reading invalid memory.
565  exe "norm! v\<C-W>:\<C-U>echo v:version"
566endfunc
567
568func Test_access_freed_mem()
569  call assert_equal(&columns, winwidth(0))
570  " This was accessing freed memory (but with what events?)
571  au BufEnter,BufLeave,WinEnter,WinLeave 0 vs xxx
572  arg 0
573  argadd
574  call assert_fails("all", "E242:")
575  au!
576  bwipe xxx
577  call assert_equal(&columns, winwidth(0))
578endfunc
579
580func Test_insert_cleared_on_switch_to_term()
581  CheckFeature terminal
582
583  set showmode
584  terminal
585  wincmd p
586
587  call feedkeys("i\<C-O>", 'ntx')
588  redraw
589
590  " The "-- (insert) --" indicator should be visible.
591  let chars = map(range(1, &columns), 'nr2char(screenchar(&lines, v:val))')
592  let str = trim(join(chars, ''))
593  call assert_equal('-- (insert) --', str)
594
595  call feedkeys("\<C-W>p", 'ntx')
596  redraw
597
598  " The "-- (insert) --" indicator should have been cleared.
599  let chars = map(range(1, &columns), 'nr2char(screenchar(&lines, v:val))')
600  let str = trim(join(chars, ''))
601  call assert_equal('', str)
602
603  set showmode&
604  %bw!
605endfunc
606
607func Test_visual_cleared_after_window_split()
608  new | only!
609  let smd_save = &showmode
610  set showmode
611  let ls_save = &laststatus
612  set laststatus=1
613  call setline(1, ['a', 'b', 'c', 'd', ''])
614  norm! G
615  exe "norm! kkvk"
616  redraw
617  exe "norm! \<C-W>v"
618  redraw
619  " check if '-- VISUAL --' disappeared from command line
620  let columns = range(1, &columns)
621  let cmdlinechars = map(columns, 'nr2char(screenchar(&lines, v:val))')
622  let cmdline = join(cmdlinechars, '')
623  let cmdline_ltrim = substitute(cmdline, '^\s*', "", "")
624  let mode_shown = substitute(cmdline_ltrim, '\s*$', "", "")
625  call assert_equal('', mode_shown)
626  let &showmode = smd_save
627  let &laststatus = ls_save
628  bwipe!
629endfunc
630
631func Test_winrestcmd()
632  2split
633  3vsplit
634  let restcmd = winrestcmd()
635  call assert_equal(2, winheight(0))
636  call assert_equal(3, winwidth(0))
637  wincmd =
638  call assert_notequal(2, winheight(0))
639  call assert_notequal(3, winwidth(0))
640  exe restcmd
641  call assert_equal(2, winheight(0))
642  call assert_equal(3, winwidth(0))
643  only
644
645  wincmd v
646  wincmd s
647  wincmd v
648  redraw
649  let restcmd = winrestcmd()
650  wincmd _
651  wincmd |
652  exe restcmd
653  redraw
654  call assert_equal(restcmd, winrestcmd())
655
656  only
657endfunc
658
659func Fun_RenewFile()
660  " Need to wait a bit for the timestamp to be older.
661  let old_ftime = getftime("tmp.txt")
662  while getftime("tmp.txt") == old_ftime
663    sleep 100m
664    silent execute '!echo "1" > tmp.txt'
665  endwhile
666  sp
667  wincmd p
668  edit! tmp.txt
669endfunc
670
671func Test_window_prevwin()
672  " Can we make this work on MS-Windows?
673  CheckUnix
674
675  set hidden autoread
676  call writefile(['2'], 'tmp.txt')
677  new tmp.txt
678  q
679  call Fun_RenewFile()
680  call assert_equal(2, winnr())
681  wincmd p
682  call assert_equal(1, winnr())
683  wincmd p
684  q
685  call Fun_RenewFile()
686  call assert_equal(2, winnr())
687  wincmd p
688  call assert_equal(1, winnr())
689  wincmd p
690  " reset
691  q
692  call delete('tmp.txt')
693  set hidden&vim autoread&vim
694  delfunc Fun_RenewFile
695endfunc
696
697func Test_relative_cursor_position_in_one_line_window()
698  new
699  only
700  call setline(1, range(1, 10000))
701  normal 50%
702  let lnum = getcurpos()[1]
703  split
704  split
705  " make third window take as many lines as possible, other windows will
706  " become one line
707  3wincmd w
708  for i in range(1, &lines - 6)
709    wincmd +
710    redraw!
711  endfor
712
713  " first and second window should show cursor line
714  let wininfo = getwininfo()
715  call assert_equal(lnum, wininfo[0].topline)
716  call assert_equal(lnum, wininfo[1].topline)
717
718  only!
719  bwipe!
720  call assert_fails('call winrestview(test_null_dict())', 'E474:')
721endfunc
722
723func Test_relative_cursor_position_after_move_and_resize()
724  let so_save = &so
725  set so=0
726  enew
727  call setline(1, range(1, 10000))
728  normal 50%
729  split
730  1wincmd w
731  " Move cursor to first line in window
732  normal H
733  redraw!
734  " Reduce window height to two lines
735  let height = winheight(0)
736  while winheight(0) > 2
737    wincmd -
738    redraw!
739  endwhile
740  " move cursor to second/last line in window
741  normal j
742  " restore previous height
743  while winheight(0) < height
744    wincmd +
745    redraw!
746  endwhile
747  " make window two lines again
748  while winheight(0) > 2
749    wincmd -
750    redraw!
751  endwhile
752
753  " cursor should be at bottom line
754  let info = getwininfo(win_getid())[0]
755  call assert_equal(info.topline + 1, getcurpos()[1])
756
757  only!
758  bwipe!
759  let &so = so_save
760endfunc
761
762func Test_relative_cursor_position_after_resize()
763  let so_save = &so
764  set so=0
765  enew
766  call setline(1, range(1, 10000))
767  normal 50%
768  split
769  1wincmd w
770  let winid1 = win_getid()
771  let info = getwininfo(winid1)[0]
772  " Move cursor to second line in window
773  exe "normal " . (info.topline + 1) . "G"
774  redraw!
775  let lnum = getcurpos()[1]
776
777  " Make the window only two lines high, cursor should end up in top line
778  2wincmd w
779  exe (info.height - 2) . "wincmd +"
780  redraw!
781  let info = getwininfo(winid1)[0]
782  call assert_equal(lnum, info.topline)
783
784  only!
785  bwipe!
786  let &so = so_save
787endfunc
788
789func Test_relative_cursor_second_line_after_resize()
790  let so_save = &so
791  set so=0
792  enew
793  call setline(1, range(1, 10000))
794  normal 50%
795  split
796  1wincmd w
797  let winid1 = win_getid()
798  let info = getwininfo(winid1)[0]
799
800  " Make the window only two lines high
801  2wincmd _
802
803  " Move cursor to second line in window
804  normal H
805  normal j
806
807  " Make window size bigger, then back to 2 lines
808  for i in range(1, 10)
809    wincmd +
810    redraw!
811  endfor
812  for i in range(1, 10)
813    wincmd -
814    redraw!
815  endfor
816
817  " cursor should end up in bottom line
818  let info = getwininfo(winid1)[0]
819  call assert_equal(info.topline + 1, getcurpos()[1])
820
821  only!
822  bwipe!
823  let &so = so_save
824endfunc
825
826func Test_split_noscroll()
827  let so_save = &so
828  enew
829  call setline(1, range(1, 8))
830  normal 100%
831  split
832
833  1wincmd w
834  let winid1 = win_getid()
835  let info1 = getwininfo(winid1)[0]
836
837  2wincmd w
838  let winid2 = win_getid()
839  let info2 = getwininfo(winid2)[0]
840
841  call assert_equal(1, info1.topline)
842  call assert_equal(1, info2.topline)
843
844  " window that fits all lines by itself, but not when split: closing other
845  " window should restore fraction.
846  only!
847  call setline(1, range(1, &lines - 10))
848  exe &lines / 4
849  let winid1 = win_getid()
850  let info1 = getwininfo(winid1)[0]
851  call assert_equal(1, info1.topline)
852  new
853  redraw
854  close
855  let info1 = getwininfo(winid1)[0]
856  call assert_equal(1, info1.topline)
857
858  bwipe!
859  let &so = so_save
860endfunc
861
862" Tests for the winnr() function
863func Test_winnr()
864  only | tabonly
865  call assert_equal(1, winnr('j'))
866  call assert_equal(1, winnr('k'))
867  call assert_equal(1, winnr('h'))
868  call assert_equal(1, winnr('l'))
869
870  " create a set of horizontally and vertically split windows
871  leftabove new | wincmd p
872  leftabove new | wincmd p
873  rightbelow new | wincmd p
874  rightbelow new | wincmd p
875  leftabove vnew | wincmd p
876  leftabove vnew | wincmd p
877  rightbelow vnew | wincmd p
878  rightbelow vnew | wincmd p
879
880  call assert_equal(8, winnr('j'))
881  call assert_equal(2, winnr('k'))
882  call assert_equal(4, winnr('h'))
883  call assert_equal(6, winnr('l'))
884  call assert_equal(9, winnr('2j'))
885  call assert_equal(1, winnr('2k'))
886  call assert_equal(3, winnr('2h'))
887  call assert_equal(7, winnr('2l'))
888
889  " Error cases
890  call assert_fails("echo winnr('0.2k')", 'E15:')
891  call assert_equal(2, winnr('-2k'))
892  call assert_fails("echo winnr('-2xj')", 'E15:')
893  call assert_fails("echo winnr('j2j')", 'E15:')
894  call assert_fails("echo winnr('ll')", 'E15:')
895  call assert_fails("echo winnr('5')", 'E15:')
896  call assert_equal(4, winnr('0h'))
897  call assert_fails("let w = winnr([])", 'E730:')
898  call assert_equal('unknown', win_gettype(-1))
899  call assert_equal(-1, winheight(-1))
900  call assert_equal(-1, winwidth(-1))
901
902  tabnew
903  call assert_equal(8, tabpagewinnr(1, 'j'))
904  call assert_equal(2, 1->tabpagewinnr('k'))
905  call assert_equal(4, tabpagewinnr(1, 'h'))
906  call assert_equal(6, tabpagewinnr(1, 'l'))
907
908  only | tabonly
909endfunc
910
911func Test_winrestview()
912  split runtest.vim
913  normal 50%
914  let view = winsaveview()
915  close
916  split runtest.vim
917  eval view->winrestview()
918  call assert_equal(view, winsaveview())
919
920  bwipe!
921  call assert_fails('call winrestview(test_null_dict())', 'E474:')
922endfunc
923
924func Test_win_splitmove()
925  CheckFeature quickfix
926
927  edit a
928  leftabove split b
929  leftabove vsplit c
930  leftabove split d
931  call assert_equal(0, win_splitmove(winnr(), winnr('l')))
932  call assert_equal(bufname(winbufnr(1)), 'c')
933  call assert_equal(bufname(winbufnr(2)), 'd')
934  call assert_equal(bufname(winbufnr(3)), 'b')
935  call assert_equal(bufname(winbufnr(4)), 'a')
936  call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'vertical': 1}))
937  call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'vertical': 1}))
938  call assert_equal(bufname(winbufnr(1)), 'c')
939  call assert_equal(bufname(winbufnr(2)), 'b')
940  call assert_equal(bufname(winbufnr(3)), 'd')
941  call assert_equal(bufname(winbufnr(4)), 'a')
942  call assert_equal(0, win_splitmove(winnr(), winnr('k'), {'vertical': 1}))
943  call assert_equal(bufname(winbufnr(1)), 'd')
944  call assert_equal(bufname(winbufnr(2)), 'c')
945  call assert_equal(bufname(winbufnr(3)), 'b')
946  call assert_equal(bufname(winbufnr(4)), 'a')
947  call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'rightbelow': v:true}))
948  call assert_equal(bufname(winbufnr(1)), 'c')
949  call assert_equal(bufname(winbufnr(2)), 'b')
950  call assert_equal(bufname(winbufnr(3)), 'a')
951  call assert_equal(bufname(winbufnr(4)), 'd')
952  call assert_fails('call win_splitmove(winnr(), winnr("k"), test_null_dict())', 'E474:')
953  only | bd
954
955  call assert_fails('call win_splitmove(winnr(), 123)', 'E957:')
956  call assert_fails('call win_splitmove(123, winnr())', 'E957:')
957  call assert_fails('call win_splitmove(winnr(), winnr())', 'E957:')
958
959  tabnew
960  call assert_fails('call win_splitmove(1, win_getid(1, 1))', 'E957:')
961  tabclose
962endfunc
963
964" Test for the :only command
965func Test_window_only()
966  new
967  set modified
968  new
969  call assert_fails('only', 'E445:')
970  only!
971  " Test for :only with a count
972  let wid = win_getid()
973  new
974  new
975  3only
976  call assert_equal(1, winnr('$'))
977  call assert_equal(wid, win_getid())
978  call assert_fails('close', 'E444:')
979  call assert_fails('%close', 'E16:')
980endfunc
981
982" Test for errors with :wincmd
983func Test_wincmd_errors()
984  call assert_fails('wincmd g', 'E474:')
985  call assert_fails('wincmd ab', 'E474:')
986endfunc
987
988" Test for errors with :winpos
989func Test_winpos_errors()
990  if !has("gui_running") && !has('win32')
991    call assert_fails('winpos', 'E188:')
992  endif
993  call assert_fails('winpos 10', 'E466:')
994endfunc
995
996" Test for +cmd in a :split command
997func Test_split_cmd()
998  split +set\ readonly
999  call assert_equal(1, &readonly)
1000  call assert_equal(2, winnr('$'))
1001  close
1002endfunc
1003
1004" Create maximum number of horizontally or vertically split windows and then
1005" run commands that create a new horizontally/vertically split window
1006func Run_noroom_for_newwindow_test(dir_arg)
1007  let dir = (a:dir_arg == 'v') ? 'vert ' : ''
1008
1009  " Open as many windows as possible
1010  while v:true
1011    try
1012      exe dir . 'new'
1013    catch /E36:/
1014      break
1015    endtry
1016  endwhile
1017
1018  call writefile(['first', 'second', 'third'], 'Xfile1')
1019  call writefile([], 'Xfile2')
1020  call writefile([], 'Xfile3')
1021
1022  " Argument list related commands
1023  args Xfile1 Xfile2 Xfile3
1024  next
1025  for cmd in ['sargument 2', 'snext', 'sprevious', 'sNext', 'srewind',
1026			\ 'sfirst', 'slast']
1027    call assert_fails(dir .. cmd, 'E36:')
1028  endfor
1029  %argdelete
1030
1031  " Buffer related commands
1032  set modified
1033  hide enew
1034  for cmd in ['sbuffer Xfile1', 'sbnext', 'sbprevious', 'sbNext', 'sbrewind',
1035		\ 'sbfirst', 'sblast', 'sball', 'sbmodified', 'sunhide']
1036    call assert_fails(dir .. cmd, 'E36:')
1037  endfor
1038
1039  " Window related commands
1040  for cmd in ['split', 'split Xfile2', 'new', 'new Xfile3', 'sview Xfile1',
1041		\ 'sfind runtest.vim']
1042    call assert_fails(dir .. cmd, 'E36:')
1043  endfor
1044
1045  " Help
1046  call assert_fails(dir .. 'help', 'E36:')
1047  call assert_fails(dir .. 'helpgrep window', 'E36:')
1048
1049  " Command-line window
1050  if a:dir_arg == 'h'
1051    " Cmd-line window is always a horizontally split window
1052    call assert_beeps('call feedkeys("q:\<CR>", "xt")')
1053  endif
1054
1055  " Quickfix and location list window
1056  if has('quickfix')
1057    cexpr ''
1058    call assert_fails(dir .. 'copen', 'E36:')
1059    lexpr ''
1060    call assert_fails(dir .. 'lopen', 'E36:')
1061
1062    " Preview window
1063    call assert_fails(dir .. 'pedit Xfile2', 'E36:')
1064    call setline(1, 'abc')
1065    call assert_fails(dir .. 'psearch abc', 'E36:')
1066  endif
1067
1068  " Window commands (CTRL-W ^ and CTRL-W f)
1069  if a:dir_arg == 'h'
1070    call assert_fails('call feedkeys("\<C-W>^", "xt")', 'E36:')
1071    call setline(1, 'Xfile1')
1072    call assert_fails('call feedkeys("gg\<C-W>f", "xt")', 'E36:')
1073  endif
1074  enew!
1075
1076  " Tag commands (:stag, :stselect and :stjump)
1077  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
1078        \ "second\tXfile1\t2",
1079        \ "third\tXfile1\t3",],
1080        \ 'Xtags')
1081  set tags=Xtags
1082  call assert_fails(dir .. 'stag second', 'E36:')
1083  call assert_fails('call feedkeys(":" .. dir .. "stselect second\n1\n", "xt")', 'E36:')
1084  call assert_fails(dir .. 'stjump second', 'E36:')
1085  call assert_fails(dir .. 'ptag second', 'E36:')
1086  set tags&
1087  call delete('Xtags')
1088
1089  " :isplit and :dsplit
1090  call setline(1, ['#define FOO 1', 'FOO'])
1091  normal 2G
1092  call assert_fails(dir .. 'isplit FOO', 'E36:')
1093  call assert_fails(dir .. 'dsplit FOO', 'E36:')
1094
1095  " terminal
1096  if has('terminal')
1097    call assert_fails(dir .. 'terminal', 'E36:')
1098  endif
1099
1100  %bwipe!
1101  call delete('Xfile1')
1102  call delete('Xfile2')
1103  call delete('Xfile3')
1104  only
1105endfunc
1106
1107func Test_split_cmds_with_no_room()
1108  call Run_noroom_for_newwindow_test('h')
1109  call Run_noroom_for_newwindow_test('v')
1110endfunc
1111
1112" Test for various wincmd failures
1113func Test_wincmd_fails()
1114  only!
1115  call assert_beeps("normal \<C-W>w")
1116  call assert_beeps("normal \<C-W>p")
1117  call assert_beeps("normal \<C-W>gk")
1118  call assert_beeps("normal \<C-W>r")
1119  call assert_beeps("normal \<C-W>K")
1120  call assert_beeps("normal \<C-W>H")
1121  call assert_beeps("normal \<C-W>2gt")
1122endfunc
1123
1124func Test_window_resize()
1125  " Vertical :resize (absolute, relative, min and max size).
1126  vsplit
1127  vert resize 8
1128  call assert_equal(8, winwidth(0))
1129  vert resize +2
1130  call assert_equal(10, winwidth(0))
1131  vert resize -2
1132  call assert_equal(8, winwidth(0))
1133  vert resize
1134  call assert_equal(&columns - 2, winwidth(0))
1135  vert resize 0
1136  call assert_equal(1, winwidth(0))
1137  vert resize 99999
1138  call assert_equal(&columns - 2, winwidth(0))
1139
1140  %bwipe!
1141
1142  " Horizontal :resize (with absolute, relative size, min and max size).
1143  split
1144  resize 8
1145  call assert_equal(8, winheight(0))
1146  resize +2
1147  call assert_equal(10, winheight(0))
1148  resize -2
1149  call assert_equal(8, winheight(0))
1150  resize
1151  call assert_equal(&lines - 4, winheight(0))
1152  resize 0
1153  call assert_equal(1, winheight(0))
1154  resize 99999
1155  call assert_equal(&lines - 4, winheight(0))
1156
1157  " :resize with explicit window number.
1158  let other_winnr = winnr('j')
1159  exe other_winnr .. 'resize 10'
1160  call assert_equal(10, winheight(other_winnr))
1161  call assert_equal(&lines - 10 - 3, winheight(0))
1162  exe other_winnr .. 'resize +1'
1163  exe other_winnr .. 'resize +1'
1164  call assert_equal(12, winheight(other_winnr))
1165  call assert_equal(&lines - 10 - 3 -2, winheight(0))
1166  close
1167
1168  vsplit
1169  wincmd l
1170  let other_winnr = winnr('h')
1171  call assert_notequal(winnr(), other_winnr)
1172  exe 'vert ' .. other_winnr .. 'resize -' .. &columns
1173  call assert_equal(0, winwidth(other_winnr))
1174
1175  %bwipe!
1176endfunc
1177
1178" Test for adjusting the window width when a window is closed with some
1179" windows using 'winfixwidth'
1180func Test_window_width_adjust()
1181  only
1182  " Three vertical windows. Windows 1 and 2 have 'winfixwidth' set and close
1183  " window 2.
1184  wincmd v
1185  vert resize 10
1186  set winfixwidth
1187  wincmd v
1188  set winfixwidth
1189  wincmd c
1190  call assert_inrange(10, 12, winwidth(1))
1191  " Three vertical windows. Windows 2 and 3 have 'winfixwidth' set and close
1192  " window 3.
1193  only
1194  set winfixwidth
1195  wincmd v
1196  vert resize 10
1197  set winfixwidth
1198  wincmd v
1199  set nowinfixwidth
1200  wincmd b
1201  wincmd c
1202  call assert_inrange(10, 12, winwidth(2))
1203
1204  new | only
1205endfunc
1206
1207" Test for jumping to a vertical/horizontal neighbor window based on the
1208" current cursor position
1209func Test_window_goto_neightbor()
1210  %bw!
1211
1212  " Vertical window movement
1213
1214  " create the following window layout:
1215  "     +--+--+
1216  "     |w1|w3|
1217  "     +--+  |
1218  "     |w2|  |
1219  "     +--+--+
1220  "     |w4   |
1221  "     +-----+
1222  new
1223  vsplit
1224  split
1225  " vertically jump from w4
1226  wincmd b
1227  call setline(1, repeat(' ', &columns))
1228  call cursor(1, 1)
1229  wincmd k
1230  call assert_equal(2, winnr())
1231  wincmd b
1232  call cursor(1, &columns)
1233  redraw!
1234  wincmd k
1235  call assert_equal(3, winnr())
1236  %bw!
1237
1238  " create the following window layout:
1239  "     +--+--+--+
1240  "     |w1|w2|w3|
1241  "     +--+--+--+
1242  "     |w4      |
1243  "     +--------+
1244  new
1245  vsplit
1246  vsplit
1247  wincmd b
1248  call setline(1, repeat(' ', &columns))
1249  call cursor(1, 1)
1250  wincmd k
1251  call assert_equal(1, winnr())
1252  wincmd b
1253  call cursor(1, &columns / 2)
1254  redraw!
1255  wincmd k
1256  call assert_equal(2, winnr())
1257  wincmd b
1258  call cursor(1, &columns)
1259  redraw!
1260  wincmd k
1261  call assert_equal(3, winnr())
1262  %bw!
1263
1264  " Horizontal window movement
1265
1266  " create the following window layout:
1267  "     +--+--+--+
1268  "     |w1|w2|w4|
1269  "     +--+--+  |
1270  "     |w3   |  |
1271  "     +-----+--+
1272  vsplit
1273  split
1274  vsplit
1275  4wincmd l
1276  call setline(1, repeat([' '], &lines))
1277  call cursor(1, 1)
1278  redraw!
1279  wincmd h
1280  call assert_equal(2, winnr())
1281  4wincmd l
1282  call cursor(&lines, 1)
1283  redraw!
1284  wincmd h
1285  call assert_equal(3, winnr())
1286  %bw!
1287
1288  " create the following window layout:
1289  "     +--+--+
1290  "     |w1|w4|
1291  "     +--+  +
1292  "     |w2|  |
1293  "     +--+  +
1294  "     |w3|  |
1295  "     +--+--+
1296  vsplit
1297  split
1298  split
1299  wincmd l
1300  call setline(1, repeat([' '], &lines))
1301  call cursor(1, 1)
1302  redraw!
1303  wincmd h
1304  call assert_equal(1, winnr())
1305  wincmd l
1306  call cursor(&lines / 2, 1)
1307  redraw!
1308  wincmd h
1309  call assert_equal(2, winnr())
1310  wincmd l
1311  call cursor(&lines, 1)
1312  redraw!
1313  wincmd h
1314  call assert_equal(3, winnr())
1315  %bw!
1316endfunc
1317
1318" Test for an autocmd closing the destination window when jumping from one
1319" window to another.
1320func Test_close_dest_window()
1321  split
1322  edit Xfile
1323
1324  " Test for BufLeave
1325  augroup T1
1326    au!
1327    au BufLeave Xfile $wincmd c
1328  augroup END
1329  wincmd b
1330  call assert_equal(1, winnr('$'))
1331  call assert_equal('Xfile', @%)
1332  augroup T1
1333    au!
1334  augroup END
1335
1336  " Test for WinLeave
1337  new
1338  wincmd p
1339  augroup T1
1340    au!
1341    au WinLeave * 1wincmd c
1342  augroup END
1343  wincmd t
1344  call assert_equal(1, winnr('$'))
1345  call assert_equal('Xfile', @%)
1346  augroup T1
1347    au!
1348  augroup END
1349  augroup! T1
1350  %bw!
1351endfunc
1352
1353" vim: shiftwidth=2 sts=2 expandtab
1354