414 lines
16 KiB
Text
414 lines
16 KiB
Text
*coc-api.txt* NodeJS client for Vim & Neovim.
|
|
|
|
CONTENTS
|
|
|
|
Vim sources |coc-api-vim-source|
|
|
Extension introduction |coc-api-intro|
|
|
Extension package json |coc-api-json|
|
|
Single file extensions |coc-api-single|
|
|
Create custom Extensions |coc-api-extension|
|
|
Debug extensions |coc-api-debug|
|
|
|
|
==============================================================================
|
|
|
|
This is the guide for extend coc.nvim by create vim completion sources and
|
|
coc.nvim extensions.
|
|
|
|
------------------------------------------------------------------------------
|
|
VIM SOURCES *coc-api-vim-source*
|
|
|
|
During initialization, coc.nvim searches vim's |runtimepath| for file pattern
|
|
`autoload/coc/source/${name}.vim`, matched files would be loaded as vim
|
|
completion sources.
|
|
|
|
Note: LSP completion features like `TextEdit`, `additionalTextEdits`,
|
|
`command` are not supported by vim sources, use the NodeJS API
|
|
`languages.registerCompletionItemProvider` for LSP completion.
|
|
|
|
For example, create a file `autoload/coc/source/email.vim` inside your plugin
|
|
folder. With code:
|
|
>
|
|
" vim source for emails
|
|
function! coc#source#email#init() abort
|
|
return {
|
|
\ 'priority': 9,
|
|
\ 'shortcut': 'Email',
|
|
\ 'triggerCharacters': ['@']
|
|
\}
|
|
endfunction
|
|
|
|
function! coc#source#email#complete(option, cb) abort
|
|
let items = ['foo@gmail.com', 'bar@yahoo.com']
|
|
call a:cb(items)
|
|
endfunction
|
|
<
|
|
`init` and `complete` are required functions for vim sources, error message
|
|
will be shown when not exists.
|
|
|
|
Source option:~
|
|
|
|
The source option object is returned by `coc#source#{name}#init`
|
|
function, available properties:
|
|
|
|
• shortcut: The shortcut characters shown in popup menu, first three
|
|
characters from the source name would be used when not exists.
|
|
• priority: The priority of source, default to `9`.
|
|
• filetypes: Array of filetype names this source should be triggered
|
|
by. Available for all filetypes when not exists.
|
|
• firstMatch: When is truthy value, only the completion item that has the
|
|
first letter matching the user input will be shown.
|
|
• triggerCharacters: Trigger characters for this source, default to `[]`.
|
|
• triggerOnly: The source should only be triggered by trigger characters,
|
|
when trigger characters is false or empty, the source would only be
|
|
triggered by api |coc#start()|.
|
|
• isSnippet: All complete items returned by `complete` are snippets,
|
|
which would have snippet indicator text added to the label in popup
|
|
menu. The "isSnippet" property of completion item override this
|
|
option.
|
|
|
|
All options are optional.
|
|
|
|
Source configurations:~
|
|
|
|
Vim sources register |coc-configuration| for allow the user to customize the
|
|
source behavior.
|
|
|
|
• `coc.source.${name}.enable` Enable the source, default to `true`.
|
|
• `coc.source.${name}.disableSyntaxes` Disabled syntax names when trigger
|
|
completion.
|
|
• `coc.source.${name}.firstMatch` Default to "firstMatch" of source option.
|
|
• `coc.source.${name}.priority` Default to "priority" of source option.
|
|
• `coc.source.${name}.shortcut` Default to "shortcut" of source option.
|
|
• `coc.source.${name}.filetypes` Default to "filetypes" of source option.
|
|
|
|
Complete function:~
|
|
|
|
The complete function is called with complete option as the first argument
|
|
and a callback function as the second argument, the callback function should
|
|
be called with list of complete item or `v:null` synchronously or
|
|
asynchronously.
|
|
|
|
Note: synchronously compute complete items blocks vim's operation.
|
|
Note: Error during completion is not thrown, use |:CocOpenLog| to check the
|
|
error log.
|
|
|
|
Complete option have following properties:
|
|
|
|
• bufnr: Current buffer number.
|
|
• line: Content line when trigger completion.
|
|
• col: Start col of completion, start col of the keywords before cursor by
|
|
default, 0 based.
|
|
• input: Input text between start col and curosr col.
|
|
• filetype: Filetype of current buffer.
|
|
• filepath: Fullpath of current buffer.
|
|
• changedtick: b:changedtick value when trigger completion.
|
|
• triggerCharacter: The character which trigger the completion, could be
|
|
empty string.
|
|
• colnr: Cursor col when trigger completion, 1 based.
|
|
• linenr: Line number of curosr, 1 based.
|
|
|
|
Complete items extends vim's |complete-items| with the following properties:
|
|
|
|
• deprecated: The complete item would be rendered with strike through
|
|
highlight when truthy.
|
|
• labelDetails: Additional details for a completion item label, which have
|
|
optional `detail` and/or `description` text.
|
|
• sortText: A string that should be used when comparing this item with other
|
|
items, word is used when not exists.
|
|
• filterText: A string that should be used when filtering a set of
|
|
complete items, word is used when not exists.
|
|
• insertText: The text to insert, could be snippet text, word is used when
|
|
not exists.
|
|
• isSnippet: The text to insert is snippet when is truthy value, when
|
|
truthy and `on_complete` not provided by vim source, the `insertText` is
|
|
expanded as textmate snippet when confirm completion.
|
|
• documentation: Array of `Documentation`, which provide `filetype` and
|
|
`content` text to be displayed in preview window.
|
|
|
|
Only the "word" property is mandatory for complete items.
|
|
|
|
Optional functions:~
|
|
|
|
The vim source could provide some optional functions which would be invoked
|
|
by coc.nvim:
|
|
|
|
• `coc#source#{name}#get_startcol(option)` Used to alter the start col of
|
|
completion, the returned col must <= current curosr col.
|
|
• `coc#source#{name}#on_complete(item)` Called with selected complete item
|
|
when user confirm the completion by |coc#pum#confirm()| or
|
|
|coc#_select_confirm()|. Normally used for apply nesessary edits to the
|
|
buffer.
|
|
• `coc#source#{name}#on_enter(option)` Called on |BufEnter| with option
|
|
contains:
|
|
• bufnr: The buffer number.
|
|
• uri: The uri text of buffer.
|
|
• languageId: The mapped filetype of buffer, see |coc-document-filetype|.
|
|
• `coc#source#{name}#refresh()` Called when the user trigger refresh action
|
|
for the source.
|
|
|
|
------------------------------------------------------------------------------
|
|
EXTENSION INTRODUCTION *coc-api-intro*
|
|
|
|
Every extension of coc.nvim has a JavaScript entry file, that file is loaded
|
|
by NodeJS API `vm.runInContext` with an identical global context (like iframe
|
|
in browser).
|
|
|
|
The JavaScript entry file should be a CommonJS module with `activate` method
|
|
exported, and `require('coc.nvim')` can be used to access modules exported by
|
|
coc.nvim, for example:
|
|
>
|
|
const {window} = require('coc.nvim')
|
|
exports.activate = async context => {
|
|
window.showInformationMessage('extension activated')
|
|
}
|
|
<
|
|
When `exports.deactivate` is exported from the JavaScript entry file as a
|
|
function, it would be called on extension deactivate.
|
|
|
|
Limitation of extension context:~
|
|
|
|
Some methods/properties provided by NodeJS can't be used inside extension
|
|
context, including:
|
|
|
|
• `process.reallyExit()`
|
|
• `process.abort()`
|
|
• `process.setuid()`
|
|
• `process.setgid()`
|
|
• `process.setgroups()`
|
|
• `process._fatalException()`
|
|
• `process.exit()`
|
|
• `process.kill()`
|
|
• `process.umask()` Could only be used to get umask value.
|
|
• `process.chdir()` Could be called, but no effect at all.
|
|
|
|
Some globals may can't be accessed directly, for example `TextDecoder`,
|
|
`TextEncoder`, use `globalThis` like `globalThis.TextDecoder` to access them.
|
|
|
|
*coc-api-console*
|
|
|
|
Stdin and stdout of the NodeJS process is used for communication between vim
|
|
and NodeJS process, use the methods related to `process.stdin` and
|
|
`process.stdout` may cause unexpected behavior. However, some methods of
|
|
`console` are provided for debugging purpose.
|
|
|
|
Messages from `console` of extension would be redirected to the log file
|
|
|:CocOpenLog|. Available methods:
|
|
|
|
• `debug(...args: any[])` Write debug message to the log file.
|
|
• `log(...args: any[])` Write info message to the log file.
|
|
• `info(...args: any[])` Write info message to the log file.
|
|
• `error(...args: any[])` Write error message to the log file.
|
|
• `warn(...args: any[])` Write warning message to the log file.
|
|
|
|
Check the full NodeJS API interfaces at:
|
|
https://github.com/neoclide/coc.nvim/blob/master/typings/index.d.ts
|
|
|
|
------------------------------------------------------------------------------
|
|
EXTENSION PACKAGE JSON *coc-api-json*
|
|
|
|
The package.json file inside extension root defines the meta data of the
|
|
extension. For example:
|
|
>
|
|
{
|
|
"name": "coc-my-extension",
|
|
"version": "1.0.0",
|
|
"main": "lib/index.js",
|
|
"engines": {
|
|
"coc": "^0.0.82"
|
|
},
|
|
"activationEvents": [
|
|
"*",
|
|
],
|
|
"contributes": {
|
|
"rootPatterns": [{
|
|
"filetype": "myfiletype",
|
|
"patterns": [
|
|
"project_root.json"
|
|
]
|
|
}],
|
|
"commands": [{
|
|
"title": "My command",
|
|
"category": "myextension",
|
|
"id": "myextension.myCommand"
|
|
}],
|
|
"configuration": {
|
|
"type": "object",
|
|
"properties": {
|
|
"myextension.enable": {
|
|
"type": "boolean",
|
|
"default": true,
|
|
"scope": "resource",
|
|
"description": "Enable running of my extension."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
<
|
|
Required properties of package.json:
|
|
|
|
• name: The unique name of extension, to publish the extension, the name
|
|
should not be taken by exists packages at https://www.npmjs.com/
|
|
• version: The semver version of extension.
|
|
• engines: Should have `coc` property with minimal required coc.nvim version.
|
|
|
|
The `main` property contains the relative filepath of the javascript entry
|
|
file, `index.js` would be used when not exists.
|
|
|
|
The `activationEvents` property tell coc.nvim when to activate the extension,
|
|
when the property not exists or `*` is included, the extension would be
|
|
activated during coc.nvim initialize. Other possible events:
|
|
|
|
• onLanguage: Activate the extension when document of specific languageId
|
|
exists, ex: `"onLanguage:vim"` activate the extension when there's buffer with
|
|
languageId as vim loaded.
|
|
• onFileSystem: Activate the extension when document with custom schema
|
|
loaded, ex: `"onFileSystem:fugitive"` activate the extension when there's
|
|
buffer with schema `fugitive` loaded.
|
|
• onCommand: activate the extension when specific command invoked by user,
|
|
ex: `"onCommand:tsserver.reloadProjects"`
|
|
• workspaceContains: activate the extension when the glob pattern match one
|
|
of the file in current workspace folder, ex:
|
|
`"workspaceContains:**/package.json"`
|
|
|
|
Optional `contributes` property contains the meta data that contributed to
|
|
coc.nvim, inclduing:
|
|
|
|
• rootPatterns: The patterns to resolve |coc-workspace-folders| for
|
|
associated filetype.
|
|
• commands: List of commands with `id` and `title` that can be invoked by
|
|
|:CocCommand|.
|
|
• configuration: Contains `properties` object or a list of configurations
|
|
that each one provide `properties` objects which define the configuration
|
|
properties contributed by this extension.
|
|
|
|
The `contributes` property could also contains other properties that used by
|
|
other extensions, for example: the `jsonValidation` property could be used by
|
|
coc-json.
|
|
|
|
It's recommended to install `coc-json` for json intellisense support.
|
|
|
|
------------------------------------------------------------------------------
|
|
SINGLE FILE EXTENSIONS *coc-api-single*
|
|
|
|
The easiest way to access the NodeJS API is make use of single file
|
|
extensions.
|
|
|
|
All Javascript files that ends with `.js` inside the folder "coc-extensions"
|
|
under |g:coc_config_home| are considered as coc extensions.
|
|
|
|
The javascript files would be loaded during coc.nvim initialize by default.
|
|
|
|
To contribute extension meta data, create file `${name}.json` aside with
|
|
`${name}.js`, the json file works the same as package.json of extension
|
|
|coc-api-json|, except that only `activationEvents` and `contributes`
|
|
properties are used.
|
|
|
|
Single file extensions can't be managed by extensions list.
|
|
|
|
------------------------------------------------------------------------------
|
|
CREATE CUSTOM EXTENSIONS *coc-api-extension*
|
|
|
|
To make an extension installable by |:CocInstall|, the easiest way is make use
|
|
of https://github.com/fannheyward/create-coc-extension. Simply run command
|
|
>
|
|
npm init coc-extension [extension-name]
|
|
<
|
|
or
|
|
>
|
|
yarn create coc-extension [extension-name]
|
|
<
|
|
in terminal and you will be prompted for create a javascript/typescript
|
|
extension step by step.
|
|
|
|
To manually create an extension, follow these step:
|
|
|
|
• Create an empty folder and goto that folder.
|
|
• Create the package.json file |coc-api-json|.
|
|
• Create a javascript file with name `index.js` and write code.
|
|
• Add the created folder to your vim's runtimepath by
|
|
add `set runtimepath^=/path/to/folder` in your vimrc.
|
|
|
|
Recommended steps:
|
|
|
|
• Install types of NodeJS and coc.nvim by terminal command
|
|
`yarn install @types/node@14.14 coc.nvim` in extension folder.
|
|
• Bundle the javascript files when using multiple node dependencies by
|
|
esbuild to save the time of installation. A typical build script looks
|
|
like:
|
|
>
|
|
async function start() {
|
|
await require('esbuild').build({
|
|
entryPoints: ['src/index.ts'],
|
|
bundle: true,
|
|
minify: process.env.NODE_ENV === 'production',
|
|
sourcemap: process.env.NODE_ENV === 'development',
|
|
mainFields: ['module', 'main'],
|
|
external: ['coc.nvim'],
|
|
platform: 'node',
|
|
target: 'node14.14',
|
|
outfile: 'lib/index.js'
|
|
})
|
|
}
|
|
|
|
start().catch(e => {
|
|
console.error(e)
|
|
})
|
|
<
|
|
------------------------------------------------------------------------------
|
|
DEBUG EXTENSIONS *coc-api-debug*
|
|
|
|
Uncaught errors:~
|
|
|
|
When an uncaught error raised on the NodeJS process, the error message would
|
|
be send to vim through stderr, and echoed by vim (unless
|
|
|g:coc_disable_uncaught_error| is enabeld).
|
|
|
|
The error messages are not stored by vim's message history, use
|
|
|:CocPrintErrors| to show previous errors.
|
|
|
|
When error happens on the vim side, the promise would be rejected when sending
|
|
request to vim, for notifications, vim would send `nvim_error_event` to the
|
|
NodeJS process, and the node-client would create error log for it.
|
|
|
|
Use the log file:~
|
|
|
|
• Configure `NVIM_COC_LOG_LEVEL` to `trace` in vimrc:
|
|
`let $NVIM_COC_LOG_LEVEL='trace'`
|
|
• Configure `NVIM_COC_LOG_FILE` to a fixed in vimrc:
|
|
`let $NVIM_COC_LOG_FILE=/tmp/coc.log`, otherwise it would be different for
|
|
each vim instance.
|
|
• Use |coc-api-console| to add console statements in javascript/typescript
|
|
code and compile the extension when needed.
|
|
• Tail the log file by `tail` command and make the issue happen.
|
|
|
|
Add source map support:~
|
|
|
|
When the javascript code is bundled by esbuild, it would be useful to have
|
|
correct source map support for the error stack.
|
|
|
|
• Install global source-map-support by `npm install -g source-map-support`
|
|
• Find out the npm root by `npm root -g`
|
|
• Load source-map-support with coc.nvim by append arguments to node in vimrc:
|
|
`let g:coc_node_args = ['-r', '/path/to/npm/root/source-map-support/register']`
|
|
Repalce the part `/path/to/npm/root` with result from `npm root -g` terminal
|
|
command.
|
|
|
|
Note: the source-map-support module slows down the coc.nvim initialization.
|
|
|
|
Debug javascript code in chrome:~
|
|
|
|
• Add `let g:coc_node_args = ['--nolazy', '--inspect-brk=5858']`
|
|
• Open vim and you will get the error message indicate that the debugger is
|
|
listening.
|
|
• Open Chrome browser with url chrome://inspect/#devices, configure
|
|
the `Target discovery settings` and you will get the remote target to
|
|
inspect.
|
|
• Click the inspect link to open the devtools.
|
|
• Click the sources label to debug javascript code.
|
|
|
|
Other debugger clients can be used as well, see:
|
|
https://nodejs.org/en/docs/guides/debugging-getting-started/
|
|
|
|
==============================================================================
|
|
vim:tw=78:sta:noet:ts=8:sts=0:ft=help:fen:
|