diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-11-30 20:35:25 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-11-30 20:35:25 +0000 |
commit | 1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch) | |
tree | cd08258054db80bb9a11b1061bb091c70b76926a /test/functional/lua/snippet_spec.lua | |
parent | eaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff) | |
parent | 4a8bf24ac690004aedf5540fa440e788459e5e34 (diff) | |
download | rneovim-1b7b916b7631ddf73c38e3a0070d64e4636cb2f3.tar.gz rneovim-1b7b916b7631ddf73c38e3a0070d64e4636cb2f3.tar.bz2 rneovim-1b7b916b7631ddf73c38e3a0070d64e4636cb2f3.zip |
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'test/functional/lua/snippet_spec.lua')
-rw-r--r-- | test/functional/lua/snippet_spec.lua | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/test/functional/lua/snippet_spec.lua b/test/functional/lua/snippet_spec.lua new file mode 100644 index 0000000000..f0b3b44139 --- /dev/null +++ b/test/functional/lua/snippet_spec.lua @@ -0,0 +1,202 @@ +local helpers = require('test.functional.helpers')(after_each) + +local buf_lines = helpers.buf_lines +local clear = helpers.clear +local eq = helpers.eq +local exec_lua = helpers.exec_lua +local feed = helpers.feed +local matches = helpers.matches +local pcall_err = helpers.pcall_err +local sleep = helpers.sleep + +describe('vim.snippet', function() + before_each(function() + clear() + + exec_lua([[ + vim.keymap.set({ 'i', 's' }, '<Tab>', function() vim.snippet.jump(1) end, { buffer = true }) + vim.keymap.set({ 'i', 's' }, '<S-Tab>', function() vim.snippet.jump(-1) end, { buffer = true }) + ]]) + end) + after_each(clear) + + --- @param snippet string[] + --- @param expected string[] + --- @param settings? string + --- @param prefix? string + local function test_expand_success(snippet, expected, settings, prefix) + if settings then + exec_lua(settings) + end + if prefix then + feed('i' .. prefix) + end + exec_lua('vim.snippet.expand(...)', table.concat(snippet, '\n')) + eq(expected, buf_lines(0)) + end + + --- @param snippet string + --- @param err string + local function test_expand_fail(snippet, err) + matches(err, pcall_err(exec_lua, string.format('vim.snippet.expand("%s")', snippet))) + end + + it('adds base indentation to inserted text', function() + test_expand_success( + { 'function $1($2)', ' $0', 'end' }, + { ' function ()', ' ', ' end' }, + '', + ' ' + ) + end) + + it('adds indentation based on the start of snippet lines', function() + test_expand_success({ 'if $1 then', ' $0', 'end' }, { 'if then', ' ', 'end' }) + end) + + it('replaces tabs with spaces when expandtab is set', function() + test_expand_success( + { 'function $1($2)', '\t$0', 'end' }, + { 'function ()', ' ', 'end' }, + [[ + vim.o.expandtab = true + vim.o.shiftwidth = 2 + ]] + ) + end) + + it('respects tabs when expandtab is not set', function() + test_expand_success( + { 'function $1($2)', '\t$0', 'end' }, + { 'function ()', '\t', 'end' }, + 'vim.o.expandtab = false' + ) + end) + + it('inserts known variable value', function() + test_expand_success({ '; print($TM_CURRENT_LINE)' }, { 'foo; print(foo)' }, nil, 'foo') + end) + + it('uses default when variable is not set', function() + test_expand_success({ 'print(${TM_CURRENT_WORD:foo})' }, { 'print(foo)' }) + end) + + it('replaces unknown variables by placeholders', function() + test_expand_success({ 'print($UNKNOWN)' }, { 'print(UNKNOWN)' }) + end) + + it('does not jump outside snippet range', function() + test_expand_success({ 'function $1($2)', ' $0', 'end' }, { 'function ()', ' ', 'end' }) + eq(false, exec_lua('return vim.snippet.jumpable(-1)')) + feed('<Tab><Tab>i') + eq(false, exec_lua('return vim.snippet.jumpable(1)')) + end) + + it('navigates backwards', function() + test_expand_success({ 'function $1($2) end' }, { 'function () end' }) + feed('<Tab><S-Tab>foo') + eq({ 'function foo() end' }, buf_lines(0)) + end) + + it('visits all tabstops', function() + local function cursor() + return exec_lua('return vim.api.nvim_win_get_cursor(0)') + end + + test_expand_success({ 'function $1($2)', ' $0', 'end' }, { 'function ()', ' ', 'end' }) + eq({ 1, 9 }, cursor()) + feed('<Tab>') + eq({ 1, 10 }, cursor()) + feed('<Tab>') + eq({ 2, 2 }, cursor()) + end) + + it('syncs text of tabstops with equal indexes', function() + test_expand_success({ 'var double = ${1:x} + ${1:x}' }, { 'var double = x + x' }) + feed('123') + eq({ 'var double = 123 + 123' }, buf_lines(0)) + end) + + it('cancels session with changes outside the snippet', function() + test_expand_success({ 'print($1)' }, { 'print()' }) + feed('<Esc>O-- A comment') + eq(false, exec_lua('return vim.snippet.active()')) + eq({ '-- A comment', 'print()' }, buf_lines(0)) + end) + + it('handles non-consecutive tabstops', function() + test_expand_success({ 'class $1($3) {', ' $0', '}' }, { 'class () {', ' ', '}' }) + feed('Foo') -- First tabstop + feed('<Tab><Tab>') -- Jump to $0 + feed('// Inside') -- Insert text + eq({ 'class Foo() {', ' // Inside', '}' }, buf_lines(0)) + end) + + it('handles multiline placeholders', function() + test_expand_success( + { 'public void foo() {', ' ${0:// TODO Auto-generated', ' throw;}', '}' }, + { 'public void foo() {', ' // TODO Auto-generated', ' throw;', '}' } + ) + end) + + it('inserts placeholder in all tabstops when the first tabstop has the placeholder', function() + test_expand_success( + { 'for (${1:int} ${2:x} = ${3:0}; $2 < ${4:N}; $2++) {', ' $0', '}' }, + { 'for (int x = 0; x < N; x++) {', ' ', '}' } + ) + end) + + it('inserts placeholder in all tabstops when a later tabstop has the placeholder', function() + test_expand_success( + { 'for (${1:int} $2 = ${3:0}; ${2:x} < ${4:N}; $2++) {', ' $0', '}' }, + { 'for (int x = 0; x < N; x++) {', ' ', '}' } + ) + end) + + it('errors with multiple placeholders for the same index', function() + test_expand_fail('class ${1:Foo} { void ${1:foo}() {} }', 'multiple placeholders for tabstop $1') + end) + + it('errors with multiple $0 tabstops', function() + test_expand_fail('function $1() { $0 }$0', 'multiple $0 tabstops') + end) + + it('cancels session when deleting the snippet', function() + test_expand_success({ 'local function $1()', ' $0', 'end' }, { 'local function ()', ' ', 'end' }) + feed('<esc>Vjjd') + eq(false, exec_lua('return vim.snippet.active()')) + end) + + it('cancels session when inserting outside snippet region', function() + feed('i<cr>') + test_expand_success({ 'local function $1()', ' $0', 'end' }, { '', 'local function ()', ' ', 'end' }) + feed('<esc>O-- A comment') + eq(false, exec_lua('return vim.snippet.active()')) + end) + + it('inserts choice', function () + test_expand_success({ 'console.${1|assert,log,error|}()' }, { 'console.()' }) + sleep(100) + feed('<Down><C-y>') + eq({ 'console.log()' }, buf_lines(0)) + end) + + it('closes the choice completion menu when jumping', function () + test_expand_success({ 'console.${1|assert,log,error|}($2)' }, { 'console.()' }) + sleep(100) + exec_lua('vim.snippet.jump(1)') + eq(0, exec_lua('return vim.fn.pumvisible()')) + end) + + it('jumps to next tabstop after inserting choice', function() + test_expand_success( + { '${1|public,protected,private|} function ${2:name}() {', '\t$0', '}' }, + { ' function name() {', '\t', '}' } + ) + sleep(100) + feed('<C-y><Tab>') + sleep(10) + feed('foo') + eq({ 'public function foo() {', '\t', '}' }, buf_lines(0)) + end) +end) |