Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Support of ultisnips snippet #3682

Merged
merged 29 commits into from
Mar 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
740a56c
feat(snippets): UltiSnips support
chemzqm Mar 2, 2022
3af408c
chore(snippets): more tests
chemzqm Mar 6, 2022
61ed172
fix(snippets): fix line count change check
chemzqm Mar 6, 2022
efb3b36
fix(snippets): not consider plain text when activated
chemzqm Mar 6, 2022
a6354d9
feat(snippets): convert regex for ultisnips
chemzqm Mar 6, 2022
5f47dc1
fix(snippets): indent for plain text
chemzqm Mar 6, 2022
d14ad17
feat(snippets): new variables of VSCode snippets
chemzqm Mar 6, 2022
081042d
refactor(snippets): rework placeholder sychronize
chemzqm Mar 7, 2022
183fbb9
fix(snippets): fix check of knownRegexOptions
chemzqm Mar 8, 2022
5184b4c
fix(snippets): convert python regex trigger
chemzqm Mar 8, 2022
b776bc0
chore(util): remove unnecessary code
chemzqm Mar 8, 2022
67720cd
chore(snippets): test for snip.c
chemzqm Mar 8, 2022
a9a13ac
feat(snippets): make sure cursor in new placeholder range
chemzqm Mar 8, 2022
90a9cf0
fix(snippets): use getChangedPosition for new cursor position
chemzqm Mar 8, 2022
b72174b
feat(snippets): avoid nest for snippet with placeholder reference
chemzqm Mar 8, 2022
ed945ff
fix(snippets): avoid nest for snippet with python
chemzqm Mar 8, 2022
440c78c
feat(snippets): use getParts for insertSnippet
chemzqm Mar 8, 2022
2eb2a92
feat(snippets): sychronize placeholder when insert snippet
chemzqm Mar 9, 2022
2fe5ff1
refactor(signature): not check coc_last_placeholder
chemzqm Mar 9, 2022
9ee060d
feat(snippets): support nested python snippet
chemzqm Mar 9, 2022
6764a9c
feat(snippets): resolve python on resolveSnippet
chemzqm Mar 9, 2022
c78746c
feat(snippets): add highlight support
chemzqm Mar 9, 2022
d4547e2
fix(snippets): fix nested placeholder resolve
chemzqm Mar 9, 2022
9487ed6
fix(snippets): fix no highlight for transform placeholders
chemzqm Mar 10, 2022
d820d15
fix(source-language): check cursor position on CompleteDone
chemzqm Mar 10, 2022
9c1a0ce
fix(highlight): fix highlight for range have more lines
chemzqm Mar 10, 2022
55bd8a0
fix(snippets): avoid sychronize when pumvisible
chemzqm Mar 10, 2022
9d7b5b6
fix(snippets): fix highlight ranges in parent placeholders
chemzqm Mar 10, 2022
3012045
chore(compat): avoid unnecessary silent
chemzqm Mar 10, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions autoload/coc/compat.vim
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function! coc#compat#buf_del_var(bufnr, name) abort
if exists('*nvim_buf_del_var')
silent! call nvim_buf_del_var(a:bufnr, a:name)
else
if bufnr == bufnr('%')
if a:bufnr == bufnr('%')
execute 'unlet! b:'.a:name
elseif exists('*win_execute')
let winid = coc#compat#buf_win_id(a:bufnr)
Expand Down Expand Up @@ -122,6 +122,14 @@ function! coc#compat#matchaddgroups(winid, groups) abort
endif
endfunction

function! coc#compat#del_var(name) abort
if exists('*nvim_del_var')
silent! call nvim_del_var(a:name)
else
execute 'unlet! '.a:name
endif
endfunction

" remove keymap for specific buffer
function! coc#compat#buf_del_keymap(bufnr, mode, lhs) abort
if !bufloaded(a:bufnr)
Expand All @@ -142,7 +150,7 @@ function! coc#compat#buf_del_keymap(bufnr, mode, lhs) abort
if exists('*win_execute')
let winid = coc#compat#buf_win_id(a:bufnr)
if winid != -1
call win_execute(winid, 'silent! '.a:mode.'unmap <buffer> '.a:lhs)
call win_execute(winid, a:mode.'unmap <buffer> '.a:lhs, 'silent!')
endif
endif
endfunction
Expand Down
2 changes: 1 addition & 1 deletion autoload/coc/highlight.vim
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ function! coc#highlight#ranges(bufnr, key, hlGroup, ranges, ...) abort
endif
" TODO don't know how to count UTF16 code point, should work most cases.
let colStart = lnum == start['line'] + 1 ? strlen(strcharpart(line, 0, start['character'])) : 0
let colEnd = lnum == end['line'] + 1 ? strlen(strcharpart(line, 0, end['character'])) : -1
let colEnd = lnum == end['line'] + 1 ? strlen(strcharpart(line, 0, end['character'])) : strlen(line)
if colStart == colEnd
continue
endif
Expand Down
7 changes: 4 additions & 3 deletions autoload/coc/snippet.vim
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:map_next = 1
let s:cmd_mapping = has('nvim') || has('patch-8.2.1978')

function! coc#snippet#_select_mappings()
if !get(g:, 'coc_selectmode_mapping', 1)
Expand Down Expand Up @@ -38,7 +39,6 @@ function! coc#snippet#enable()
return
endif
let b:coc_snippet_active = 1
silent! unlet g:coc_selected_text
call coc#snippet#_select_mappings()
let nextkey = get(g:, 'coc_snippet_next', '<C-j>')
let prevkey = get(g:, 'coc_snippet_prev', '<C-k>')
Expand All @@ -48,9 +48,10 @@ function! coc#snippet#enable()
if s:map_next
execute 'inoremap <buffer><nowait><silent>'.nextkey." <C-R>=coc#rpc#request('snippetNext', [])<cr>"
endif
let pre = s:cmd_mapping ? '<Cmd>' : '<Esc>'
execute 'inoremap <buffer><nowait><silent>'.prevkey." <C-R>=coc#rpc#request('snippetPrev', [])<cr>"
execute 'snoremap <buffer><nowait><silent>'.prevkey." <Esc>:call coc#rpc#request('snippetPrev', [])<cr>"
execute 'snoremap <buffer><nowait><silent>'.nextkey." <Esc>:call coc#rpc#request('snippetNext', [])<cr>"
execute 'snoremap <buffer><nowait><silent>'.prevkey." ".pre.":call coc#rpc#request('snippetPrev', [])<cr>"
execute 'snoremap <buffer><nowait><silent>'.nextkey." ".pre.":call coc#rpc#request('snippetNext', [])<cr>"
endfunction

function! coc#snippet#disable()
Expand Down
3 changes: 3 additions & 0 deletions autoload/health/coc.vim
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ function! s:checkEnvironment() abort
silent pyx print("")
catch /.*/
call health#report_warn('pyx command not work, some extensions may fail to work, checkout ":h pythonx"')
if has('nvim')
call health#report_warn('Install pynvim by command: pip install pynvim --upgrade')
endif
endtry
endif
return valid
Expand Down
5 changes: 5 additions & 0 deletions data/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,11 @@
"default": "SNIP",
"description": "Text shown in statusline to indicate snippet session is activated."
},
"coc.preferences.snippetHighlight": {
"type": "boolean",
"description": "Use highlight group 'CocSnippetVisual' to highlight placeholders with same index of current one.",
"default": true
},
"coc.preferences.currentFunctionSymbolAutoUpdate": {
"type": "boolean",
"description": "Automatically update the value of b:coc_current_function on CursorHold event",
Expand Down
8 changes: 8 additions & 0 deletions doc/coc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,13 @@ Built-in configurations:~

Valid options: ["daily","weekly","never"]

"coc.preferences.snippetHighlight":~

Use highlight group 'CocSnippetVisual' to highlight placeholders with
same index of current one.

default: `true`

"coc.preferences.snippetStatusText":~

Text shown in 'statusline' to indicate snippet session is activate.
Expand Down Expand Up @@ -3036,6 +3043,7 @@ Others~
*CocMenuSel* for current menu item in menu dialog, works on neovim only since
vim doesn't support change highlight group of cursorline inside popup.
*CocSelectedRange* for highlight ranges of outgoing calls.
*CocSnippetVisual* for highlight snippet placeholders.

Semantic highlights~
*coc-semantic-highlights*
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
"vscode-languageserver": "7.0.0"
},
"dependencies": {
"@chemzqm/neovim": "^5.7.4",
"@chemzqm/neovim": "^5.7.5",
"ansi-styles": "^5.0.0",
"bytes": "^3.1.0",
"cli-table": "^0.3.4",
Expand Down
2 changes: 2 additions & 0 deletions plugin/coc.vim
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,8 @@ function! s:Hi() abort
hi default link CocCursorRange Search
hi default link CocHighlightRead CocHighlightText
hi default link CocHighlightWrite CocHighlightText
" Snippet
hi default link CocSnippetVisual Visual
" Tree view highlights
hi default link CocTreeTitle Title
hi default link CocTreeDescription Comment
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/core/editors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('editors', () => {
resolve(e)
}, null, disposables)
})
await nvim.command('vs')
await nvim.command('sp')
let editor = await promise
let winid = await nvim.call('win_getid')
expect(editor.winid).toBe(winid)
Expand Down
1 change: 1 addition & 0 deletions src/__tests__/core/terminals.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ describe('create terminal', () => {
})
let res = await terminal.show(true)
expect(res).toBe(true)
expect(typeof terminal.bufnr).toBe('number')
let winid = await nvim.call('bufwinid', [terminal.bufnr])
let curr = await nvim.call('win_getid', [])
expect(winid != curr).toBe(true)
Expand Down
6 changes: 3 additions & 3 deletions src/__tests__/handler/outline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,8 @@ describe('symbols outline', () => {
strictIndexing: false
})
await doc.synchronize()
await helper.wait(200)
buf = await getOutlineBuffer()
await helper.waitFor('eval', [`getbufline(${buf.id},1)[0]`], /No\sresults/)
let lines = await buf.lines
expect(lines).toEqual([
'No results',
Expand Down Expand Up @@ -355,10 +355,10 @@ describe('symbols outline', () => {
await createBuffer()
let bufnr = await nvim.call('bufnr', ['%'])
await symbols.showOutline(0)
await helper.waitFor('getline', [1], 'OUTLINE')
await helper.waitFor('getline', [3], /fun1/)
await nvim.command('exe 3')
await nvim.input('<tab>')
await helper.wait(50)
await helper.waitFloat()
await nvim.input('<cr>')
await helper.waitFor('mode', [], 'v')
let buf = await nvim.buffer
Expand Down
8 changes: 4 additions & 4 deletions src/__tests__/handler/semanticTokens.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,16 +401,16 @@ describe('semanticTokens', () => {

describe('rangeProvider', () => {
it('should invoke range provider first time when both kind exists', async () => {
let t = 0
let fn = jest.fn()
disposables.push(registerRangeProvider('rust', () => {
t++
fn()
return []
}))
let buf = await createRustBuffer()
let item = highlighter.getItem(buf.id)
await item.waitRefresh()
await helper.wait(30)
expect(t).toBe(1)
expect(fn).toBeCalled()
})

it('should do range highlight first time', async () => {
Expand Down Expand Up @@ -445,7 +445,7 @@ describe('semanticTokens', () => {
return []
}))
await nvim.command('normal! G')
await helper.wait(50)
await helper.wait(100)
expect(r).toBeDefined()
expect(r.end).toEqual({ line: 201, character: 0 })
})
Expand Down
33 changes: 0 additions & 33 deletions src/__tests__/handler/signature.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,39 +89,6 @@ describe('signatureHelp', () => {
let lines = await helper.getWinLines(win.id)
expect(lines.join('\n')).toMatch(/description/)
})

it('should consider coc_last_placeholder on select mode', async () => {
let pos: Position
disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], {
provideSignatureHelp: (_doc, position) => {
pos = position
return {
signatures: [
SignatureInformation.create('foo(a, b)', 'my signature', ParameterInformation.create('a', 'description')),
],
activeParameter: 1,
activeSignature: null
}
}
}, []))
let doc = await helper.createDocument()
let line = await nvim.call('line', ['.'])
await nvim.setLine(' fn(abc, def)')
await nvim.command('normal! 0fave')
await nvim.input('<C-g>')
let placeholder = {
bufnr: doc.bufnr,
start: Position.create(line - 1, 5),
end: Position.create(line - 1, 8)
}
await nvim.setVar('coc_last_placeholder', placeholder)
let m = await nvim.mode
expect(m.mode).toBe('s')
await signature.triggerSignatureHelp()
let win = await helper.getFloat()
expect(win).toBeDefined()
expect(pos).toEqual(Position.create(0, 5))
})
})

describe('events', () => {
Expand Down
13 changes: 11 additions & 2 deletions src/__tests__/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ export class Helper extends EventEmitter {
this.setMaxListeners(99)
}

public setupNvim(): void {
const vimrc = path.resolve(__dirname, 'vimrc')
let proc = this.proc = cp.spawn('nvim', ['-u', vimrc, '-i', 'NONE', '--embed'], {
cwd: __dirname
})
let plugin = attach({ proc })
this.nvim = plugin.nvim
}

public setup(): Promise<void> {
const vimrc = path.resolve(__dirname, 'vimrc')
let proc = this.proc = cp.spawn('nvim', ['-u', vimrc, '-i', 'NONE', '--embed'], {
Expand Down Expand Up @@ -79,7 +88,7 @@ export class Helper extends EventEmitter {
}

public async shutdown(): Promise<void> {
this.plugin.dispose()
if (this.plugin) this.plugin.dispose()
this.nvim.removeAllListeners()
this.nvim = null
if (this.proc) {
Expand Down Expand Up @@ -278,7 +287,7 @@ export class Helper extends EventEmitter {
for (let i = 0; i < 40; i++) {
await this.wait(50)
let res = await this.nvim.call(method, args) as T
if (res == value) {
if (res == value || (value instanceof RegExp && value.test(res.toString()))) {
find = true
break
}
Expand Down
43 changes: 7 additions & 36 deletions src/__tests__/modules/completion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { Neovim } from '@chemzqm/neovim'
import { Disposable } from 'vscode-jsonrpc'
import { CompletionItem, CompletionList, InsertTextFormat, Position, Range, TextEdit } from 'vscode-languageserver-types'
import completion from '../../completion'
import events from '../../events'
import languages from '../../languages'
import { CompletionItemProvider } from '../../provider'
import snippetManager from '../../snippets/manager'
import sources from '../../sources'
import { CompleteOption, CompleteResult, ISource, SourceType } from '../../types'
import { disposeAll } from '../../util'
import workspace from '../../workspace'
import events from '../../events'
import helper from '../helper'

let nvim: Neovim
Expand Down Expand Up @@ -130,7 +130,6 @@ describe('completion resumeCompletion', () => {

it('should stop if no filtered items', async () => {
await nvim.setLine('foo ')
await helper.wait(50)
await nvim.input('Af')
await helper.waitPopup()
expect(completion.isActivated).toBe(true)
Expand Down Expand Up @@ -482,9 +481,7 @@ describe('completion TextChangedP', () => {
await nvim.input('i?')
await helper.waitPopup()
await nvim.eval('feedkeys("\\<C-n>", "in")')
await helper.wait(200)
let line = await nvim.line
expect(line).toBe('?foo')
await helper.waitFor('getline', ['.'], '?foo')
})

it('should fix cursor position with snippet on additionalTextEdits', async () => {
Expand All @@ -503,16 +500,7 @@ describe('completion TextChangedP', () => {
let res = await helper.getItems()
let idx = res.findIndex(o => o.menu == '[edit]')
await helper.selectCompleteItem(idx)
let line: string
for (let i = 0; i < 40; i++) {
await helper.wait(50)
line = await nvim.line
if (line == 'bar if()') break
}
expect(line).toBe('bar if()')
let [, lnum, col] = await nvim.call('getcurpos')
expect(lnum).toBe(1)
expect(col).toBe(8)
await helper.waitFor('col', ['.'], 8)
})

it('should fix cursor position with plain text snippet on additionalTextEdits', async () => {
Expand Down Expand Up @@ -553,10 +541,8 @@ describe('completion TextChangedP', () => {
await nvim.input('if')
await helper.waitPopup()
await helper.selectCompleteItem(0)
await helper.wait(200)
let line = await nvim.line
await helper.waitFor('getline', ['.'], 'bar func(do)')
let [, lnum, col] = await nvim.call('getcurpos')
expect(line).toBe('bar func(do)')
expect(lnum).toBe(1)
expect(col).toBe(12)
})
Expand All @@ -582,7 +568,7 @@ describe('completion TextChangedP', () => {
await helper.selectCompleteItem(idx)
await helper.waitFor('getline', ['.'], 'foo = foo0bar1')
await helper.wait(50)
expect(snippetManager.isActived(doc.bufnr)).toBe(true)
expect(snippetManager.session).toBeDefined()
let [, lnum, col] = await nvim.call('getcurpos')
expect(lnum).toBe(1)
expect(col).toBe(3)
Expand Down Expand Up @@ -839,9 +825,8 @@ describe('completion TextChangedI', () => {
helper.updateConfiguration('suggest.acceptSuggestionOnCommitCharacter', true)
helper.updateConfiguration('suggest.noselect', false)
let source: ISource = {
priority: 0,
enable: true,
name: 'slow',
name: 'commit',
sourceType: SourceType.Service,
triggerCharacters: ['.'],
doComplete: (opt: CompleteOption): Promise<CompleteResult> => {
Expand All @@ -856,20 +841,6 @@ describe('completion TextChangedI', () => {
await nvim.input('if')
await helper.waitPopup()
await nvim.input('.')
await helper.wait(100)
let line = await nvim.line
expect(line).toBe('foo.')
})

it('should cancel completion with same pretext', async () => {
await nvim.setLine('foo')
await nvim.input('of')
await helper.waitPopup()
await nvim.input('<space><bs>')
await helper.wait(100)
let line = await nvim.line
let visible = await nvim.call('pumvisible')
expect(line).toBe('f')
expect(visible).toBe(0)
await helper.waitFor('getline', ['.'], 'foo.')
})
})
Loading