" Test for various Normal mode commands

source shared.vim

func Setup_NewWindow()
  10new
  call setline(1, range(1,100))
endfunc

func MyFormatExpr()
  " Adds '->$' at lines having numbers followed by trailing whitespace
  for ln in range(v:lnum, v:lnum+v:count-1)
    let line = getline(ln)
    if getline(ln) =~# '\d\s\+$'
      call setline(ln, substitute(line, '\s\+$', '', '') . '->$')
    endif
  endfor
endfunc

func CountSpaces(type, ...)
  " for testing operatorfunc
  " will count the number of spaces
  " and return the result in g:a
  let sel_save = &selection
  let &selection = "inclusive"
  let reg_save = @@

  if a:0  " Invoked from Visual mode, use gv command.
    silent exe "normal! gvy"
  elseif a:type == 'line'
    silent exe "normal! '[V']y"
  else
    silent exe "normal! `[v`]y"
  endif
  let g:a=strlen(substitute(@@, '[^ ]', '', 'g'))
  let &selection = sel_save
  let @@ = reg_save
endfunc

func OpfuncDummy(type, ...)
  " for testing operatorfunc
  let g:opt=&linebreak

  if a:0  " Invoked from Visual mode, use gv command.
    silent exe "normal! gvy"
  elseif a:type == 'line'
    silent exe "normal! '[V']y"
  else
    silent exe "normal! `[v`]y"
  endif
  " Create a new dummy window
  new
  let g:bufnr=bufnr('%')
endfunc

fun! Test_normal00_optrans()
  new
  call append(0, ['1 This is a simple test: abcd', '2 This is the second line', '3 this is the third line'])
  1
  exe "norm! Sfoobar\<esc>"
  call assert_equal(['foobar', '2 This is the second line', '3 this is the third line', ''], getline(1,'$'))
  2
  exe "norm! $vbsone"
  call assert_equal(['foobar', '2 This is the second one', '3 this is the third line', ''], getline(1,'$'))
  norm! VS Second line here
  call assert_equal(['foobar', ' Second line here', '3 this is the third line', ''], getline(1, '$'))
  %d
  call append(0, ['4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line'])
  call append(0, ['1 This is a simple test: abcd', '2 This is the second line', '3 this is the third line'])

  1
  norm! 2D
  call assert_equal(['3 this is the third line', '4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line', ''], getline(1,'$'))
  " Nvim: no "#" flag in 'cpoptions'.
  " set cpo+=#
  " norm! 4D
  " call assert_equal(['', '4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line', ''], getline(1,'$'))

  " clean up
  set cpo-=#
  bw!
endfunc

func Test_normal01_keymodel()
  call Setup_NewWindow()
  " Test 1: depending on 'keymodel' <s-down> does something different
  50
  call feedkeys("V\<S-Up>y", 'tx')
  call assert_equal(['47', '48', '49', '50'], getline("'<", "'>"))
  set keymodel=startsel
  50
  call feedkeys("V\<S-Up>y", 'tx')
  call assert_equal(['49', '50'], getline("'<", "'>"))
  " Start visual mode when keymodel = startsel
  50
  call feedkeys("\<S-Up>y", 'tx')
  call assert_equal(['49', '5'], getreg(0, 0, 1))
  " Do not start visual mode when keymodel=
  set keymodel=
  50
  call feedkeys("\<S-Up>y$", 'tx')
  call assert_equal(['42'], getreg(0, 0, 1))
  " Stop visual mode when keymodel=stopsel
  set keymodel=stopsel
  50
  call feedkeys("Vkk\<Up>yy", 'tx')
  call assert_equal(['47'], getreg(0, 0, 1))

  set keymodel=
  50
  call feedkeys("Vkk\<Up>yy", 'tx')
  call assert_equal(['47', '48', '49', '50'], getreg(0, 0, 1))

  " clean up
  bw!
endfunc

func Test_normal02_selectmode()
  " some basic select mode tests
  call Setup_NewWindow()
  50
  norm! gHy
  call assert_equal('y51', getline('.'))
  call setline(1, range(1,100))
  50
  exe ":norm! V9jo\<c-g>y"
  call assert_equal('y60', getline('.'))
  " clean up
  bw!
endfunc

func Test_normal02_selectmode2()
  " some basic select mode tests
  call Setup_NewWindow()
  50
  call feedkeys(":set im\n\<c-o>gHc\<c-o>:set noim\n", 'tx')
  call assert_equal('c51', getline('.'))
  " clean up
  bw!
endfunc

func Test_normal03_join()
  " basic join test
  call Setup_NewWindow()
  50
  norm! VJ
  call assert_equal('50 51', getline('.'))
  $
  norm! J
  call assert_equal('100', getline('.'))
  $
  norm! V9-gJ
  call assert_equal('919293949596979899100', getline('.'))
  call setline(1, range(1,100))
  $
  :j 10
  call assert_equal('100', getline('.'))
  " clean up
  bw!
endfunc

func Test_normal04_filter()
  " basic filter test
  " only test on non windows platform
  if has('win32')
    return
  endif
  call Setup_NewWindow()
  1
  call feedkeys("!!sed -e 's/^/|    /'\n", 'tx')
  call assert_equal('|    1', getline('.'))
  90
  :sil :!echo one
  call feedkeys('.', 'tx')
  call assert_equal('|    90', getline('.'))
  95
  set cpo+=!
  " 2 <CR>, 1: for executing the command,
  "         2: clear hit-enter-prompt
  call feedkeys("!!\n", 'tx')
  call feedkeys(":!echo one\n\n", 'tx')
  call feedkeys(".", 'tx')
  call assert_equal('one', getline('.'))
  set cpo-=!
  bw!
endfunc

func Test_normal05_formatexpr()
  " basic formatexpr test
  call Setup_NewWindow()
  %d_
  call setline(1, ['here: 1   ', '2', 'here: 3   ', '4', 'not here:   '])
  1
  set formatexpr=MyFormatExpr()
  norm! gqG
  call assert_equal(['here: 1->$', '2', 'here: 3->$', '4', 'not here:   '], getline(1,'$'))
  set formatexpr=
  bw!
endfunc

func Test_normal05_formatexpr_newbuf()
  " Edit another buffer in the 'formatexpr' function
  new
  func! Format()
    edit another
  endfunc
  set formatexpr=Format()
  norm gqG
  bw!
  set formatexpr=
endfunc

func Test_normal05_formatexpr_setopt()
  " Change the 'formatexpr' value in the function
  new
  func! Format()
    set formatexpr=
  endfunc
  set formatexpr=Format()
  norm gqG
  bw!
  set formatexpr=
endfunc

" When 'formatexpr' returns non-zero, internal formatting is used.
func Test_normal_formatexpr_returns_nonzero()
  new
  call setline(1, ['one', 'two'])
  func! Format()
    return 1
  endfunc
  setlocal formatexpr=Format()
  normal VGgq
  call assert_equal(['one two'], getline(1, '$'))
  setlocal formatexpr=
  delfunc Format
  close!
endfunc

func Test_normal06_formatprg()
  " basic test for formatprg
  " only test on non windows platform
  if has('win32')
    return
  endif

  " uses sed to number non-empty lines
  call writefile(['#!/bin/sh', 'sed ''/./=''|sed ''/./{', 'N', 's/\n/    /', '}'''], 'Xsed_format.sh')
  call system('chmod +x ./Xsed_format.sh')
  let text = ['a', '', 'c', '', ' ', 'd', 'e']
  let expected = ['1    a', '', '3    c', '', '5     ', '6    d', '7    e']

  10new
  call setline(1, text)
  set formatprg=./Xsed_format.sh
  norm! gggqG
  call assert_equal(expected, getline(1, '$'))
  bw!

  10new
  call setline(1, text)
  set formatprg=donothing
  setlocal formatprg=./Xsed_format.sh
  norm! gggqG
  call assert_equal(expected, getline(1, '$'))
  bw!

  " clean up
  set formatprg=
  setlocal formatprg=
  call delete('Xsed_format.sh')
endfunc

func Test_normal07_internalfmt()
  " basic test for internal formmatter to textwidth of 12
  let list=range(1,11)
  call map(list, 'v:val."    "')
  10new
  call setline(1, list)
  set tw=12
  norm! gggqG
  call assert_equal(['1    2    3', '4    5    6', '7    8    9', '10    11    '], getline(1, '$'))
  " clean up
  set tw=0
  bw!
endfunc

func Test_normal08_fold()
  " basic tests for foldopen/folddelete
  if !has("folding")
    return
  endif
  call Setup_NewWindow()
  50
  setl foldenable fdm=marker
  " First fold
  norm! V4jzf
  " check that folds have been created
  call assert_equal(['50/*{{{*/', '51', '52', '53', '54/*}}}*/'], getline(50,54))
  " Second fold
  46
  norm! V10jzf
  " check that folds have been created
  call assert_equal('46/*{{{*/', getline(46))
  call assert_equal('60/*}}}*/', getline(60))
  norm! k
  call assert_equal('45', getline('.'))
  norm! j
  call assert_equal('46/*{{{*/', getline('.'))
  norm! j
  call assert_equal('61', getline('.'))
  norm! k
  " open a fold
  norm! Vzo
  norm! k
  call assert_equal('45', getline('.'))
  norm! j
  call assert_equal('46/*{{{*/', getline('.'))
  norm! j
  call assert_equal('47', getline('.'))
  norm! k
  norm! zcVzO
  call assert_equal('46/*{{{*/', getline('.'))
  norm! j
  call assert_equal('47', getline('.'))
  norm! j
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('51', getline('.'))
  " delete folds
  :46
  " collapse fold
  norm! V14jzC
  " delete all folds recursively
  norm! VzD
  call assert_equal(['46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60'], getline(46,60))

  " clean up
  setl nofoldenable fdm=marker
  bw!
endfunc

func Test_normal09_operatorfunc()
  " Test operatorfunc
  call Setup_NewWindow()
  " Add some spaces for counting
  50,60s/$/  /
  unlet! g:a
  let g:a=0
  nmap <buffer><silent> ,, :set opfunc=CountSpaces<CR>g@
  vmap <buffer><silent> ,, :<C-U>call CountSpaces(visualmode(), 1)<CR>
  50
  norm V2j,,
  call assert_equal(6, g:a)
  norm V,,
  call assert_equal(2, g:a)
  norm ,,l
  call assert_equal(0, g:a)
  50
  exe "norm 0\<c-v>10j2l,,"
  call assert_equal(11, g:a)
  50
  norm V10j,,
  call assert_equal(22, g:a)

  " clean up
  unmap <buffer> ,,
  set opfunc=
  unlet! g:a
  bw!
endfunc

func Test_normal09a_operatorfunc()
  " Test operatorfunc
  call Setup_NewWindow()
  " Add some spaces for counting
  50,60s/$/  /
  unlet! g:opt
  set linebreak
  nmap <buffer><silent> ,, :set opfunc=OpfuncDummy<CR>g@
  50
  norm ,,j
  exe "bd!" g:bufnr
  call assert_true(&linebreak)
  call assert_equal(g:opt, &linebreak)
  set nolinebreak
  norm ,,j
  exe "bd!" g:bufnr
  call assert_false(&linebreak)
  call assert_equal(g:opt, &linebreak)

  " clean up
  unmap <buffer> ,,
  set opfunc=
  bw!
  unlet! g:opt
endfunc

func Test_normal10_expand()
  " Test for expand()
  10new
  call setline(1, ['1', 'ifooar,,cbar'])
  2
  norm! $
  call assert_equal('cbar', expand('<cword>'))
  call assert_equal('ifooar,,cbar', expand('<cWORD>'))

  call setline(1, ['prx = list[idx];'])
  1
  let expected = ['', 'prx', 'prx', 'prx',
	\ 'list', 'list', 'list', 'list', 'list', 'list', 'list',
	\ 'idx', 'idx', 'idx', 'idx',
	\ 'list[idx]',
	\ '];',
	\ ]
  for i in range(1, 16)
    exe 'norm ' . i . '|'
    call assert_equal(expected[i], expand('<cexpr>'), 'i == ' . i)
  endfor

  if executable('echo')
    " Test expand(`...`) i.e. backticks command expansion.
    " MS-Windows has a trailing space.
    call assert_match('^abcde *$', expand('`echo abcde`'))
  endif

  " Test expand(`=...`) i.e. backticks expression expansion
  call assert_equal('5', expand('`=2+3`'))

  " clean up
  bw!
endfunc

func Test_normal11_showcmd()
  " test for 'showcmd'
  10new
  exe "norm! ofoobar\<esc>"
  call assert_equal(2, line('$'))
  set showcmd
  exe "norm! ofoobar2\<esc>"
  call assert_equal(3, line('$'))
  exe "norm! VAfoobar3\<esc>"
  call assert_equal(3, line('$'))
  exe "norm! 0d3\<del>2l"
  call assert_equal('obar2foobar3', getline('.'))
  bw!
endfunc

func Test_normal12_nv_error()
  " Test for nv_error
  10new
  call setline(1, range(1,5))
  " should not do anything, just beep
  exe "norm! <c-k>"
  call assert_equal(map(range(1,5), 'string(v:val)'), getline(1,'$'))
  bw!
endfunc

func Test_normal13_help()
  " Test for F1
  call assert_equal(1, winnr())
  call feedkeys("\<f1>", 'txi')
  call assert_match('help\.txt', bufname('%'))
  call assert_equal(2, winnr('$'))
  bw!
endfunc

func Test_normal14_page()
  " basic test for Ctrl-F and Ctrl-B
  call Setup_NewWindow()
  exe "norm! \<c-f>"
  call assert_equal('9', getline('.'))
  exe "norm! 2\<c-f>"
  call assert_equal('25', getline('.'))
  exe "norm! 2\<c-b>"
  call assert_equal('18', getline('.'))
  1
  set scrolloff=5
  exe "norm! 2\<c-f>"
  call assert_equal('21', getline('.'))
  exe "norm! \<c-b>"
  call assert_equal('13', getline('.'))
  1
  set scrolloff=99
  exe "norm! \<c-f>"
  call assert_equal('13', getline('.'))
  set scrolloff=0
  100
  exe "norm! $\<c-b>"
  call assert_equal('92', getline('.'))
  call assert_equal([0, 92, 1, 0, 1], getcurpos())
  100
  set nostartofline
  exe "norm! $\<c-b>"
  call assert_equal('92', getline('.'))
  call assert_equal([0, 92, 2, 0, 2147483647], getcurpos())
  " cleanup
  set startofline
  bw!
endfunc

func Test_normal14_page_eol()
  10new
  norm oxxxxxxx
  exe "norm 2\<c-f>"
  " check with valgrind that cursor is put back in column 1
  exe "norm 2\<c-b>"
  bw!
endfunc

" Test for errors with z command
func Test_normal_z_error()
  call assert_beeps('normal! z2p')
  call assert_beeps('normal! zq')
endfunc

func Test_normal15_z_scroll_vert()
  " basic test for z commands that scroll the window
  call Setup_NewWindow()
  100
  norm! >>
  " Test for z<cr>
  exe "norm! z\<cr>"
  call assert_equal('	100', getline('.'))
  call assert_equal(100, winsaveview()['topline'])
  call assert_equal([0, 100, 2, 0, 9], getcurpos())

  " Test for zt
  21
  norm! >>0zt
  call assert_equal('	21', getline('.'))
  call assert_equal(21, winsaveview()['topline'])
  call assert_equal([0, 21, 1, 0, 8], getcurpos())

  " Test for zb
  30
  norm! >>$ztzb
  call assert_equal('	30', getline('.'))
  call assert_equal(30, winsaveview()['topline']+winheight(0)-1)
  call assert_equal([0, 30, 3, 0, 2147483647], getcurpos())

  " Test for z-
  1
  30
  norm! 0z-
  call assert_equal('	30', getline('.'))
  call assert_equal(30, winsaveview()['topline']+winheight(0)-1)
  call assert_equal([0, 30, 2, 0, 9], getcurpos())

  " Test for z{height}<cr>
  call assert_equal(10, winheight(0))
  exe "norm! z12\<cr>"
  call assert_equal(12, winheight(0))
  exe "norm! z10\<cr>"
  call assert_equal(10, winheight(0))

  " Test for z.
  1
  21
  norm! 0z.
  call assert_equal('	21', getline('.'))
  call assert_equal(17, winsaveview()['topline'])
  call assert_equal([0, 21, 2, 0, 9], getcurpos())

  " Test for zz
  1
  21
  norm! 0zz
  call assert_equal('	21', getline('.'))
  call assert_equal(17, winsaveview()['topline'])
  call assert_equal([0, 21, 1, 0, 8], getcurpos())

  " Test for z+
  11
  norm! zt
  norm! z+
  call assert_equal('	21', getline('.'))
  call assert_equal(21, winsaveview()['topline'])
  call assert_equal([0, 21, 2, 0, 9], getcurpos())

  " Test for [count]z+
  1
  norm! 21z+
  call assert_equal('	21', getline('.'))
  call assert_equal(21, winsaveview()['topline'])
  call assert_equal([0, 21, 2, 0, 9], getcurpos())

  " Test for z^
  norm! 22z+0
  norm! z^
  call assert_equal('	21', getline('.'))
  call assert_equal(12, winsaveview()['topline'])
  call assert_equal([0, 21, 2, 0, 9], getcurpos())

  " Test for [count]z^
  1
  norm! 30z^
  call assert_equal('	21', getline('.'))
  call assert_equal(12, winsaveview()['topline'])
  call assert_equal([0, 21, 2, 0, 9], getcurpos())

  " cleanup
  bw!
endfunc

func Test_normal16_z_scroll_hor()
  " basic test for z commands that scroll the window
  10new
  15vsp
  set nowrap listchars=
  let lineA='abcdefghijklmnopqrstuvwxyz'
  let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  $put =lineA
  $put =lineB
  1d

  " Test for zl
  1
  norm! 5zl
  call assert_equal(lineA, getline('.'))
  call assert_equal(6, col('.'))
  call assert_equal(5, winsaveview()['leftcol'])
  norm! yl
  call assert_equal('f', @0)

  " Test for zh
  norm! 2zh
  call assert_equal(lineA, getline('.'))
  call assert_equal(6, col('.'))
  norm! yl
  call assert_equal('f', @0)
  call assert_equal(3, winsaveview()['leftcol'])

  " Test for zL
  norm! zL
  call assert_equal(11, col('.'))
  norm! yl
  call assert_equal('k', @0)
  call assert_equal(10, winsaveview()['leftcol'])
  norm! 2zL
  call assert_equal(25, col('.'))
  norm! yl
  call assert_equal('y', @0)
  call assert_equal(24, winsaveview()['leftcol'])

  " Test for zH
  norm! 2zH
  call assert_equal(25, col('.'))
  call assert_equal(10, winsaveview()['leftcol'])
  norm! yl
  call assert_equal('y', @0)

  " Test for zs
  norm! $zs
  call assert_equal(26, col('.'))
  call assert_equal(25, winsaveview()['leftcol'])
  norm! yl
  call assert_equal('z', @0)

  " Test for ze
  norm! ze
  call assert_equal(26, col('.'))
  call assert_equal(11, winsaveview()['leftcol'])
  norm! yl
  call assert_equal('z', @0)

  " cleanup
  set wrap listchars=eol:$
  bw!
endfunc

func Test_normal17_z_scroll_hor2()
  " basic test for z commands that scroll the window
  " using 'sidescrolloff' setting
  10new
  20vsp
  set nowrap listchars= sidescrolloff=5
  let lineA='abcdefghijklmnopqrstuvwxyz'
  let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  $put =lineA
  $put =lineB
  1d

  " Test for zl
  1
  norm! 5zl
  call assert_equal(lineA, getline('.'))
  call assert_equal(11, col('.'))
  call assert_equal(5, winsaveview()['leftcol'])
  norm! yl
  call assert_equal('k', @0)

  " Test for zh
  norm! 2zh
  call assert_equal(lineA, getline('.'))
  call assert_equal(11, col('.'))
  norm! yl
  call assert_equal('k', @0)
  call assert_equal(3, winsaveview()['leftcol'])

  " Test for zL
  norm! 0zL
  call assert_equal(16, col('.'))
  norm! yl
  call assert_equal('p', @0)
  call assert_equal(10, winsaveview()['leftcol'])
  norm! 2zL
  call assert_equal(26, col('.'))
  norm! yl
  call assert_equal('z', @0)
  call assert_equal(15, winsaveview()['leftcol'])

  " Test for zH
  norm! 2zH
  call assert_equal(15, col('.'))
  call assert_equal(0, winsaveview()['leftcol'])
  norm! yl
  call assert_equal('o', @0)

  " Test for zs
  norm! $zs
  call assert_equal(26, col('.'))
  call assert_equal(20, winsaveview()['leftcol'])
  norm! yl
  call assert_equal('z', @0)

  " Test for ze
  norm! ze
  call assert_equal(26, col('.'))
  call assert_equal(11, winsaveview()['leftcol'])
  norm! yl
  call assert_equal('z', @0)

  " cleanup
  set wrap listchars=eol:$ sidescrolloff=0
  bw!
endfunc

func Test_normal18_z_fold()
  " basic tests for foldopen/folddelete
  if !has("folding")
    return
  endif
  call Setup_NewWindow()
  50
  setl foldenable fdm=marker foldlevel=5

  " Test for zF
  " First fold
  norm! 4zF
  " check that folds have been created
  call assert_equal(['50/*{{{*/', '51', '52', '53/*}}}*/'], getline(50,53))

  " Test for zd
  51
  norm! 2zF
  call assert_equal(2, foldlevel('.'))
  norm! kzd
  call assert_equal(['50', '51/*{{{*/', '52/*}}}*/', '53'], getline(50,53))
  norm! j
  call assert_equal(1, foldlevel('.'))

  " Test for zD
  " also deletes partially selected folds recursively
  51
  norm! zF
  call assert_equal(2, foldlevel('.'))
  norm! kV2jzD
  call assert_equal(['50', '51', '52', '53'], getline(50,53))

  " Test for zE
  85
  norm! 4zF
  86
  norm! 2zF
  90
  norm! 4zF
  call assert_equal(['85/*{{{*/', '86/*{{{*/', '87/*}}}*/', '88/*}}}*/', '89', '90/*{{{*/', '91', '92', '93/*}}}*/'], getline(85,93))
  norm! zE
  call assert_equal(['85', '86', '87', '88', '89', '90', '91', '92', '93'], getline(85,93))

  " Test for zn
  50
  set foldlevel=0
  norm! 2zF
  norm! zn
  norm! k
  call assert_equal('49', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('51/*}}}*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))
  call assert_equal(0, &foldenable)

  " Test for zN
  49
  norm! zN
  call assert_equal('49', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))
  call assert_equal(1, &foldenable)

  " Test for zi
  norm! zi
  call assert_equal(0, &foldenable)
  norm! zi
  call assert_equal(1, &foldenable)
  norm! zi
  call assert_equal(0, &foldenable)
  norm! zi
  call assert_equal(1, &foldenable)

  " Test for za
  50
  norm! za
  norm! k
  call assert_equal('49', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('51/*}}}*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))
  50
  norm! za
  norm! k
  call assert_equal('49', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))

  49
  norm! 5zF
  norm! k
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))
  49
  norm! za
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))
  set nofoldenable
  " close fold and set foldenable
  norm! za
  call assert_equal(1, &foldenable)

  50
  " have to use {count}za to open all folds and make the cursor visible
  norm! 2za
  norm! 2k
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('51/*}}}*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))

  " Test for zA
  49
  set foldlevel=0
  50
  norm! zA
  norm! 2k
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('51/*}}}*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))

  " zA on a opened fold when foldenable is not set
  50
  set nofoldenable
  norm! zA
  call assert_equal(1, &foldenable)
  norm! k
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))

  " Test for zc
  norm! zE
  50
  norm! 2zF
  49
  norm! 5zF
  set nofoldenable
  50
  " There most likely is a bug somewhere:
  " https://groups.google.com/d/msg/vim_dev/v2EkfJ_KQjI/u-Cvv94uCAAJ
  " TODO: Should this only close the inner most fold or both folds?
  norm! zc
  call assert_equal(1, &foldenable)
  norm! k
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))
  set nofoldenable
  50
  norm! Vjzc
  norm! k
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))

  " Test for zC
  set nofoldenable
  50
  norm! zCk
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))

  " Test for zx
  " 1) close folds at line 49-54
  set nofoldenable
  48
  norm! zx
  call assert_equal(1, &foldenable)
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))

  " 2) do not close fold under cursor
  51
  set nofoldenable
  norm! zx
  call assert_equal(1, &foldenable)
  norm! 3k
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('51/*}}}*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))
  norm! j
  call assert_equal('53', getline('.'))
  norm! j
  call assert_equal('54/*}}}*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))

  " 3) close one level of folds
  48
  set nofoldenable
  set foldlevel=1
  norm! zx
  call assert_equal(1, &foldenable)
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))
  norm! j
  call assert_equal('53', getline('.'))
  norm! j
  call assert_equal('54/*}}}*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))

  " Test for zX
  " Close all folds
  set foldlevel=0 nofoldenable
  50
  norm! zX
  call assert_equal(1, &foldenable)
  norm! k
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))

  " Test for zm
  50
  set nofoldenable foldlevel=2
  norm! zm
  call assert_equal(1, &foldenable)
  call assert_equal(1, &foldlevel)
  norm! zm
  call assert_equal(0, &foldlevel)
  norm! zm
  call assert_equal(0, &foldlevel)
  norm! k
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))

  " Test for zM
  48
  set nofoldenable foldlevel=99
  norm! zM
  call assert_equal(1, &foldenable)
  call assert_equal(0, &foldlevel)
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('55', getline('.'))

  " Test for zr
  48
  set nofoldenable foldlevel=0
  norm! zr
  call assert_equal(0, &foldenable)
  call assert_equal(1, &foldlevel)
  set foldlevel=0 foldenable
  norm! zr
  call assert_equal(1, &foldenable)
  call assert_equal(1, &foldlevel)
  norm! zr
  call assert_equal(2, &foldlevel)
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('51/*}}}*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))

  " Test for zR
  48
  set nofoldenable foldlevel=0
  norm! zR
  call assert_equal(0, &foldenable)
  call assert_equal(2, &foldlevel)
  set foldenable foldlevel=0
  norm! zR
  call assert_equal(1, &foldenable)
  call assert_equal(2, &foldlevel)
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('51/*}}}*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))
  call append(50, ['a /*{{{*/', 'b /*}}}*/'])
  48
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('a /*{{{*/', getline('.'))
  norm! j
  call assert_equal('51/*}}}*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))
  48
  norm! zR
  call assert_equal(1, &foldenable)
  call assert_equal(3, &foldlevel)
  call assert_equal('48', getline('.'))
  norm! j
  call assert_equal('49/*{{{*/', getline('.'))
  norm! j
  call assert_equal('50/*{{{*/', getline('.'))
  norm! j
  call assert_equal('a /*{{{*/', getline('.'))
  norm! j
  call assert_equal('b /*}}}*/', getline('.'))
  norm! j
  call assert_equal('51/*}}}*/', getline('.'))
  norm! j
  call assert_equal('52', getline('.'))

  " clean up
  setl nofoldenable fdm=marker foldlevel=0
  bw!
endfunc

func Test_normal20_exmode()
  if !has("unix")
    " Reading from redirected file doesn't work on MS-Windows
    return
  endif
  call writefile(['1a', 'foo', 'bar', '.', 'w! Xfile2', 'q!'], 'Xscript')
  call writefile(['1', '2'], 'Xfile')
  call system(v:progpath .' -e -s < Xscript Xfile')
  let a=readfile('Xfile2')
  call assert_equal(['1', 'foo', 'bar', '2'], a)

  " clean up
  for file in ['Xfile', 'Xfile2', 'Xscript']
    call delete(file)
  endfor
  bw!
endfunc

func Test_normal21_nv_hat()

  " Edit a fresh file and wipe the buffer list so that there is no alternate
  " file present.  Next, check for the expected command failures.
  edit Xfoo | %bw
  call assert_fails(':buffer #', 'E86')
  call assert_fails(':execute "normal! \<C-^>"', 'E23')

  " Test for the expected behavior when switching between two named buffers.
  edit Xfoo | edit Xbar
  call feedkeys("\<C-^>", 'tx')
  call assert_equal('Xfoo', fnamemodify(bufname('%'), ':t'))
  call feedkeys("\<C-^>", 'tx')
  call assert_equal('Xbar', fnamemodify(bufname('%'), ':t'))

  " Test for the expected behavior when only one buffer is named.
  enew | let l:nr = bufnr('%')
  call feedkeys("\<C-^>", 'tx')
  call assert_equal('Xbar', fnamemodify(bufname('%'), ':t'))
  call feedkeys("\<C-^>", 'tx')
  call assert_equal('', bufname('%'))
  call assert_equal(l:nr, bufnr('%'))

  " Test that no action is taken by "<C-^>" when an operator is pending.
  edit Xfoo
  call feedkeys("ci\<C-^>", 'tx')
  call assert_equal('Xfoo', fnamemodify(bufname('%'), ':t'))

  %bw!
endfunc

func Test_normal22_zet()
  " Test for ZZ
  " let shell = &shell
  " let &shell = 'sh'

  " Remove any stale test files from previous run.
  for file in ['Xfile_Test_normal22_zet']
    call delete(file)
  endfor

  call writefile(['1', '2'], 'Xfile_Test_normal22_zet')
  let args = ' --headless -u NONE -N -U NONE -i NONE --noplugins'
  call system(v:progpath . args . ' -c "%d" -c ":norm! ZZ" Xfile_Test_normal22_zet')
  let a = readfile('Xfile_Test_normal22_zet')
  call assert_equal([], a)
  " Test for ZQ
  call writefile(['1', '2'], 'Xfile_Test_normal22_zet')
  call system(v:progpath . args . ' -c "%d" -c ":norm! ZQ" Xfile_Test_normal22_zet')
  let a = readfile('Xfile_Test_normal22_zet')
  call assert_equal(['1', '2'], a)

  " Nvim: This sometimes hangs the TSAN build.
  " for file in ['Xfile_Test_normal22_zet']
  "   call delete(file)
  " endfor
  " let &shell = shell
endfunc

func Test_normal23_K()
  " Test for K command
  new
  call append(0, ['helphelp.txt', 'man', 'aa%bb', 'cc|dd'])
  let k = &keywordprg
  set keywordprg=:help
  1
  norm! VK
  call assert_equal('helphelp.txt', fnamemodify(bufname('%'), ':t'))
  call assert_equal('help', &ft)
  call assert_match('\*helphelp.txt\*', getline('.'))
  helpclose
  norm! 0K
  call assert_equal('helphelp.txt', fnamemodify(bufname('%'), ':t'))
  call assert_equal('help', &ft)
  call assert_match('Help on help files', getline('.'))
  helpclose

  set keywordprg=:new
  set iskeyword+=%
  set iskeyword+=\|
  2
  norm! K
  call assert_equal('man', fnamemodify(bufname('%'), ':t'))
  bwipe!
  3
  norm! K
  call assert_equal('aa%bb', fnamemodify(bufname('%'), ':t'))
  bwipe!
  if !has('win32')
    4
    norm! K
    call assert_equal('cc|dd', fnamemodify(bufname('%'), ':t'))
    bwipe!
  endif
  set iskeyword-=%
  set iskeyword-=\|

  " Only expect "man" to work on Unix
  if !has("unix") || has('nvim')  " Nvim K uses :terminal. #15398
    let &keywordprg = k
    bw!
    return
  endif

  let not_gnu_man = has('mac') || has('bsd')
  if not_gnu_man
    " In MacOS and BSD, the option for specifying a pager is different
    set keywordprg=man\ -P\ cat
  else
    set keywordprg=man\ --pager=cat
  endif
  " Test for using man
  2
  let a = execute('unsilent norm! K')
  if not_gnu_man
    call assert_match("man -P cat 'man'", a)
  else
    call assert_match("man --pager=cat 'man'", a)
  endif

  " clean up
  let &keywordprg = k
  bw!
endfunc

func Test_normal24_rot13()
  " Testing for g?? g?g?
  new
  call append(0, 'abcdefghijklmnopqrstuvwxyzäüö')
  1
  norm! g??
  call assert_equal('nopqrstuvwxyzabcdefghijklmäüö', getline('.'))
  norm! g?g?
  call assert_equal('abcdefghijklmnopqrstuvwxyzäüö', getline('.'))

  " clean up
  bw!
endfunc

func Test_normal25_tag()
  " Testing for CTRL-] g CTRL-] g]
  " CTRL-W g] CTRL-W CTRL-] CTRL-W g CTRL-]
  h
  " Test for CTRL-]
  call search('\<x\>$')
  exe "norm! \<c-]>"
  call assert_equal("change.txt", fnamemodify(bufname('%'), ':t'))
  norm! yiW
  call assert_equal("*x*", @0)
  exe ":norm \<c-o>"

  " Test for g_CTRL-]
  call search('\<v_u\>$')
  exe "norm! g\<c-]>"
  call assert_equal("change.txt", fnamemodify(bufname('%'), ':t'))
  norm! yiW
  call assert_equal("*v_u*", @0)
  exe ":norm \<c-o>"

  " Test for g]
  call search('\<i_<Esc>$')
  let a = execute(":norm! g]")
  call assert_match('i_<Esc>.*insert.txt', a)

  if !empty(exepath('cscope')) && has('cscope')
    " setting cscopetag changes how g] works
    set cst
    exe "norm! g]"
    call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t'))
    norm! yiW
    call assert_equal("*i_<Esc>*", @0)
    exe ":norm \<c-o>"
    " Test for CTRL-W g]
    exe "norm! \<C-W>g]"
    call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t'))
    norm! yiW
    call assert_equal("*i_<Esc>*", @0)
    call assert_equal(3, winnr('$'))
    helpclose
    set nocst
  endif

  " Test for CTRL-W g]
  let a = execute("norm! \<C-W>g]")
  call assert_match('i_<Esc>.*insert.txt', a)

  " Test for CTRL-W CTRL-]
  exe "norm! \<C-W>\<C-]>"
  call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t'))
  norm! yiW
  call assert_equal("*i_<Esc>*", @0)
  call assert_equal(3, winnr('$'))
  helpclose

  " Test for CTRL-W g CTRL-]
  exe "norm! \<C-W>g\<C-]>"
  call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t'))
  norm! yiW
  call assert_equal("*i_<Esc>*", @0)
  call assert_equal(3, winnr('$'))
  helpclose

  " clean up
  helpclose
endfunc

func Test_normal26_put()
  " Test for ]p ]P [p and [P
  new
  call append(0, ['while read LINE', 'do', '  ((count++))', '  if [ $? -ne 0 ]; then', "    echo 'Error writing file'", '  fi', 'done'])
  1
  /Error/y a
  2
  norm! "a]pj"a[p
  call assert_equal(['do', "echo 'Error writing file'", "  echo 'Error writing file'", '  ((count++))'], getline(2,5))
  1
  /^\s\{4}/
  exe "norm!  \"a]P3Eldt'"
  exe "norm! j\"a[P2Eldt'"
  call assert_equal(['  if [ $? -ne 0 ]; then', "    echo 'Error writing'", "    echo 'Error'", "    echo 'Error writing file'", '  fi'], getline(6,10))

  " clean up
  bw!
endfunc

func Test_normal27_bracket()
  " Test for [' [` ]' ]`
  call Setup_NewWindow()
  1,21s/.\+/  &   b/
  1
  norm! $ma
  5
  norm! $mb
  10
  norm! $mc
  15
  norm! $md
  20
  norm! $me

  " Test for ['
  9
  norm! 2['
  call assert_equal('  1   b', getline('.'))
  call assert_equal(1, line('.'))
  call assert_equal(3, col('.'))

  " Test for ]'
  norm! ]'
  call assert_equal('  5   b', getline('.'))
  call assert_equal(5, line('.'))
  call assert_equal(3, col('.'))

  " No mark after line 21, cursor moves to first non blank on current line
  21
  norm! $]'
  call assert_equal('  21   b', getline('.'))
  call assert_equal(21, line('.'))
  call assert_equal(3, col('.'))

  " Test for [`
  norm! 2[`
  call assert_equal('  15   b', getline('.'))
  call assert_equal(15, line('.'))
  call assert_equal(8, col('.'))

  " Test for ]`
  norm! ]`
  call assert_equal('  20   b', getline('.'))
  call assert_equal(20, line('.'))
  call assert_equal(8, col('.'))

  " clean up
  bw!
endfunc

func Test_normal28_parenthesis()
  " basic testing for ( and )
  new
  call append(0, ['This is a test. With some sentences!', '', 'Even with a question? And one more. And no sentence here'])

  $
  norm! d(
  call assert_equal(['This is a test. With some sentences!', '', 'Even with a question? And one more. ', ''], getline(1, '$'))
  norm! 2d(
  call assert_equal(['This is a test. With some sentences!', '', ' ', ''], getline(1, '$'))
  1
  norm! 0d)
  call assert_equal(['With some sentences!', '', ' ', ''], getline(1, '$'))

  call append('$', ['This is a long sentence', '', 'spanning', 'over several lines. '])
  $
  norm! $d(
  call assert_equal(['With some sentences!', '', ' ', '', 'This is a long sentence', ''], getline(1, '$'))

  " clean up
  bw!
endfunc

fun! Test_normal29_brace()
  " basic test for { and } movements
  let text =<< trim [DATA]
    A paragraph begins after each empty line, and also at each of a set of
    paragraph macros, specified by the pairs of characters in the 'paragraphs'
    option.  The default is "IPLPPPQPP TPHPLIPpLpItpplpipbp", which corresponds to
    the macros ".IP", ".LP", etc.  (These are nroff macros, so the dot must be in
    the first column).  A section boundary is also a paragraph boundary.
    Note that a blank line (only containing white space) is NOT a paragraph
    boundary.


    Also note that this does not include a '{' or '}' in the first column.  When
    the '{' flag is in 'cpoptions' then '{' in the first column is used as a
    paragraph boundary |posix|.
    {
    This is no paragraph
    unless the '{' is set
    in 'cpoptions'
    }
    .IP
    The nroff macros IP separates a paragraph
    That means, it must be a '.'
    followed by IP
    .LPIt does not matter, if afterwards some
    more characters follow.
    .SHAlso section boundaries from the nroff
    macros terminate a paragraph. That means
    a character like this:
    .NH
    End of text here
  [DATA]

  new
  call append(0, text)
  1
  norm! 0d2}

  let expected =<< trim [DATA]
    .IP
    The nroff macros IP separates a paragraph
    That means, it must be a '.'
    followed by IP
    .LPIt does not matter, if afterwards some
    more characters follow.
    .SHAlso section boundaries from the nroff
    macros terminate a paragraph. That means
    a character like this:
    .NH
    End of text here

  [DATA]
  call assert_equal(expected, getline(1, '$'))

  norm! 0d}

  let expected =<< trim [DATA]
    .LPIt does not matter, if afterwards some
    more characters follow.
    .SHAlso section boundaries from the nroff
    macros terminate a paragraph. That means
    a character like this:
    .NH
    End of text here

  [DATA]
  call assert_equal(expected, getline(1, '$'))

  $
  norm! d{

  let expected =<< trim [DATA]
    .LPIt does not matter, if afterwards some
    more characters follow.
    .SHAlso section boundaries from the nroff
    macros terminate a paragraph. That means
    a character like this:

  [DATA]
  call assert_equal(expected, getline(1, '$'))

  norm! d{

  let expected =<< trim [DATA]
    .LPIt does not matter, if afterwards some
    more characters follow.

  [DATA]
  call assert_equal(expected, getline(1, '$'))

  " Test with { in cpooptions
  %d
  call append(0, text)
  " Nvim: no "{" flag in 'cpoptions'.
  " set cpo+={
  " 1
  " norm! 0d2}
  " let expected =<< trim [DATA]
  "   {
  "   This is no paragraph
  "   unless the '{' is set
  "   in 'cpoptions'
  "   }
  "   .IP
  "   The nroff macros IP separates a paragraph
  "   That means, it must be a '.'
  "   followed by IP
  "   .LPIt does not matter, if afterwards some
  "   more characters follow.
  "   .SHAlso section boundaries from the nroff
  "   macros terminate a paragraph. That means
  "   a character like this:
  "   .NH
  "   End of text here
  "
  " [DATA]
  " call assert_equal(expected, getline(1, '$'))
  "
  " $
  " norm! d}
  " let expected =<< trim [DATA]
  "   {
  "   This is no paragraph
  "   unless the '{' is set
  "   in 'cpoptions'
  "   }
  "   .IP
  "   The nroff macros IP separates a paragraph
  "   That means, it must be a '.'
  "   followed by IP
  "   .LPIt does not matter, if afterwards some
  "   more characters follow.
  "   .SHAlso section boundaries from the nroff
  "   macros terminate a paragraph. That means
  "   a character like this:
  "   .NH
  "   End of text here
  "
  " [DATA]
  " call assert_equal(expected, getline(1, '$'))
  "
  " norm! gg}
  " norm! d5}
  "
  " let expected =<< trim [DATA]
  "   {
  "   This is no paragraph
  "   unless the '{' is set
  "   in 'cpoptions'
  "   }

  " [DATA]
  " call assert_equal(expected, getline(1, '$'))

  " clean up
  set cpo-={
  bw!
endfunc

fun! Test_normal30_changecase()
  new
  call append(0, 'This is a simple test: äüöß')
  norm! 1ggVu
  call assert_equal('this is a simple test: äüöß', getline('.'))
  norm! VU
  call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
  norm! guu
  call assert_equal('this is a simple test: äüöss', getline('.'))
  norm! gUgU
  call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
  norm! gugu
  call assert_equal('this is a simple test: äüöss', getline('.'))
  norm! gUU
  call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
  norm! 010~
  call assert_equal('this is a SIMPLE TEST: ÄÜÖSS', getline('.'))
  norm! V~
  call assert_equal('THIS IS A simple test: äüöss', getline('.'))

  " Turkish ASCII turns to multi-byte.  On some systems Turkish locale
  " is available but toupper()/tolower() don't do the right thing.
  try
    lang tr_TR.UTF-8
    set casemap=
    let iupper = toupper('i')
    if iupper == "\u0130"
      call setline(1, 'iI')
      1normal gUU
      call assert_equal("\u0130I", getline(1))
      call assert_equal("\u0130I", toupper("iI"))

      call setline(1, 'iI')
      1normal guu
      call assert_equal("i\u0131", getline(1))
      call assert_equal("i\u0131", tolower("iI"))
    elseif iupper == "I"
      call setline(1, 'iI')
      1normal gUU
      call assert_equal("II", getline(1))
      call assert_equal("II", toupper("iI"))

      call setline(1, 'iI')
      1normal guu
      call assert_equal("ii", getline(1))
      call assert_equal("ii", tolower("iI"))
    else
      call assert_true(false, "expected toupper('i') to be either 'I' or '\u0131'")
    endif
    set casemap&
    call setline(1, 'iI')
    1normal gUU
    call assert_equal("II", getline(1))
    call assert_equal("II", toupper("iI"))

    call setline(1, 'iI')
    1normal guu
    call assert_equal("ii", getline(1))
    call assert_equal("ii", tolower("iI"))

    lang en_US.UTF-8
  catch /E197:/
    " can't use Turkish locale
    throw 'Skipped: Turkish locale not available'
  endtry

  " clean up
  bw!
endfunc

fun! Test_normal31_r_cmd()
  " Test for r command
  new
  call append(0, 'This is a simple test: abcd')
  exe "norm! 1gg$r\<cr>"
  call assert_equal(['This is a simple test: abc', '', ''], getline(1,'$'))
  exe "norm! 1gg2wlr\<cr>"
  call assert_equal(['This is a', 'simple test: abc', '', ''], getline(1,'$'))
  exe "norm! 2gg0W5r\<cr>"
  call assert_equal(['This is a', 'simple ', ' abc', '', ''], getline('1', '$'))
  set autoindent
  call setline(2, ['simple test: abc', ''])
  exe "norm! 2gg0W5r\<cr>"
  call assert_equal(['This is a', 'simple ', 'abc', '', '', ''], getline('1', '$'))
  exe "norm! 1ggVr\<cr>"
  call assert_equal('^M^M^M^M^M^M^M^M^M', strtrans(getline(1)))
  call setline(1, 'This is a')
  exe "norm! 1gg05rf"
  call assert_equal('fffffis a', getline(1))

  " clean up
  set noautoindent
  bw!
endfunc

func Test_normal32_g_cmd1()
  " Test for g*, g#
  new
  call append(0, ['abc.x_foo', 'x_foobar.abc'])
  1
  norm! $g*
  call assert_equal('x_foo', @/)
  call assert_equal('x_foobar.abc', getline('.'))
  norm! $g#
  call assert_equal('abc', @/)
  call assert_equal('abc.x_foo', getline('.'))

  " clean up
  bw!
endfunc

fun! Test_normal33_g_cmd2()
  if !has("jumplist")
    return
  endif
  " Tests for g cmds
  call Setup_NewWindow()
  " Test for g`
  clearjumps
  norm! ma10j
  let a=execute(':jumps')
  " empty jumplist
  call assert_equal('>', a[-1:])
  norm! g`a
  call assert_equal('>', a[-1:])
  call assert_equal(1, line('.'))
  call assert_equal('1', getline('.'))

  " Test for g; and g,
  norm! g;
  " there is only one change in the changelist
  " currently, when we setup the window
  call assert_equal(2, line('.'))
  call assert_fails(':norm! g;', 'E662')
  call assert_fails(':norm! g,', 'E663')
  let &ul=&ul
  call append('$', ['a', 'b', 'c', 'd'])
  let &ul=&ul
  call append('$', ['Z', 'Y', 'X', 'W'])
  let a = execute(':changes')
  call assert_match('2\s\+0\s\+2', a)
  call assert_match('101\s\+0\s\+a', a)
  call assert_match('105\s\+0\s\+Z', a)
  norm! 3g;
  call assert_equal(2, line('.'))
  norm! 2g,
  call assert_equal(105, line('.'))

  " Test for g& - global substitute
  %d
  call setline(1, range(1,10))
  call append('$', ['a', 'b', 'c', 'd'])
  $s/\w/&&/g
  exe "norm! /[1-8]\<cr>"
  norm! g&
  call assert_equal(['11', '22', '33', '44', '55', '66', '77', '88', '9', '110', 'a', 'b', 'c', 'dd'], getline(1, '$'))

  " Test for gv
  %d
  call append('$', repeat(['abcdefgh'], 8))
  exe "norm! 2gg02l\<c-v>2j2ly"
  call assert_equal(['cde', 'cde', 'cde'], getreg(0, 1, 1))
  " in visual mode, gv swaps current and last selected region
  exe "norm! G0\<c-v>4k4lgvd"
  call assert_equal(['', 'abfgh', 'abfgh', 'abfgh', 'abcdefgh', 'abcdefgh', 'abcdefgh', 'abcdefgh', 'abcdefgh'], getline(1,'$'))
  exe "norm! G0\<c-v>4k4ly"
  exe "norm! gvood"
  call assert_equal(['', 'abfgh', 'abfgh', 'abfgh', 'fgh', 'fgh', 'fgh', 'fgh', 'fgh'], getline(1,'$'))

  " Test for gk/gj
  %d
  15vsp
  set wrap listchars= sbr=
  let lineA='abcdefghijklmnopqrstuvwxyz'
  let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let lineC='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  $put =lineA
  $put =lineB

  norm! 3gg0dgk
  call assert_equal(['', 'abcdefghijklmno', '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'], getline(1, '$'))
  set nu
  norm! 3gg0gjdgj
  call assert_equal(['', 'abcdefghijklmno', '0123456789AMNOPQRSTUVWXYZ'], getline(1,'$'))

  " Test for gJ
  norm! 2gggJ
  call assert_equal(['', 'abcdefghijklmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$'))
  call assert_equal(16, col('.'))
  " shouldn't do anything
  norm! 10gJ
  call assert_equal(1, col('.'))

  " Test for g0 g^ gm g$
  exe "norm! 2gg0gji   "
  call assert_equal(['', 'abcdefghijk   lmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$'))
  norm! g0yl
  call assert_equal(12, col('.'))
  call assert_equal(' ', getreg(0))
  norm! g$yl
  call assert_equal(22, col('.'))
  call assert_equal('3', getreg(0))
  norm! gmyl
  call assert_equal(17, col('.'))
  call assert_equal('n', getreg(0))
  norm! g^yl
  call assert_equal(15, col('.'))
  call assert_equal('l', getreg(0))

  norm! 2ggdd
  $put =lineC

  " Test for gM
  norm! gMyl
  call assert_equal(73, col('.'))
  call assert_equal('0', getreg(0))
  " Test for 20gM
  norm! 20gMyl
  call assert_equal(29, col('.'))
  call assert_equal('S', getreg(0))
  " Test for 60gM
  norm! 60gMyl
  call assert_equal(87, col('.'))
  call assert_equal('E', getreg(0))

  " Test for g Ctrl-G
  set ff=unix
  let a=execute(":norm! g\<c-g>")
  call assert_match('Col 87 of 144; Line 2 of 2; Word 1 of 1; Byte 88 of 146', a)

  " Test for gI
  norm! gIfoo
  call assert_equal(['', 'foo0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'], getline(1,'$'))

  " Test for gi
  wincmd c
  %d
  set tw=0
  call setline(1, ['foobar', 'new line'])
  norm! A next word
  $put ='third line'
  norm! gi another word
  call assert_equal(['foobar next word another word', 'new line', 'third line'], getline(1,'$'))

  " clean up
  bw!
endfunc

func Test_g_ctrl_g()
  new

  let a = execute(":norm! g\<c-g>")
  call assert_equal("\n--No lines in buffer--", a)

  call setline(1, ['first line', 'second line'])

  " Test g CTRL-g with dos, mac and unix file type.
  norm! gojll
  set ff=dos
  let a = execute(":norm! g\<c-g>")
  call assert_equal("\nCol 3 of 11; Line 2 of 2; Word 3 of 4; Byte 15 of 25", a)

  set ff=mac
  let a = execute(":norm! g\<c-g>")
  call assert_equal("\nCol 3 of 11; Line 2 of 2; Word 3 of 4; Byte 14 of 23", a)

  set ff=unix
  let a = execute(":norm! g\<c-g>")
  call assert_equal("\nCol 3 of 11; Line 2 of 2; Word 3 of 4; Byte 14 of 23", a)

  " Test g CTRL-g in visual mode (v)
  let a = execute(":norm! gojllvlg\<c-g>")
  call assert_equal("\nSelected 1 of 2 Lines; 1 of 4 Words; 2 of 23 Bytes", a)

  " Test g CTRL-g in visual mode (CTRL-V) with end col > start col
  let a = execute(":norm! \<Esc>gojll\<C-V>kllg\<c-g>")
  call assert_equal("\nSelected 3 Cols; 2 of 2 Lines; 2 of 4 Words; 6 of 23 Bytes", a)

  " Test g_CTRL-g in visual mode (CTRL-V) with end col < start col
  let a = execute(":norm! \<Esc>goll\<C-V>jhhg\<c-g>")
  call assert_equal("\nSelected 3 Cols; 2 of 2 Lines; 2 of 4 Words; 6 of 23 Bytes", a)

  " Test g CTRL-g in visual mode (CTRL-V) with end_vcol being MAXCOL
  let a = execute(":norm! \<Esc>gojll\<C-V>k$g\<c-g>")
  call assert_equal("\nSelected 2 of 2 Lines; 4 of 4 Words; 17 of 23 Bytes", a)

  " There should be one byte less with noeol
  set bin noeol
  let a = execute(":norm! \<Esc>gog\<c-g>")
  call assert_equal("\nCol 1 of 10; Line 1 of 2; Word 1 of 4; Char 1 of 23; Byte 1 of 22", a)
  set bin & eol&

  call setline(1, ['Français', '日本語'])

  let a = execute(":norm! \<Esc>gojlg\<c-g>")
  call assert_equal("\nCol 4-3 of 9-6; Line 2 of 2; Word 2 of 2; Char 11 of 13; Byte 16 of 20", a)

  let a = execute(":norm! \<Esc>gojvlg\<c-g>")
  call assert_equal("\nSelected 1 of 2 Lines; 1 of 2 Words; 2 of 13 Chars; 6 of 20 Bytes", a)

  let a = execute(":norm! \<Esc>goll\<c-v>jlg\<c-g>")
  call assert_equal("\nSelected 4 Cols; 2 of 2 Lines; 2 of 2 Words; 6 of 13 Chars; 11 of 20 Bytes", a)

  set fenc=utf8 bomb
  let a = execute(":norm! \<Esc>gojlg\<c-g>")
  call assert_equal("\nCol 4-3 of 9-6; Line 2 of 2; Word 2 of 2; Char 11 of 13; Byte 16 of 20(+3 for BOM)", a)

  set fenc=utf16 bomb
  let a = execute(":norm! g\<c-g>")
  call assert_equal("\nCol 4-3 of 9-6; Line 2 of 2; Word 2 of 2; Char 11 of 13; Byte 16 of 20(+2 for BOM)", a)

  set fenc=utf32 bomb
  let a = execute(":norm! g\<c-g>")
  call assert_equal("\nCol 4-3 of 9-6; Line 2 of 2; Word 2 of 2; Char 11 of 13; Byte 16 of 20(+4 for BOM)", a)

  set fenc& bomb&

  set ff&
  bwipe!
endfunc

fun! Test_normal34_g_cmd3()
  " Test for g8
  new
  let a=execute(':norm! 1G0g8')
  call assert_equal("\nNUL", a)

  call setline(1, 'abcdefghijklmnopqrstuvwxyzäüö')
  let a=execute(':norm! 1G$g8')
  call assert_equal("\nc3 b6 ", a)

  call setline(1, "a\u0302")
  let a=execute(':norm! 1G0g8')
  call assert_equal("\n61 + cc 82 ", a)

  " clean up
  bw!
endfunc

func Test_normal_8g8()
  new

  " Test 8g8 which finds invalid utf8 at or after the cursor.

  " With invalid byte.
  call setline(1, "___\xff___")
  norm! 1G08g8g
  call assert_equal([0, 1, 4, 0, 1], getcurpos())

  " With invalid byte before the cursor.
  call setline(1, "___\xff___")
  norm! 1G$h8g8g
  call assert_equal([0, 1, 6, 0, 9], getcurpos())

  " With truncated sequence.
  call setline(1, "___\xE2\x82___")
  norm! 1G08g8g
  call assert_equal([0, 1, 4, 0, 1], getcurpos())

  " With overlong sequence.
  call setline(1, "___\xF0\x82\x82\xAC___")
  norm! 1G08g8g
  call assert_equal([0, 1, 4, 0, 1], getcurpos())

  " With valid utf8.
  call setline(1, "café")
  norm! 1G08g8
  call assert_equal([0, 1, 1, 0, 1], getcurpos())

  bw!
endfunc

fun! Test_normal35_g_cmd4()
  " Test for g<
  " Cannot capture its output,
  " probably a bug, therefore, test disabled:
  throw "Skipped: output of g< can't be tested currently"
  echo "a\nb\nc\nd"
  let b=execute(':norm! g<')
  call assert_true(!empty(b), 'failed `execute(g<)`')
endfunc

fun! Test_normal36_g_cmd5()
  new
  call append(0, 'abcdefghijklmnopqrstuvwxyz')
  set ff=unix
  " Test for gp gP
  call append(1, range(1,10))
  1
  norm! 1yy
  3
  norm! gp
  call assert_equal([0, 5, 1, 0, 1], getcurpos())
  $
  norm! gP
  call assert_equal([0, 14, 1, 0, 1], getcurpos())

  " Test for go
  norm! 26go
  call assert_equal([0, 1, 26, 0, 26], getcurpos())
  norm! 27go
  call assert_equal([0, 1, 26, 0, 26], getcurpos())
  norm! 28go
  call assert_equal([0, 2, 1, 0, 1], getcurpos())
  set ff=dos
  norm! 29go
  call assert_equal([0, 2, 1, 0, 1], getcurpos())
  set ff=unix
  norm! gg0
  norm! 101go
  call assert_equal([0, 13, 26, 0, 26], getcurpos())
  norm! 103go
  call assert_equal([0, 14, 1, 0, 1], getcurpos())
  " count > buffer content
  norm! 120go
  call assert_equal([0, 14, 1, 0, 2147483647], getcurpos())
  " clean up
  bw!
endfunc

fun! Test_normal37_g_cmd6()
  " basic test for gt and gT
  tabnew 1.txt
  tabnew 2.txt
  tabnew 3.txt
  norm! 1gt
  call assert_equal(1, tabpagenr())
  norm! 3gt
  call assert_equal(3, tabpagenr())
  norm! 1gT
  " count gT goes not to the absolute tabpagenumber
  " but, but goes to the count previous tabpagenumber
  call assert_equal(2, tabpagenr())
  " wrap around
  norm! 3gT
  call assert_equal(3, tabpagenr())
  " gt does not wrap around
  norm! 5gt
  call assert_equal(3, tabpagenr())

  for i in range(3)
    tabclose
  endfor
  " clean up
  call assert_fails(':tabclose', 'E784')
endfunc

fun! Test_normal38_nvhome()
  " Test for <Home> and <C-Home> key
  new
  call setline(1, range(10))
  $
  setl et sw=2
  norm! V10>$
  " count is ignored
  exe "norm! 10\<home>"
  call assert_equal(1, col('.'))
  exe "norm! \<home>"
  call assert_equal([0, 10, 1, 0, 1], getcurpos())
  exe "norm! 5\<c-home>"
  call assert_equal([0, 5, 1, 0, 1], getcurpos())
  exe "norm! \<c-home>"
  call assert_equal([0, 1, 1, 0, 1], getcurpos())

  " clean up
  bw!
endfunc

fun! Test_normal39_cw()
  " Test for cw and cW on whitespace
  " and cpo+=w setting
  new
  set tw=0
  call append(0, 'here      are   some words')
  norm! 1gg0elcwZZZ
  call assert_equal('hereZZZare   some words', getline('.'))
  norm! 1gg0elcWYYY
  call assert_equal('hereZZZareYYYsome words', getline('.'))
  " Nvim: no "w" flag in 'cpoptions'.
  " set cpo+=w
  " call setline(1, 'here      are   some words')
  " norm! 1gg0elcwZZZ
  " call assert_equal('hereZZZ     are   some words', getline('.'))
  " norm! 1gg2elcWYYY
  " call assert_equal('hereZZZ     areYYY  some words', getline('.'))
  set cpo-=w
  norm! 2gg0cwfoo
  call assert_equal('foo', getline('.'))

  " clean up
  bw!
endfunc

fun! Test_normal40_ctrl_bsl()
  " Basic test for CTRL-\ commands
  new
  call append(0, 'here      are   some words')
  exe "norm! 1gg0a\<C-\>\<C-N>"
  call assert_equal('n', mode())
  call assert_equal(1, col('.'))
  call assert_equal('', visualmode())
  exe "norm! 1gg0viw\<C-\>\<C-N>"
  call assert_equal('n', mode())
  call assert_equal(4, col('.'))
  exe "norm! 1gg0a\<C-\>\<C-G>"
  call assert_equal('n', mode())
  call assert_equal(1, col('.'))
  "imap <buffer> , <c-\><c-n>
  set im
  exe ":norm! \<c-\>\<c-n>dw"
  set noim
  call assert_equal('are   some words', getline(1))
  call assert_false(&insertmode)

  " clean up
  bw!
endfunc

fun! Test_normal41_insert_reg()
  " Test for <c-r>=, <c-r><c-r>= and <c-r><c-o>=
  " in insert mode
  new
  set sts=2 sw=2 ts=8 tw=0
  call append(0, ["aaa\tbbb\tccc", '', '', ''])
  let a=getline(1)
  norm! 2gg0
  exe "norm! a\<c-r>=a\<cr>"
  norm! 3gg0
  exe "norm! a\<c-r>\<c-r>=a\<cr>"
  norm! 4gg0
  exe "norm! a\<c-r>\<c-o>=a\<cr>"
  call assert_equal(['aaa	bbb	ccc', 'aaa bbb	ccc', 'aaa bbb	ccc', 'aaa	bbb	ccc', ''], getline(1, '$'))

  " clean up
  set sts=0 sw=8 ts=8
  bw!
endfunc

func Test_normal42_halfpage()
  " basic test for Ctrl-D and Ctrl-U
  call Setup_NewWindow()
  call assert_equal(5, &scroll)
  exe "norm! \<c-d>"
  call assert_equal('6', getline('.'))
  exe "norm! 2\<c-d>"
  call assert_equal('8', getline('.'))
  call assert_equal(2, &scroll)
  set scroll=5
  exe "norm! \<c-u>"
  call assert_equal('3', getline('.'))
  1
  set scrolloff=5
  exe "norm! \<c-d>"
  call assert_equal('10', getline('.'))
  exe "norm! \<c-u>"
  call assert_equal('5', getline('.'))
  1
  set scrolloff=99
  exe "norm! \<c-d>"
  call assert_equal('10', getline('.'))
  set scrolloff=0
  100
  exe "norm! $\<c-u>"
  call assert_equal('95', getline('.'))
  call assert_equal([0, 95, 1, 0, 1], getcurpos())
  100
  set nostartofline
  exe "norm! $\<c-u>"
  call assert_equal('95', getline('.'))
  call assert_equal([0, 95, 2, 0, 2147483647], getcurpos())
  " cleanup
  set startofline
  bw!
endfunc

fun! Test_normal43_textobject1()
  " basic tests for text object aw
  new
  call append(0, ['foobar,eins,foobar', 'foo,zwei,foo    '])
  " diw
  norm! 1gg0diw
  call assert_equal([',eins,foobar', 'foo,zwei,foo    ', ''], getline(1,'$'))
  " daw
  norm! 2ggEdaw
  call assert_equal([',eins,foobar', 'foo,zwei,', ''], getline(1, '$'))
  %d
  call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo   "])
  " diW
  norm! 2ggwd2iW
  call assert_equal(['foo	eins	foobar', 'foo	foo   ', ''], getline(1,'$'))
  " daW
  norm! 1ggd2aW
  call assert_equal(['foobar', 'foo	foo   ', ''], getline(1,'$'))

  %d
  call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo   "])
  " aw in visual line mode switches to characterwise mode
  norm! 2gg$Vawd
  call assert_equal(['foo	eins	foobar', 'foo	zwei	foo'], getline(1,'$'))
  norm! 1gg$Viwd
  call assert_equal(['foo	eins	', 'foo	zwei	foo'], getline(1,'$'))

  " clean up
  bw!
endfunc

func Test_normal44_textobjects2()
  " basic testing for is and as text objects
  new
  call append(0, ['This is a test. With some sentences!', '', 'Even with a question? And one more. And no sentence here'])
  " Test for dis - does not remove trailing whitespace
  norm! 1gg0dis
  call assert_equal([' With some sentences!', '', 'Even with a question? And one more. And no sentence here', ''], getline(1,'$'))
  " Test for das - removes leading whitespace
  norm! 3ggf?ldas
  call assert_equal([' With some sentences!', '', 'Even with a question? And no sentence here', ''], getline(1,'$'))
  " when used in visual mode, is made characterwise
  norm! 3gg$Visy
  call assert_equal('v', visualmode())
  " reset visualmode()
  norm! 3ggVy
  norm! 3gg$Vasy
  call assert_equal('v', visualmode())
  " basic testing for textobjects a< and at
  %d
  call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>','    </div>', ' '])
  " a<
  norm! 1gg0da<
  call assert_equal([' ', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
  norm! 1pj
  call assert_equal([' <div>', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
  " at
  norm! d2at
  call assert_equal([' '], getline(1,'$'))
  %d
  call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>','    </div>', ' '])
  " i<
  norm! 1gg0di<
  call assert_equal(['<> ', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
  norm! 1Pj
  call assert_equal(['<div> ', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
  norm! d2it
  call assert_equal(['<div></div>',' '], getline(1,'$'))
  " basic testing for a[ and i[ text object
  %d
  call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
  norm! 3gg0di[
  call assert_equal([' ', '[', ']'], getline(1,'$'))
  call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
  norm! 3gg0ftd2a[
  call assert_equal([' '], getline(1,'$'))
  %d
  " Test for i" when cursor is in front of a quoted object
  call append(0, 'foo "bar"')
  norm! 1gg0di"
  call assert_equal(['foo ""', ''], getline(1,'$'))

  " clean up
  bw!
endfunc

func Test_normal45_drop()
  if !has('dnd')
    " The ~ register does not exist
    call assert_beeps('norm! "~')
    return
  endif

  " basic test for drag-n-drop
  " unfortunately, without a gui, we can't really test much here,
  " so simply test that ~p fails (which uses the drop register)
  new
  call assert_fails(':norm! "~p', 'E353')
  call assert_equal([],  getreg('~', 1, 1))
  " the ~ register is read only
  call assert_fails(':let @~="1"', 'E354')
  bw!
endfunc

func Test_normal46_ignore()
  new
  " How to test this?
  " let's just for now test, that the buffer
  " does not change
  call feedkeys("\<c-s>", 't')
  call assert_equal([''], getline(1,'$'))

  " no valid commands
  exe "norm! \<char-0x100>"
  call assert_equal([''], getline(1,'$'))

  exe "norm! ä"
  call assert_equal([''], getline(1,'$'))

  " clean up
  bw!
endfunc

func Test_normal47_visual_buf_wipe()
  " This was causing a crash or ml_get error.
  enew!
  call setline(1,'xxx')
  normal $
  new
  call setline(1, range(1,2))
  2
  exe "norm \<C-V>$"
  bw!
  norm yp
  set nomodified
endfunc

func Test_normal47_autocmd()
  " disabled, does not seem to be possible currently
  throw "Skipped: not possible to test cursorhold autocmd while waiting for input in normal_cmd"
  new
  call append(0, repeat('-',20))
  au CursorHold * call feedkeys('2l', '')
  1
  set updatetime=20
  " should delete 12 chars (d12l)
  call feedkeys('d1', '!')
  call assert_equal('--------', getline(1))

  " clean up
  au! CursorHold
  set updatetime=4000
  bw!
endfunc

func Test_normal48_wincmd()
  new
  exe "norm! \<c-w>c"
  call assert_equal(1, winnr('$'))
  call assert_fails(":norm! \<c-w>c", "E444")
endfunc

func Test_normal49_counts()
  new
  call setline(1, 'one two three four five six seven eight nine ten')
  1
  norm! 3d2w
  call assert_equal('seven eight nine ten', getline(1))
  bw!
endfunc

func Test_normal50_commandline()
  if !has("timers") || !has("cmdline_hist") || !has("vertsplit")
    return
  endif
  func! DoTimerWork(id)
    call assert_equal('[Command Line]', bufname(''))
    " should fail, with E11, but does fail with E23?
    "call feedkeys("\<c-^>", 'tm')

    " should also fail with E11
    call assert_fails(":wincmd p", 'E11')
    " return from commandline window
    call feedkeys("\<cr>")
  endfunc

  let oldlang=v:lang
  lang C
  set updatetime=20
  call timer_start(100, 'DoTimerWork')
  try
    " throws E23, for whatever reason...
    call feedkeys('q:', 'x!')
  catch /E23/
    " no-op
  endtry
  " clean up
  set updatetime=4000
  exe "lang" oldlang
  bw!
endfunc

func Test_normal51_FileChangedRO()
  if !has("autocmd")
    return
  endif
  call writefile(['foo'], 'Xreadonly.log')
  new Xreadonly.log
  setl ro
  au FileChangedRO <buffer> :call feedkeys("\<c-^>", 'tix')
  call assert_fails(":norm! Af", 'E788')
  call assert_equal(['foo'], getline(1,'$'))
  call assert_equal('Xreadonly.log', bufname(''))

  " cleanup
  bw!
  call delete("Xreadonly.log")
endfunc

func Test_normal52_rl()
  if !has("rightleft")
    return
  endif
  new
  call setline(1, 'abcde fghij klmnopq')
  norm! 1gg$
  set rl
  call assert_equal(19, col('.'))
  call feedkeys('l', 'tx')
  call assert_equal(18, col('.'))
  call feedkeys('h', 'tx')
  call assert_equal(19, col('.'))
  call feedkeys("\<right>", 'tx')
  call assert_equal(18, col('.'))
  call feedkeys("\<s-right>", 'tx')
  call assert_equal(13, col('.'))
  call feedkeys("\<c-right>", 'tx')
  call assert_equal(7, col('.'))
  call feedkeys("\<c-left>", 'tx')
  call assert_equal(13, col('.'))
  call feedkeys("\<s-left>", 'tx')
  call assert_equal(19, col('.'))
  call feedkeys("<<", 'tx')
  call assert_equal('	abcde fghij klmnopq',getline(1))
  call feedkeys(">>", 'tx')
  call assert_equal('abcde fghij klmnopq',getline(1))

  " cleanup
  set norl
  bw!
endfunc

func Test_normal53_digraph()
  if !has('digraphs')
    return
  endif
  new
  call setline(1, 'abcdefgh|')
  exe "norm! 1gg0f\<c-k>!!"
  call assert_equal(9, col('.'))
  set cpo+=D
  exe "norm! 1gg0f\<c-k>!!"
  call assert_equal(1, col('.'))

  set cpo-=D
  bw!
endfunc

func Test_normal54_Ctrl_bsl()
  new
  call setline(1, 'abcdefghijklmn')
  exe "norm! df\<c-\>\<c-n>"
  call assert_equal(['abcdefghijklmn'], getline(1,'$'))
  exe "norm! df\<c-\>\<c-g>"
  call assert_equal(['abcdefghijklmn'], getline(1,'$'))
  exe "norm! df\<c-\>m"
  call assert_equal(['abcdefghijklmn'], getline(1,'$'))

  call setline(2, 'abcdefghijklmnāf')
  norm! 2gg0
  exe "norm! df\<Char-0x101>"
  call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$'))
  norm! 1gg0
  exe "norm! df\<esc>"
  call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$'))

  " clean up
  bw!
endfunc

func Test_normal_large_count()
  " This may fail with 32bit long, how do we detect that?
  new
  normal o
  normal 6666666666dL
  bwipe!
endfunc

func Test_delete_until_paragraph()
  new
  normal grádv}
  call assert_equal('á', getline(1))
  normal grád}
  call assert_equal('', getline(1))
  bwipe!
endfunc

" Test for the gr (virtual replace) command
" Test for the bug fixed by 7.4.387
func Test_gr_command()
  enew!
  let save_cpo = &cpo
  call append(0, ['First line', 'Second line', 'Third line'])
  exe "normal i\<C-G>u"
  call cursor(2, 1)
  set cpo-=X
  normal 4gro
  call assert_equal('oooond line', getline(2))
  undo
  set cpo+=X
  normal 4gro
  call assert_equal('ooooecond line', getline(2))
  let &cpo = save_cpo
  enew!
endfunc

" When splitting a window the changelist position is wrong.
" Test the changelist position after splitting a window.
" Test for the bug fixed by 7.4.386
func Test_changelist()
  let save_ul = &ul
  enew!
  call append('$', ['1', '2'])
  exe "normal i\<C-G>u"
  exe "normal Gkylpa\<C-G>u"
  set ul=100
  exe "normal Gylpa\<C-G>u"
  set ul=100
  normal gg
  vsplit
  normal g;
  call assert_equal([3, 2], [line('.'), col('.')])
  normal g;
  call assert_equal([2, 2], [line('.'), col('.')])
  call assert_fails('normal g;', 'E662:')
  %bwipe!
  let &ul = save_ul
endfunc

func Test_nv_hat_count()
  %bwipeout!
  let l:nr = bufnr('%') + 1
  call assert_fails(':execute "normal! ' . l:nr . '\<C-^>"', 'E92')

  edit Xfoo
  let l:foo_nr = bufnr('Xfoo')

  edit Xbar
  let l:bar_nr = bufnr('Xbar')

  " Make sure we are not just using the alternate file.
  edit Xbaz

  call feedkeys(l:foo_nr . "\<C-^>", 'tx')
  call assert_equal('Xfoo', fnamemodify(bufname('%'), ':t'))

  call feedkeys(l:bar_nr . "\<C-^>", 'tx')
  call assert_equal('Xbar', fnamemodify(bufname('%'), ':t'))

  %bwipeout!
endfunc

func Test_message_when_using_ctrl_c()
  " Make sure no buffers are changed.
  %bwipe!

  exe "normal \<C-C>"
  call assert_match("Type  :qa  and press <Enter> to exit Nvim", Screenline(&lines))

  new
  cal setline(1, 'hi!')
  exe "normal \<C-C>"
  call assert_match("Type  :qa!  and press <Enter> to abandon all changes and exit Nvim", Screenline(&lines))

  bwipe!
endfunc

" Test for '[m', ']m', '[M' and ']M'
" Jumping to beginning and end of methods in Java-like languages
func Test_java_motion()
  new
  a
Piece of Java
{
	tt m1 {
		t1;
	} e1

	tt m2 {
		t2;
	} e2

	tt m3 {
		if (x)
		{
			t3;
		}
	} e3
}
.

  normal gg

  normal 2]maA
  call assert_equal("\ttt m1 {A", getline('.'))
  call assert_equal([3, 9, 16], [line('.'), col('.'), virtcol('.')])

  normal j]maB
  call assert_equal("\ttt m2 {B", getline('.'))
  call assert_equal([7, 9, 16], [line('.'), col('.'), virtcol('.')])

  normal ]maC
  call assert_equal("\ttt m3 {C", getline('.'))
  call assert_equal([11, 9, 16], [line('.'), col('.'), virtcol('.')])

  normal [maD
  call assert_equal("\ttt m3 {DC", getline('.'))
  call assert_equal([11, 9, 16], [line('.'), col('.'), virtcol('.')])

  normal k2[maE
  call assert_equal("\ttt m1 {EA", getline('.'))
  call assert_equal([3, 9, 16], [line('.'), col('.'), virtcol('.')])

  normal 3[maF
  call assert_equal("{F", getline('.'))
  call assert_equal([2, 2, 2], [line('.'), col('.'), virtcol('.')])

  normal ]MaG
  call assert_equal("\t}G e1", getline('.'))
  call assert_equal([5, 3, 10], [line('.'), col('.'), virtcol('.')])

  normal j2]MaH
  call assert_equal("\t}H e3", getline('.'))
  call assert_equal([16, 3, 10], [line('.'), col('.'), virtcol('.')])

  normal ]M]M
  normal aI
  call assert_equal("}I", getline('.'))
  call assert_equal([17, 2, 2], [line('.'), col('.'), virtcol('.')])

  normal 2[MaJ
  call assert_equal("\t}JH e3", getline('.'))
  call assert_equal([16, 3, 10], [line('.'), col('.'), virtcol('.')])

  normal k[MaK
  call assert_equal("\t}K e2", getline('.'))
  call assert_equal([9, 3, 10], [line('.'), col('.'), virtcol('.')])

  normal 3[MaL
  call assert_equal("{LF", getline('.'))
  call assert_equal([2, 2, 2], [line('.'), col('.'), virtcol('.')])

  close!
endfunc

fun! Test_normal_gdollar_cmd()
  if !has("jumplist")
    return
  endif
  " Tests for g cmds
  call Setup_NewWindow()
  " Make long lines that will wrap
  %s/$/\=repeat(' foobar', 10)/
  20vsp
  set wrap
  " Test for g$ with count
  norm! gg
  norm! 0vg$y
  call assert_equal(20, col("'>"))
  call assert_equal('1 foobar foobar foob', getreg(0))
  norm! gg
  norm! 0v4g$y
  call assert_equal(72, col("'>"))
  call assert_equal('1 foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar'.."\n", getreg(0))
  norm! gg
  norm! 0v6g$y
  call assert_equal(40, col("'>"))
  call assert_equal('1 foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar'.. "\n"..
		  \ '2 foobar foobar foobar foobar foobar foo', getreg(0))
  set nowrap
  " clean up
  norm! gg
  norm! 0vg$y
  call assert_equal(20, col("'>"))
  call assert_equal('1 foobar foobar foob', getreg(0))
  norm! gg
  norm! 0v4g$y
  call assert_equal(20, col("'>"))
  call assert_equal('1 foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar'.. "\n"..
                 \  '2 foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar'.. "\n"..
                 \  '3 foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar'.. "\n"..
                 \  '4 foobar foobar foob', getreg(0))
  norm! gg
  norm! 0v6g$y
  call assert_equal(20, col("'>"))
  call assert_equal('1 foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar'.. "\n"..
                 \  '2 foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar'.. "\n"..
                 \  '3 foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar'.. "\n"..
                 \  '4 foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar'.. "\n"..
                 \  '5 foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar'.. "\n"..
                 \  '6 foobar foobar foob', getreg(0))
  " Move to last line, also down movement is not possible, should still move
  " the cursor to the last visible char
  norm! G
  norm! 0v6g$y
  call assert_equal(20, col("'>"))
  call assert_equal('100 foobar foobar fo', getreg(0))
  bw!
endfunc

func Test_normal_gk()
  " needs 80 column new window
  new
  vert 80new
  put =[repeat('x',90)..' {{{1', 'x {{{1']
  norm! gk
  " In a 80 column wide terminal the window will be only 78 char
  " (because Vim will leave space for the other window),
  " but if the terminal is larger, it will be 80 chars, so verify the
  " cursor column correctly.
  call assert_equal(winwidth(0)+1, col('.'))
  call assert_equal(winwidth(0)+1, virtcol('.'))
  norm! j
  call assert_equal(6, col('.'))
  call assert_equal(6, virtcol('.'))
  norm! gk
  call assert_equal(95, col('.'))
  call assert_equal(95, virtcol('.'))
  bw!
  bw!

  " needs 80 column new window
  new
  vert 80new
  set number
  set numberwidth=10
  set cpoptions+=n
  put =[repeat('0',90), repeat('1',90)]
  norm! 075l
  call assert_equal(76, col('.'))
  norm! gk
  call assert_equal(1, col('.'))
  norm! gk
  call assert_equal(76, col('.'))
  norm! gk
  call assert_equal(1, col('.'))
  norm! gj
  call assert_equal(76, col('.'))
  norm! gj
  call assert_equal(1, col('.'))
  norm! gj
  call assert_equal(76, col('.'))
  bw!
  bw!
  set cpoptions& number& numberwidth&
endfunc

" Some commands like yy, cc, dd, >>, << and !! accept a count after
" typing the first letter of the command.
func Test_normal_count_after_operator()
  new
  setlocal shiftwidth=4 tabstop=8 autoindent
  call setline(1, ['one', 'two', 'three', 'four', 'five'])
  let @a = ''
  normal! j"ay4y
  call assert_equal("two\nthree\nfour\nfive\n", @a)
  normal! 3G>2>
  call assert_equal(['one', 'two', '    three', '    four', 'five'],
        \ getline(1, '$'))
  exe "normal! 3G0c2cred\nblue"
  call assert_equal(['one', 'two', '    red', '    blue', 'five'],
        \ getline(1, '$'))
  exe "normal! gg<8<"
  call assert_equal(['one', 'two', 'red', 'blue', 'five'],
        \ getline(1, '$'))
  exe "normal! ggd3d"
  call assert_equal(['blue', 'five'], getline(1, '$'))
  call setline(1, range(1, 4))
  call feedkeys("gg!3!\<C-B>\"\<CR>", 'xt')
  call assert_equal('".,.+2!', @:)
  call feedkeys("gg!1!\<C-B>\"\<CR>", 'xt')
  call assert_equal('".!', @:)
  call feedkeys("gg!9!\<C-B>\"\<CR>", 'xt')
  call assert_equal('".,$!', @:)
  bw!
endfunc

" vim: shiftwidth=2 sts=2 expandtab
