🇯🇵

Neovimプラグイン開発: snacks.nvimのpickerでskkeleton日本語入力を可能にする

2025/03/08に公開

snacks.nvimのpickerで日本語入力できるようにするプラグインを作った

はじめに

SKKは最高です。私はPC内の全ての入力でSKKを利用しています。
(SKKについては、↓のtoriwasaさんの記事が詳しいです。 私もSKK入門しようか悩んだ時に参考にさせていただきました)

https://zenn.dev/toriwasa/articles/946af5939093dc

エディタはNeovim愛用しているのですが、例に漏れず、skkeletonというSKK実装のプラグインを使っています。

最近、snacks.nvimというファインダー系のプラグインを使い始めたのですが、検索ウィンドウでSKKの日本語入力モードが起動できないという問題がありました。

検索ウィンドウでSKKが利用できない

良い機会だと思い、AIの恩恵を最大限受けつつ、今回始めて自分でプラグインを作ってみることにしました。

https://github.com/urugus/skkeleton-snacks

この記事では、自作したskkeleton-snacksプラグインについて紹介したいと思います。

問題の背景

snacks.nvimとは

snacks.nvimは、Neovimのための多機能ユーティリティプラグインです。ファイル検索、コマンド実行、ダッシュボード表示など、様々な機能を提供しています。特にpicker機能は、ファイル検索やgrepなどを行うための強力なインターフェースを提供します。

skkeletonとは

skkeletonは、Neovimで動作するSKK(Simple Kana to Kanji conversion program)の実装です。日本語入力をするための効率的な方法を提供します。

問題点

snacks.nvimのpickerは、通常のNeovimのバッファとは異なる特殊なフローティングウィンドウを使用しています。このウィンドウでは、skkeletonによる日本語入力が正常に機能しません。

具体的には、以下のような問題がありました:

  1. pickerのinputウィンドウでskkeletonのトグルキー(<C-j>)が機能しない
  2. skkeletonの設定がpickerのウィンドウに適用されない

解決策:skkeleton-snacksプラグイン

この問題を解決するために、skkeleton-snacksというプラグインを開発しました。

検索ウィンドウでSKKが利用できる

プラグインの基本的な仕組み

このプラグインは、以下の方法で問題を解決します:

  1. snacks.nvimのpickerのフローティングウィンドウを検出する
  2. 検出したウィンドウのバッファに対して、skkeletonを有効にする設定を適用する
  3. バッファローカルなキーマッピングを設定して、skkeletonのトグルキーを機能させる

実装の詳細

プラグインの核となる部分は、フローティングウィンドウを検出して、そのウィンドウでskkeletonを有効にする処理です。

-- snacks の picker の input ウィンドウが開かれたときに実行される関数
local function enable_skkeleton_in_snacks()
  -- バッファのタイプやウィンドウの特性を確認
  local buf = vim.api.nvim_get_current_buf()
  local win = vim.api.nvim_get_current_win()

  -- snacks の picker の input ウィンドウかどうかを確認
  -- ウィンドウの名前や特性で判断
  local win_config = vim.api.nvim_win_get_config(win)
  if win_config.relative ~= "" then -- フローティングウィンドウの場合
    -- skkeleton プラグインが利用可能かどうかを確認
    local has_skkeleton = pcall(function() return vim.fn["skkeleton#is_enabled"] end)
    if not has_skkeleton then
      if M.config.debug then
        vim.notify("skkeleton is not available, skipping", vim.log.levels.DEBUG)
      end
      return
    end

    -- バッファローカルなキーマッピングを設定
    vim.api.nvim_buf_set_keymap(buf, "i", M.config.toggle_key, "<Plug>(skkeleton-toggle)", { silent = true, noremap = false })

    -- skkeleton を有効にする
    vim.b[buf].skkeleton = true

    -- デバッグ用のメッセージ
    if M.config.debug then
      vim.notify("skkeleton enabled in snacks picker", vim.log.levels.INFO)
    end
  end
end

この関数を、以下のイベントで実行するように設定しています:

-- WinEnter イベントで自動コマンドを設定
vim.api.nvim_create_autocmd("WinEnter", {
  group = group,
  callback = enable_skkeleton_in_snacks,
})

-- BufEnter イベントでも自動コマンドを設定
vim.api.nvim_create_autocmd("BufEnter", {
  group = group,
  callback = enable_skkeleton_in_snacks,
})

-- 特にフローティングウィンドウが作成されたときのイベント
vim.api.nvim_create_autocmd("WinNew", {
  group = group,
  callback = function()
    -- 少し遅延させて実行
    vim.defer_fn(enable_skkeleton_in_snacks, 10)
  end,
})

開発中に遭遇した問題と解決策

問題1: プラグインの読み込み順序

最初の実装では、プラグインの初期化時に依存関係(skkeleton、snacks.nvim)をチェックしていました。しかし、プラグインマネージャー(lazy.nvim)の読み込み順序によっては、依存プラグインが読み込まれる前にskkeleton-snacksが初期化されることがありました。

これにより、「skkeleton is not available」というエラーが表示されることがありました。

解決策1: 遅延初期化と動的チェック

この問題を解決するために、以下の変更を行いました:

  1. プラグインの読み込みを遅延させる(event = "VeryLazy"
  2. 依存関係のチェックを初期化時ではなく、実際に機能が必要になったときに行う
  3. エラーメッセージの代わりに静かにスキップする処理に変更

問題2: キーマッピングの競合

最初の実装では、pickerのinputウィンドウで<C-j>キーを押すと、pickerが閉じられてしまう問題がありました。これは、snacks.nvimの既存のキーマッピングと競合していたためです。

解決策2: バッファローカルなキーマッピング

この問題を解決するために、バッファローカルなキーマッピングを使用しました。これにより、特定のバッファ(pickerのinputウィンドウ)でのみキーマッピングが有効になり、他のキーマッピングと競合しなくなりました。

プラグインについて

インストール方法は README をご確認ください。
https://github.com/urugus/skkeleton-snacks

まとめ

skkeleton-snacksプラグインを作成することで、snacks.nvimのpickerでもskkeleton日本語入力を使用できるようになりました。これにより、Neovimでの日本語環境がより快適になりました。
同じ悩みを抱えている方の役に立てれば嬉しいです。

Discussion