textchanged_spec.lua (5191B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 4 local clear = n.clear 5 local exec = n.exec 6 local command = n.command 7 local feed = n.feed 8 local eq = t.eq 9 local neq = t.neq 10 local eval = n.eval 11 local poke_eventloop = n.poke_eventloop 12 local write_file = t.write_file 13 14 -- oldtest: Test_ChangedP() 15 it('TextChangedI and TextChangedP autocommands', function() 16 clear() 17 -- The oldtest uses feedkeys() with 'x' flag, which never triggers TextChanged. 18 -- So don't add TextChanged autocommand here. 19 exec([[ 20 call setline(1, ['foo', 'bar', 'foobar']) 21 set complete=. completeopt=menuone 22 au! TextChangedI <buffer> let g:autocmd ..= 'I' 23 au! TextChangedP <buffer> let g:autocmd ..= 'P' 24 call cursor(3, 1) 25 ]]) 26 27 command([[let g:autocmd = '']]) 28 feed('o') 29 poke_eventloop() 30 feed('<esc>') 31 -- TextChangedI triggers only if text is actually changed in Insert mode 32 eq('I', eval('g:autocmd')) 33 34 command([[let g:autocmd = '']]) 35 feed('S') 36 poke_eventloop() 37 feed('f') 38 poke_eventloop() 39 eq('II', eval('g:autocmd')) 40 feed('<esc>') 41 42 command([[let g:autocmd = '']]) 43 feed('S') 44 poke_eventloop() 45 feed('f') 46 poke_eventloop() 47 feed('<C-N>') 48 poke_eventloop() 49 eq('IIP', eval('g:autocmd')) 50 feed('<esc>') 51 52 command([[let g:autocmd = '']]) 53 feed('S') 54 poke_eventloop() 55 feed('f') 56 poke_eventloop() 57 feed('<C-N>') 58 poke_eventloop() 59 feed('<C-N>') 60 poke_eventloop() 61 eq('IIPP', eval('g:autocmd')) 62 feed('<esc>') 63 64 command([[let g:autocmd = '']]) 65 feed('S') 66 poke_eventloop() 67 feed('f') 68 poke_eventloop() 69 feed('<C-N>') 70 poke_eventloop() 71 feed('<C-N>') 72 poke_eventloop() 73 feed('<C-N>') 74 poke_eventloop() 75 eq('IIPPP', eval('g:autocmd')) 76 feed('<esc>') 77 78 command([[let g:autocmd = '']]) 79 feed('S') 80 poke_eventloop() 81 feed('f') 82 poke_eventloop() 83 feed('<C-N>') 84 poke_eventloop() 85 feed('<C-N>') 86 poke_eventloop() 87 feed('<C-N>') 88 poke_eventloop() 89 feed('<C-N>') 90 eq('IIPPPP', eval('g:autocmd')) 91 feed('<esc>') 92 93 eq({ 'foo', 'bar', 'foobar', 'foo' }, eval('getline(1, "$")')) 94 end) 95 96 -- oldtest: Test_TextChangedI_with_setline() 97 it('TextChangedI with setline()', function() 98 clear() 99 exec([[ 100 let g:setline_handled = v:false 101 func SetLineOne() 102 if !g:setline_handled 103 call setline(1, "(x)") 104 let g:setline_handled = v:true 105 endif 106 endfunc 107 autocmd TextChangedI <buffer> call SetLineOne() 108 ]]) 109 110 feed('i') 111 poke_eventloop() 112 feed('(') 113 poke_eventloop() 114 feed('<CR>') 115 poke_eventloop() 116 feed('<Esc>') 117 eq('(', eval('getline(1)')) 118 eq('x)', eval('getline(2)')) 119 command('undo') 120 eq('', eval('getline(1)')) 121 eq('', eval('getline(2)')) 122 end) 123 124 -- oldtest: Test_TextChanged_with_norm() 125 it('TextChanged is triggered after :norm that enters Insert mode', function() 126 clear() 127 exec([[ 128 let g:a = 0 129 au TextChanged * let g:a += 1 130 ]]) 131 eq(0, eval('g:a')) 132 feed(':norm! ia<CR>') 133 eq(1, eval('g:a')) 134 end) 135 136 -- oldtest: Test_Changed_ChangedI() 137 it('TextChangedI and TextChanged', function() 138 write_file('XTextChangedI2', 'one\ntwo\nthree') 139 finally(function() 140 os.remove('XTextChangedI2') 141 end) 142 clear('XTextChangedI2') 143 144 exec([[ 145 let [g:autocmd_n, g:autocmd_i] = ['',''] 146 147 func TextChangedAutocmd(char) 148 let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick 149 endfunc 150 151 au TextChanged <buffer> :call TextChangedAutocmd('N') 152 au TextChangedI <buffer> :call TextChangedAutocmd('I') 153 154 nnoremap <CR> o<Esc> 155 ]]) 156 157 -- TextChanged should trigger if a mapping enters and leaves Insert mode. 158 feed('<CR>') 159 eq('N4', eval('g:autocmd_n')) 160 eq('', eval('g:autocmd_i')) 161 162 feed('i') 163 eq('N4', eval('g:autocmd_n')) 164 eq('', eval('g:autocmd_i')) 165 -- TextChangedI should trigger if change is done in Insert mode. 166 feed('f') 167 eq('N4', eval('g:autocmd_n')) 168 eq('I5', eval('g:autocmd_i')) 169 feed('o') 170 eq('N4', eval('g:autocmd_n')) 171 eq('I6', eval('g:autocmd_i')) 172 feed('o') 173 eq('N4', eval('g:autocmd_n')) 174 eq('I7', eval('g:autocmd_i')) 175 -- TextChanged shouldn't trigger when leaving Insert mode and TextChangedI 176 -- has been triggered. 177 feed('<Esc>') 178 eq('N4', eval('g:autocmd_n')) 179 eq('I7', eval('g:autocmd_i')) 180 181 -- TextChanged should trigger if change is done in Normal mode. 182 feed('yyp') 183 eq('N8', eval('g:autocmd_n')) 184 eq('I7', eval('g:autocmd_i')) 185 186 -- TextChangedI shouldn't trigger if change isn't done in Insert mode. 187 feed('i') 188 eq('N8', eval('g:autocmd_n')) 189 eq('I7', eval('g:autocmd_i')) 190 feed('<Esc>') 191 eq('N8', eval('g:autocmd_n')) 192 eq('I7', eval('g:autocmd_i')) 193 194 -- TextChangedI should trigger if change is a mix of Normal and Insert modes. 195 local function validate_mixed_textchangedi(keys) 196 feed('ifoo<Esc>') 197 command(":let [g:autocmd_n, g:autocmd_i] = ['', '']") 198 feed(keys) 199 eq('', eval('g:autocmd_n')) 200 neq('', eval('g:autocmd_i')) 201 feed('<Esc>') 202 eq('', eval('g:autocmd_n')) 203 neq('', eval('g:autocmd_i')) 204 end 205 206 validate_mixed_textchangedi('o') 207 validate_mixed_textchangedi('O') 208 validate_mixed_textchangedi('ciw') 209 validate_mixed_textchangedi('cc') 210 validate_mixed_textchangedi('C') 211 validate_mixed_textchangedi('s') 212 validate_mixed_textchangedi('S') 213 end)