*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: