From a38989c3167919bd40b07ec5169aab3102736da2 Mon Sep 17 00:00:00 2001 From: Heyward Fann Date: Thu, 21 Nov 2024 15:36:04 +0800 Subject: [PATCH] feat(neovim): bundled neoclide/neovim Closes #5194 --- package-lock.json | 17 +- package.json | 2 +- src/__tests__/client/diagnostics.test.ts | 2 +- src/__tests__/client/progressPart.test.ts | 2 +- .../client/textSynchronization.test.ts | 2 +- src/__tests__/completion/basic.test.ts | 2 +- src/__tests__/completion/float.test.ts | 2 +- src/__tests__/completion/language.test.ts | 2 +- src/__tests__/completion/sources.test.ts | 2 +- src/__tests__/completion/util.test.ts | 2 +- src/__tests__/core/autocmds.test.ts | 2 +- src/__tests__/core/documents.test.ts | 2 +- src/__tests__/core/editors.test.ts | 2 +- src/__tests__/core/files.test.ts | 2 +- src/__tests__/core/keymaps.test.ts | 2 +- src/__tests__/core/locations.test.ts | 2 +- src/__tests__/core/terminals.test.ts | 2 +- src/__tests__/core/ui.test.ts | 2 +- src/__tests__/core/workspaceFolder.test.ts | 2 +- src/__tests__/handler/callHierarchy.test.ts | 2 +- src/__tests__/handler/codeActions.test.ts | 2 +- src/__tests__/handler/codelens.test.ts | 2 +- src/__tests__/handler/commands.test.ts | 2 +- src/__tests__/handler/documentColors.test.ts | 2 +- src/__tests__/handler/documentLinks.test.ts | 2 +- src/__tests__/handler/fold.test.ts | 2 +- src/__tests__/handler/format.test.ts | 2 +- src/__tests__/handler/highlights.test.ts | 2 +- src/__tests__/handler/hover.test.ts | 2 +- src/__tests__/handler/index.test.ts | 2 +- src/__tests__/handler/inlayHint.test.ts | 2 +- src/__tests__/handler/inlineValue.test.ts | 2 +- src/__tests__/handler/linkedEditing.test.ts | 2 +- src/__tests__/handler/locations.test.ts | 2 +- src/__tests__/handler/outline.test.ts | 2 +- src/__tests__/handler/refactor.test.ts | 2 +- src/__tests__/handler/rename.test.ts | 2 +- src/__tests__/handler/search.test.ts | 2 +- src/__tests__/handler/selectionRange.test.ts | 2 +- src/__tests__/handler/semanticTokens.test.ts | 2 +- src/__tests__/handler/signature.test.ts | 2 +- src/__tests__/handler/symbols.test.ts | 2 +- src/__tests__/handler/typeHierarchy.test.ts | 2 +- src/__tests__/handler/workspace.test.ts | 2 +- src/__tests__/helper.ts | 2 +- src/__tests__/list/commandTask.test.ts | 2 +- src/__tests__/list/manager.test.ts | 2 +- src/__tests__/list/mappings.test.ts | 2 +- src/__tests__/list/session.test.ts | 2 +- src/__tests__/list/sources.test.ts | 6 +- src/__tests__/list/ui.test.ts | 2 +- src/__tests__/list/worker.test.ts | 2 +- src/__tests__/modules/attach.test.ts | 2 +- src/__tests__/modules/cursors.test.ts | 2 +- .../modules/diagnosticBuffer.test.ts | 2 +- .../modules/diagnosticManager.test.ts | 2 +- src/__tests__/modules/dialog.test.ts | 2 +- src/__tests__/modules/document.test.ts | 2 +- .../modules/extensionManager.test.ts | 2 +- .../modules/extensionModules.test.ts | 2 +- src/__tests__/modules/floatFactory.test.ts | 2 +- src/__tests__/modules/highlighter.test.ts | 2 +- src/__tests__/modules/menu.test.ts | 2 +- src/__tests__/modules/outputChannel.test.ts | 2 +- src/__tests__/modules/picker.test.ts | 2 +- src/__tests__/modules/plugin.test.ts | 2 +- src/__tests__/modules/quickpick.test.ts | 2 +- src/__tests__/modules/services.test.ts | 2 +- src/__tests__/modules/sources.test.ts | 2 +- src/__tests__/modules/task.test.ts | 2 +- src/__tests__/modules/terminal.test.ts | 2 +- src/__tests__/modules/window.test.ts | 4 +- src/__tests__/modules/workspace.test.ts | 2 +- src/__tests__/snippets/manager.test.ts | 2 +- src/__tests__/snippets/session.test.ts | 2 +- src/__tests__/snippets/snippet.test.ts | 2 +- src/__tests__/tree/treeView.test.ts | 2 +- src/__tests__/vim.test.ts | 2 +- src/attach.ts | 4 +- src/commands.ts | 4 +- src/completion/complete.ts | 2 +- src/completion/index.ts | 2 +- src/completion/pum.ts | 2 +- src/completion/source.ts | 2 +- src/completion/sources.ts | 2 +- src/core/autocmds.ts | 2 +- src/core/channels.ts | 2 +- src/core/contentProvider.ts | 2 +- src/core/dialogs.ts | 2 +- src/core/documents.ts | 2 +- src/core/editors.ts | 2 +- src/core/files.ts | 2 +- src/core/funcs.ts | 2 +- src/core/highlights.ts | 2 +- src/core/keymaps.ts | 2 +- src/core/notifications.ts | 2 +- src/core/terminals.ts | 2 +- src/core/ui.ts | 6 +- src/core/watchers.ts | 2 +- src/cursors/index.ts | 2 +- src/cursors/session.ts | 2 +- src/diagnostic/buffer.ts | 22 +- src/diagnostic/manager.ts | 2 +- src/diagnostic/util.ts | 2 +- src/handler/callHierarchy.ts | 2 +- src/handler/codeActions.ts | 2 +- src/handler/codelens/buffer.ts | 2 +- src/handler/codelens/index.ts | 2 +- src/handler/colors/colorBuffer.ts | 2 +- src/handler/colors/index.ts | 2 +- src/handler/commands.ts | 2 +- src/handler/fold.ts | 2 +- src/handler/format.ts | 2 +- src/handler/highlights.ts | 2 +- src/handler/hover.ts | 2 +- src/handler/index.ts | 2 +- src/handler/inlayHint/buffer.ts | 2 +- src/handler/inlayHint/index.ts | 2 +- src/handler/linkedEditing.ts | 2 +- src/handler/links.ts | 2 +- src/handler/locations.ts | 2 +- src/handler/refactor/buffer.ts | 2 +- src/handler/refactor/index.ts | 2 +- src/handler/refactor/search.ts | 2 +- src/handler/rename.ts | 2 +- src/handler/selectionRange.ts | 2 +- src/handler/semanticTokens/buffer.ts | 2 +- src/handler/semanticTokens/index.ts | 2 +- src/handler/signature.ts | 2 +- src/handler/symbols/index.ts | 2 +- src/handler/symbols/outline.ts | 2 +- src/handler/typeHierarchy.ts | 2 +- src/handler/workspace.ts | 2 +- src/list/basic.ts | 2 +- src/list/manager.ts | 2 +- src/list/mappings.ts | 2 +- src/list/prompt.ts | 2 +- src/list/session.ts | 2 +- src/list/source/outline.ts | 2 +- src/list/types.ts | 2 +- src/list/ui.ts | 2 +- src/model/dialog.ts | 2 +- src/model/document.ts | 2 +- src/model/editInspect.ts | 2 +- src/model/floatFactory.ts | 2 +- src/model/highlighter.ts | 2 +- src/model/input.ts | 2 +- src/model/menu.ts | 2 +- src/model/notification.ts | 3 +- src/model/outputChannel.ts | 2 +- src/model/picker.ts | 2 +- src/model/popup.ts | 2 +- src/model/progress.ts | 2 +- src/model/quickpick.ts | 2 +- src/model/status.ts | 2 +- src/model/task.ts | 4 +- src/model/terminal.ts | 2 +- src/neovim/api/Base.ts | 120 ++++ src/neovim/api/Buffer.ts | 592 ++++++++++++++++++ src/neovim/api/Neovim.ts | 480 ++++++++++++++ src/neovim/api/Tabpage.ts | 43 ++ src/neovim/api/Window.ts | 147 +++++ src/neovim/api/client.ts | 394 ++++++++++++ src/neovim/api/index.ts | 5 + src/neovim/api/types.ts | 63 ++ src/neovim/attach/attach.test.ts | 150 +++++ src/neovim/attach/attach.ts | 56 ++ src/neovim/index.ts | 6 + src/neovim/transport/base.ts | 104 +++ src/neovim/transport/connection.ts | 118 ++++ src/neovim/transport/nvim.ts | 191 ++++++ src/neovim/transport/request.ts | 46 ++ src/neovim/transport/vim.ts | 148 +++++ src/neovim/types.ts | 70 +++ src/neovim/utils/buffered.ts | 59 ++ src/neovim/utils/constants.ts | 4 + src/neovim/utils/devnull.ts | 9 + src/neovim/utils/lodash.ts | 54 ++ src/neovim/utils/logger.ts | 126 ++++ src/plugin.ts | 2 +- src/snippets/eval.ts | 4 +- src/snippets/manager.ts | 2 +- src/snippets/parser.ts | 2 +- src/snippets/session.ts | 2 +- src/snippets/snippet.ts | 2 +- src/snippets/variableResolve.ts | 3 +- src/tree/TreeView.ts | 2 +- src/tree/filter.ts | 2 +- src/types.ts | 2 +- src/window.ts | 28 +- src/workspace.ts | 2 +- 191 files changed, 3175 insertions(+), 229 deletions(-) create mode 100644 src/neovim/api/Base.ts create mode 100644 src/neovim/api/Buffer.ts create mode 100644 src/neovim/api/Neovim.ts create mode 100644 src/neovim/api/Tabpage.ts create mode 100644 src/neovim/api/Window.ts create mode 100644 src/neovim/api/client.ts create mode 100644 src/neovim/api/index.ts create mode 100644 src/neovim/api/types.ts create mode 100644 src/neovim/attach/attach.test.ts create mode 100644 src/neovim/attach/attach.ts create mode 100644 src/neovim/index.ts create mode 100644 src/neovim/transport/base.ts create mode 100644 src/neovim/transport/connection.ts create mode 100644 src/neovim/transport/nvim.ts create mode 100644 src/neovim/transport/request.ts create mode 100644 src/neovim/transport/vim.ts create mode 100644 src/neovim/types.ts create mode 100644 src/neovim/utils/buffered.ts create mode 100644 src/neovim/utils/constants.ts create mode 100644 src/neovim/utils/devnull.ts create mode 100644 src/neovim/utils/lodash.ts create mode 100644 src/neovim/utils/logger.ts diff --git a/package-lock.json b/package-lock.json index 3fdbc779be0..de63383c948 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "coc.nvim-master", "version": "0.0.82", "dependencies": { - "@chemzqm/neovim": "^6.1.2", + "@chemzqm/msgpack-lite": "^0.1.29", "ansi-styles": "^5.2.0", "bytes": "^3.1.2", "cli-table": "^0.3.11", @@ -709,6 +709,7 @@ "version": "0.1.29", "resolved": "https://registry.npmjs.org/@chemzqm/msgpack-lite/-/msgpack-lite-0.1.29.tgz", "integrity": "sha512-WbOT869c9BBLTpd51tQaFQRxwQZGaFzaaz03/df8zvXpHW8Xkfvw5u9SBxYuf+noJqeRKQxXsLWzeipMj2p3bQ==", + "license": "MIT", "dependencies": { "ieee754": "^1.1.8", "int64-buffer": "^0.1.9" @@ -717,14 +718,6 @@ "msgpack": "bin/msgpack" } }, - "node_modules/@chemzqm/neovim": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@chemzqm/neovim/-/neovim-6.1.2.tgz", - "integrity": "sha512-gUQrGlz8cYOgywfj0S8Nht2WfTFQtLvun/erdCIhFdnK0eh1GhxcR2nM5xk1PcSXP3ewRK40gbRgJ3RFP6CSqQ==", - "dependencies": { - "@chemzqm/msgpack-lite": "^0.1.29" - } - }, "node_modules/@es-joy/jsdoccomment": { "version": "0.46.0", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz", @@ -4219,7 +4212,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { "version": "5.3.1", @@ -4293,7 +4287,8 @@ "node_modules/int64-buffer": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/int64-buffer/-/int64-buffer-0.1.10.tgz", - "integrity": "sha512-v7cSY1J8ydZ0GyjUHqF+1bshJ6cnEVLo9EnjB8p+4HDRPZc9N5jjmvUV7NvEsqQOKyH0pmIBFWXVQbiS0+OBbA==" + "integrity": "sha512-v7cSY1J8ydZ0GyjUHqF+1bshJ6cnEVLo9EnjB8p+4HDRPZc9N5jjmvUV7NvEsqQOKyH0pmIBFWXVQbiS0+OBbA==", + "license": "MIT" }, "node_modules/is-arrayish": { "version": "0.2.1", diff --git a/package.json b/package.json index 3afc2a1b2e1..35abb7b3dd9 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "vscode-languageserver": "^9.0.1" }, "dependencies": { - "@chemzqm/neovim": "^6.1.2", + "@chemzqm/msgpack-lite": "^0.1.29", "ansi-styles": "^5.2.0", "bytes": "^3.1.2", "cli-table": "^0.3.11", diff --git a/src/__tests__/client/diagnostics.test.ts b/src/__tests__/client/diagnostics.test.ts index 094a4802c4e..9381a9c1783 100644 --- a/src/__tests__/client/diagnostics.test.ts +++ b/src/__tests__/client/diagnostics.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import os from 'os' import path from 'path' import { v4 as uuid } from 'uuid' diff --git a/src/__tests__/client/progressPart.test.ts b/src/__tests__/client/progressPart.test.ts index d3b8dcc3968..f6c425bd363 100644 --- a/src/__tests__/client/progressPart.test.ts +++ b/src/__tests__/client/progressPart.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Emitter, Event, NotificationHandler, WorkDoneProgressBegin, WorkDoneProgressEnd, WorkDoneProgressReport } from 'vscode-languageserver-protocol' import { ProgressContext, ProgressPart } from '../../language-client/progressPart' import helper from '../helper' diff --git a/src/__tests__/client/textSynchronization.test.ts b/src/__tests__/client/textSynchronization.test.ts index fb450975ac4..25eaef845d0 100644 --- a/src/__tests__/client/textSynchronization.test.ts +++ b/src/__tests__/client/textSynchronization.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import os from 'os' import path from 'path' diff --git a/src/__tests__/completion/basic.test.ts b/src/__tests__/completion/basic.test.ts index b33f0b4bb63..f77465f9fab 100644 --- a/src/__tests__/completion/basic.test.ts +++ b/src/__tests__/completion/basic.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, Disposable, Position, TextEdit } from 'vscode-languageserver-protocol' import commands from '../../commands' import completion, { Completion } from '../../completion' diff --git a/src/__tests__/completion/float.test.ts b/src/__tests__/completion/float.test.ts index 49785fd1c99..1e89410775e 100644 --- a/src/__tests__/completion/float.test.ts +++ b/src/__tests__/completion/float.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import Floating from '../../completion/floating' import { getInsertWord, prefixWord } from '../../completion/pum' import sources from '../../completion/sources' diff --git a/src/__tests__/completion/language.test.ts b/src/__tests__/completion/language.test.ts index f9c8d3fdc16..af71b9288b9 100644 --- a/src/__tests__/completion/language.test.ts +++ b/src/__tests__/completion/language.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, Disposable } from 'vscode-languageserver-protocol' import { CompletionItem, CompletionItemKind, CompletionList, InsertReplaceEdit, InsertTextFormat, InsertTextMode, Position, Range, TextEdit } from 'vscode-languageserver-types' import commandManager from '../../commands' diff --git a/src/__tests__/completion/sources.test.ts b/src/__tests__/completion/sources.test.ts index dff77b2bbb7..bc43078da4b 100644 --- a/src/__tests__/completion/sources.test.ts +++ b/src/__tests__/completion/sources.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import path from 'path' import os from 'os' import fs from 'fs' diff --git a/src/__tests__/completion/util.test.ts b/src/__tests__/completion/util.test.ts index c7dec083e9e..3b6531e4564 100644 --- a/src/__tests__/completion/util.test.ts +++ b/src/__tests__/completion/util.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, CompletionItem, CompletionItemKind, CompletionItemTag, Disposable, InsertTextFormat, Position, Range, TextEdit } from 'vscode-languageserver-protocol' import { caseScore, matchScore, matchScoreWithPositions } from '../../completion/match' import sources from '../../completion/sources' diff --git a/src/__tests__/core/autocmds.test.ts b/src/__tests__/core/autocmds.test.ts index 9e2fd3d0870..936801e8211 100644 --- a/src/__tests__/core/autocmds.test.ts +++ b/src/__tests__/core/autocmds.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable, Emitter } from 'vscode-languageserver-protocol' import { URI } from 'vscode-uri' import { createCommand } from '../../core/autocmds' diff --git a/src/__tests__/core/documents.test.ts b/src/__tests__/core/documents.test.ts index e54c3d09dc1..a75eebec1f8 100644 --- a/src/__tests__/core/documents.test.ts +++ b/src/__tests__/core/documents.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import os from 'os' import path from 'path' diff --git a/src/__tests__/core/editors.test.ts b/src/__tests__/core/editors.test.ts index 4ac8d70d652..0282fe7249a 100644 --- a/src/__tests__/core/editors.test.ts +++ b/src/__tests__/core/editors.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import Editors, { TextEditor, renamed } from '../../core/editors' import workspace from '../../workspace' import window from '../../window' diff --git a/src/__tests__/core/files.test.ts b/src/__tests__/core/files.test.ts index b2870329994..60947a6cac6 100644 --- a/src/__tests__/core/files.test.ts +++ b/src/__tests__/core/files.test.ts @@ -1,4 +1,4 @@ -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../../neovim' import fs from 'fs' import os from 'os' import path from 'path' diff --git a/src/__tests__/core/keymaps.test.ts b/src/__tests__/core/keymaps.test.ts index 539bfb7e669..27501a92c6c 100644 --- a/src/__tests__/core/keymaps.test.ts +++ b/src/__tests__/core/keymaps.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import workspace from '../../workspace' import Keymaps, { getBufnr, getKeymapModifier } from '../../core/keymaps' import helper from '../helper' diff --git a/src/__tests__/core/locations.test.ts b/src/__tests__/core/locations.test.ts index f751422b12f..0482ff8e373 100644 --- a/src/__tests__/core/locations.test.ts +++ b/src/__tests__/core/locations.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import os from 'os' import path from 'path' import { Location, Position, Range } from 'vscode-languageserver-protocol' diff --git a/src/__tests__/core/terminals.test.ts b/src/__tests__/core/terminals.test.ts index 11059f51f14..55cf96702e9 100644 --- a/src/__tests__/core/terminals.test.ts +++ b/src/__tests__/core/terminals.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import os from 'os' import path from 'path' import which from 'which' diff --git a/src/__tests__/core/ui.test.ts b/src/__tests__/core/ui.test.ts index 49e2c162fdc..9dfa886a686 100644 --- a/src/__tests__/core/ui.test.ts +++ b/src/__tests__/core/ui.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Position, Range } from 'vscode-languageserver-types' import * as ui from '../../core/ui' import helper from '../helper' diff --git a/src/__tests__/core/workspaceFolder.test.ts b/src/__tests__/core/workspaceFolder.test.ts index 9e528af2a57..ae6407a16fe 100644 --- a/src/__tests__/core/workspaceFolder.test.ts +++ b/src/__tests__/core/workspaceFolder.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import os from 'os' import path from 'path' diff --git a/src/__tests__/handler/callHierarchy.test.ts b/src/__tests__/handler/callHierarchy.test.ts index e1d6f5064bc..9e8f9b654ae 100644 --- a/src/__tests__/handler/callHierarchy.test.ts +++ b/src/__tests__/handler/callHierarchy.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable, CallHierarchyItem, SymbolKind, Range, SymbolTag, CancellationToken, Position } from 'vscode-languageserver-protocol' import CallHierarchyHandler from '../../handler/callHierarchy' import languages from '../../languages' diff --git a/src/__tests__/handler/codeActions.test.ts b/src/__tests__/handler/codeActions.test.ts index 40f386e9b48..9a07f1de8a7 100644 --- a/src/__tests__/handler/codeActions.test.ts +++ b/src/__tests__/handler/codeActions.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, CodeAction, CodeActionContext, CodeActionKind, Command, Disposable, Position, Range, TextEdit } from 'vscode-languageserver-protocol' import { TextDocument } from 'vscode-languageserver-textdocument' import commands from '../../commands' diff --git a/src/__tests__/handler/codelens.test.ts b/src/__tests__/handler/codelens.test.ts index 404a002cf4c..c04397c00ca 100644 --- a/src/__tests__/handler/codelens.test.ts +++ b/src/__tests__/handler/codelens.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, CodeLens, Command, Disposable, Position, Range, TextEdit } from 'vscode-languageserver-protocol' import commands from '../../commands' import events from '../../events' diff --git a/src/__tests__/handler/commands.test.ts b/src/__tests__/handler/commands.test.ts index 828c05e9e8c..3c1882ce27a 100644 --- a/src/__tests__/handler/commands.test.ts +++ b/src/__tests__/handler/commands.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable } from 'vscode-languageserver-protocol' import commandManager from '../../commands' import CommandsHandler from '../../handler/commands' diff --git a/src/__tests__/handler/documentColors.test.ts b/src/__tests__/handler/documentColors.test.ts index cc6df61f761..e4b0708bdd5 100644 --- a/src/__tests__/handler/documentColors.test.ts +++ b/src/__tests__/handler/documentColors.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, Color, ColorInformation, ColorPresentation, Disposable, Position, Range } from 'vscode-languageserver-protocol' import { TextDocument } from 'vscode-languageserver-textdocument' import commands from '../../commands' diff --git a/src/__tests__/handler/documentLinks.test.ts b/src/__tests__/handler/documentLinks.test.ts index 6294cfb1c21..e510a45a58f 100644 --- a/src/__tests__/handler/documentLinks.test.ts +++ b/src/__tests__/handler/documentLinks.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, Disposable, DocumentLink, Range } from 'vscode-languageserver-protocol' import { TextDocument } from 'vscode-languageserver-textdocument' import events from '../../events' diff --git a/src/__tests__/handler/fold.test.ts b/src/__tests__/handler/fold.test.ts index 7a630f2f2c2..d100d424ab3 100644 --- a/src/__tests__/handler/fold.test.ts +++ b/src/__tests__/handler/fold.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, CancellationTokenSource, Disposable, FoldingRange } from 'vscode-languageserver-protocol' import FoldHandler from '../../handler/fold' import languages from '../../languages' diff --git a/src/__tests__/handler/format.test.ts b/src/__tests__/handler/format.test.ts index 972acab20c5..8c04f32ca10 100644 --- a/src/__tests__/handler/format.test.ts +++ b/src/__tests__/handler/format.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, CancellationTokenSource, Disposable, Position, Range, TextEdit } from 'vscode-languageserver-protocol' import commands from '../../commands' import Format from '../../handler/format' diff --git a/src/__tests__/handler/highlights.test.ts b/src/__tests__/handler/highlights.test.ts index a1f3308e4e8..786f399b19a 100644 --- a/src/__tests__/handler/highlights.test.ts +++ b/src/__tests__/handler/highlights.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable, DocumentHighlightKind, Position, Range, TextEdit } from 'vscode-languageserver-protocol' import commands from '../../commands' import Highlights from '../../handler/highlights' diff --git a/src/__tests__/handler/hover.test.ts b/src/__tests__/handler/hover.test.ts index da11ab7a6d5..635340b2d5b 100644 --- a/src/__tests__/handler/hover.test.ts +++ b/src/__tests__/handler/hover.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable, MarkedString, Hover, Range, TextEdit, Position, CancellationToken, MarkupKind } from 'vscode-languageserver-protocol' import HoverHandler, { addDefinitions, addDocument, isDocumentation, readLines } from '../../handler/hover' import { URI } from 'vscode-uri' diff --git a/src/__tests__/handler/index.test.ts b/src/__tests__/handler/index.test.ts index 3e1779d4a8e..5641d421cf9 100644 --- a/src/__tests__/handler/index.test.ts +++ b/src/__tests__/handler/index.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable, SymbolKind } from 'vscode-languageserver-protocol' import commands from '../../commands' import Handler from '../../handler/index' diff --git a/src/__tests__/handler/inlayHint.test.ts b/src/__tests__/handler/inlayHint.test.ts index 846392c2b17..8e5ed5e6dd8 100644 --- a/src/__tests__/handler/inlayHint.test.ts +++ b/src/__tests__/handler/inlayHint.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationTokenSource, Disposable, InlayHint, InlayHintKind, Position, Range, TextEdit } from 'vscode-languageserver-protocol' import commands from '../../commands' import InlayHintHandler from '../../handler/inlayHint/index' diff --git a/src/__tests__/handler/inlineValue.test.ts b/src/__tests__/handler/inlineValue.test.ts index 078a1143d84..a2a7e181f29 100644 --- a/src/__tests__/handler/inlineValue.test.ts +++ b/src/__tests__/handler/inlineValue.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, Disposable, InlineValueText, Range } from 'vscode-languageserver-protocol' import languages, { ProviderName } from '../../languages' import { disposeAll } from '../../util' diff --git a/src/__tests__/handler/linkedEditing.test.ts b/src/__tests__/handler/linkedEditing.test.ts index 93cfdce5e9c..d0defcdde4b 100644 --- a/src/__tests__/handler/linkedEditing.test.ts +++ b/src/__tests__/handler/linkedEditing.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable, Position, Range, TextEdit } from 'vscode-languageserver-protocol' import LinkedEditingHandler from '../../handler/linkedEditing' import languages from '../../languages' diff --git a/src/__tests__/handler/locations.test.ts b/src/__tests__/handler/locations.test.ts index cf3e1a3a9fe..c1a080c176c 100644 --- a/src/__tests__/handler/locations.test.ts +++ b/src/__tests__/handler/locations.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable, LocationLink, Location, Range, Position, CancellationTokenSource, CancellationToken } from 'vscode-languageserver-protocol' import LocationHandler from '../../handler/locations' import languages from '../../languages' diff --git a/src/__tests__/handler/outline.test.ts b/src/__tests__/handler/outline.test.ts index 7f3869f59ad..f719d6c9202 100644 --- a/src/__tests__/handler/outline.test.ts +++ b/src/__tests__/handler/outline.test.ts @@ -1,4 +1,4 @@ -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../../neovim' import { CodeAction, CodeActionKind, Disposable, DocumentSymbol, Range, SymbolKind, SymbolTag, TextEdit } from 'vscode-languageserver-protocol' import events from '../../events' import Symbols from '../../handler/symbols/index' diff --git a/src/__tests__/handler/refactor.test.ts b/src/__tests__/handler/refactor.test.ts index 38e38b0f43a..6325fd5314f 100644 --- a/src/__tests__/handler/refactor.test.ts +++ b/src/__tests__/handler/refactor.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import { Position, Range, TextDocumentEdit, TextEdit, WorkspaceEdit } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' diff --git a/src/__tests__/handler/rename.test.ts b/src/__tests__/handler/rename.test.ts index 82e3d20c402..ded525f3086 100644 --- a/src/__tests__/handler/rename.test.ts +++ b/src/__tests__/handler/rename.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, Disposable, Position, Range, TextEdit } from 'vscode-languageserver-protocol' import { TextDocument } from 'vscode-languageserver-textdocument' import commands from '../../commands' diff --git a/src/__tests__/handler/search.test.ts b/src/__tests__/handler/search.test.ts index ed29320ea66..3880a70c47f 100644 --- a/src/__tests__/handler/search.test.ts +++ b/src/__tests__/handler/search.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import Refactor from '../../handler/refactor' import Search, { getPathFromArgs } from '../../handler/refactor/search' import helper from '../helper' diff --git a/src/__tests__/handler/selectionRange.test.ts b/src/__tests__/handler/selectionRange.test.ts index 20224f70268..737cb6c444d 100644 --- a/src/__tests__/handler/selectionRange.test.ts +++ b/src/__tests__/handler/selectionRange.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, Disposable, Position, Range, TextEdit } from 'vscode-languageserver-protocol' import SelectionRange from '../../handler/selectionRange' import languages from '../../languages' diff --git a/src/__tests__/handler/semanticTokens.test.ts b/src/__tests__/handler/semanticTokens.test.ts index e888ab6ed6a..0eb5578c3d1 100644 --- a/src/__tests__/handler/semanticTokens.test.ts +++ b/src/__tests__/handler/semanticTokens.test.ts @@ -1,4 +1,4 @@ -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../../neovim' import fs from 'fs' import os from 'os' import path from 'path' diff --git a/src/__tests__/handler/signature.test.ts b/src/__tests__/handler/signature.test.ts index 7c3e9905cfc..c4b679955d7 100644 --- a/src/__tests__/handler/signature.test.ts +++ b/src/__tests__/handler/signature.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable, ParameterInformation, SignatureInformation } from 'vscode-languageserver-protocol' import commands from '../../commands' import Signature from '../../handler/signature' diff --git a/src/__tests__/handler/symbols.test.ts b/src/__tests__/handler/symbols.test.ts index cd060da273d..715c96bd99a 100644 --- a/src/__tests__/handler/symbols.test.ts +++ b/src/__tests__/handler/symbols.test.ts @@ -1,4 +1,4 @@ -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../../neovim' import { CancellationToken, Disposable, Range, SymbolInformation, SymbolKind } from 'vscode-languageserver-protocol' import events from '../../events' import Symbols from '../../handler/symbols/index' diff --git a/src/__tests__/handler/typeHierarchy.test.ts b/src/__tests__/handler/typeHierarchy.test.ts index 00ed28f22e7..4a3ece5c608 100644 --- a/src/__tests__/handler/typeHierarchy.test.ts +++ b/src/__tests__/handler/typeHierarchy.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationToken, TypeHierarchyItem, Disposable, Range, SymbolKind, Position, SymbolTag } from 'vscode-languageserver-protocol' import { URI } from 'vscode-uri' import languages, { ProviderName } from '../../languages' diff --git a/src/__tests__/handler/workspace.test.ts b/src/__tests__/handler/workspace.test.ts index fa396048e4c..b8a686f370b 100644 --- a/src/__tests__/handler/workspace.test.ts +++ b/src/__tests__/handler/workspace.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import os from 'os' import path from 'path' diff --git a/src/__tests__/helper.ts b/src/__tests__/helper.ts index e0170bd9da9..afc3ef70ccd 100644 --- a/src/__tests__/helper.ts +++ b/src/__tests__/helper.ts @@ -1,4 +1,4 @@ -import type { Buffer, Neovim, Window } from '@chemzqm/neovim' +import type { Buffer, Neovim, Window } from '../neovim' import * as cp from 'child_process' import { EventEmitter } from 'events' import fs from 'fs' diff --git a/src/__tests__/list/commandTask.test.ts b/src/__tests__/list/commandTask.test.ts index 3437a26703f..2252450fa7d 100644 --- a/src/__tests__/list/commandTask.test.ts +++ b/src/__tests__/list/commandTask.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import path from 'path' import { ListContext, ListTask } from '../../list/types' import manager from '../../list/manager' diff --git a/src/__tests__/list/manager.test.ts b/src/__tests__/list/manager.test.ts index f0378ab3270..ac5063b80d5 100644 --- a/src/__tests__/list/manager.test.ts +++ b/src/__tests__/list/manager.test.ts @@ -1,4 +1,4 @@ -import { Neovim, Window } from '@chemzqm/neovim' +import { Neovim, Window } from '../../neovim' import EventEmitter from 'events' import path from 'path' import { Range } from 'vscode-languageserver-types' diff --git a/src/__tests__/list/mappings.test.ts b/src/__tests__/list/mappings.test.ts index c9e613061e9..9978a17a734 100644 --- a/src/__tests__/list/mappings.test.ts +++ b/src/__tests__/list/mappings.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import path from 'path' import { CancellationToken, Disposable } from 'vscode-languageserver-protocol' import BasicList from '../../list/basic' diff --git a/src/__tests__/list/session.test.ts b/src/__tests__/list/session.test.ts index bed88f269a2..1312bac25de 100644 --- a/src/__tests__/list/session.test.ts +++ b/src/__tests__/list/session.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable } from 'vscode-languageserver-protocol' import BasicList from '../../list/basic' import manager from '../../list/manager' diff --git a/src/__tests__/list/sources.test.ts b/src/__tests__/list/sources.test.ts index 2942ecb40d2..0e53b28ed6e 100644 --- a/src/__tests__/list/sources.test.ts +++ b/src/__tests__/list/sources.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import os from 'os' import { v4 as uuid } from 'uuid' @@ -696,7 +696,7 @@ describe('list sources', () => { const workspaceFolder = path.join(__dirname, 'workspace-folder1') jest.spyOn(workspace, 'getWorkspaceFolder').mockReturnValue({ - name : 'workspace-folder1', + name: 'workspace-folder1', uri: URI.file(workspaceFolder).toString() }) await manager.start(['diagnostics', '--workspace-folder']) @@ -721,7 +721,7 @@ describe('list sources', () => { const workspaceFolder = path.join(__dirname, 'workspace-folder4') jest.spyOn(workspace, 'getWorkspaceFolder').mockReturnValue({ - name : 'workspace-folder4', + name: 'workspace-folder4', uri: URI.file(workspaceFolder).toString() }) await manager.start(['diagnostics', '--workspace-folder']) diff --git a/src/__tests__/list/ui.test.ts b/src/__tests__/list/ui.test.ts index 6d0b09b3298..205b06569ed 100644 --- a/src/__tests__/list/ui.test.ts +++ b/src/__tests__/list/ui.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { EventEmitter } from 'events' import { Disposable } from 'vscode-languageserver-protocol' import BasicList from '../../list/basic' diff --git a/src/__tests__/list/worker.test.ts b/src/__tests__/list/worker.test.ts index e4ea1e06b3c..8c64827f489 100644 --- a/src/__tests__/list/worker.test.ts +++ b/src/__tests__/list/worker.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import styles from 'ansi-styles' import { EventEmitter } from 'events' import { CancellationToken, Disposable } from 'vscode-languageserver-protocol' diff --git a/src/__tests__/modules/attach.test.ts b/src/__tests__/modules/attach.test.ts index 2cd4b0fa7ca..b4f79e7c951 100644 --- a/src/__tests__/modules/attach.test.ts +++ b/src/__tests__/modules/attach.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import events from '../../events' import helper from '../helper' import workspace from '../../workspace' diff --git a/src/__tests__/modules/cursors.test.ts b/src/__tests__/modules/cursors.test.ts index 93d66ab1a85..49d1f38c017 100644 --- a/src/__tests__/modules/cursors.test.ts +++ b/src/__tests__/modules/cursors.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Position, Range, TextEdit } from 'vscode-languageserver-types' import Cursors from '../../cursors' import CursorsSession, { surrondChanges } from '../../cursors/session' diff --git a/src/__tests__/modules/diagnosticBuffer.test.ts b/src/__tests__/modules/diagnosticBuffer.test.ts index b0218cb6e51..cca4fecd557 100644 --- a/src/__tests__/modules/diagnosticBuffer.test.ts +++ b/src/__tests__/modules/diagnosticBuffer.test.ts @@ -1,5 +1,5 @@ import helper from '../helper' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { DiagnosticBuffer } from '../../diagnostic/buffer' import { Range, DiagnosticSeverity, Diagnostic, DiagnosticTag, Position, TextEdit } from 'vscode-languageserver-types' import workspace from '../../workspace' diff --git a/src/__tests__/modules/diagnosticManager.test.ts b/src/__tests__/modules/diagnosticManager.test.ts index b413e7cb287..f26372ef53d 100644 --- a/src/__tests__/modules/diagnosticManager.test.ts +++ b/src/__tests__/modules/diagnosticManager.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import os from 'os' import path from 'path' import { Diagnostic, DiagnosticSeverity, DiagnosticTag, Location, Position, Range } from 'vscode-languageserver-protocol' diff --git a/src/__tests__/modules/dialog.test.ts b/src/__tests__/modules/dialog.test.ts index a299a2868b3..c6ce4dd2ba3 100644 --- a/src/__tests__/modules/dialog.test.ts +++ b/src/__tests__/modules/dialog.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import events from '../../events' import { Dialog, DialogButton } from '../../model/dialog' import ProgressNotification from '../../model/progress' diff --git a/src/__tests__/modules/document.test.ts b/src/__tests__/modules/document.test.ts index 8e8661a1b6e..387eeb8188b 100644 --- a/src/__tests__/modules/document.test.ts +++ b/src/__tests__/modules/document.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import path from 'path' import { Position, Range, TextEdit } from 'vscode-languageserver-protocol' diff --git a/src/__tests__/modules/extensionManager.test.ts b/src/__tests__/modules/extensionManager.test.ts index 28f03801b0d..3938e8fe450 100644 --- a/src/__tests__/modules/extensionManager.test.ts +++ b/src/__tests__/modules/extensionManager.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import os from 'os' import path from 'path' diff --git a/src/__tests__/modules/extensionModules.test.ts b/src/__tests__/modules/extensionModules.test.ts index 59675d36d1b..4528fcb3cdf 100644 --- a/src/__tests__/modules/extensionModules.test.ts +++ b/src/__tests__/modules/extensionModules.test.ts @@ -1,5 +1,5 @@ process.env.COC_NO_PLUGINS = '1' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import os from 'os' import path from 'path' diff --git a/src/__tests__/modules/floatFactory.test.ts b/src/__tests__/modules/floatFactory.test.ts index 55720a4b221..5174fdecdee 100644 --- a/src/__tests__/modules/floatFactory.test.ts +++ b/src/__tests__/modules/floatFactory.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import events from '../../events' import FloatFactoryImpl from '../../model/floatFactory' import snippetManager from '../../snippets/manager' diff --git a/src/__tests__/modules/highlighter.test.ts b/src/__tests__/modules/highlighter.test.ts index 11f41d2673c..047a765d8bf 100644 --- a/src/__tests__/modules/highlighter.test.ts +++ b/src/__tests__/modules/highlighter.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import Highlighter from '../../model/highlighter' import helper from '../helper' diff --git a/src/__tests__/modules/menu.test.ts b/src/__tests__/modules/menu.test.ts index 6103a35b17a..b5e6990a7fe 100644 --- a/src/__tests__/modules/menu.test.ts +++ b/src/__tests__/modules/menu.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationTokenSource } from 'vscode-languageserver-protocol' import Menu, { isMenuItem, toIndexText } from '../../model/menu' import helper from '../helper' diff --git a/src/__tests__/modules/outputChannel.test.ts b/src/__tests__/modules/outputChannel.test.ts index 049ed245bc9..a34430783c7 100644 --- a/src/__tests__/modules/outputChannel.test.ts +++ b/src/__tests__/modules/outputChannel.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import OutputChannel from '../../model/outputChannel' import { wait } from '../../util' import helper from '../helper' diff --git a/src/__tests__/modules/picker.test.ts b/src/__tests__/modules/picker.test.ts index ea06e46d29b..9ce40fe0d96 100644 --- a/src/__tests__/modules/picker.test.ts +++ b/src/__tests__/modules/picker.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationTokenSource } from 'vscode-languageserver-protocol' import events from '../../events' import Picker, { toPickerItems } from '../../model/picker' diff --git a/src/__tests__/modules/plugin.test.ts b/src/__tests__/modules/plugin.test.ts index 9c7c5df9daa..91abcb48c44 100644 --- a/src/__tests__/modules/plugin.test.ts +++ b/src/__tests__/modules/plugin.test.ts @@ -2,7 +2,7 @@ import helper from '../helper' import path from 'path' import workspace from '../../workspace' import Plugin from '../../plugin' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import * as exportObj from '../../index' import * as vsTypes from 'vscode-languageserver-types' diff --git a/src/__tests__/modules/quickpick.test.ts b/src/__tests__/modules/quickpick.test.ts index a68c21c7c64..f270feeea28 100644 --- a/src/__tests__/modules/quickpick.test.ts +++ b/src/__tests__/modules/quickpick.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CancellationTokenSource, Disposable } from 'vscode-languageserver-protocol' import { QuickPickItem } from '../../types' import { disposeAll } from '../../util' diff --git a/src/__tests__/modules/services.test.ts b/src/__tests__/modules/services.test.ts index 7b9d999601b..9028ab22e04 100644 --- a/src/__tests__/modules/services.test.ts +++ b/src/__tests__/modules/services.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import net from 'net' import os from 'os' diff --git a/src/__tests__/modules/sources.test.ts b/src/__tests__/modules/sources.test.ts index b7029910269..cc3088ea863 100644 --- a/src/__tests__/modules/sources.test.ts +++ b/src/__tests__/modules/sources.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import path from 'path' import { Disposable } from 'vscode-languageserver-protocol' import sources from '../../completion/sources' diff --git a/src/__tests__/modules/task.test.ts b/src/__tests__/modules/task.test.ts index 1dd18c5d7cf..5c7636f779b 100644 --- a/src/__tests__/modules/task.test.ts +++ b/src/__tests__/modules/task.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable } from 'vscode-languageserver-protocol' import { disposeAll } from '../../util' import workspace from '../../workspace' diff --git a/src/__tests__/modules/terminal.test.ts b/src/__tests__/modules/terminal.test.ts index b9e485999b4..c7cdae573c1 100644 --- a/src/__tests__/modules/terminal.test.ts +++ b/src/__tests__/modules/terminal.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import helper from '../helper' import { TerminalModel } from '../../model/terminal' diff --git a/src/__tests__/modules/window.test.ts b/src/__tests__/modules/window.test.ts index 680af5aab92..42f34c79dd9 100644 --- a/src/__tests__/modules/window.test.ts +++ b/src/__tests__/modules/window.test.ts @@ -1,5 +1,5 @@ -import { Buffer, Neovim } from '@chemzqm/neovim' -import { HighlightItem } from '@chemzqm/neovim/lib/api/Buffer' +import { Buffer, Neovim } from '../../neovim' +import { HighlightItem } from '../../neovim/api/Buffer' import { CancellationToken, Disposable, Emitter } from 'vscode-languageserver-protocol' import { URI } from 'vscode-uri' import { convertHighlightItem } from '../../core/highlights' diff --git a/src/__tests__/modules/workspace.test.ts b/src/__tests__/modules/workspace.test.ts index c3b4d37dddc..5872d2f9624 100644 --- a/src/__tests__/modules/workspace.test.ts +++ b/src/__tests__/modules/workspace.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import fs from 'fs' import os from 'os' import path from 'path' diff --git a/src/__tests__/snippets/manager.test.ts b/src/__tests__/snippets/manager.test.ts index c3fa228ca04..227f2f14b25 100644 --- a/src/__tests__/snippets/manager.test.ts +++ b/src/__tests__/snippets/manager.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import path from 'path' import { InsertTextMode, Range, TextEdit } from 'vscode-languageserver-protocol' import commandManager from '../../commands' diff --git a/src/__tests__/snippets/session.test.ts b/src/__tests__/snippets/session.test.ts index dc1e1f4bb06..0afcdae0224 100644 --- a/src/__tests__/snippets/session.test.ts +++ b/src/__tests__/snippets/session.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import path from 'path' import { Position, Range, TextEdit } from 'vscode-languageserver-protocol' import { UltiSnippetContext } from '../../snippets/eval' diff --git a/src/__tests__/snippets/snippet.test.ts b/src/__tests__/snippets/snippet.test.ts index fdc63637b12..064ba362fff 100644 --- a/src/__tests__/snippets/snippet.test.ts +++ b/src/__tests__/snippets/snippet.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import path from 'path' import { CancellationTokenSource } from 'vscode-languageserver-protocol' import { Position, Range, TextEdit } from 'vscode-languageserver-types' diff --git a/src/__tests__/tree/treeView.test.ts b/src/__tests__/tree/treeView.test.ts index 6aa594c3c49..946c00ef038 100644 --- a/src/__tests__/tree/treeView.test.ts +++ b/src/__tests__/tree/treeView.test.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Disposable } from 'vscode-languageserver-protocol' import { URI } from 'vscode-uri' import events from '../../events' diff --git a/src/__tests__/vim.test.ts b/src/__tests__/vim.test.ts index 15ca38125ce..8910b328fb9 100644 --- a/src/__tests__/vim.test.ts +++ b/src/__tests__/vim.test.ts @@ -1,5 +1,5 @@ process.env.VIM_NODE_RPC = '1' -import type { Buffer, Neovim, Tabpage, Window } from '@chemzqm/neovim' +import type { Buffer, Neovim, Tabpage, Window } from '../neovim' import { CompleteResult, ExtendedCompleteItem } from '../completion/types' import { sameFile } from '../util/fs' import type { Helper } from './helper' diff --git a/src/attach.ts b/src/attach.ts index 3fb11df4aae..c4c0e940e7d 100644 --- a/src/attach.ts +++ b/src/attach.ts @@ -1,5 +1,5 @@ 'use strict' -import { attach, Attach, Neovim } from '@chemzqm/neovim' +import { attach, Attach, Neovim } from './neovim' import { URI } from 'vscode-uri' import events from './events' import { createLogger } from './logger' @@ -30,7 +30,7 @@ export function pathReplace(patterns: object | undefined): void { } export default (opts: Attach, requestApi = false): Plugin => { - const nvim: Neovim = attach(opts, createLogger('node-client'), requestApi) + const nvim: Neovim = attach(opts, createLogger('node-client-root'), requestApi) nvim.setVar('coc_process_pid', process.pid, true) nvim.setClientInfo('coc', { major: semVer.major, minor: semVer.minor, patch: semVer.patch }, 'remote', {}, {}) const plugin = new Plugin(nvim) diff --git a/src/commands.ts b/src/commands.ts index b1f6f2e9977..1baf625f35c 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from './neovim' import { Command as VCommand } from 'vscode-languageserver-types' import events from './events' import { createLogger } from './logger' @@ -93,7 +93,6 @@ class CommandManager implements Disposable { * * Registering a command with an existing command identifier twice * will cause an error. - * * @param command A unique identifier for the command. * @param impl A command handler function. * @param thisArg The `this` context used when invoking the handler function. @@ -116,7 +115,6 @@ class CommandManager implements Disposable { * `number`, `undefined`, and `null`, as well as [`Position`](#Position), [`Range`](#Range), [`URI`](#URI) and [`Location`](#Location). * * *Note 2:* There are no restrictions when executing commands that have been contributed * by extensions. - * * @param command Identifier of the command to execute. * @param rest Parameters passed to the command function. * @return A promise that resolves to the returned value of the given command. `undefined` when diff --git a/src/completion/complete.ts b/src/completion/complete.ts index c05b6431c52..1ec9a17a2a2 100644 --- a/src/completion/complete.ts +++ b/src/completion/complete.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Neovim } from '@chemzqm/neovim' +import type { Neovim } from '../neovim' import { Position, Range } from 'vscode-languageserver-types' import { createLogger } from '../logger' import type Document from '../model/document' diff --git a/src/completion/index.ts b/src/completion/index.ts index 00d91f03339..06d565dd8cd 100644 --- a/src/completion/index.ts +++ b/src/completion/index.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Position } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import commands from '../commands' diff --git a/src/completion/pum.ts b/src/completion/pum.ts index cf8afe06b1d..0657fcec61b 100644 --- a/src/completion/pum.ts +++ b/src/completion/pum.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { CompletionItemKind } from 'vscode-languageserver-types' import { matchSpansReverse } from '../model/fuzzyMatch' import { FloatConfig, HighlightItem } from '../types' diff --git a/src/completion/source.ts b/src/completion/source.ts index b16e063aea1..e50b0072860 100644 --- a/src/completion/source.ts +++ b/src/completion/source.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import events from '../events' import { defaultValue, disposeAll, getConditionValue, waitImmediate } from '../util' import { isFalsyOrEmpty, toArray } from '../util/array' diff --git a/src/completion/sources.ts b/src/completion/sources.ts index cb741ba4bf7..83ad96b732f 100644 --- a/src/completion/sources.ts +++ b/src/completion/sources.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import events from '../events' import extensions from '../extension' import { createLogger } from '../logger' diff --git a/src/core/autocmds.ts b/src/core/autocmds.ts index 6ecdbd652be..e91617542e8 100644 --- a/src/core/autocmds.ts +++ b/src/core/autocmds.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Autocmd } from '../types' import { disposeAll } from '../util' import { isFalsyOrEmpty } from '../util/array' diff --git a/src/core/channels.ts b/src/core/channels.ts index 22710f436a5..66fa77a4908 100644 --- a/src/core/channels.ts +++ b/src/core/channels.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { URI } from 'vscode-uri' import events from '../events' import BufferChannel from '../model/outputChannel' diff --git a/src/core/contentProvider.ts b/src/core/contentProvider.ts index f339bd88ee7..a9d768d5d4f 100644 --- a/src/core/contentProvider.ts +++ b/src/core/contentProvider.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { URI } from 'vscode-uri' import events from '../events' import { TextDocumentContentProvider } from '../provider' diff --git a/src/core/dialogs.ts b/src/core/dialogs.ts index 2e3cee74dc0..4d1029adb59 100644 --- a/src/core/dialogs.ts +++ b/src/core/dialogs.ts @@ -1,4 +1,4 @@ -import type { Neovim } from '@chemzqm/neovim' +import type { Neovim } from '../neovim' import type { WorkspaceConfiguration } from '../configuration/types' import events from '../events' import { Dialog, DialogConfig, DialogPreferences } from '../model/dialog' diff --git a/src/core/documents.ts b/src/core/documents.ts index 1b1d6721a9d..ae843dbbda5 100644 --- a/src/core/documents.ts +++ b/src/core/documents.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { FormattingOptions, Location, LocationLink, TextEdit } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import Configurations from '../configuration' diff --git a/src/core/editors.ts b/src/core/editors.ts index 5471c163271..b5eb10b9d51 100644 --- a/src/core/editors.ts +++ b/src/core/editors.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Range } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import events from '../events' diff --git a/src/core/files.ts b/src/core/files.ts index 412161f526a..412b75a6826 100644 --- a/src/core/files.ts +++ b/src/core/files.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import type { TextDocument } from 'vscode-languageserver-textdocument' import { ChangeAnnotation, CreateFile, CreateFileOptions, DeleteFile, DeleteFileOptions, Position, RenameFile, RenameFileOptions, TextDocumentEdit, TextEdit, WorkspaceEdit } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' diff --git a/src/core/funcs.ts b/src/core/funcs.ts index 49a30fb3ed6..1a46160f707 100644 --- a/src/core/funcs.ts +++ b/src/core/funcs.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Neovim } from '@chemzqm/neovim' +import type { Neovim } from '../neovim' import type { DocumentFilter, DocumentSelector } from 'vscode-languageserver-protocol' import { URI } from 'vscode-uri' import Configurations from '../configuration' diff --git a/src/core/highlights.ts b/src/core/highlights.ts index 326dce7b192..e6efd538c97 100644 --- a/src/core/highlights.ts +++ b/src/core/highlights.ts @@ -1,4 +1,4 @@ -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { HighlightItem } from '../types' import { defaultValue } from '../util' import { equals } from '../util/object' diff --git a/src/core/keymaps.ts b/src/core/keymaps.ts index a7906a630f9..2f75cf06c83 100644 --- a/src/core/keymaps.ts +++ b/src/core/keymaps.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import events from '../events' import { createLogger } from '../logger' import { KeymapOption } from '../types' diff --git a/src/core/notifications.ts b/src/core/notifications.ts index abfa1c996c4..5d5114362ab 100644 --- a/src/core/notifications.ts +++ b/src/core/notifications.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { WorkspaceConfiguration } from '../configuration/types' import Notification, { MessageItem, NotificationConfig, NotificationKind, NotificationPreferences, toButtons, toTitles } from '../model/notification' import ProgressNotification, { formatMessage, Progress } from '../model/progress' diff --git a/src/core/terminals.ts b/src/core/terminals.ts index a5ef6e25fe9..d39ee3c1895 100644 --- a/src/core/terminals.ts +++ b/src/core/terminals.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import events from '../events' import { TerminalModel, TerminalOptions } from '../model/terminal' import { disposeAll } from '../util' diff --git a/src/core/ui.ts b/src/core/ui.ts index d84043c363b..05558d13abb 100644 --- a/src/core/ui.ts +++ b/src/core/ui.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Position, Range } from 'vscode-languageserver-types' import FloatFactoryImpl, { FloatWinConfig } from '../model/floatFactory' import { Documentation, FloatConfig, FloatFactory, FloatOptions } from '../types' @@ -59,7 +59,6 @@ export function createFloatFactory(nvim: Neovim, conf: FloatWinConfig, defaults: /** * Prompt user for confirm, a float/popup window would be used when possible, * use vim's |confirm()| function as callback. - * * @param title The prompt text. * @returns Result of confirm. */ @@ -70,7 +69,6 @@ export async function showPrompt(nvim: Neovim, title: string): Promise /** * Move cursor to position. - * * @param position LSP position. */ export async function moveTo(nvim: Neovim, position: Position, redraw: boolean): Promise { @@ -81,7 +79,6 @@ export async function moveTo(nvim: Neovim, position: Position, redraw: boolean): /** * Get current cursor character offset in document, * length of line break would always be 1. - * * @returns Character offset. */ export async function getOffset(nvim: Neovim): Promise { @@ -91,7 +88,6 @@ export async function getOffset(nvim: Neovim): Promise { /** * Get screen position of current cursor(relative to editor), * both `row` and `col` are 0 based. - * * @returns Cursor screen position. */ export async function getCursorScreenPosition(nvim: Neovim): Promise { diff --git a/src/core/watchers.ts b/src/core/watchers.ts index 02f65651f14..55c89ceffbb 100644 --- a/src/core/watchers.ts +++ b/src/core/watchers.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Neovim } from '@chemzqm/neovim' +import type { Neovim } from '../neovim' import events from '../events' import { createLogger } from '../logger' import { ProviderResult } from '../provider' diff --git a/src/cursors/index.ts b/src/cursors/index.ts index 089d92ca275..f83c1f335c1 100644 --- a/src/cursors/index.ts +++ b/src/cursors/index.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Range } from 'vscode-languageserver-types' import Document from '../model/document' import { IConfigurationChangeEvent } from '../types' diff --git a/src/cursors/session.ts b/src/cursors/session.ts index baf2106e972..aa03ce6a513 100644 --- a/src/cursors/session.ts +++ b/src/cursors/session.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { TextDocument } from 'vscode-languageserver-textdocument' import { Range, TextEdit } from 'vscode-languageserver-types' import { createLogger } from '../logger' diff --git a/src/diagnostic/buffer.ts b/src/diagnostic/buffer.ts index a883f3cfa8b..f52fd987196 100644 --- a/src/diagnostic/buffer.ts +++ b/src/diagnostic/buffer.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Buffer, Neovim, VirtualTextOption } from '@chemzqm/neovim' +import type { Buffer, Neovim, VirtualTextOption } from '../neovim' import { Diagnostic, DiagnosticSeverity, Position, TextEdit } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import events from '../events' @@ -360,18 +360,20 @@ export class DiagnosticBuffer implements SyncItem { if (config.showRelatedInformation && diagnostic.relatedInformation?.length) { msg = `${diagnostic.message}\n\nRelated information:\n` for (const info of diagnostic.relatedInformation) { - const fsPath = URI.parse(info.location.uri).fsPath - const basename = path.basename(fsPath) - const line = info.location.range.start.line + 1 - const column = info.location.range.start.character + 1 - msg = `${msg}\n * ${basename}#${line},${column}: ${info.message}` + const fsPath = URI.parse(info.location.uri).fsPath + const basename = path.basename(fsPath) + const line = info.location.range.start.line + 1 + const column = info.location.range.start.character + 1 + msg = `${msg}\n * ${basename}#${line},${column}: ${info.message}` } msg = msg + "\n\n" } - docs.push({ filetype, content: formatDiagnostic(config.format, { - ...diagnostic, - message: msg - }) }) + docs.push({ + filetype, content: formatDiagnostic(config.format, { + ...diagnostic, + message: msg + }) + }) if (link) { docs.push({ filetype: 'txt', content: link }) } diff --git a/src/diagnostic/manager.ts b/src/diagnostic/manager.ts index 8d94b83ef5b..9c42fb45b02 100644 --- a/src/diagnostic/manager.ts +++ b/src/diagnostic/manager.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Neovim } from '@chemzqm/neovim' +import type { Neovim } from '../neovim' import { Diagnostic, DiagnosticSeverity, DiagnosticTag, Location, Position, Range, TextDocumentIdentifier } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import commands from '../commands' diff --git a/src/diagnostic/util.ts b/src/diagnostic/util.ts index 1bf459c3362..9259f41d784 100644 --- a/src/diagnostic/util.ts +++ b/src/diagnostic/util.ts @@ -1,5 +1,5 @@ 'use strict' -import type { VirtualTextOption } from '@chemzqm/neovim' +import type { VirtualTextOption } from '../neovim' import { Diagnostic, DiagnosticSeverity, DiagnosticTag, Range, TextEdit } from 'vscode-languageserver-types' import { FloatConfig } from '../types' import { comparePosition, rangeOverlap } from '../util/position' diff --git a/src/handler/callHierarchy.ts b/src/handler/callHierarchy.ts index e4e544ad2f5..705d06ebd63 100644 --- a/src/handler/callHierarchy.ts +++ b/src/handler/callHierarchy.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { TextDocument } from 'vscode-languageserver-textdocument' import { CallHierarchyIncomingCall, CallHierarchyItem, CallHierarchyOutgoingCall, Position, Range } from 'vscode-languageserver-types' import commands from '../commands' diff --git a/src/handler/codeActions.ts b/src/handler/codeActions.ts index 91b8e221e0f..38130ae7683 100644 --- a/src/handler/codeActions.ts +++ b/src/handler/codeActions.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { CodeAction, CodeActionContext, CodeActionKind, CodeActionTriggerKind, Range } from 'vscode-languageserver-types' import commandManager from '../commands' import diagnosticManager from '../diagnostic/manager' diff --git a/src/handler/codelens/buffer.ts b/src/handler/codelens/buffer.ts index 93bd82a1a07..3bfa0de13f0 100644 --- a/src/handler/codelens/buffer.ts +++ b/src/handler/codelens/buffer.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Neovim } from '@chemzqm/neovim' +import type { Neovim } from '../../neovim' import { CodeLens, Command } from 'vscode-languageserver-types' import commandManager from '../../commands' import languages, { ProviderName } from '../../languages' diff --git a/src/handler/codelens/index.ts b/src/handler/codelens/index.ts index deabfba4782..8191a6958df 100644 --- a/src/handler/codelens/index.ts +++ b/src/handler/codelens/index.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Neovim } from '@chemzqm/neovim' +import type { Neovim } from '../../neovim' import type { DocumentSelector } from 'vscode-languageserver-protocol' import { debounce } from '../..//util/node' import commands from '../../commands' diff --git a/src/handler/colors/colorBuffer.ts b/src/handler/colors/colorBuffer.ts index b0a5c47979f..01bc5ecdd1a 100644 --- a/src/handler/colors/colorBuffer.ts +++ b/src/handler/colors/colorBuffer.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../../neovim' import { Color, ColorInformation, Position, Range } from 'vscode-languageserver-types' import languages, { ProviderName } from '../../languages' import { SyncItem } from '../../model/bufferSync' diff --git a/src/handler/colors/index.ts b/src/handler/colors/index.ts index 53f1b9df33b..df7531a4042 100644 --- a/src/handler/colors/index.ts +++ b/src/handler/colors/index.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { ColorInformation, Position } from 'vscode-languageserver-types' import commandManager from '../../commands' import events from '../../events' diff --git a/src/handler/commands.ts b/src/handler/commands.ts index b5840758822..7658fbb3126 100644 --- a/src/handler/commands.ts +++ b/src/handler/commands.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import commandManager from '../commands' import listManager from '../list/manager' import workspace from '../workspace' diff --git a/src/handler/fold.ts b/src/handler/fold.ts index d3a66236bef..54160c7c7b1 100644 --- a/src/handler/fold.ts +++ b/src/handler/fold.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import type { FoldingRangeKind } from 'vscode-languageserver-types' import languages, { ProviderName } from '../languages' import { HandlerDelegate } from './types' diff --git a/src/handler/format.ts b/src/handler/format.ts index 49e44c3915e..db1c917de88 100644 --- a/src/handler/format.ts +++ b/src/handler/format.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { TextDocument } from 'vscode-languageserver-textdocument' import { Position, Range, TextEdit } from 'vscode-languageserver-types' import commandManager from '../commands' diff --git a/src/handler/highlights.ts b/src/handler/highlights.ts index 0c3f8214bba..fcf3aba522e 100644 --- a/src/handler/highlights.ts +++ b/src/handler/highlights.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Buffer as NodeBuffer } from 'buffer' import { DocumentHighlight, DocumentHighlightKind, Position, Range } from 'vscode-languageserver-types' import commands from '../commands' diff --git a/src/handler/hover.ts b/src/handler/hover.ts index 971dec37e88..9b8c346d39d 100644 --- a/src/handler/hover.ts +++ b/src/handler/hover.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { DefinitionLink, Hover, MarkedString, MarkupContent, Position, Range } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import { IConfigurationChangeEvent } from '../configuration/types' diff --git a/src/handler/index.ts b/src/handler/index.ts index 9024c9204d4..3b5005ef79c 100644 --- a/src/handler/index.ts +++ b/src/handler/index.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { CodeAction, CodeActionKind, Location, Position, Range, SymbolKind } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import commands from '../commands' diff --git a/src/handler/inlayHint/buffer.ts b/src/handler/inlayHint/buffer.ts index 4eec0debbd8..32b8b14d705 100644 --- a/src/handler/inlayHint/buffer.ts +++ b/src/handler/inlayHint/buffer.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { InlayHintKind, Range } from 'vscode-languageserver-types' import events from '../../events' import languages, { ProviderName } from '../../languages' diff --git a/src/handler/inlayHint/index.ts b/src/handler/inlayHint/index.ts index a68c1d4c857..7bb2ecf2fa8 100644 --- a/src/handler/inlayHint/index.ts +++ b/src/handler/inlayHint/index.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import commands from '../../commands' import events from '../../events' import languages, { ProviderName } from '../../languages' diff --git a/src/handler/linkedEditing.ts b/src/handler/linkedEditing.ts index 94291c4ffdb..d93b46dcb32 100644 --- a/src/handler/linkedEditing.ts +++ b/src/handler/linkedEditing.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim, Window } from '@chemzqm/neovim' +import { Neovim, Window } from '../neovim' import { Position, TextEdit } from 'vscode-languageserver-types' import TextRange from '../cursors/textRange' import { getBeforeCount, getChange, getDelta } from '../cursors/util' diff --git a/src/handler/links.ts b/src/handler/links.ts index b1926088424..2c706557bca 100644 --- a/src/handler/links.ts +++ b/src/handler/links.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../neovim' import debounce from 'debounce' import { DocumentLink, Range } from 'vscode-languageserver-types' import { IConfigurationChangeEvent } from '../configuration/types' diff --git a/src/handler/locations.ts b/src/handler/locations.ts index 5f2bbcf75ec..6364e7cef93 100644 --- a/src/handler/locations.ts +++ b/src/handler/locations.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { TextDocument } from 'vscode-languageserver-textdocument' import { Location, LocationLink, Position } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' diff --git a/src/handler/refactor/buffer.ts b/src/handler/refactor/buffer.ts index bca1426b7bb..e24b8bb301a 100644 --- a/src/handler/refactor/buffer.ts +++ b/src/handler/refactor/buffer.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../../neovim' import { TextDocument } from 'vscode-languageserver-textdocument' import { Position, Range, TextEdit } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' diff --git a/src/handler/refactor/index.ts b/src/handler/refactor/index.ts index b4e9dafdbe6..bb1de6071db 100644 --- a/src/handler/refactor/index.ts +++ b/src/handler/refactor/index.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Location, Range, TextDocumentEdit, TextEdit, WorkspaceEdit } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import { IConfigurationChangeEvent } from '../../configuration/types' diff --git a/src/handler/refactor/search.ts b/src/handler/refactor/search.ts index 201abff66f1..8f73ceafa9c 100644 --- a/src/handler/refactor/search.ts +++ b/src/handler/refactor/search.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { ChildProcess, spawn } from 'child_process' import { EventEmitter } from 'events' import { Range } from 'vscode-languageserver-types' diff --git a/src/handler/rename.ts b/src/handler/rename.ts index 7e82129bf93..41abb23ab4e 100644 --- a/src/handler/rename.ts +++ b/src/handler/rename.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Range, WorkspaceEdit } from 'vscode-languageserver-types' import languages, { ProviderName } from '../languages' import { emptyRange } from '../util/position' diff --git a/src/handler/selectionRange.ts b/src/handler/selectionRange.ts index 9f06acbd728..07bd20965b5 100644 --- a/src/handler/selectionRange.ts +++ b/src/handler/selectionRange.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Neovim } from '@chemzqm/neovim' +import type { Neovim } from '../neovim' import { Position, Range, SelectionRange } from 'vscode-languageserver-types' import languages, { ProviderName } from '../languages' import { isFalsyOrEmpty } from '../util/array' diff --git a/src/handler/semanticTokens/buffer.ts b/src/handler/semanticTokens/buffer.ts index 09a88725c4c..5d497579eae 100644 --- a/src/handler/semanticTokens/buffer.ts +++ b/src/handler/semanticTokens/buffer.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../../neovim' import { Range, SemanticTokens, SemanticTokensDelta, SemanticTokensLegend, uinteger } from 'vscode-languageserver-types' import languages, { ProviderName } from '../../languages' import { createLogger } from '../../logger' diff --git a/src/handler/semanticTokens/index.ts b/src/handler/semanticTokens/index.ts index fab5b222ef5..03800fda6fb 100644 --- a/src/handler/semanticTokens/index.ts +++ b/src/handler/semanticTokens/index.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Neovim } from '@chemzqm/neovim' +import type { Neovim } from '../../neovim' import commands from '../../commands' import events from '../../events' import languages from '../../languages' diff --git a/src/handler/signature.ts b/src/handler/signature.ts index 98baa6721d3..b2f2a5e17f0 100644 --- a/src/handler/signature.ts +++ b/src/handler/signature.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { MarkupContent, Position, SignatureHelp } from 'vscode-languageserver-types' import { IConfigurationChangeEvent } from '../configuration/types' import events from '../events' diff --git a/src/handler/symbols/index.ts b/src/handler/symbols/index.ts index bccab412ed0..56fbb31140d 100644 --- a/src/handler/symbols/index.ts +++ b/src/handler/symbols/index.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { Position, Range, WorkspaceSymbol } from 'vscode-languageserver-types' import events from '../../events' import languages, { ProviderName } from '../../languages' diff --git a/src/handler/symbols/outline.ts b/src/handler/symbols/outline.ts index 9298a0fb2c8..2ed01f02170 100644 --- a/src/handler/symbols/outline.ts +++ b/src/handler/symbols/outline.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { CodeActionKind, DocumentSymbol, Position, Range, SymbolKind, SymbolTag } from 'vscode-languageserver-types' import type { IConfigurationChangeEvent } from '../../configuration/types' import events from '../../events' diff --git a/src/handler/typeHierarchy.ts b/src/handler/typeHierarchy.ts index e523f7bd2c2..f1c8c419538 100644 --- a/src/handler/typeHierarchy.ts +++ b/src/handler/typeHierarchy.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { TextDocument } from 'vscode-languageserver-textdocument' import { Position, TypeHierarchyItem } from 'vscode-languageserver-types' import commands from '../commands' diff --git a/src/handler/workspace.ts b/src/handler/workspace.ts index 405cfecdaa1..39b6ea4b3e5 100644 --- a/src/handler/workspace.ts +++ b/src/handler/workspace.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { v4 as uuid } from 'uuid' import { writeHeapSnapshot } from 'v8' import { Location } from 'vscode-languageserver-types' diff --git a/src/list/basic.ts b/src/list/basic.ts index b3a49cd50db..7961950b6d5 100644 --- a/src/list/basic.ts +++ b/src/list/basic.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Location, Range } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import { WorkspaceConfiguration } from '../configuration/types' diff --git a/src/list/manager.ts b/src/list/manager.ts index 4ce570d8226..e6ee05191ae 100644 --- a/src/list/manager.ts +++ b/src/list/manager.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Extensions, IConfigurationNode, IConfigurationRegistry } from '../configuration/registry' import { ConfigurationScope, ConfigurationTarget } from '../configuration/types' import events from '../events' diff --git a/src/list/mappings.ts b/src/list/mappings.ts index 8d04c023100..43283696ec2 100644 --- a/src/list/mappings.ts +++ b/src/list/mappings.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { ListMode } from './types' import window from '../window' import listConfiguration, { validKeys } from './configuration' diff --git a/src/list/prompt.ts b/src/list/prompt.ts index 70c95348c8b..6ff64afd8f7 100644 --- a/src/list/prompt.ts +++ b/src/list/prompt.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Emitter, Event } from '../util/protocol' import { getUnicodeClass } from '../util/string' import listConfiguration from './configuration' diff --git a/src/list/session.ts b/src/list/session.ts index ebdf59d060e..7b348ea9b93 100644 --- a/src/list/session.ts +++ b/src/list/session.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Buffer, Neovim, Window } from '@chemzqm/neovim' +import type { Buffer, Neovim, Window } from '../neovim' import Highlighter from '../model/highlighter' import { defaultValue, disposeAll, getConditionValue, wait } from '../util' import { debounce } from '../util/node' diff --git a/src/list/source/outline.ts b/src/list/source/outline.ts index efc2a067773..796309bfab8 100644 --- a/src/list/source/outline.ts +++ b/src/list/source/outline.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../../neovim' import { DocumentSymbol, Location, Range, SymbolInformation } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import languages from '../../languages' diff --git a/src/list/types.ts b/src/list/types.ts index 64444fcf678..24d64cd3298 100644 --- a/src/list/types.ts +++ b/src/list/types.ts @@ -1,4 +1,4 @@ -import type { Window, Buffer } from '@chemzqm/neovim' +import type { Window, Buffer } from '../neovim' import type { ProviderResult } from '../provider/index' import type { LocationWithTarget } from '../types' import type { CancellationToken } from '../util/protocol' diff --git a/src/list/ui.ts b/src/list/ui.ts index 1ff2adfe3d5..ca607a92d85 100644 --- a/src/list/ui.ts +++ b/src/list/ui.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer, Neovim, Window } from '@chemzqm/neovim' +import { Buffer, Neovim, Window } from '../neovim' import events from '../events' import { HighlightItem } from '../types' import { defaultValue, disposeAll, getConditionValue } from '../util' diff --git a/src/model/dialog.ts b/src/model/dialog.ts index 38341c9451e..6cba10aa0fa 100644 --- a/src/model/dialog.ts +++ b/src/model/dialog.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Disposable, Emitter, Event } from '../util/protocol' import events from '../events' import { HighlightItem } from '../types' diff --git a/src/model/document.ts b/src/model/document.ts index 99de4fe74df..9be17cc1ddd 100644 --- a/src/model/document.ts +++ b/src/model/document.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer, Neovim, VimValue } from '@chemzqm/neovim' +import { Buffer, Neovim, VimValue } from '../neovim' import { Buffer as NodeBuffer } from 'buffer' import { Position, Range, TextEdit } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' diff --git a/src/model/editInspect.ts b/src/model/editInspect.ts index 48efef612f1..564078b741d 100644 --- a/src/model/editInspect.ts +++ b/src/model/editInspect.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { ChangeAnnotation, CreateFile, DeleteFile, Position, RenameFile, TextDocumentEdit, WorkspaceEdit } from 'vscode-languageserver-types' import { URI } from 'vscode-uri' import type { LinesChange } from '../core/files' diff --git a/src/model/floatFactory.ts b/src/model/floatFactory.ts index b437938b400..26d119b34ae 100644 --- a/src/model/floatFactory.ts +++ b/src/model/floatFactory.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer, Neovim, Window } from '@chemzqm/neovim' +import { Buffer, Neovim, Window } from '../neovim' import { debounce } from '../util/node' import events, { BufEvents } from '../events' import { parseDocuments } from '../markdown' diff --git a/src/model/highlighter.ts b/src/model/highlighter.ts index b0c963b6c36..6da45277a7a 100644 --- a/src/model/highlighter.ts +++ b/src/model/highlighter.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer } from '@chemzqm/neovim' +import { Buffer } from '../neovim' import { parseAnsiHighlights } from '../util/ansiparse' import { byteLength } from '../util/string' import { HighlightItem } from '../types' diff --git a/src/model/input.ts b/src/model/input.ts index da54c6e717a..bfa4cd10930 100644 --- a/src/model/input.ts +++ b/src/model/input.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import events from '../events' import { disposeAll } from '../util' import { omitUndefined } from '../util/object' diff --git a/src/model/menu.ts b/src/model/menu.ts index d0c4686337d..b04b15a1051 100644 --- a/src/model/menu.ts +++ b/src/model/menu.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../neovim' import { CancellationToken, Disposable, Emitter, Event } from '../util/protocol' import events from '../events' import { HighlightItem } from '../types' diff --git a/src/model/notification.ts b/src/model/notification.ts index efa9fa2106f..fd66788520a 100644 --- a/src/model/notification.ts +++ b/src/model/notification.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Disposable } from '../util/protocol' import events from '../events' import { disposeAll } from '../util' @@ -9,7 +9,6 @@ import { toArray } from '../util/array' /** * Represents an action that is shown with an information, warning, or * error message. - * * @see [showInformationMessage](#window.showInformationMessage) * @see [showWarningMessage](#window.showWarningMessage) * @see [showErrorMessage](#window.showErrorMessage) diff --git a/src/model/outputChannel.ts b/src/model/outputChannel.ts index b0cb4dad3ba..5af934f9320 100644 --- a/src/model/outputChannel.ts +++ b/src/model/outputChannel.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { OutputChannel } from '../types' function escapeQuote(input: string): string { diff --git a/src/model/picker.ts b/src/model/picker.ts index aeeb1444e77..2442732a8a3 100644 --- a/src/model/picker.ts +++ b/src/model/picker.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../neovim' import events from '../events' import { HighlightItem, QuickPickItem } from '../types' import { disposeAll } from '../util' diff --git a/src/model/popup.ts b/src/model/popup.ts index b4f7c84a60e..0900d9ff080 100644 --- a/src/model/popup.ts +++ b/src/model/popup.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { isVim } from '../util/constants' interface WindowInfo { diff --git a/src/model/progress.ts b/src/model/progress.ts index d419e428220..2749da112e2 100644 --- a/src/model/progress.ts +++ b/src/model/progress.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import events from '../events' import { createLogger } from '../logger' import { CancellationToken, CancellationTokenSource, Emitter, Event } from '../util/protocol' diff --git a/src/model/quickpick.ts b/src/model/quickpick.ts index dd396768b86..acf8eb4d367 100644 --- a/src/model/quickpick.ts +++ b/src/model/quickpick.ts @@ -1,5 +1,5 @@ 'use strict' -import { Buffer, Neovim } from '@chemzqm/neovim' +import { Buffer, Neovim } from '../neovim' import events from '../events' import { createLogger } from '../logger' import { HighlightItem, QuickPickItem } from '../types' diff --git a/src/model/status.ts b/src/model/status.ts index 8c5a9656480..718e3b535fd 100644 --- a/src/model/status.ts +++ b/src/model/status.ts @@ -1,7 +1,7 @@ 'use strict' import type { Disposable } from '../util/protocol' import { v1 as uuidv1 } from 'uuid' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' export const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] diff --git a/src/model/task.ts b/src/model/task.ts index bfa871b083f..6f814a6e5ce 100644 --- a/src/model/task.ts +++ b/src/model/task.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import events from '../events' import { disposeAll } from '../util' import { Disposable, Emitter, Event } from '../util/protocol' @@ -16,7 +16,6 @@ export interface TaskOptions { /** * Controls long running task started by vim. * Useful to keep the task running after CocRestart. - * * @public */ export default class Task implements Disposable { @@ -52,7 +51,6 @@ export default class Task implements Disposable { /** * Start task, task will be restarted when already running. - * * @param {TaskOptions} opts * @returns {Promise} */ diff --git a/src/model/terminal.ts b/src/model/terminal.ts index adfd586b65d..301d1664808 100644 --- a/src/model/terminal.ts +++ b/src/model/terminal.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' export interface TerminalOptions { /** diff --git a/src/neovim/api/Base.ts b/src/neovim/api/Base.ts new file mode 100644 index 00000000000..1ceffe04431 --- /dev/null +++ b/src/neovim/api/Base.ts @@ -0,0 +1,120 @@ +import Transport from '../transport/base' +import { VimValue } from '../types' +import { NeovimClient } from './client' + +export interface BaseConstructorOptions { + data?: number + client?: any +} + +export class BaseApi { + protected prefix: string + public data: number | undefined + protected client: NeovimClient + + constructor({ + data, + client, + }: BaseConstructorOptions) { + this.data = data + if (client) { + this.client = client + } else { + Object.defineProperty(this, 'client', { + value: this + }) + } + } + + protected get transport(): Transport { + return this.client._transport + } + + public equals(other: BaseApi): boolean { + try { + return String(this.data) === String(other.data) + } catch (e) { + return false + } + } + + public async request(name: string, args: any[] = [], fullArgs = false): Promise { + Error.captureStackTrace(args) + return new Promise((resolve, reject) => { + this.transport.request(name, fullArgs ? args : this.getArgsByPrefix(args), (err: any, res: any) => { + if (err) { + let e = new Error(err[1]) + if (!name.endsWith('get_var')) { + let stack = (args as any).stack + e.stack = `Error: request error on "${name}" - ${err[1]}\n` + stack.split(/\r?\n/).slice(3).join('\n') + this.client.logError(`request error on "${name}"`, args, e) + } + reject(e) + } else { + resolve(res) + } + }) + }) + } + + protected getArgsByPrefix(args: any[]): any[] { + // Check if class is Neovim and if so, should not send `this` as first arg + if (this.prefix !== 'nvim_' && args[0] != this) { + let id = this.transport.isVim ? this.data : this + return [id, ...args] + } + return args + } + + /** Retrieves a scoped variable depending on type (using `this.prefix`) */ + public getVar(name: string): Promise { + return this.request(`${this.prefix}get_var`, [name]).then( + res => res, + _err => { + return null + } + ) + } + + /** Set a scoped variable */ + public setVar(name: string, value: VimValue, isNotify: true): void + public setVar(name: string, value: VimValue, isNotify?: false): Promise + public setVar(name: string, value: VimValue, isNotify = false): Promise | void { + if (isNotify) { + this.notify(`${this.prefix}set_var`, [name, value]) + return + } + return this.request(`${this.prefix}set_var`, [name, value]) + } + + /** Delete a scoped variable */ + public deleteVar(name: string): void { + this.notify(`${this.prefix}del_var`, [name]) + } + + /** Retrieves a scoped option depending on type of `this` */ + public getOption(name: string): Promise { + const method = this.transport.isVim ? `${this.prefix}get_option` : `nvim_get_option_value` + const args = this.transport.isVim ? [name] : [name, {}] + return this.request(method, args, true) + } + + /** Set scoped option */ + public setOption(name: string, value: VimValue): Promise + public setOption(name: string, value: VimValue, isNotify: true): void + public setOption(name: string, value: VimValue, isNotify?: boolean): Promise | void { + const method = this.transport.isVim ? `${this.prefix}set_option` : `nvim_set_option_value` + const args = this.transport.isVim ? [name, value] : [name, value, {}] + + return isNotify ? this.notify(method, args, true) : this.request(method, args, true) + } + + /** `request` is basically the same except you can choose to wait forpromise to be resolved */ + public notify(name: string, args: any[] = [], fullArgs = false): void { + this.transport.notify(name, fullArgs ? args : this.getArgsByPrefix(args)) + } + + public toJSON(): number { + return this.data ?? 0 + } +} diff --git a/src/neovim/api/Buffer.ts b/src/neovim/api/Buffer.ts new file mode 100644 index 00000000000..d11667222f9 --- /dev/null +++ b/src/neovim/api/Buffer.ts @@ -0,0 +1,592 @@ +import { Range } from '../types' +import { BaseApi } from './Base' +import { Disposable, KeymapOption } from './types' + +export interface BufferSetLines { + start?: number + end?: number + strictIndexing?: boolean +} +export interface BufferHighlight { + hlGroup?: string + line?: number + colStart?: number + colEnd?: number + srcId?: number +} + +export interface VirtualTextOption { + /** + * Used on vim9 only. + */ + col?: number + /** + * highlight mode + */ + hl_mode?: 'combine' | 'replace' | 'blend' + /** + * nvim and vim. + */ + text_align?: 'after' | 'right' | 'below' | 'above' + /** + * neovim only + */ + virt_text_win_col?: number + /** + * vim9 only + */ + text_wrap?: 'wrap' | 'truncate' + /** + * Add line indent when text_align is below or above. + */ + indent?: boolean +} + +export interface ExtmarkOptions { + id?: number + // 0-based inclusive. + end_line?: number + // 0-based exclusive. + end_col?: number + // name of the highlight group used to highlight this mark. + hl_group?: string + hl_mode?: 'replace' | 'combine' | 'blend' + hl_eol?: boolean + // A list of [text, highlight] tuples + virt_text?: [string, string | string[]][] + virt_text_pos?: 'eol' | 'overlay' | 'right_align' | 'inline' + virt_text_win_col?: number + virt_text_hide?: boolean + virt_lines?: [string, string | string[]][][] + virt_lines_above?: boolean + virt_lines_leftcol?: boolean + right_gravity?: boolean + end_right_gravity?: boolean + priority?: number +} + +export interface ExtmarkDetails { + end_col: number + end_row: number + priority: number + hl_group?: string + virt_text?: [string, string][] + virt_lines?: [string, string][][] +} + +export interface BufferClearHighlight { + srcId?: number + lineStart?: number + lineEnd?: number +} + +export interface SignPlaceOption { + id?: number // 0 + group?: string // '' + name: string + lnum: number + priority?: number +} + +export interface SignUnplaceOption { + group?: string + id?: number +} + +export interface SignPlacedOption { + group?: string + id?: number + lnum?: number +} + +export interface SignItem { + group: string + id: number + lnum: number + name: string + priority: number +} + +export interface HighlightItem { + hlGroup: string + /** + * 0 based + */ + lnum: number + /** + * 0 based + */ + colStart: number + /** + * 0 based + */ + colEnd: number + /** + * See :h prop_type_add on vim8 + */ + combine?: boolean + start_incl?: boolean + end_incl?: boolean +} + +export interface VimHighlightItem { + hlGroup: string + /** + * 0 based + */ + lnum: number + /** + * 0 based + */ + colStart: number + /** + * 0 based + */ + colEnd: number + /** + * Extmark id + */ + id?: number +} + +export interface HighlightOption { + start?: number + end?: number + priority?: number + changedtick?: number +} + +type Chunk = [string, string] + +export class Buffer extends BaseApi { + public prefix = 'nvim_buf_' + + /** + * Attach to buffer to listen to buffer events + * @param sendBuffer Set to true if the initial notification should contain + * the whole buffer. If so, the first notification will be a + * `nvim_buf_lines_event`. Otherwise, the first notification will be + * a `nvim_buf_changedtick_event` + */ + public async attach(sendBuffer = false, options: {} = {}): Promise { + return await this.request(`${this.prefix}attach`, [sendBuffer, options]) + } + + /** + * Detach from buffer to stop listening to buffer events + */ + public async detach(): Promise { + return await this.request(`${this.prefix}detach`, []) + } + + /** + * Get the bufnr of Buffer + */ + public get id(): number { + return this.data as number + } + + /** Total number of lines in buffer */ + public get length(): Promise { + return this.request(`${this.prefix}line_count`, []) + } + + /** Get lines in buffer */ + public get lines(): Promise { + return this.getLines() + } + + /** Gets a changed tick of a buffer */ + public get changedtick(): Promise { + return this.request(`${this.prefix}get_changedtick`, []) + } + + public get commands(): Promise { + return this.getCommands() + } + + public getCommands(options = {}): Promise { + return this.request(`${this.prefix}get_commands`, [options]) + } + + /** Get specific lines of buffer */ + public getLines( + { start, end, strictIndexing } = { start: 0, end: -1, strictIndexing: true } + ): Promise { + const indexing = + typeof strictIndexing === 'undefined' ? true : strictIndexing + return this.request(`${this.prefix}get_lines`, [ + start, + end, + indexing, + ]) + } + + /** Set lines of buffer given indices */ + public setLines(lines: string | string[], opts?: BufferSetLines): Promise + public setLines(lines: string | string[], opts: BufferSetLines, notify: true): void + public setLines(lines: string | string[], opts?: BufferSetLines, notify = false) { + let { start, end, strictIndexing } = opts ?? {} + start = start ?? 0 + end = end ?? start + 1 + const indexing = strictIndexing ?? true + const method = notify ? 'notify' : 'request' + return this[method](`${this.prefix}set_lines`, [ + start, + end, + indexing, + typeof lines === 'string' ? [lines] : lines + ]) + } + + /** + * Set virtual text for a line, works on nvim >= 0.5.0 and vim9 + * @public + * @param {number} src_id - Source group to use or 0 to use a new group, or -1 + * @param {number} line - Line to annotate with virtual text (zero-indexed) + * @param {Chunk[]} chunks - List with [text, hl_group] + * @param {{[index} opts + * @returns {Promise} + */ + public setVirtualText(src_id: number, line: number, chunks: Chunk[], opts: VirtualTextOption = {}): void { + this.client.call('coc#vtext#add', [this.id, src_id, line, chunks, opts], true) + return Promise.resolve(src_id) as any + } + + /** + * Removes an ext mark by notification. + * @public + * @param {number} ns_id - Namespace id + * @param {number} id - Extmark id + */ + public deleteExtMark(ns_id: number, id: number): void { + this.notify(`${this.prefix}del_extmark`, [ + ns_id, + id, + ]) + } + + /** + * Gets the position (0-indexed) of an extmark. + * @param {number} ns_id - Namespace id + * @param {number} id - Extmark id + * @param {Object} opts - Optional parameters. + * @returns {Promise<[] | [number, number] | [number, number, ExtmarkDetails]>} + */ + public async getExtMarkById(ns_id: number, id: number, opts: { details?: boolean } = {}): Promise<[] | [number, number] | [number, number, ExtmarkDetails]> { + return this.request(`${this.prefix}get_extmark_by_id`, [ns_id, id, opts]) + } + + /** + * Gets extmarks in "traversal order" from a |charwise| region defined by + * buffer positions (inclusive, 0-indexed |api-indexing|). + * + * Region can be given as (row,col) tuples, or valid extmark ids (whose + * positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1) + * respectively, thus the following are equivalent: + * + * nvim_buf_get_extmarks(0, my_ns, 0, -1, {}) + * nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {}) + * @param {number} ns_id - Namespace id + * @param {[number, number] | number} start + * @param {[number, number] | number} end + * @param {Object} opts + * @returns {Promise<[number, number, number, ExtmarkDetails?][]>} + */ + public async getExtMarks(ns_id: number, start: [number, number] | number, end: [number, number] | number, opts: { details?: boolean, limit?: number } = {}): Promise<[number, number, number, ExtmarkDetails?][]> { + return this.request(`${this.prefix}get_extmarks`, [ns_id, start, end, opts]) + } + + /** + * Creates or updates an extmark by notification, `:h nvim_buf_set_extmark`. + * @param {number} ns_id + * @param {number} line + * @param {number} col + * @param {ExtmarkOptions} opts + * @returns {void} + */ + public setExtMark(ns_id: number, line: number, col: number, opts: ExtmarkOptions = {}): void { + this.notify(`${this.prefix}set_extmark`, [ + ns_id, + line, + col, + opts + ]) + } + + /** Insert lines at `start` index */ + public insert(lines: string[] | string, start: number) { + return this.setLines(lines, { + start, + end: start, + strictIndexing: true, + }) + } + + /** Replace lines starting at `start` index */ + public replace(_lines: string[] | string, start: number) { + const lines = typeof _lines === 'string' ? [_lines] : _lines + return this.setLines(lines, { + start, + end: start + lines.length, + strictIndexing: false, + }) + } + + /** Remove lines at index */ + public remove(start: number, end: number, strictIndexing = false) { + return this.setLines([], { start, end, strictIndexing }) + } + + /** Append a string or list of lines to end of buffer */ + public append(lines: string[] | string) { + return this.setLines(lines, { + start: -1, + end: -1, + strictIndexing: false, + }) + } + + /** Get buffer name */ + public get name(): Promise { + return this.request(`${this.prefix}get_name`, []) + } + + /** Set current buffer name */ + public setName(value: string): Promise { + return this.request(`${this.prefix}set_name`, [value]) + } + + /** Is current buffer valid */ + public get valid(): Promise { + return this.request(`${this.prefix}is_valid`, []) + } + + /** Get mark position given mark name */ + public mark(name: string): Promise<[number, number]> { + return this.request(`${this.prefix}get_mark`, [name]) + } + + // range(start, end) { + // """Return a `Range` object, which represents part of the Buffer.""" + // return Range(this, start, end) + // } + + /** Gets keymap */ + public getKeymap(mode: string): Promise { + return this.request(`${this.prefix}get_keymap`, [mode]) + } + + /** + * Add buffer keymap by notification, replace keycodes for expr keymap enabled by default. + */ + public setKeymap(mode: string, lhs: string, rhs: string, opts: KeymapOption = {}): void { + let option = opts.expr ? Object.assign({ replace_keycodes: true }, opts) : opts + this.notify(`${this.prefix}set_keymap`, [mode, lhs, rhs, option]) + } + + public deleteKeymap(mode: string, lhs: string): void { + this.notify(`${this.prefix}del_keymap`, [mode, lhs]) + } + + /** + * Checks if a buffer is valid and loaded. See |api-buffer| for + * more info about unloaded buffers. + */ + public get loaded(): Promise { + return this.request(`${this.prefix}is_loaded`, []) + } + + /** + * Returns the byte offset for a line. + * + * Line 1 (index=0) has offset 0. UTF-8 bytes are counted. EOL is + * one byte. 'fileformat' and 'fileencoding' are ignored. The + * line index just after the last line gives the total byte-count + * of the buffer. A final EOL byte is counted if it would be + * written, see 'eol'. + * + * Unlike |line2byte()|, throws error for out-of-bounds indexing. + * Returns -1 for unloaded buffer. + * @return {Number} Integer byte offset, or -1 for unloaded buffer. + */ + public getOffset(index: number): Promise { + return this.request(`${this.prefix}get_offset`, [index]) + } + + /** + * Adds a highlight to buffer. + * + * This can be used for plugins which dynamically generate + * highlights to a buffer (like a semantic highlighter or + * linter). The function adds a single highlight to a buffer. + * Unlike matchaddpos() highlights follow changes to line + * numbering (as lines are inserted/removed above the highlighted + * line), like signs and marks do. + * + * "src_id" is useful for batch deletion/updating of a set of + * highlights. When called with src_id = 0, an unique source id + * is generated and returned. Succesive calls can pass in it as + * "src_id" to add new highlights to the same source group. All + * highlights in the same group can then be cleared with + * nvim_buf_clear_namespace. If the highlight never will be + * manually deleted pass in -1 for "src_id". + * + * If "hl_group" is the empty string no highlight is added, but a + * new src_id is still returned. This is useful for an external + * plugin to synchrounously request an unique src_id at + * initialization, and later asynchronously add and clear + * highlights in response to buffer changes. + */ + public addHighlight({ + hlGroup, + line, + colStart: _start, + colEnd: _end, + srcId: _srcId, + }: BufferHighlight): Promise { + if (!hlGroup) throw new Error('hlGroup should not empty') + const colEnd = typeof _end !== 'undefined' ? _end : -1 + const colStart = typeof _start !== 'undefined' ? _start : -0 + const srcId = typeof _srcId !== 'undefined' ? _srcId : -1 + const method = srcId == 0 ? 'request' : 'notify' + let res = this[method](`${this.prefix}add_highlight`, [ + srcId, + hlGroup, + line, + colStart, + colEnd, + ]) + return method === 'request' ? res as Promise : Promise.resolve(null) + } + + /** + * Clear highlights of specified lins. + * @deprecated use clearNamespace() instead. + */ + public clearHighlight(args: BufferClearHighlight = {}) { + const defaults = { + srcId: -1, + lineStart: 0, + lineEnd: -1, + } + + const { srcId, lineStart, lineEnd } = Object.assign({}, defaults, args) + + return this.notify(`${this.prefix}clear_highlight`, [ + srcId, + lineStart, + lineEnd, + ]) + } + + /** + * Add highlight to ranges by notification. + * @param {string | number} srcId Unique key or namespace number. + * @param {string} hlGroup Highlight group. + * @param {Range[]} ranges List of highlight ranges + */ + public highlightRanges(srcId: string | number, hlGroup: string, ranges: Range[]): void { + this.client.call('coc#highlight#ranges', [this.id, srcId, hlGroup, ranges], true) + } + + /** + * Clear namespace by id or name. + * @param key Unique key or namespace number, use -1 for all namespaces + * @param lineStart Start of line, 0 based, default to 0. + * @param lineEnd End of line, 0 based, default to -1. + */ + public clearNamespace(key: number | string, lineStart = 0, lineEnd = -1) { + this.client.call('coc#highlight#clear_highlight', [this.id, key, lineStart, lineEnd], true) + } + + /** + * Add sign to buffer by notification. + * @param {SignPlaceOption} sign + * @returns {void} + */ + public placeSign(sign: SignPlaceOption): void { + let opts: any = { lnum: sign.lnum } + if (typeof sign.priority === 'number') opts.priority = sign.priority + this.client.call('sign_place', [sign.id || 0, sign.group || '', sign.name, this.id, opts], true) + } + + /** + * Unplace signs by notification + */ + public unplaceSign(opts: SignUnplaceOption): void { + let details: any = { buffer: this.id } + if (opts.id != null) details.id = opts.id + this.client.call('sign_unplace', [opts.group || '', details], true) + } + + /** + * Get signs by group name or id and lnum. + * @param {SignPlacedOption} opts + * @returns {Promise} + */ + public async getSigns(opts: SignPlacedOption): Promise { + let res = await this.client.call('sign_getplaced', [this.id, opts || {}]) as any[] + return res[0].signs + } + + /** + * Get highlight items by name space (end inclusive). + * @param {string} ns Namespace key. + * @param {number} start 0 based line number. + * @param {number} end 0 based line number. + * @returns {Promise} + */ + public async getHighlights(ns: string, start = 0, end = -1): Promise { + let res: VimHighlightItem[] = [] + let arr = await this.client.call('coc#highlight#get_highlights', [this.id, ns, start, end]) as [string, number, number, number, number?][] + for (let item of arr) { + res.push({ + hlGroup: item[0], + lnum: item[1], + colStart: item[2], + colEnd: item[3], + id: item[4] + }) + } + return res + } + + /** + * Update highlight items by notification. + * @param {string | number} ns Namespace key or id. + * @param {HighlightItem[]} highlights Highlight items. + * @param {HighlightOption} opts Optional options. + * @returns {void} + */ + public updateHighlights(ns: string, highlights: HighlightItem[], opts: HighlightOption = {}): void { + if (typeof opts === 'number') { + this.client.logError('Bad option for buffer.updateHighlights()', new Error()) + return + } + let start = typeof opts.start === 'number' ? opts.start : 0 + let end = typeof opts.end === 'number' ? opts.end : -1 + let changedtick = typeof opts.changedtick === 'number' ? opts.changedtick : null + let priority = typeof opts.priority === 'number' ? opts.priority : null + if (start == 0 && end == -1) { + let arr = highlights.map(o => [o.hlGroup, o.lnum, o.colStart, o.colEnd, o.combine === false ? 0 : 1, o.start_incl ? 1 : 0, o.end_incl ? 1 : 0]) + this.client.call('coc#highlight#buffer_update', [this.id, ns, arr, priority, changedtick], true) + return + } + this.client.call('coc#highlight#update_highlights', [this.id, ns, highlights, start, end, priority, changedtick], true) + } + + /** + * Listens to buffer for events + */ + public listen(eventName: string, cb: Function, disposables?: Disposable[]): void { + this.client.attachBufferEvent(this.id, eventName, cb) + if (disposables) { + disposables.push({ + dispose: () => { + this.client.detachBufferEvent(this.id, eventName, cb) + } + }) + } + } +} diff --git a/src/neovim/api/Neovim.ts b/src/neovim/api/Neovim.ts new file mode 100644 index 00000000000..bbfaa63854b --- /dev/null +++ b/src/neovim/api/Neovim.ts @@ -0,0 +1,480 @@ +import { ApiInfo, VimValue } from '../types' +import { BaseApi } from './Base' +import { Buffer } from './Buffer' +import { Tabpage } from './Tabpage' +import { Window } from './Window' +import { FloatOptions, KeymapOption } from './types' +import { isCocNvim } from '../utils/constants' + +export interface UiAttachOptions { + rgb?: boolean + // eslint-disable-next-line camelcase + ext_popupmenu?: boolean + // eslint-disable-next-line camelcase + ext_tabline?: boolean + // eslint-disable-next-line camelcase + ext_wildmenu?: boolean + // eslint-disable-next-line camelcase + ext_cmdline?: boolean + // eslint-disable-next-line camelcase + ext_linegrid?: boolean + // eslint-disable-next-line camelcase + ext_hlstate?: boolean +} + +export interface Proc { + ppid: number + name: string + pid: number +} + +export type MouseButton = 'left' | 'right' | 'middle' | 'wheel' + +export type ButtonAction = 'press' | 'drag' | 'release' | 'up' | 'down' | 'left' | 'right' + +function getArgs(args?: VimValue | VimValue[]): VimValue[] { + if (!args) return [] + if (Array.isArray(args)) return args + return [args] +} + +/** + * Neovim API + */ +export class Neovim extends BaseApi { + protected prefix = 'nvim_' + + public get apiInfo(): Promise<[number, ApiInfo]> { + return this.request(`${this.prefix}get_api_info`) + } + + /** Get list of all buffers */ + public get buffers(): Promise { + return this.request(`${this.prefix}list_bufs`) + } + + /** Get current buffer */ + public get buffer(): Promise { + return this.request(`${this.prefix}get_current_buf`) + } + + /** Set current buffer */ + public async setBuffer(buffer: Buffer): Promise { + await this.request(`${this.prefix}set_current_buf`, [buffer]) + } + + public get chans(): Promise { + return this.request(`${this.prefix}list_chans`) + } + + public getChanInfo(chan: number): Promise { + return this.request(`${this.prefix}get_chan_info`, [chan]) + } + + public createNamespace(name = ""): Promise { + if (isCocNvim) { + name = name.startsWith('coc-') ? name.slice(4) : name + return this.request(`${this.prefix}call_function`, ['coc#highlight#create_namespace', [name]]) + } + return this.request(`${this.prefix}create_namespace`, [name]) + } + + public get namespaces(): Promise<{ [name: string]: number }> { + return this.request(`${this.prefix}get_namespaces`, []) + } + + public get commands(): Promise { + return this.getCommands() + } + + public getCommands(options = {}): Promise { + return this.request(`${this.prefix}get_commands`, [options]) + } + + /** Get list of all tabpages */ + public get tabpages(): Promise { + return this.request(`${this.prefix}list_tabpages`) + } + + /** Get current tabpage */ + public get tabpage(): Promise { + return this.request(`${this.prefix}get_current_tabpage`) + } + + /** Set current tabpage */ + public async setTabpage(tabpage: Tabpage): Promise { + await this.request(`${this.prefix}set_current_tabpage`, [tabpage]) + } + + /** Get list of all windows */ + public get windows(): Promise { + return this.getWindows() + } + + /** Get current window */ + public get window(): Promise { + return this.request(`${this.prefix}get_current_win`) + } + + /** Get list of all windows */ + public getWindows(): Promise { + return this.request(`${this.prefix}list_wins`) + } + + public async setWindow(win: Window): Promise { + // Throw error if win is not instance of Window? + await this.request(`${this.prefix}set_current_win`, [win]) + } + + /** Get list of all runtime paths */ + public get runtimePaths(): Promise { + return this.request(`${this.prefix}list_runtime_paths`) + } + + /** Set current directory */ + public setDirectory(dir: string): Promise { + return this.request(`${this.prefix}set_current_dir`, [dir]) + } + + /** Get current line. Always returns a Promise. */ + public get line(): Promise { + return this.getLine() + } + + public createNewBuffer(listed = false, scratch = false): Promise { + return this.request(`${this.prefix}create_buf`, [listed, scratch]) + } + + public openFloatWindow(buffer: Buffer, enter: boolean, options: FloatOptions): Promise { + return this.request(`${this.prefix}open_win`, [buffer, enter, options]) + } + + public getLine(): Promise { + return this.request(`${this.prefix}get_current_line`) + } + + /** Set current line */ + public setLine(line: string): Promise { + return this.request(`${this.prefix}set_current_line`, [line]) + } + + /** Gets keymap */ + public getKeymap(mode: string): Promise { + return this.request(`${this.prefix}get_keymap`, [mode]) + } + + /** + * Add keymap by notification, replace keycodes for expr keymap enabled by default. + */ + public setKeymap(mode: string, lhs: string, rhs: string, opts: KeymapOption = {}): void { + let option = opts.expr ? Object.assign({ replace_keycodes: true }, opts) : opts + this.notify(`${this.prefix}set_keymap`, [mode, lhs, rhs, option]) + } + + public deleteKeymap(mode: string, lhs: string): void { + this.notify(`${this.prefix}del_keymap`, [mode, lhs]) + } + + /** Gets current mode */ + public get mode(): Promise<{ mode: string; blocking: boolean }> { + return this.request(`${this.prefix}get_mode`) + } + + /** Gets map of defined colors */ + public get colorMap(): Promise<{ [name: string]: number }> { + return this.request(`${this.prefix}get_color_map`) + } + + /** Get color by name */ + public getColorByName(name: string): Promise { + return this.request(`${this.prefix}get_color_by_name`, [name]) + } + + /** Get highlight by name or id */ + public getHighlight( + nameOrId: string | number, + isRgb = true + ): Promise | void { + const functionName = typeof nameOrId === 'string' ? 'by_name' : 'by_id' + return this.request(`${this.prefix}get_hl_${functionName}`, [ + nameOrId, + isRgb, + ]) + } + + public getHighlightByName(name: string, isRgb = true): Promise { + return this.request(`${this.prefix}get_hl_by_name`, [name, isRgb]) + } + + public getHighlightById(id: number, isRgb = true): Promise { + return this.request(`${this.prefix}get_hl_by_id`, [id, isRgb]) + } + + /** Delete current line in buffer */ + public deleteCurrentLine(): Promise { + return this.request(`${this.prefix}del_current_line`) + } + + /** + * Evaluates a VimL expression (:help expression). Dictionaries + * and Lists are recursively expanded. On VimL error: Returns a + * generic error; v:errmsg is not updated. + * + */ + public eval(expr: string): Promise { + return this.request(`${this.prefix}eval`, [expr]) + } + + /** + * Executes lua, it's possible neovim client does not support this + */ + public lua(code: string, args: VimValue[] = []): Promise { + return this.request(`${this.prefix}exec_lua`, [code, args]) + } + + // Alias for `lua()` to be consistent with neovim API + public executeLua(code: string, args: VimValue[] = []): Promise { + const _args = getArgs(args) + return this.lua(code, _args) + } + + public callDictFunction( + dict: object, + fname: string, + args: VimValue | VimValue[] = [] + ): Promise { + const _args = getArgs(args) + return this.request(`${this.prefix}call_dict_function`, [ + dict, + fname, + _args, + ]) + } + + /** Call a vim function */ + public call(fname: string, args?: VimValue | VimValue[]): Promise + public call(fname: string, args: VimValue | VimValue[], isNotify: true): null + public call(fname: string, args: VimValue | VimValue[] = [], isNotify?: boolean): Promise { + const _args = getArgs(args) + if (isNotify) { + this.notify(`${this.prefix}call_function`, [fname, _args]) + return null + } + return this.request(`${this.prefix}call_function`, [fname, _args]) + } + + /** Call a function with timer on vim*/ + public callTimer(fname: string, args?: VimValue | VimValue[]): Promise + public callTimer(fname: string, args: VimValue | VimValue[], isNotify: true): null + public callTimer(fname: string, args: VimValue | VimValue[] = [], isNotify?: boolean): Promise { + const _args = getArgs(args) + if (isNotify) { + this.notify(`${this.prefix}call_function`, ['coc#util#timer', [fname, _args]]) + return null + } + if (this.transport.isVim) { + this.notify(`${this.prefix}call_function`, ['coc#util#timer', [fname, _args]]) + return new Promise(resolve => { + setTimeout(() => { + resolve(null) + }, 20) + }) + } + return this.request(`${this.prefix}call_function`, ['coc#util#timer', [fname, _args]]) + } + + public callAsync(fname: string, args: VimValue | VimValue[] = []): Promise { + const _args = getArgs(args) + return this.client.sendAsyncRequest(fname, _args) + } + + /** Alias for `call` */ + public callFunction(fname: string, args: VimValue | VimValue[] = []): Promise | null { + return this.call(fname, args) + } + + /** Call Atomic calls */ + public callAtomic(calls: [string, VimValue[]][]): Promise<[any[], boolean]> { + return this.request(`${this.prefix}call_atomic`, [calls]) + } + + /** Runs a vim command */ + public command(arg: string): Promise + public command(arg: string, isNotify: true): null + public command(arg: string, isNotify?: boolean): Promise | null { + if (isNotify) { + this.notify(`${this.prefix}command`, [arg]) + return null + } + return this.request(`${this.prefix}command`, [arg]) + } + + /** + * Runs a command and returns output. + * @deprecated Use exec instead. + */ + public commandOutput(arg: string): Promise { + return this.request(`${this.prefix}command_output`, [arg]) + } + + /** + * Executes Vimscript (multiline block of Ex-commands), like + * anonymous |:source| + */ + public exec(src: string, output = false): Promise { + return this.request(`${this.prefix}exec`, [src, output]) + } + + /** Gets a v: variable */ + public getVvar(name: string): Promise { + return this.request(`${this.prefix}get_vvar`, [name]) + } + + /** feedKeys */ + public feedKeys(keys: string, mode: string, escapeCsi: boolean): Promise { + return this.request(`${this.prefix}feedkeys`, [keys, mode, escapeCsi]) + } + + /** Sends input keys */ + public input(keys: string): Promise { + return this.request(`${this.prefix}input`, [keys]) + } + + /** + * Send mouse event from GUI. Neovim only. + * @param {MouseButton} button Mouse button: one of "left", "right", "middle", "wheel", "move". + * @param {ButtonAction} action For ordinary buttons, one of "press", "drag", "release". + * @param {string} modifier String of modifiers each represented by a single char. + * @param {number} row Mouse row-position (zero-based, like redraw events) + * @param {number} col Mouse column-position (zero-based, like redraw events) + * @param {number} grid Grid number if the client uses |ui-multigrid|, else 0. + * @returns {Promise} + */ + public inputMouse(button: MouseButton, action: ButtonAction, modifier: string, row: number, col: number, grid = 0): Promise { + return this.request(`${this.prefix}input_mouse`, [button, action, modifier, grid, row, col]) + } + + /** + * Parse a VimL Expression + * + * TODO: return type, see :help + */ + public parseExpression( + expr: string, + flags: string, + highlight: boolean + ): Promise { + return this.request(`${this.prefix}parse_expression`, [ + expr, + flags, + highlight, + ]) + } + + public getProc(pid: number): Promise { + return this.request(`${this.prefix}get_proc`, [pid]) + } + + public getProcChildren(pid: number): Promise { + return this.request(`${this.prefix}get_proc_children`, [pid]) + } + + /** Replace term codes */ + public replaceTermcodes( + str: string, + fromPart: boolean, + doIt: boolean, + special: boolean + ): Promise { + return this.request(`${this.prefix}replace_termcodes`, [ + str, + fromPart, + doIt, + special, + ]) + } + + /** Gets width of string */ + public strWidth(str: string): Promise { + return this.request(`${this.prefix}strwidth`, [str]) + } + + /** Write to output buffer */ + public outWrite(str: string): void { + this.notify(`${this.prefix}out_write`, [str]) + } + + public outWriteLine(str: string): void { + this.outWrite(`${str}\n`) + } + + /** Write to error buffer */ + public errWrite(str: string): void { + this.notify(`${this.prefix}err_write`, [str]) + } + + /** Write to error buffer */ + public errWriteLine(str: string): void { + this.notify(`${this.prefix}err_writeln`, [str]) + } + + // TODO: add type + public get uis(): Promise { + return this.request(`${this.prefix}list_uis`) + } + + public uiAttach( + width: number, + height: number, + options: UiAttachOptions + ): Promise { + return this.request(`${this.prefix}ui_attach`, [width, height, options]) + } + + public uiDetach(): Promise { + return this.request(`${this.prefix}ui_detach`, []) + } + + public uiTryResize(width: number, height: number): Promise { + return this.request(`${this.prefix}ui_try_resize`, [width, height]) + } + + /** Set UI Option */ + public uiSetOption(name: string, value: any): Promise { + return this.request(`${this.prefix}ui_set_option`, [name, value]) + } + + /** Subscribe to nvim event broadcasts */ + public subscribe(event: string): Promise { + return this.request(`${this.prefix}subscribe`, [event]) + } + + /** Unsubscribe to nvim event broadcasts */ + public unsubscribe(event: string): Promise { + return this.request(`${this.prefix}unsubscribe`, [event]) + } + + public setClientInfo( + name: string, + version: object, + type: string, + methods: object, + attributes: object + ): void { + this.notify(`${this.prefix}set_client_info`, [ + name, + version, + type, + methods, + attributes, + ]) + } + + /** Quit nvim */ + public async quit(): Promise { + this.command('qa!', true) + if (this.transport) { + this.transport.detach() + } + } +} diff --git a/src/neovim/api/Tabpage.ts b/src/neovim/api/Tabpage.ts new file mode 100644 index 00000000000..03fb62f7ac7 --- /dev/null +++ b/src/neovim/api/Tabpage.ts @@ -0,0 +1,43 @@ +import { BaseApi } from './Base' +import { Window } from './Window' + +export class Tabpage extends BaseApi { + public prefix = 'nvim_tabpage_' + /** + * The windowid that not change within a Vim session + */ + public get id(): number { + return this.data as number + } + + /** Returns all windows of tabpage */ + public get windows(): Promise { + return this.request(`${this.prefix}list_wins`, []) + } + + /** Gets the current window of tabpage */ + public get window(): Promise { + return this.request(`${this.prefix}get_win`, []) + } + + /** Is current tabpage valid */ + public get valid(): Promise { + return this.request(`${this.prefix}is_valid`, []) + } + + /** Tabpage number */ + // eslint-disable-next-line id-blacklist + public get number(): Promise { + return this.request(`${this.prefix}get_number`, []) + } + + /** Invalid */ + public getOption(): any { + throw new Error('Tabpage does not have `getOption`') + } + + /** Invalid */ + public setOption(): any { + throw new Error('Tabpage does not have `setOption`') + } +} diff --git a/src/neovim/api/Window.ts b/src/neovim/api/Window.ts new file mode 100644 index 00000000000..22e1629affe --- /dev/null +++ b/src/neovim/api/Window.ts @@ -0,0 +1,147 @@ +import { Range } from '../types' +import { BaseApi } from './Base' +import { Buffer } from './Buffer' +import { Tabpage } from './Tabpage' +import { FloatOptions } from './types' + +export class Window extends BaseApi { + public prefix = 'nvim_win_' + + /** + * The windowid that not change within a Vim session + */ + public get id(): number { + return this.data as number + } + + public setBuffer(buffer: Buffer): Promise { + return this.request(`${this.prefix}set_buf`, [buffer]) + } + + /** Get current buffer of window */ + public get buffer(): Promise { + return this.request(`${this.prefix}get_buf`, []) + } + + /** Get the Tabpage that contains the window */ + public get tabpage(): Promise { + return this.request(`${this.prefix}get_tabpage`, []) + } + + /** Get cursor position */ + public get cursor(): Promise<[number, number]> { + return this.request(`${this.prefix}get_cursor`, []) + } + + /** Set cursor position */ + public setCursor(pos: [number, number]): Promise + public setCursor(pos: [number, number], isNotify: true): null + public setCursor(pos: [number, number], isNotify = false): Promise | null { + let method = isNotify ? 'notify' : 'request' + return this[method](`${this.prefix}set_cursor`, [pos]) + } + + /** Get window height by number of rows */ + public get height(): Promise { + return this.request(`${this.prefix}get_height`, []) + } + + /** Set window height by number of rows */ + public setHeight(height: number): Promise + public setHeight(height: number, isNotify: true): null + public setHeight(height: number, isNotify = false): Promise | null { + let method = isNotify ? 'notify' : 'request' + return this[method](`${this.prefix}set_height`, [height]) + } + + /** Get window width by number of columns */ + public get width(): Promise { + return this.request(`${this.prefix}get_width`, []) + } + + /** Set window width by number of columns */ + public setWidth(width: number): Promise + public setWidth(width: number, isNotify: true): null + public setWidth(width: number, isNotify = false): Promise | null { + let method = isNotify ? 'notify' : 'request' + return this[method](`${this.prefix}set_width`, [width]) + } + + /** Get window position */ + public get position(): Promise<[number, number]> { + return this.request(`${this.prefix}get_position`, []) + } + + /** 0-indexed, on-screen window position(row) in display cells. */ + public get row(): Promise { + return this.request(`${this.prefix}get_position`, []).then( + position => position[0] + ) + } + + /** 0-indexed, on-screen window position(col) in display cells. */ + public get col(): Promise { + return this.request(`${this.prefix}get_position`, []).then( + position => position[1] + ) + } + + /** Is window valid */ + public get valid(): Promise { + return this.request(`${this.prefix}is_valid`, []) + } + + /** Get window number */ + // eslint-disable-next-line id-blacklist + public get number(): Promise { + return this.request(`${this.prefix}get_number`, []) + } + + public setConfig(options: FloatOptions): Promise + public setConfig(options: FloatOptions, isNotify: true): null + public setConfig(options: FloatOptions, isNotify?: boolean): Promise { + let method = isNotify ? 'notify' : 'request' + return this[method](`${this.prefix}set_config`, [options]) + } + + public getConfig(): Promise { + return this.request(`${this.prefix}get_config`, []) + } + + public close(force: boolean): Promise + public close(force: boolean, isNotify: true): null + public close(force: boolean, isNotify?: boolean): Promise { + if (isNotify) { + this.notify(`${this.prefix}close`, [force]) + return null + } + return this.request(`${this.prefix}close`, [force]) + } + + /** + * Add highlight to ranges by using matchaddpos. + */ + public highlightRanges(hlGroup: string, ranges: Range[], priority?: number): Promise + public highlightRanges(hlGroup: string, ranges: Range[], priority: number, isNotify: true): null + public highlightRanges(hlGroup: string, ranges: Range[], priority = 10, isNotify?: boolean): Promise | null { + if (isNotify) { + this.client.call('coc#highlight#match_ranges', [this.id, 0, ranges, hlGroup, priority], true) + return undefined + } + return this.client.call('coc#highlight#match_ranges', [this.id, 0, ranges, hlGroup, priority]) as Promise + } + + /** + * Clear match by highlight group. + */ + public clearMatchGroup(hlGroup: string): void { + this.client.call('coc#highlight#clear_match_group', [this.id, hlGroup], true) + } + + /** + * Clear match by match ids. + */ + public clearMatches(ids: number[]): void { + this.client.call('coc#highlight#clear_matches', [this.id, ids], true) + } +} diff --git a/src/neovim/api/client.ts b/src/neovim/api/client.ts new file mode 100644 index 00000000000..3ba8ffca92e --- /dev/null +++ b/src/neovim/api/client.ts @@ -0,0 +1,394 @@ +/** + * Handles attaching transport + */ +import { NvimTransport } from '../transport/nvim' +import { VimTransport } from '../transport/vim' +import { AtomicResult, VimValue } from '../types' +import { isCocNvim, isTester } from '../utils/constants' +import { ILogger } from '../utils/logger' +import { Buffer } from './Buffer' +import { Neovim } from './Neovim' +import { Tabpage } from './Tabpage' +import { Window } from './Window' +import { EventEmitter } from 'events' +import Transport from '../transport/base' + +export type Callback = (err?: Error | null, res?: any) => void + +const functionsOnVim = [ + 'nvim_buf_attach', + 'nvim_get_mode', + 'nvim_list_runtime_paths', + 'nvim_win_del_var', + 'nvim_create_buf', + 'nvim_exec', + 'nvim_tabpage_list_wins', + 'nvim_buf_del_var', + 'nvim_buf_get_mark', + 'nvim_tabpage_set_var', + 'nvim_create_namespace', + 'nvim_win_get_position', + 'nvim_win_set_height', + 'nvim_call_atomic', + 'nvim_buf_detach', + 'nvim_buf_line_count', + 'nvim_set_current_buf', + 'nvim_set_current_dir', + 'nvim_get_var', + 'nvim_del_current_line', + 'nvim_win_set_width', + 'nvim_out_write', + 'nvim_win_is_valid', + 'nvim_set_current_win', + 'nvim_get_current_tabpage', + 'nvim_tabpage_is_valid', + 'nvim_set_var', + 'nvim_win_get_height', + 'nvim_win_get_buf', + 'nvim_win_get_width', + 'nvim_buf_set_name', + 'nvim_subscribe', + 'nvim_get_current_win', + 'nvim_feedkeys', + 'nvim_get_vvar', + 'nvim_tabpage_get_number', + 'nvim_get_current_buf', + 'nvim_win_get_option', + 'nvim_win_get_cursor', + 'nvim_get_current_line', + 'nvim_win_get_var', + 'nvim_buf_get_var', + 'nvim_set_current_tabpage', + 'nvim_buf_clear_namespace', + 'nvim_err_write', + 'nvim_del_var', + 'nvim_call_dict_function', + 'nvim_set_current_line', + 'nvim_get_api_info', + 'nvim_unsubscribe', + 'nvim_get_option', + 'nvim_get_option_value', + 'nvim_list_wins', + 'nvim_set_client_info', + 'nvim_win_set_cursor', + 'nvim_win_set_option', + 'nvim_eval', + 'nvim_tabpage_get_var', + 'nvim_buf_get_option', + 'nvim_tabpage_del_var', + 'nvim_buf_get_name', + 'nvim_list_bufs', + 'nvim_win_set_buf', + 'nvim_win_close', + 'nvim_command_output', + 'nvim_command', + 'nvim_tabpage_get_win', + 'nvim_win_set_var', + 'nvim_buf_add_highlight', + 'nvim_buf_set_var', + 'nvim_win_get_number', + 'nvim_strwidth', + 'nvim_buf_set_lines', + 'nvim_err_writeln', + 'nvim_buf_set_option', + 'nvim_list_tabpages', + 'nvim_set_option', + 'nvim_buf_get_lines', + 'nvim_buf_get_changedtick', + 'nvim_win_get_tabpage', + 'nvim_call_function', + 'nvim_buf_is_valid' +] + +export class AsyncResponse { + private finished = false + constructor(public readonly requestId: number, private cb: Callback) { + } + + public finish(err?: string | null, res?: any): void { + if (this.finished) return + this.finished = true + if (err) { + this.cb(new Error(err)) + return + } + this.cb(null, res) + } +} + +function applyMixins(derivedCtor: any, constructors: any[]) { + constructors.forEach(baseCtor => { + Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => { + Object.defineProperty( + derivedCtor.prototype, + name, + Object.getOwnPropertyDescriptor(baseCtor.prototype, name) || + Object.create(null) + ) + }) + }) +} + +// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging +export interface NeovimClient extends Neovim, EventEmitter {} + +// eslint-disable-next-line no-redeclare, @typescript-eslint/no-unsafe-declaration-merging +export class NeovimClient extends Neovim { + private _isReady: Promise + private requestId = 1 + private responses: Map = new Map() + private _channelId: number + private attachedBuffers: Map> = new Map() + public _transport: Transport + + constructor(private logger: ILogger, public readonly isVim: boolean) { + // Neovim has no `data` or `metadata` + super({}) + this._transport = isVim ? new VimTransport(logger) : new NvimTransport(logger) + this.handleRequest = this.handleRequest.bind(this) + this.handleNotification = this.handleNotification.bind(this) + } + + protected get transport(): Transport { + return this._transport + } + + public echoError(msg: unknown): void { + let prefix = isCocNvim ? '[coc.nvim] ' : '' + if (msg instanceof Error) { + if (!isTester) this.errWriteLine(prefix + msg.message + ' use :CocOpenLog for details') + this.logError(msg.message || 'Unknown error', msg) + } else { + if (!isTester) this.errWriteLine(prefix + msg) + this.logError(msg.toString(), new Error()) + } + } + + public logError(msg: string, ...args: any[]): void { + if (isTester) console.error(msg, ...args) + if (!this.logger) return + this.logger.error(msg, ...args) + } + + public createBuffer(id: number): Buffer { + return new Buffer({ + data: id, + client: this + }) + } + + public createWindow(id: number): Window { + return new Window({ + data: id, + client: this + }) + } + + public createTabpage(id: number): Tabpage { + return new Tabpage({ + data: id, + client: this + }) + } + + /** + * Invoke redraw on vim. + */ + public redrawVim(force?: boolean): void { + if (!this.isVim) return + this.transport.notify('nvim_command', ['redraw' + (force ? '!' : '')]) + } + + /** Attaches msgpack to read/write streams * */ + public attach({ + reader, + writer, + }: { + reader: NodeJS.ReadableStream + writer: NodeJS.WritableStream + }, requestApi = true): void { + this.transport.attach(writer, reader, this) + this.transport.on('request', this.handleRequest) + this.transport.on('notification', this.handleNotification) + this.transport.on('detach', () => { + this.emit('disconnect') + this.transport.removeAllListeners('request') + this.transport.removeAllListeners('notification') + this.transport.removeAllListeners('detach') + }) + if (requestApi) { + this._isReady = this.generateApi().catch(err => { + this.logger.error(err) + return false + }) + } else { + this._channelId = -1 + this._isReady = Promise.resolve(true) + } + } + + /* called when attach process disconnected*/ + public detach(): void { + this.attachedBuffers.clear() + this.transport.detach() + this.removeAllListeners() + } + + public get channelId(): Promise { + return this._isReady.then(() => { + return this._channelId + }) + } + + private handleRequest( + method: string, + args: VimValue[], + resp: any, + ): void { + this.emit('request', method, args, resp) + } + + public sendAsyncRequest(method: string, args: any[]): Promise { + let id = this.requestId + this.requestId = id + 1 + this.notify('nvim_call_function', ['coc#rpc#async_request', [id, method, args || []]]) + return new Promise((resolve, reject) => { + let response = new AsyncResponse(id, (err?: Error, res?: any): void => { + if (err) return reject(err) + resolve(res) + }) + this.responses.set(id, response) + }) + } + + private handleNotification(method: string, args: VimValue[]): void { + if (method.endsWith('_event')) { + if (method.startsWith('nvim_buf_')) { + const shortName = method.replace(/nvim_buf_(.*)_event/, '$1') + const { id } = args[0] as Buffer + if (!this.attachedBuffers.has(id)) return + const bufferMap = this.attachedBuffers.get(id) + const cbs = bufferMap.get(shortName) || [] + cbs.forEach(cb => cb(...args)) + // Handle `nvim_buf_detach_event` + // clean `attachedBuffers` since it will no longer be attached + if (shortName === 'detach') { + this.attachedBuffers.delete(id) + } + return + } + // async_request_event from vim + if (method == 'nvim_async_request_event') { + const [id, method, arr] = args + this.handleRequest(method as string, arr as any[], { + send: (resp: any, isError?: boolean): void => { + this.notify('nvim_call_function', ['coc#rpc#async_response', [id, resp, isError]]) + } + }) + return + } + // nvim_async_response_event + if (method == 'nvim_async_response_event') { + const [id, err, res] = args + const response = this.responses.get(id as number) + if (!response) { + this.logError(`Response not found for request ${id}`) + return + } + this.responses.delete(id as number) + response.finish(err as string, res) + return + } + if (method === 'nvim_error_event') { + this.logger.error(`Error event from nvim:`, args[0], args[1]) + this.emit('vim_error', args[1]) + return + } + this.logger.warn(`Unhandled event: ${method}`, args) + } else { + this.emit('notification', method, args) + } + } + + public requestApi(): Promise { + return new Promise((resolve, reject) => { + this.transport.request( + 'nvim_get_api_info', + [], + (err: any, res: any[]) => { + if (err) { + reject(new Error(Array.isArray(err) ? err[1] : err.message || err.toString())) + } else { + resolve(res) + } + } + ) + }) + } + + private async generateApi(): Promise { + let results = await this.requestApi() + const [channelId, metadata] = results + // TODO metadata not used + // this.functions = metadata.functions.map(f => f.name) + this._channelId = channelId + return true + } + + public attachBufferEvent(bufnr: number, eventName: string, cb: Function): void { + const bufferMap = this.attachedBuffers.get(bufnr) || new Map() + const cbs = bufferMap.get(eventName) || [] + if (cbs.includes(cb)) return + cbs.push(cb) + bufferMap.set(eventName, cbs) + this.attachedBuffers.set(bufnr, bufferMap) + return + } + + /** + * Returns `true` if buffer should be detached + */ + public detachBufferEvent(bufnr: number, eventName: string, cb: Function): void { + const bufferMap = this.attachedBuffers.get(bufnr) + if (!bufferMap || !bufferMap.has(eventName)) return + const handlers = bufferMap.get(eventName).filter(handler => handler !== cb) + bufferMap.set(eventName, handlers) + } + + public pauseNotification(): void { + let o: any = {} + Error.captureStackTrace(o) + if (this.transport.pauseLevel != 0) { + this.logError(`Nested nvim.pauseNotification() detected, please avoid it:`, o.stack) + } + this.transport.pauseNotification() + process.nextTick(() => { + if (this.transport.pauseLevel > 0) { + this.logError(`resumeNotification not called within same tick:`, o.stack) + } + }) + } + + public resumeNotification(redrawVim?: boolean): Promise + public resumeNotification(redrawVim: boolean, notify: true): null + public resumeNotification(redrawVim?: boolean, notify?: boolean): Promise | null { + if (this.isVim && redrawVim) { + this.transport.notify('nvim_command', ['redraw']) + } + if (notify) { + this.transport.resumeNotification(true) + return Promise.resolve(null) + } + return this.transport.resumeNotification() + } + + /** + * @deprecated + */ + public hasFunction(name: string): boolean { + if (!this.isVim) return true + return functionsOnVim.includes(name) + } +} + +applyMixins(NeovimClient, [EventEmitter]) diff --git a/src/neovim/api/index.ts b/src/neovim/api/index.ts new file mode 100644 index 00000000000..aa1b952d1f1 --- /dev/null +++ b/src/neovim/api/index.ts @@ -0,0 +1,5 @@ +export { NeovimClient as Neovim } from './client' +export { NeovimClient } from './client' +export { Buffer } from './Buffer' +export { Window } from './Window' +export { Tabpage } from './Tabpage' diff --git a/src/neovim/api/types.ts b/src/neovim/api/types.ts new file mode 100644 index 00000000000..fde754a6c19 --- /dev/null +++ b/src/neovim/api/types.ts @@ -0,0 +1,63 @@ +import { Buffer } from './Buffer' +import { Window } from './Window' +import { Tabpage } from './Tabpage' + +export interface Disposable { + /** + * Dispose this object. + */ + dispose(): void +} + +export interface KeymapOption { + noremap?: boolean + nowait?: boolean + silent?: boolean + script?: boolean + expr?: boolean + unique?: boolean +} + +export enum ExtType { + Buffer, + Window, + Tabpage, +} +export interface ExtTypeConstructor { + new(...args: any[]): T +} + +export interface FloatOptions { + standalone?: boolean + focusable?: boolean + relative?: 'editor' | 'cursor' | 'win' + anchor?: 'NW' | 'NE' | 'SW' | 'SE' + height: number + width: number + row: number + col: number +} + +export interface MetadataType { + constructor: ExtTypeConstructor + name: string + prefix: string +} + +export const Metadata: MetadataType[] = [ + { + constructor: Buffer, + name: 'Buffer', + prefix: 'nvim_buf_', + }, + { + constructor: Window, + name: 'Window', + prefix: 'nvim_win_', + }, + { + constructor: Tabpage, + name: 'Tabpage', + prefix: 'nvim_tabpage_', + }, +] diff --git a/src/neovim/attach/attach.test.ts b/src/neovim/attach/attach.test.ts new file mode 100644 index 00000000000..5031b91438f --- /dev/null +++ b/src/neovim/attach/attach.test.ts @@ -0,0 +1,150 @@ +import * as cp from 'child_process' +import * as which from 'which' +import { Neovim } from '../api' +import { attach } from './attach' +// import { pack, Packr, addExtension } from 'msgpackr' + +try { + which.sync('nvim') +} catch (e) { + // eslint-disable-next-line no-console + console.error( + 'A Neovim installation is required to run the tests', + '(see https://github.com/neovim/neovim/wiki/Installing)' + ) + process.exit(1) +} + +describe('Nvim Promise API', () => { + let proc + let nvim: Neovim + let requests + let notifications + + beforeAll(async () => { + try { + proc = cp.spawn( + 'nvim', + ['-u', 'NONE', '-N', '--embed', '-c', 'set noswapfile'], + { + cwd: __dirname, + } + ) + + nvim = attach({ proc }) + nvim.on('request', (method, args, resp) => { + requests.push({ method, args }) + resp.send(`received ${method}(${args})`) + }) + nvim.on('notification', (method, args) => { + notifications.push({ method, args }) + }) + + } catch (err) { + // eslint-disable-next-line no-console + console.log(err) + } + }) + + afterAll(async () => { + await nvim.quit() + if (proc && typeof proc.disconnect === 'function') { + proc.disconnect() + } + }) + + beforeEach(() => { + requests = [] + notifications = [] + }) + + // it('can pack data', async () => { + // addExtension({ + // Class: Buffer, + // type: 0, + // write(instance) { + // console.log(33) + // return instance.id + // }, + // read(data) { + // return new Buffer({ + // transport: undefined, + // client: undefined, + // data, + // }) + // } + // }) + // let packer = new Packr({ + // useRecords: false, + // encodeUndefinedAsNil: false, + // moreTypes: false + // }) + // let b = new Buffer({ data: 3 }) + // let buf = packer.encode([b]) + // console.log(buf) + // }) + + it('can send requests and receive response', async () => { + const result = await nvim.eval('{"k1": "v1", "k2": 2}') + expect(result).toEqual({ k1: 'v1', k2: 2 }) + }) + + it('can receive requests and send responses', async () => { + const res = await nvim.eval('rpcrequest(1, "request", 1, 2, 3)') + expect(res).toEqual('received request(1,2,3)') + expect(requests).toEqual([{ method: 'request', args: [1, 2, 3] }]) + expect(notifications).toEqual([]) + }) + + it('can receive notifications', async () => { + const res = await nvim.eval('rpcnotify(1, "notify", 1, 2, 3)') + expect(res).toEqual(1) + expect(requests).toEqual([]) + return new Promise(resolve => + setImmediate(() => { + expect(notifications).toEqual([{ method: 'notify', args: [1, 2, 3] }]) + resolve(undefined) + }) + ) + }) + + it('can deal with custom types', async () => { + await nvim.command('vsp') + await nvim.command('vsp') + await nvim.command('vsp') + const windows = await nvim.windows + + expect(windows.length).toEqual(4) + + await nvim.setWindow(windows[2]) + const win = await nvim.window + + expect(win.equals(windows[0])).toBe(false) + expect(win.equals(windows[2])).toBe(true) + + const buf = await nvim.buffer + + const lines = await buf.getLines({ start: 0, end: -1, strictIndexing: false }) + expect(lines).toEqual([]) + + await buf.setLines(['line1', 'line2'], { start: 0, end: 1 }) + const newLines = await buf.getLines({ start: 0, end: -1, strictIndexing: false }) + expect(newLines).toEqual(['line1', 'line2']) + }) + + it('emits "disconnect" after quit', async done => { + const disconnectMock = jest.fn() + nvim.on('disconnect', disconnectMock) + await nvim.quit() + + proc.on('close', () => { + expect(disconnectMock.mock.calls.length).toBe(1) + done() + }) + + // Event doesn't actually emit when we quit nvim, but when the child process is killed + if (typeof proc.disconnect === 'function') { + proc.disconnect() + } + }) +}) diff --git a/src/neovim/attach/attach.ts b/src/neovim/attach/attach.ts new file mode 100644 index 00000000000..dc7921ca2e5 --- /dev/null +++ b/src/neovim/attach/attach.ts @@ -0,0 +1,56 @@ +import { createConnection } from 'net' +import * as child from 'child_process' +import { NeovimClient } from './../api/client' +import { ILogger, nullLogger } from '../utils/logger' + +export interface Attach { + reader?: NodeJS.ReadableStream + writer?: NodeJS.WritableStream + proc?: NodeJS.Process | child.ChildProcess + socket?: string +} + +export function attach({ + reader: _reader, + writer: _writer, + proc, + socket, +}: Attach, logger: ILogger = null, requestApi = true): NeovimClient { + let writer: NodeJS.WritableStream + let reader: NodeJS.ReadableStream + let neovim: NeovimClient + if (!logger) logger = nullLogger + + if (socket) { + const client = createConnection(socket) + writer = client + reader = client + client.once('close', () => { + neovim.detach() + }) + } else if (_reader && _writer) { + writer = _writer + reader = _reader + } else if (proc) { + writer = proc.stdin + reader = proc.stdout + proc.once('disconnect', () => { + neovim.detach() + }) + } + writer.on('error', err => { + if (err.code == 'EPIPE') { + neovim.detach() + } + }) + + if (writer && reader) { + neovim = new NeovimClient(logger, process.env.VIM_NODE_RPC == '1') + neovim.attach({ + writer, + reader, + }, requestApi) + return neovim + } + throw new Error('Invalid arguments, could not attach') +} diff --git a/src/neovim/index.ts b/src/neovim/index.ts new file mode 100644 index 00000000000..f07ee92ffcf --- /dev/null +++ b/src/neovim/index.ts @@ -0,0 +1,6 @@ +export { attach, Attach } from './attach/attach' +export { FloatOptions, KeymapOption } from './api/types' +export { VimValue } from './types' +export { UiAttachOptions } from './api/Neovim' +export { BufferSetLines, BufferHighlight, BufferClearHighlight, VirtualTextOption, SignPlaceOption, SignUnplaceOption, SignPlacedOption, SignItem, VimHighlightItem } from './api/Buffer' +export { Neovim, Buffer, Tabpage, Window } from './api/index' diff --git a/src/neovim/transport/base.ts b/src/neovim/transport/base.ts new file mode 100644 index 00000000000..d0eaaeb7792 --- /dev/null +++ b/src/neovim/transport/base.ts @@ -0,0 +1,104 @@ +import { EventEmitter } from 'events' +import { createLogger, ILogger, level } from '../utils/logger' +import { NeovimClient } from '../api' +import { AtomicResult } from '../types' +const debug = level === 'debug' +const logger = createLogger('transport') + +export interface Response { + send: (resp: any, isError?: boolean) => void +} + +export default abstract class Transport extends EventEmitter { + public pauseLevel = 0 + protected paused: Map = new Map() + + constructor(protected logger: ILogger, public readonly isVim: boolean) { + super() + } + + protected debug(key: string, ...meta: any[]): void { + if (!debug) return + logger.debug(key, ...meta) + } + + protected info(key: string, ...meta: any[]): void { + logger.info(key, ...meta) + } + + protected debugMessage(msg: any[]): void { + if (!debug) return + const msgType = msg[0] + if (msgType == 0) { + logger.debug('receive request:', msg.slice(1)) + } else if (msgType == 1) { + // logger.debug('receive response:', msg.slice(1)) + } else if (msgType == 2) { + logger.debug('receive notification:', msg.slice(1)) + } else { + logger.debug('unknown message:', msg) + } + } + + public pauseNotification(): void { + this.pauseLevel = this.pauseLevel + 1 + this.paused.set(this.pauseLevel, []) + } + + public cancelNotification(): void { + let { pauseLevel } = this + if (pauseLevel > 0) { + this.paused.delete(pauseLevel) + this.pauseLevel = pauseLevel - 1 + } + } + + public resumeNotification(): Promise + public resumeNotification(isNotify: true): null + public resumeNotification(isNotify = false): Promise | null { + let { pauseLevel } = this + if (pauseLevel == 0) return isNotify ? null : Promise.resolve([[], null]) + let obj: any = {} + Error.captureStackTrace(obj) + this.pauseLevel = pauseLevel - 1 + let list = this.paused.get(pauseLevel) + this.paused.delete(pauseLevel) + if (list && list.length) { + return new Promise((resolve, reject) => { + if (!isNotify) { + return this.request('nvim_call_atomic', [list], (err, res) => { + if (err) { + let e = new Error(`call_atomic error: ${err[1]}`) + e.stack = obj.stack.replace(/^Error/, `Error: ${e.message}`) + return reject(e) + } + if (Array.isArray(res) && res[1] != null) { + let [index, errType, message] = res[1] + let [fname, args] = list[index] + let e = new Error(`call_atomic request error on "${fname}": ${message}`) + e.stack = obj.stack.replace(/^Error/, `Error: ${e.message}`) + this.logger.error(`call_atomic request error ${errType} on "${fname}"`, args, message, e) + return reject(e) + } + resolve(res) + }) + } + this.notify('nvim_call_atomic', [list]) + resolve(undefined) + }) + } + return isNotify ? null : Promise.resolve([[], undefined]) + } + + public abstract attach(writer: NodeJS.WritableStream, reader: NodeJS.ReadableStream, client: NeovimClient): void + + public abstract detach(): void + + public abstract send(arr: any[]): void + + public abstract request(method: string, args: any[], cb: Function): any + + public abstract notify(method: string, args: any[]): void + + protected abstract createResponse(method: string, requestId: number): Response +} diff --git a/src/neovim/transport/connection.ts b/src/neovim/transport/connection.ts new file mode 100644 index 00000000000..7c14d8978ed --- /dev/null +++ b/src/neovim/transport/connection.ts @@ -0,0 +1,118 @@ +import Emitter from 'events' +import { createLogger } from '../utils/logger' +const logger = createLogger('connection') +const NR_CODE = 10 + +// vim connection by using channel feature +export default class Connection extends Emitter { + private clean: () => void + constructor( + readable: NodeJS.ReadableStream, + private writeable: NodeJS.WritableStream) { + super() + let cached: Buffer[] = [] + let hasCache = false + readable.once('data', buf => { + if (!Buffer.isBuffer(buf)) throw new Error(`Vim connection expect buffer from readable stream.`) + }) + // should be utf8 encoding. + let onData = (buf: Buffer) => { + let start = 0 + let len = buf.byteLength + for (let i = 0; i < len; i++) { + if (buf[i] === NR_CODE) { // '\n' + let b = buf.slice(start, i) + if (hasCache) { + cached.push(b) + let concated = Buffer.concat(cached) + hasCache = false + cached = [] + this.parseData(concated.toString('utf8')) + } else { + this.parseData(b.toString('utf8')) + } + start = i + 1 + } + } + if (start < len) { + cached.push(start == 0 ? buf : buf.slice(start)) + hasCache = true + } + } + readable.on('data', onData) + let onClose = () => { + logger.warn('readable stream closed.') + } + readable.on('close', onClose) + this.clean = () => { + readable.off('data', onData) + readable.off('close', onClose) + } + } + + private parseData(str: string): void { + if (str.length == 0) return + let arr: any[] + try { + arr = JSON.parse(str) + } catch (e) { + // tslint:disable-next-line: no-console + console.error(`Invalid data from vim: ${str}`) + return + } + // request, notification, response + let [id, obj] = arr + if (id > 0) { + logger.debug('received request:', id, obj) + this.emit('request', id, obj) + } else if (id == 0) { + logger.debug('received notification:', obj) + this.emit('notification', obj) + } else { + logger.debug('received response:', id, obj) + // response for previous request + this.emit('response', id, obj) + } + } + + public response(requestId: number, data?: any): void { + this.send([requestId, data || null]) + } + + public notify(event: string, data?: any): void { + this.send([0, [event, data || null]]) + } + + public send(arr: any[]): void { + logger.debug('send to vim:', arr) + this.writeable.write(JSON.stringify(arr) + '\n') + } + + public redraw(force?: boolean): void { + this.send(['redraw', force ? 'force' : '']) + } + + public command(cmd: string): void { + this.send(['ex', cmd]) + } + + public expr(expr: string): void { + this.send(['expr', expr]) + } + + public call(func: string, args: any[], requestId?: number): void { + if (typeof requestId === 'number') { + this.send(['call', func, args, requestId]) + return + } + this.send(['call', func, args]) + } + + public dispose(): void { + if (typeof this.clean === 'function') { + this.clean() + this.clean = undefined + } + this.removeAllListeners() + } +} diff --git a/src/neovim/transport/nvim.ts b/src/neovim/transport/nvim.ts new file mode 100644 index 00000000000..a34870562ff --- /dev/null +++ b/src/neovim/transport/nvim.ts @@ -0,0 +1,191 @@ +import * as msgpack from '@chemzqm/msgpack-lite' +import { Metadata } from '../api/types' +import Buffered from '../utils/buffered' +import { ILogger } from '../utils/logger' +import Transport, { Response } from './base' + +export class NvimTransport extends Transport { + private pending: Map = new Map() + private nextRequestId = 1 + private encodeStream: any + private decodeStream: any + private reader: NodeJS.ReadableStream + private writer: NodeJS.WritableStream + protected codec: msgpack.Codec + private attached = false + + // Neovim client that holds state + private client: any + + constructor(logger: ILogger) { + super(logger, false) + + const codec = this.setupCodec() + this.encodeStream = msgpack.createEncodeStream({ codec }) + this.decodeStream = msgpack.createDecodeStream({ codec }) + this.decodeStream.on('data', (msg: any[]) => { + this.parseMessage(msg) + }) + this.decodeStream.on('end', () => { + this.detach() + this.emit('detach') + }) + } + + private parseMessage(msg: any[]): void { + const msgType = msg[0] + this.debugMessage(msg) + + if (msgType === 0) { + // request + // - msg[1]: id + // - msg[2]: method name + // - msg[3]: arguments + let method = msg[2].toString() + this.emit( + 'request', + method, + msg[3], + this.createResponse(method, msg[1]) + ) + } else if (msgType === 1) { + // response to a previous request: + // - msg[1]: the id + // - msg[2]: error(if any) + // - msg[3]: result(if not errored) + const id = msg[1] + const handler = this.pending.get(id) + if (handler) { + this.pending.delete(id) + let err = msg[2] + if (err && err.length != 2) { + err = [0, err.toString()] + } + handler(err, msg[3]) + } + } else if (msgType === 2) { + // notification/event + // - msg[1]: event name + // - msg[2]: arguments + this.emit('notification', msg[1].toString(), msg[2]) + } else { + // tslint:disable-next-line: no-console + console.error(`Invalid message type ${msgType}`) + } + } + + private setupCodec(): msgpack.Codec { + const codec = msgpack.createCodec() + + Metadata.forEach( + ({ constructor }, id: number): void => { + codec.addExtPacker(id, constructor, (obj: any) => + msgpack.encode(obj.data) + ) + codec.addExtUnpacker( + id, + data => + new constructor({ + client: this.client, + data: msgpack.decode(data), + }) + ) + } + ) + + this.codec = codec + return this.codec + } + + public attach( + writer: NodeJS.WritableStream, + reader: NodeJS.ReadableStream, + client: any + ): void { + this.encodeStream = this.encodeStream.pipe(writer) + const buffered = new Buffered() + reader.pipe(buffered).pipe(this.decodeStream) + this.writer = writer + this.reader = reader + this.client = client + this.attached = true + } + + public detach(): void { + if (!this.attached) return + this.attached = false + this.encodeStream.unpipe(this.writer) + this.reader.unpipe(this.decodeStream) + for (let handler of this.pending.values()) { + handler([0, 'transport disconnected']) + } + this.pending.clear() + } + + public request(method: string, args: any[], cb: Function): any { + if (!this.attached) return cb([0, 'transport disconnected']) + let id = this.nextRequestId + this.nextRequestId = this.nextRequestId + 1 + let startTs = Date.now() + this.debug('request to nvim:', id, method, args) + this.encodeStream.write( + msgpack.encode([0, id, method, args], { + codec: this.codec, + }) + ) + this.pending.set(id, (err, res) => { + this.debug('response of nvim:', id, Date.now() - startTs, res, err) + cb(err, res) + }) + } + + public notify(method: string, args: any[]): void { + if (!this.attached) return + if (this.pauseLevel != 0) { + let arr = this.paused.get(this.pauseLevel) + if (arr) { + arr.push([method, args]) + return + } + } + this.debug('nvim notification:', method, args) + this.encodeStream.write( + msgpack.encode([2, method, args], { + codec: this.codec, + }) + ) + } + + public send(arr: any[]): void { + this.encodeStream.write( + msgpack.encode(arr, { + codec: this.codec, + }) + ) + } + + protected createResponse(method: string, requestId: number): Response { + let { encodeStream } = this + let startTs = Date.now() + let called = false + let timer = setTimeout(() => { + this.debug(`request to client cost more than 1s`, requestId) + }, 1000) + return { + send: (resp: any, isError?: boolean): void => { + clearTimeout(timer) + if (called || !this.attached) return + this.debug('response of client:', requestId, `${Date.now() - startTs}ms`, resp, isError == true) + called = true + encodeStream.write( + msgpack.encode([ + 1, + requestId, + isError ? resp : null, + !isError ? resp : null, + ]) + ) + } + } + } +} diff --git a/src/neovim/transport/request.ts b/src/neovim/transport/request.ts new file mode 100644 index 00000000000..941a03c5f78 --- /dev/null +++ b/src/neovim/transport/request.ts @@ -0,0 +1,46 @@ +import { NeovimClient } from '../api' +import { isCocNvim } from '../utils/constants' +import Connection from './connection' +const func = isCocNvim ? 'coc#api#call' : 'nvim#api#call' + +export default class Request { + private method: string + constructor( + private connection: Connection, + private cb: Function, + private readonly id: number + ) { + } + + public request(method: string, args: any[] = []): void { + this.method = method + this.connection.call(func, [method.slice(5), args], this.id) + } + + public callback(client: NeovimClient, err: any, result: any): void { + let { method, cb } = this + if (err) return cb([0, err.toString()]) + switch (method) { + case 'nvim_list_wins': + case 'nvim_tabpage_list_wins': + return cb(null, result.map(o => client.createWindow(o))) + case 'nvim_tabpage_get_win': + case 'nvim_get_current_win': + case 'nvim_open_win': + return cb(null, client.createWindow(result)) + case 'nvim_list_bufs': + return cb(null, result.map(o => client.createBuffer(o))) + case 'nvim_win_get_buf': + case 'nvim_create_buf': + case 'nvim_get_current_buf': + return cb(null, client.createBuffer(result)) + case 'nvim_list_tabpages': + return cb(null, result.map(o => client.createTabpage(o))) + case 'nvim_win_get_tabpage': + case 'nvim_get_current_tabpage': + return cb(null, client.createTabpage(result)) + default: + return cb(null, result) + } + } +} diff --git a/src/neovim/transport/vim.ts b/src/neovim/transport/vim.ts new file mode 100644 index 00000000000..2e455ee50f2 --- /dev/null +++ b/src/neovim/transport/vim.ts @@ -0,0 +1,148 @@ +import { NeovimClient } from '../api' +import { isCocNvim } from '../utils/constants' +import { ILogger } from '../utils/logger' +import Transport, { Response } from './base' +import Connection from './connection' +import Request from './request' + +export class VimTransport extends Transport { + private pending: Map = new Map() + private nextRequestId = -1 + private connection: Connection + private attached = false + private client: NeovimClient + private notifyMethod: string + /** + * Cached error message + */ + private errText = '' + /** + * Cached out message + */ + private outText = '' + + constructor(logger: ILogger) { + super(logger, true) + this.notifyMethod = isCocNvim ? 'coc#api#notify' : 'nvim#api#notify' + } + + public attach( + writer: NodeJS.WritableStream, + reader: NodeJS.ReadableStream, + client: NeovimClient + ): void { + let connection = this.connection = new Connection(reader, writer) + this.attached = true + this.client = client + + connection.on('request', (id: number, obj: any) => { + let [method, args] = obj + this.emit( + 'request', + method, + args, + this.createResponse(method, id) + ) + }) + connection.on('notification', (obj: any) => { + let [event, args] = obj + this.emit('notification', event.toString(), args) + }) + connection.on('response', (id: number, obj: any) => { + let req = this.pending.get(id) + if (req) { + this.pending.delete(id) + let err = null + let result = null + if (!Array.isArray(obj)) { + err = obj + } else { + err = obj[0] + result = obj[1] + } + req.callback(this.client, err, result) + } + }) + } + + public send(arr: any[]): void { + this.connection.send(arr) + } + + public detach(): void { + if (!this.attached) return + this.attached = false + this.connection.dispose() + for (let req of this.pending.values()) { + req.callback(this.client, 'connection disconnected', null) + } + this.pending.clear() + } + + /** + * Send request to vim + */ + public request(method: string, args: any[], cb: Function): any { + if (!this.attached) return cb([0, 'transport disconnected']) + let id = this.nextRequestId + this.nextRequestId = this.nextRequestId - 1 + // let startTs = Date.now() + // if (debug) this.debug(`Send request "${method}" (${id}) to vim: `, args) + let req = new Request(this.connection, (err, res) => { + // if (debug) this.debug(`Receive response "${method}" (${id}) from vim ${Date.now() - startTs}ms`, err ?? res) + cb(err, res) + }, id) + this.pending.set(id, req) + req.request(method, args) + } + + public notify(method: string, args: any[]): void { + if (!this.attached) return + if (this.pauseLevel != 0) { + let arr = this.paused.get(this.pauseLevel) + if (arr) { + arr.push([method, args]) + return + } + } + let fname = method.slice(5) + if (fname == 'err_write') { + this.errText = this.errText + args[0].toString() + return + } + if (fname == 'out_write') { + let msg = args[0].toString() || '' + if (!msg.includes('\n')) { + this.outText = this.outText + msg + } else { + let text = this.outText + args[0].toString() + this.outText = '' + this.connection.call(this.notifyMethod, [fname, [text]]) + } + return + } + if (fname == 'err_writeln') { + let text = this.errText + args[0].toString() + this.errText = '' + this.connection.call(this.notifyMethod, [fname, [text]]) + return + } + this.connection.call(this.notifyMethod, [fname, args]) + } + + protected createResponse(method: string, requestId: number): Response { + let called = false + let { connection } = this + // let startTs = Date.now() + return { + send: (resp: any, isError?: boolean): void => { + if (called || !this.attached) return + called = true + let err: string = null + if (isError) err = typeof resp === 'string' ? resp : resp.toString() + // if (debug) this.debug(`Send "${method}" (${requestId}) response to vim ${Date.now() - startTs}ms`) + connection.response(requestId, [err, isError ? null : resp]) + } + } + } +} diff --git a/src/neovim/types.ts b/src/neovim/types.ts new file mode 100644 index 00000000000..2fcc310a85a --- /dev/null +++ b/src/neovim/types.ts @@ -0,0 +1,70 @@ +export interface Position { + /** + * Line position in a document (zero-based). + * If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document. + * If a line number is negative, it defaults to 0. + */ + line: number + /** + * Character offset on a line in a document (zero-based). Assuming that the line is + * represented as a string, the `character` value represents the gap between the + * `character` and `character + 1`. + * + * If the character value is greater than the line length it defaults back to the + * line length. + * If a line number is negative, it defaults to 0. + */ + character: number +} + +export interface Range { + /** + * The range's start position + */ + start: Position + /** + * The range's end position. + */ + end: Position +} + +export type Parameters = [string, string] + +export interface FunctionInfo { + parameters: Parameters[] + method: boolean + return_type: string + name: string + since: number +} + +export interface UiEventInfo { + parameters: Parameters[] + name: string + since: number +} + +export interface ApiInfo { + version: { + major: number + minor: number + patch: number + api_level: number + api_compatible: number + api_prerelease: number + } + functions: FunctionInfo[] + ui_events: UiEventInfo[] + ui_options: string[] + error_types: object + types: object +} + +export type VimValue = + | number + | boolean + | string + | number[] + | { [key: string]: any } + +export type AtomicResult = [VimValue[], null | [number, string, string]] diff --git a/src/neovim/utils/buffered.ts b/src/neovim/utils/buffered.ts new file mode 100644 index 00000000000..68bb2637c5d --- /dev/null +++ b/src/neovim/utils/buffered.ts @@ -0,0 +1,59 @@ +import { Transform } from 'stream' + +const MIN_SIZE = Buffer.poolSize +const waterMark = 10 * 1024 * 1024 + +export default class Buffered extends Transform { + private chunks: Buffer[] | null + private timer: NodeJS.Timeout | null + constructor() { + super({ + readableHighWaterMark: waterMark, + writableHighWaterMark: waterMark + }) + this.chunks = null + this.timer = null + } + + public sendData() { + const { chunks } = this + if (chunks) { + this.chunks = null + this.push(Buffer.concat(chunks)) + } + } + + // eslint-disable-next-line consistent-return, @typescript-eslint/explicit-member-accessibility + _transform(chunk: Buffer, _encoding: any, callback: any): void { + const { chunks, timer } = this + if (timer) clearTimeout(timer) + if (chunk.length < MIN_SIZE) { + if (!chunks) return callback(null, chunk) + chunks.push(chunk) + this.sendData() + callback() + } else { + if (!chunks) { + this.chunks = [chunk] + } else { + chunks.push(chunk) + } + + this.timer = setTimeout(this.sendData.bind(this), 20) + callback() + } + } + + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility + _flush(callback: any) { + const { chunks } = this + if (chunks) { + this.chunks = null + const buf = Buffer.concat(chunks) + callback(null, buf) + } else { + callback() + } + } +} + diff --git a/src/neovim/utils/constants.ts b/src/neovim/utils/constants.ts new file mode 100644 index 00000000000..e8ef5210ee9 --- /dev/null +++ b/src/neovim/utils/constants.ts @@ -0,0 +1,4 @@ +'use strict' +export const isCocNvim = process.env.COC_NVIM == '1' + +export const isTester = process.env.COC_TESTER == '1' diff --git a/src/neovim/utils/devnull.ts b/src/neovim/utils/devnull.ts new file mode 100644 index 00000000000..f2427a43ab3 --- /dev/null +++ b/src/neovim/utils/devnull.ts @@ -0,0 +1,9 @@ +/* eslint-disable @typescript-eslint/explicit-member-accessibility */ +import { Duplex } from 'stream' + +export class DevNull extends Duplex { + _read() {} + _write(chunk: any, enc: any, cb: Function) { + cb() + } +} diff --git a/src/neovim/utils/lodash.ts b/src/neovim/utils/lodash.ts new file mode 100644 index 00000000000..fb0fbefc5fb --- /dev/null +++ b/src/neovim/utils/lodash.ts @@ -0,0 +1,54 @@ + +/** Used for built-in method references. */ +const objectProto = Object.prototype + +/** Used to check objects for own properties. */ +const hasOwnProperty = objectProto.hasOwnProperty +/** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * @since 0.1.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see defaultsDeep + * @example + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }) + * // => { 'a': 1, 'b': 2 } + */ +export function defaults(obj: any, ...sources: any[]): any { + obj = Object(obj) + sources.forEach(source => { + if (source != null) { + source = Object(source) + for (const key in source) { + const value = obj[key] + if (value === undefined || + (value === objectProto[key] && !hasOwnProperty.call(obj, key))) { + obj[key] = source[key] + } + } + } + }) + return obj +} + +export function omit(obj: T, properties: string[]): T { + let o = {} + for (let p of properties) { + Object.defineProperty(o, p, { + enumerable: true, + get: () => { + throw new Error(`property "${p}" is removed by node-client`) + } + }) + } + let res = Object.assign(obj, o) + return res as T +} diff --git a/src/neovim/utils/logger.ts b/src/neovim/utils/logger.ts new file mode 100644 index 00000000000..258f8089cd0 --- /dev/null +++ b/src/neovim/utils/logger.ts @@ -0,0 +1,126 @@ +import fs from 'fs' +import os from 'os' +import path from 'path' +import { inspect } from 'util' +import { Writable } from 'stream' + +const debugging = process.env.COC_NODE_CLIENT_DEBUG == '1' && process.env.COC_TESTER == '1' + +export interface ILogger { + debug: (data: string, ...meta: any[]) => void + info: (data: string, ...meta: any[]) => void + error: (data: string, ...meta: any[]) => void + warn: (data: string, ...meta: any[]) => void + trace: (data: string, ...meta: any[]) => void +} + +export const nullLogger: ILogger = { + debug: () => {}, + info: () => {}, + warn: () => {}, + error: () => {}, + trace: () => {}, +} + +function getLogFile(): string { + let file = process.env.NODE_CLIENT_LOG_FILE + if (file) return file + let dir = process.env.XDG_RUNTIME_DIR + if (dir) return path.join(dir, 'node-client.log') + return path.join(os.tmpdir(), `node-client-${process.pid}.log`) +} + +const LOG_FILE_PATH = getLogFile() +export const level = debugging ? 'debug' : process.env.NODE_CLIENT_LOG_LEVEL || 'info' + +let invalid = !debugging && process.getuid && process.getuid() == 0 +if (!invalid && !debugging) { + try { + fs.mkdirSync(path.dirname(LOG_FILE_PATH), { recursive: true }) + fs.writeFileSync(LOG_FILE_PATH, '', { encoding: 'utf8', mode: 0o666 }) + } catch (_e) { + invalid = true + } +} + +function toObject(arg: any): any { + if (arg == null) { + return arg + } + if (Array.isArray(arg)) { + return arg.map(o => toObject(o)) + } + if (typeof arg == 'object' && typeof arg.prefix == 'string' && typeof arg.data == 'number') { + return '[' + arg.prefix + arg.data + ']' + } + return arg +} + +function toString(arg: any): string { + if (debugging) return inspect(arg, { depth: null, colors: true, compact: false }) + if (arg == null) return String(arg) + if (typeof arg == 'object') return JSON.stringify(arg, null, 2) + return String(arg) +} + +const toTwoDigits = (v: number) => v < 10 ? `0${v}` : v.toString() +const toThreeDigits = (v: number) => v < 10 ? `00${v}` : v < 100 ? `0${v}` : v.toString() + +function toTimeString(currentTime: Date): string { + return `${toTwoDigits(currentTime.getHours())}:${toTwoDigits(currentTime.getMinutes())}:${toTwoDigits(currentTime.getSeconds())}.${toThreeDigits(currentTime.getMilliseconds())}` +} + +class Logger implements ILogger { + private _stream: Writable + constructor(private name: string) { + } + + private get stream(): Writable { + if (this._stream) return this._stream + if (debugging) { + this._stream = process.stdout + } else { + this._stream = fs.createWriteStream(LOG_FILE_PATH, { encoding: 'utf8' }) + } + return this._stream + } + + private getText(level: string, data: string, meta: any[]): string { + let more = '' + if (meta.length) { + let arr = toObject(meta) + more = ' ' + arr.map(o => toString(o)).join(', ') + } + return `${toTimeString(new Date())} ${level.toUpperCase()} [${this.name}] - ${data}${more}\n` + } + + public debug(data: string, ...meta: any[]): void { + if (level != 'debug' || invalid) return + this.stream.write(this.getText('debug', data, meta)) + } + + public info(data: string, ...meta: any[]): void { + if (invalid) return + this.stream.write(this.getText('info', data, meta)) + } + + public warn(data: string, ...meta: any[]): void { + if (invalid) return + this.stream.write(this.getText('warn', data, meta)) + } + + public error(data: string, ...meta: any[]): void { + if (invalid) return + let stream = debugging ? process.stderr : this.stream + stream.write(this.getText('error', data, meta)) + } + + public trace(data: string, ...meta: any[]): void { + if (level != 'trace' || invalid) return + this.stream.write(this.getText('trace', data, meta)) + } +} + +export function createLogger(name: string): ILogger { + return new Logger(name) +} diff --git a/src/plugin.ts b/src/plugin.ts index 57cca98d6ee..95f42561b27 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from './neovim' import { CodeActionKind, InsertTextMode, Range } from 'vscode-languageserver-types' import commandManager from './commands' import completion, { Completion } from './completion' diff --git a/src/snippets/eval.ts b/src/snippets/eval.ts index 8b78b7402af..c4fb896e1a6 100644 --- a/src/snippets/eval.ts +++ b/src/snippets/eval.ts @@ -1,6 +1,6 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' -import { Range } from '@chemzqm/neovim/lib/types' +import { Neovim } from '../neovim' +import { Range } from '../neovim/types' import { exec } from 'child_process' import { isVim } from '../util/constants' import { promisify } from '../util/node' diff --git a/src/snippets/manager.ts b/src/snippets/manager.ts index b3a1d28e940..522eeefd610 100644 --- a/src/snippets/manager.ts +++ b/src/snippets/manager.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { InsertTextMode, Position, Range, TextEdit } from 'vscode-languageserver-types' import commands from '../commands' import events from '../events' diff --git a/src/snippets/parser.ts b/src/snippets/parser.ts index aa09e80ca0e..be8487f91c9 100644 --- a/src/snippets/parser.ts +++ b/src/snippets/parser.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { createLogger } from '../logger' import { defaultValue } from '../util' import { groupBy } from '../util/array' diff --git a/src/snippets/session.ts b/src/snippets/session.ts index 422315901fa..19c8db2d5a3 100644 --- a/src/snippets/session.ts +++ b/src/snippets/session.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Position, Range, TextEdit } from 'vscode-languageserver-types' import { createLogger } from '../logger' import Document from '../model/document' diff --git a/src/snippets/snippet.ts b/src/snippets/snippet.ts index eaf1c90986a..c5d20772bcc 100644 --- a/src/snippets/snippet.ts +++ b/src/snippets/snippet.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { TextDocument } from 'vscode-languageserver-textdocument' import { Position, Range, TextEdit } from 'vscode-languageserver-types' import { LinesTextDocument } from '../model/textdocument' diff --git a/src/snippets/variableResolve.ts b/src/snippets/variableResolve.ts index 006b3f12a22..1c355d7b030 100644 --- a/src/snippets/variableResolve.ts +++ b/src/snippets/variableResolve.ts @@ -1,11 +1,10 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { v4 as uuid } from 'uuid' import { URI } from 'vscode-uri' import WorkspaceFolderController from '../core/workspaceFolder' import { path } from '../util/node' import { hasOwnProperty } from '../util/object' -import { toText } from '../util/string' import { Variable, VariableResolver } from "./parser" export function padZero(n: number): string { diff --git a/src/tree/TreeView.ts b/src/tree/TreeView.ts index d9a0350de4d..2954e5a7770 100644 --- a/src/tree/TreeView.ts +++ b/src/tree/TreeView.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { MarkupContent, MarkupKind, Range } from 'vscode-languageserver-types' import commandManager from '../commands' import type { LocalMode } from '../core/keymaps' diff --git a/src/tree/filter.ts b/src/tree/filter.ts index dbe4f0998a6..b06e3eaff38 100644 --- a/src/tree/filter.ts +++ b/src/tree/filter.ts @@ -1,6 +1,6 @@ 'use strict' import events from '../events' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from '../neovim' import { Disposable, Emitter, Event } from '../util/protocol' import { disposeAll } from '../util' export const sessionKey = 'filter' diff --git a/src/types.ts b/src/types.ts index 42df099ff3c..f4e66d19319 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,5 @@ 'use strict' -import type { Window } from '@chemzqm/neovim' +import type { Window } from './neovim' import type { Disposable, Event } from 'vscode-languageserver-protocol' import type { CreateFile, DeleteFile, Diagnostic, Location, Range, RenameFile, TextDocumentEdit } from 'vscode-languageserver-types' import type { URI } from 'vscode-uri' diff --git a/src/window.ts b/src/window.ts index f6b7958a72d..aa9984caf96 100644 --- a/src/window.ts +++ b/src/window.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from './neovim' import type { Position, Range } from 'vscode-languageserver-types' import type { WorkspaceConfiguration } from './configuration/types' import channels from './core/channels' @@ -101,7 +101,6 @@ export class Window { /** * Run command in vim terminal for result - * * @param cmd Command to run. * @param cwd Cwd of terminal, default to result of |getcwd()|. */ @@ -111,7 +110,6 @@ export class Window { /** * Open terminal window. - * * @param cmd Command to run. * @param opts Terminal option. * @returns number buffer number of terminal @@ -122,7 +120,6 @@ export class Window { /** * Reveal message with message type. - * * @param msg Message text to show. * @param messageType Type of message, could be `error` `warning` and `more`, default to `more` */ @@ -132,7 +129,6 @@ export class Window { /** * Create a new output channel - * * @param name Unique name of output channel. * @returns A new output channel. */ @@ -142,7 +138,6 @@ export class Window { /** * Reveal buffer of output channel. - * * @param name Name of output channel. * @param cmd command for open output channel. * @param preserveFocus Preserve window focus when true. @@ -154,7 +149,6 @@ export class Window { /** * Echo lines at the bottom of vim. - * * @param lines Line list. * @param truncate Truncate the lines to avoid 'press enter to continue' when true */ @@ -164,7 +158,6 @@ export class Window { /** * Get current cursor position (line, character both 0 based). - * * @returns Cursor position. */ public getCursorPosition(): Promise { @@ -173,7 +166,6 @@ export class Window { /** * Move cursor to position. - * * @param position LSP position. */ public async moveTo(position: Position): Promise { @@ -197,7 +189,6 @@ export class Window { /** * Get current cursor character offset in document, * length of line break would always be 1. - * * @returns Character offset. */ public getOffset(): Promise { @@ -207,7 +198,6 @@ export class Window { /** * Get screen position of current cursor(relative to editor), * both `row` and `col` are 0 based. - * * @returns Cursor screen position. */ public getCursorScreenPosition(): Promise { @@ -216,7 +206,6 @@ export class Window { /** * Create a {@link TreeView} instance. - * * @param viewId Id of the view, used as title of TreeView when title doesn't exist. * @param options Options for creating the {@link TreeView} * @returns a {@link TreeView}. @@ -228,7 +217,6 @@ export class Window { /** * Create statusbar item that would be included in `g:coc_status`. - * * @param priority Higher priority item would be shown right. * @param option * @return A new status bar item. @@ -240,7 +228,6 @@ export class Window { /** * Get diff from highlight items and current highlights on vim. * Return null when buffer not loaded - * * @param bufnr Buffer number * @param ns Highlight namespace * @param items Highlight items @@ -254,7 +241,6 @@ export class Window { /** * Create a FloatFactory, user's configurations are respected. - * * @param {FloatWinConfig} conf - Float window configuration * @returns {FloatFactory} */ @@ -267,7 +253,6 @@ export class Window { /** * Show quickpick for single item, use `window.menuPick` for menu at current current position. - * * @deprecated Use 'window.showMenuPicker()' or `window.showQuickPick` instead. * @param items Label list. * @param placeholder Prompt text, default to 'choose by number'. @@ -291,7 +276,6 @@ export class Window { * Note that in many cases the more convenient {@link window.showQuickPick} * is easier to use. {@link window.createQuickPick} should be used * when {@link window.showQuickPick} does not offer the required flexibility. - * * @return A new {@link QuickPick}. */ public async createQuickPick(config: QuickPickConfig = {}): Promise> { @@ -300,7 +284,6 @@ export class Window { /** * Show menu picker at current cursor position, |inputlist()| is used as fallback. - * * @param items Array of texts. * @param option Options for menu. * @param token A token that can be used to signal cancellation. @@ -313,7 +296,6 @@ export class Window { /** * Prompt user for confirm, a float/popup window would be used when possible, * use vim's |confirm()| function as callback. - * * @param title The prompt text. * @returns Result of confirm. */ @@ -324,7 +306,6 @@ export class Window { /** * Show dialog window at the center of screen. * Note that the dialog would always be closed after button click. - * * @param config Dialog configuration. * @returns Dialog or null when dialog can't work. */ @@ -334,7 +315,6 @@ export class Window { /** * Request input from user - * * @param title Title text of prompt window. * @param value Default value of input, empty text by default. * @param {InputOptions} option for input window @@ -346,7 +326,6 @@ export class Window { /** * Creates and show a {@link InputBox} to let the user enter some text input. - * * @return A new {@link InputBox}. */ public async createInputBox(title: string, value: string | undefined, option?: InputPreference): Promise { @@ -356,7 +335,6 @@ export class Window { /** * Show multiple picker at center of screen. * Use `this.workspace.env.dialog` to check if dialog could work. - * * @param items Array of QuickPickItem or string. * @param title Title of picker dialog. * @param token A token that can be used to signal cancellation. @@ -371,7 +349,6 @@ export class Window { /** * Show an information message to users. Optionally provide an array of items which will be presented as * clickable buttons. - * * @param message The message to show. * @param items A set of items that will be rendered as actions in the message. * @return Promise that resolves to the selected item or `undefined` when being dismissed. @@ -384,7 +361,6 @@ export class Window { /** * Show an warning message to users. Optionally provide an array of items which will be presented as * clickable buttons. - * * @param message The message to show. * @param items A set of items that will be rendered as actions in the message. * @return Promise that resolves to the selected item or `undefined` when being dismissed. @@ -397,7 +373,6 @@ export class Window { /** * Show an error message to users. Optionally provide an array of items which will be presented as * clickable buttons. - * * @param message The message to show. * @param items A set of items that will be rendered as actions in the message. * @return Promise that resolves to the selected item or `undefined` when being dismissed. @@ -425,7 +400,6 @@ export class Window { * * Timer is used to add highlights when there're too many highlight items to add, * the highlight process won't be finished on that case. - * * @param {number} bufnr - Buffer name * @param {string} ns - Namespace * @param {number} priority diff --git a/src/workspace.ts b/src/workspace.ts index 61d9adf60d6..7167fed20d7 100644 --- a/src/workspace.ts +++ b/src/workspace.ts @@ -1,5 +1,5 @@ 'use strict' -import { Neovim } from '@chemzqm/neovim' +import { Neovim } from './neovim' import type { DocumentSelector, WorkspaceFoldersChangeEvent } from 'vscode-languageserver-protocol' import { TextDocument } from 'vscode-languageserver-textdocument' import { CreateFileOptions, DeleteFileOptions, FormattingOptions, Location, LocationLink, Position, Range, RenameFileOptions, WorkspaceEdit, WorkspaceFolder } from 'vscode-languageserver-types'