Closed prabirshrestha closed 5 years ago
Wow! Nice work. That looks great. I'll take a look at this later this week. Very cool idea! :+1:
Hmm. After thinking more not sure my initial async omnicomplete feature is going to work. Since pum
(popup menu) is managed by plugins such as completor.vim
and deoplete.nvim
.
Here is another idea. Note s:emojicomplete
is exactly the same signature as vim's completefunc
and omnifunc
. This could allow us to easily reuse existing completion funcs.
function s:emojicomplete(findstart, base)
if a:findstart
return match(getline('.')[0:col('.') -1], ':[^: \t]*$')
elseif empty(a:base)
return []
else
return [{'word': ':smile:'}, {'word': ':+1:'}]
endif
endfunction
function s:jscomplete(findstart, base, done)
if a:findstart
call done(1)
elseif empty(a:base)
call done([])
else
" simulate async completion using timer after 1 sec
let s:timer = timer_start(1000, timer->s:jscomplete_loaded(timer, done))
endif
return { 'cancel': {->s:jscancel(s:timer)}}
endfunction
function s:jscancel(timer)
call timer_stop(a:timer)
endfunction
function s:jscomplete_loaded(timer, done)
done([{'word': 'function'}, {'word', 'var'}, {'word': 'let'}])
endfunction
completor#add_completor({
\ 'name': 'js-emoji-completor',
\ 'filetype': ['javascript', 'typescript'],
\ 'completors': [
\ { 'name': 'javascript', 'asynccompletefunc': function('s:jscomplete') },
\ { 'name': 'emoji', 'completefunc': function('s:emojicomplete') },
\ 'buffer',
\ 'syntax'
\ ]
})
completor#remove_completor('js-emoji-completor')
We could also provide a helper func to convert sync completion to async completor#to_async_complete_func(function('s:emojicomplete'))
.
Notice completors
as list of completors. Unlike vim-mucomplete we should have an option to merge instead of just chain the completors.
Ideally I would want to avoid writing another completion engine and just use completor.vim
or deoplete.nvim
if possible.
Another good article on completion in vim. http://junegunn.kr/2014/06/emoji-completion-in-vim/
Here is more notes I gathered from looking at vscode.
export interface CompletionProvider {
provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<CompletionItem[] | CompletionList>;
}
// example: let sel:DocumentSelector = 'typescript';
// example: let sel:DocumentSelector = ['typescript', { language: 'json', pattern: '**/tsconfig.json' }]
export type DocumentSelector = string | DocumentFilter | (string | DocumentFilter)[];
// trigger characters like '.' or ':'
export function registerCompletionItemProvider(selector: DocumentSelector, provider: CompletionProvider, ...triggerCharacters: string[]): Disposable;
export function registerCompletionItemProvider(languageId: string, provider: CompletionProvider): IDisposable;
export interface TextDocument {
uri: Uri,
fileName: string,
isUntitled: boolean;
languageId: string;
version: number;
isDirty: boolean;
save(): Thenable<boolean>;
lineCount: number;
lineAt(line: number): TextLine;
lineAt(position: Position): TextLine;
offsetAt(position: Position): number;
positionAt(offset: number): Position;
getText(range?: Range): string;
getWordRangeAtPosition(position: Position, regex?: RegExp): Range | undefined;
validateRange(range: Range): Range;
validatePosition(position: Position): Position;
}
export class Position {
line: number;
character: umber;
constructor(line: number, character: number);
// some more helper methods related to positions like isBefore, isAfter, is Equal
}
export enum CompletionItemKind {
Text,
Method,
Function,
Constructor,
Field,
Variable,
Class,
Interface,
Module,
Property,
Unit,
Value,
Enum,
Keyword,
Snippet,
Color,
File,
Reference,
Folder
}
export interface CompletionItem {
label: string;
kind: CompletionItemKind;
detail?: string; // human-readable string with additional information about this item, like type of symbol information
documentation?: string;
// some more at https://github.com/Microsoft/vscode/blob/5162e3b5b56ac66a79920e6142fdfdeb27c0420f/src/vs/editor/browser/standalone/standaloneLanguages.ts#L268
}
Here is somewhat of a rough vim api for completion.
function s:emoji_complete(document, position, cancelToken, done)
" sync just call done immediately
call done([':smile:', ':+1:'])
endfunction
function s:ts_complete_provider(document, position, cancelToken, done)
" simulate async with timer
call timer_start(1000, timer->s:ts_complete_done(document, position, cancelToken, done))
endfunction
function s:ts_complete_done(document, position, cancelToken, done)
" completion lib should be smart enough to ignore this done call if the buffer has changed
" so that we don't show old completion items
call done([
\ { 'label': 'function', kind: 'keyword' },
\ { 'label': 'class', kind: 'keyword' }
\ ])
endfunction
call complete#providers#register(['typescript', 'javascript'], function('s:ts_complete_provider'), ['.'])
call complete#providers#register('*', function('s:emoji_complete'), [':'])
Need to figure out what to do with parameters (document, position, cancelToken, done)
I got a working async completion library that work in both vim 8 and neovim with timers
as the only requirement. You can find it at https://github.com/prabirshrestha/asyncomplete.vim
Huge props goes to https://github.com/roxma/nvim-complete-manager
So I got a proof of concept pure async completion working at https://gist.github.com/prabirshrestha/0b3b7b4e2112c662979bfeeec4e1edb7 after studying completor.vim's initial commit. Huge credit goes to completor.vim for its simplicity. It is a month completion using timer to prove async. You will notice the completion after 1 second due to the timer. Only tested in Vim8 on windows but I believe it should work on neovim too.
The goal would be to auto implement omnifunc for the filetype if LSP server supports completionProvider. Then
\<C-x>\<C-o>
could open the completion asynchronously. This allows to use intellisense/autocomplete with just this plugin. If the users like they can install other plugins like https://github.com/lifepillar/vim-mucomplete and https://github.com/Shougo/deoplete.nvim to have a better experience like tab completion and so on.Deoplete could then use the omni func provided by this plugin.
Also would need to improve the omni pattern like deoplete.
Super excited about how this will land 😃