markset_spec.lua (6316B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 4 local api = n.api 5 local clear = n.clear 6 local command = n.command 7 local feed = n.feed 8 local poke_eventloop = n.poke_eventloop 9 local eval = n.eval 10 11 local eq = t.eq 12 local neq = t.neq 13 14 describe('MarkSet', function() 15 -- TODO(justinmk): support other marks?: [, ] <, > . ^ " ' 16 17 before_each(function() 18 clear() 19 end) 20 21 it('emits when lowercase/uppercase/[/] marks are set', function() 22 command([[ 23 let g:mark_names = '' 24 let g:mark_events = [] 25 autocmd MarkSet * call add(g:mark_events, {'event': deepcopy(v:event)}) | let g:mark_names ..= expand('<amatch>') 26 " TODO: there is a bug lurking here. 27 " autocmd MarkSet * let g:mark_names ..= expand('<amatch>') 28 ]]) 29 30 api.nvim_buf_set_lines(0, 0, -1, true, { 31 'foo\0bar', 32 'baz text', 33 'line 3', 34 }) 35 36 feed('ma') 37 feed('j') 38 command('mark b') 39 40 poke_eventloop() 41 eq('ab', eval('g:mark_names')) 42 43 -- event-data is copied to `v:event`. 44 eq({ 45 { 46 event = { 47 col = 0, 48 line = 1, 49 name = 'a', 50 }, 51 }, 52 { 53 event = { 54 col = 0, 55 line = 2, 56 name = 'b', 57 }, 58 }, 59 }, eval('g:mark_events')) 60 61 feed('mA') 62 feed('l') 63 feed('mB') 64 feed('j') 65 feed('mC') 66 67 feed('x') -- TODO(justinmk): Sets [,] marks but does not emit MarkSet event (yet). 68 feed('0vll<esc>') -- TODO(justinmk): Sets <,> marks but does not emit MarkSet event (yet). 69 -- XXX: set these marks manually to exercise these cases. 70 api.nvim_buf_set_mark(0, '[', 2, 0, {}) 71 api.nvim_buf_set_mark(0, ']', 2, 0, {}) 72 api.nvim_buf_set_mark(0, '<', 2, 0, {}) 73 api.nvim_buf_set_mark(0, '>', 2, 0, {}) 74 api.nvim_buf_set_mark(0, '"', 2, 0, {}) 75 76 poke_eventloop() 77 eq('abABC[]<>"', eval('g:mark_names')) 78 end) 79 80 it('can subscribe to specific marks by pattern', function() 81 command([[ 82 let g:mark_names = '' 83 autocmd MarkSet [ab] let g:mark_names ..= expand('<amatch>') 84 ]]) 85 86 api.nvim_buf_set_lines(0, 0, -1, true, { 87 'foo\0bar', 88 'baz text', 89 }) 90 91 feed('md') 92 feed('mc') 93 feed('l') 94 feed('mb') 95 feed('j') 96 feed('ma') 97 98 poke_eventloop() 99 eq('ba', eval('g:mark_names')) 100 end) 101 102 it('handles marks across multiple windows/buffers', function() 103 local orig_bufnr = api.nvim_get_current_buf() 104 105 command('enew') 106 local second_bufnr = api.nvim_get_current_buf() 107 api.nvim_buf_set_lines(second_bufnr, 0, -1, true, { 108 'second buffer line 1', 109 'second buffer line 2', 110 }) 111 112 command('enew') 113 local third_bufnr = api.nvim_get_current_buf() 114 api.nvim_buf_set_lines(third_bufnr, 0, -1, true, { 115 'third buffer line 1', 116 'third buffer line 2', 117 }) 118 119 command('split') 120 command('vsplit') 121 122 command('tabnew') 123 command('split') 124 125 command([[ 126 let g:markset_events = [] 127 autocmd MarkSet * call add(g:markset_events, { 'buf': 0 + expand('<abuf>'), 'event': deepcopy(v:event) }) 128 ]]) 129 130 command('buffer ' .. orig_bufnr) 131 feed('gg') 132 feed('mA') 133 134 command('wincmd w') 135 command('tabnext') 136 137 feed('mB') 138 139 command('wincmd w') 140 command('enew') 141 142 local final_bufnr = api.nvim_get_current_buf() 143 api.nvim_buf_set_lines(final_bufnr, 0, -1, true, { 144 'final buffer after chaos', 145 'line 2 of final buffer', 146 }) 147 148 feed('j') 149 feed('mC') 150 151 command('tabclose') 152 153 feed('mD') 154 155 poke_eventloop() 156 eq({ 157 { 158 buf = 1, 159 event = { 160 col = 0, 161 line = 1, 162 name = 'A', 163 }, 164 }, 165 { 166 buf = 2, 167 event = { 168 col = 0, 169 line = 1, 170 name = 'B', 171 }, 172 }, 173 { 174 buf = 4, 175 event = { 176 col = 0, 177 line = 2, 178 name = 'C', 179 }, 180 }, 181 { 182 buf = 3, 183 event = { 184 col = 0, 185 line = 1, 186 name = 'D', 187 }, 188 }, 189 }, eval('g:markset_events')) 190 end) 191 192 it('handles an autocommand that calls bwipeout!', function() 193 api.nvim_buf_set_lines(0, 0, -1, true, { 194 'line 1', 195 'line 2', 196 'line 3', 197 }) 198 199 local test_bufnr = api.nvim_get_current_buf() 200 201 command("autocmd MarkSet * let g:autocmd ..= expand('<amatch>') | bwipeout!") 202 command([[let g:autocmd = '']]) 203 204 feed('ma') 205 poke_eventloop() 206 207 eq('a', eval('g:autocmd')) 208 209 eq(false, api.nvim_buf_is_valid(test_bufnr)) 210 211 local current_bufnr = api.nvim_get_current_buf() 212 neq(current_bufnr, test_bufnr) 213 end) 214 215 it('when autocommand switches windows and tabs', function() 216 api.nvim_buf_set_lines(0, 0, -1, true, { 217 'first buffer line 1', 218 'first buffer line 2', 219 'first buffer line 3', 220 }) 221 local first_bufnr = api.nvim_get_current_buf() 222 223 command('split') 224 command('enew') 225 api.nvim_buf_set_lines(0, 0, -1, true, { 226 'second buffer line 1', 227 'second buffer line 2', 228 }) 229 local second_bufnr = api.nvim_get_current_buf() 230 231 command('tabnew') 232 api.nvim_buf_set_lines(0, 0, -1, true, { 233 'third buffer line 1', 234 'third buffer line 2', 235 'third buffer line 3', 236 }) 237 local third_bufnr = api.nvim_get_current_buf() 238 239 command([[ 240 let g:markset_events = [] 241 autocmd MarkSet * call add(g:markset_events, {'buf': 0 + expand('<abuf>'), 'event': deepcopy(v:event)}) | wincmd w | tabnext 242 ]]) 243 244 command('buffer ' .. second_bufnr) 245 feed('j') 246 feed('mA') 247 command('buffer ' .. third_bufnr) 248 feed('l') 249 feed('mB') 250 command('buffer ' .. first_bufnr) 251 feed('jj') 252 feed('mC') 253 poke_eventloop() 254 255 eq({ 256 { 257 buf = 2, 258 event = { 259 col = 0, 260 line = 2, 261 name = 'A', 262 }, 263 }, 264 { 265 buf = 3, 266 event = { 267 col = 1, 268 line = 1, 269 name = 'B', 270 }, 271 }, 272 { 273 buf = 1, 274 event = { 275 col = 0, 276 line = 3, 277 name = 'C', 278 }, 279 }, 280 }, eval('g:markset_events')) 281 282 eq({ 2, 0 }, api.nvim_buf_get_mark(second_bufnr, 'A')) 283 eq({ 1, 1 }, api.nvim_buf_get_mark(third_bufnr, 'B')) 284 eq({ 3, 0 }, api.nvim_buf_get_mark(first_bufnr, 'C')) 285 end) 286 end)