neovim

Neovim node.js 客戶端

CI (node >= 14,Linux/macOS/Windows) 覆蓋率 npm
ci Coverage Badge npm version

對於「遠端外掛」,Nvim 的 Node.js 提供器 需要全域安裝 neovim 套件

npm install -g neovim

或者,對於非外掛目的,neovim 的運作方式與其他 NPM 套件相同。請參閱下方的快速入門範例,您可以立即複製並執行。

neovim 套件提供以下函式

  • attach():主要介面。接受一個進程、socket 或一對寫入/讀取串流,並傳回一個連接到 nvim 進程的 NeovimClient
  • findNvim():嘗試在目前系統上尋找可用的 nvim 二進制檔。
  • 在載入時,neovim 模組會將 console 取代(「猴子修補」)為其 logger 介面,因此 console.log 將呼叫 logger.info,而不是寫入 stdout (這會破壞 stdio RPC 通道)。
    • 若要略過此 console.log 的修補,請將自訂的 logger 傳遞給 attach()
    • 在任何情況下,最佳做法是使用 attach() 傳回的 NeovimClient 中提供的 logger,而不是 console 日誌記錄函式。
  • 設定 $NVIM_NODE_LOG_FILE 環境變數以(也)將日誌寫入檔案。
  • 設定 $ALLOW_CONSOLE 環境變數以(也)將日誌寫入 stdout。這將會破壞任何 (stdio) RPC 通道,因為寫入 stdout 的日誌是無效的 RPC 訊息。

以下是一個完整且可運作的範例。

  1. 在任何目錄中本機安裝 neovim 套件 (即不使用 -g。如果腳本匯入全域安裝的套件,Node 會擲回 ERR_MODULE_NOT_FOUND)。
    npm install neovim
    
  2. 將以下腳本貼到 demo.mjs 檔案中並執行!
    ALLOW_CONSOLE=1 node demo.mjs
    
    • 必須設定 $ALLOW_CONSOLE 環境變數,因為日誌通常不會列印到 stdout。
      • 注意:$ALLOW_CONSOLE 僅用於演示目的。它不能用於遠端外掛或任何 stdio 是 RPC 通道的情況,因為將日誌寫入 stdout 會破壞 RPC 通道。
    • 腳本
    import * as child_process from 'node:child_process'
    import * as assert from 'node:assert'
    import { attach, findNvim } from 'neovim'

    // Find `nvim` on the system and open a channel to it.
    (async function() {
    const found = findNvim({ orderBy: 'desc', minVersion: '0.9.0' })
    console.log(found);
    const nvim_proc = child_process.spawn(found.matches[0].path, ['--clean', '--embed'], {});
    const nvim = attach({ proc: nvim_proc });

    nvim.command('vsp | vsp | vsp');

    const windows = await nvim.windows;
    assert.deepStrictEqual(windows.length, 4);
    assert.ok(windows[0] instanceof nvim.Window);

    nvim.window = windows[2];
    const win = await nvim.window;
    assert.ok(win.id !== windows[0].id);
    assert.deepStrictEqual(win.id, windows[2].id);

    const buf = await nvim.buffer;
    assert.ok(buf instanceof nvim.Buffer);
    const lines = await buf.lines;
    assert.deepStrictEqual(lines, []);

    await buf.replace(['line1', 'line2'], 0);
    const newLines = await buf.lines;
    assert.deepStrictEqual(newLines, ['line1', 'line2']);

    if (nvim_proc.disconnect) {
    nvim_proc.disconnect();
    }
    nvim.quit();
    while (nvim_proc.exitCode === null) {
    await new Promise(resolve => setTimeout(resolve, 100))
    console.log('waiting for Nvim (pid %d) to exit', nvim_proc.pid);
    }
    console.log('Nvim exit code: %d', nvim_proc.exitCode);
    })();

Neovim 支援遠端外掛,這些外掛實作為 Nvim API 客戶端。此套件包含「API 客戶端」(與 nvim 通訊) 和「遠端外掛主機」(探索並執行 Nvim node.js 遠端外掛)。

您可以在 Nvim 的 'runtimepath' 上的 rplugin/node/ 目錄中,將遠端外掛定義為檔案或資料夾。如果外掛是資料夾,則會載入 package.json 中的 main 腳本。

外掛必須匯出一個函式,該函式會將 NvimPlugin 物件作為其唯一參數。然後,您可以透過呼叫 NvimPlugin 物件上的方法來註冊 autocmd、命令和函式。在此階段避免繁重的初始化或非同步函式,因為 Nvim 可能只會收集有關外掛的資訊,而不想實際使用它。相反地,請等待呼叫您的其中一個 autocmd、命令或函式,然後再開始任何處理。

請參閱 examples/ 以取得遠端外掛範例。

  NvimPlugin.nvim

這是您可以從外掛向 nvim 發送命令的 nvim api 物件。

  NvimPlugin.setOptions(options: NvimPluginOptions);

interface NvimPluginOptions {
dev?: boolean;
alwaysInit?: boolean;
}

將您的外掛設定為開發模式,這會導致每次調用時重新載入模組。alwaysInit 將永遠嘗試重新實例化外掛。例如,每次調用外掛的命令時,都會呼叫您的外掛類別。

  NvimPlugin.registerAutocmd(name: string, fn: Function, options: AutocmdOptions): void;
NvimPlugin.registerAutocmd(name: string, fn: [any, Function], options: AutocmdOptions): void;

interface AutocmdOptions {
pattern: string; // See `:help autocmd-pattern`.
eval?: string; // Vimscript expression evaluated by the Nvim peer.
sync?: boolean; // Force blocking (non-async) behavior.
}

使用 options 為事件 name 註冊一個 autocmd,呼叫您的函式 fn。Pattern 是唯一需要的選項。如果您希望在物件上呼叫方法,則可以將 fn 作為 [object, object.method] 的陣列傳遞。

依預設,autocmd、命令和函式都會被視為非同步,且應傳回 Promises (或應為 async 函式)。

  NvimPlugin.registerCommand(name: string, fn: Function, options?: CommandOptions): void;
NvimPlugin.registerCommand(name: string, fn: [any, Function], options?: CommandOptions): void;

interface CommandOptions {
sync?: boolean; // Force blocking (non-async) behavior.
range?: string; // See `:help :range`.
nargs?: string; // See `:help :command-nargs`.
}

使用 options 註冊一個名為 name 的命令,呼叫函式 fn。這將會從在一般模式下輸入 :name 來從 nvim 調用。

  NvimPlugin.registerFunction(name: string, fn: Function, options?: NvimFunctionOptions): void;
NvimPlugin.registerFunction(name: string, fn: [any, Function], options?: NvimFunctionOptions): void;

interface NvimFunctionOptions {
sync?: boolean; // Force blocking (non-async) behavior.
range?: string; // See `:help :range`.
eval?: string; // Vimscript expression evaluated by the Nvim peer.
}

使用 options 註冊一個名為 name 的函式,呼叫函式 fn。這將會從在一般模式下輸入,例如 :call name() 來從 nvim 調用。

為了偵錯和設定記錄,您可以設定以下 neovim 套件(或 nvim 本身,在有註明的情況下)使用的環境變數

  • NVIM_NODE_HOST_DEBUG:使用 --inspect-brk 產生呼叫 neovim-client-host 的 node 進程,以便您可以擁有除錯工具。將其與此Node Inspector Manager Chrome 外掛配對
  • 記錄:記錄是透過 logger 模組使用 winston 完成的。此套件會將 console 取代為此介面。
    • NVIM_NODE_LOG_LEVEL:設定 winston 的記錄層級。預設值為 debug。可用層級:{ error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5 }
    • NVIM_NODE_LOG_FILE:設定記錄檔路徑。
  • 透過 node REPL 使用
    • NVIM_LISTEN_ADDRESS:
      1. 使用已知位址啟動 Nvim (或使用正在執行執行個體的 $NVIM_LISTEN_ADDRESS)
        $ NVIM_LISTEN_ADDRESS=/tmp/nvim nvim
        
      2. 在另一個終端機中,將 node REPL 連接到 Nvim
        // `scripts/nvim` will detect if `NVIM_LISTEN_ADDRESS` is set and use that unix socket
        // Otherwise will create an embedded `nvim` instance
        require('neovim/scripts/nvim').then((nvim) => {
        nvim.command('vsp');
        });

請參閱測試和 scripts 以取得更多範例。

複製儲存庫後,執行 npm install 以安裝開發相依性。主要的 neovim 程式庫位於 packages/neovim 中。

npm run build && NVIM_NODE_LOG_FILE=log npm run test

只有 neovim NPM 套件的維護者才能發布版本。請按照以下步驟發布版本

  1. 更新 CHANGELOG.md
  2. 更新版本。建置並發布套件。標記發布並推送。
    # Choose major/minor/patch as needed.
    npm version --no-git-tag-version patch
    npm version -w packages/neovim/ patch
    git add package*.json packages/neovim/package.json
    git commit -m 'release'
    # Note: this copies the top-level README.md/CHANGELOG.md to packages/neovim/.
    npm run publish:neovim
    export _VERSION=$(grep -o 'version": "[^"]\+' packages/neovim/package.json | sed 's/.*"//')
    git tag "v${_VERSION}"
    git push --tags
    git push
  3. 發布後任務
    • 將存根新增至 CHANGELOG.md
    • 增加版本並提交。
      npm version --no-git-tag-version prerelease --preid dev
      npm version -w packages/neovim/ --no-git-tag-version prerelease --preid dev
      git add package*.json packages/neovim/package.json
      git commit -m bump
      git push

文件網站目前尚未自動化。請按照以下步驟重新產生它

npm run doc -w packages/neovim
git checkout gh-pages
mv -f packages/neovim/doc/assets/* assets/
mv -f packages/neovim/doc/classes/* classes/
mv -f packages/neovim/doc/functions/* functions/
mv -f packages/neovim/doc/types/* types/
mv packages/neovim/doc/* .
rm -r packages/
git add *
git commit -m 'publish docs'
git push origin HEAD:gh-pages