🐡

coc.nvimでフローティングウインドウを作るよりluaを使ったほうが簡単そう

に公開

coc.nvimの機能を使ってフローティングウインドウを作るよりluaを使ったほうが簡単に欲しい機能が追加できると思った話。

-- フローティングウィンドウの作成とキーマップの設定
local function create_float_window()
  -- ウィンドウの内容
  local content = {
    "Neovim ネイティブフローティングウィンドウ",
    "------------------------------",
    "q: ウィンドウを閉じる",
    "r: 内容をリロード",
    "o: アクションを実行",
    "",
    "Neovimのネイティブ機能だけで作成されています"
  }

  -- バッファを作成
  local buf = vim.api.nvim_create_buf(false, true)

  -- バッファに内容を設定
  vim.api.nvim_buf_set_lines(buf, 0, -1, false, content)

  -- ウィンドウの幅と高さを計算
  local width = 60
  local height = #content

  -- エディタの中央に配置するための位置を計算
  local ui = vim.api.nvim_list_uis()[1]
  local row = math.floor((ui.height - height) / 2 - 1)
  local col = math.floor((ui.width - width) / 2)

  -- ウィンドウオプション
  local opts = {
    relative = "editor",
    width = width,
    height = height,
    row = row,
    col = col,
    style = "minimal",
    border = "rounded",
    title = "サンプルウィンドウ",
    title_pos = "center"
  }

  -- ウィンドウを作成
  local win = vim.api.nvim_open_win(buf, true, opts)

  -- ウィンドウのハイライト設定
  vim.api.nvim_win_set_option(win, "winhl", "Normal:FloatBorder")

  -- 現在のバッファのみにキーマップを設定
  vim.api.nvim_buf_set_keymap(buf, 'n', 'q',
    ':lua vim.api.nvim_win_close(' .. win .. ', true)<CR>',
    {silent = true, noremap = true}
  )

  -- rキーで内容をリロード
  vim.api.nvim_buf_set_keymap(buf, 'n', 'r',
    ':lua reload_float_content(' .. buf .. ')<CR>',
    {silent = true, noremap = true}
  )

  -- oキーでアクション実行
  vim.api.nvim_buf_set_keymap(buf, 'n', 'o',
    ':lua execute_action()<CR>',
    {silent = true, noremap = true}
  )

  -- ウィンドウを離れたときに自動的に閉じる(オプション)
  vim.api.nvim_command('autocmd WinLeave <buffer=' .. buf .. '> lua vim.api.nvim_win_close(' .. win .. ', true)')

  return buf, win
end

-- 内容をリロードする関数
function reload_float_content(buf)
  local new_content = {
    "リロードされた内容",
    "------------------------------",
    "q: ウィンドウを閉じる",
    "r: 内容をリロード",
    "o: アクションを実行",
    "",
    "内容がリロードされました!"
  }

  vim.api.nvim_buf_set_lines(buf, 0, -1, false, new_content)
  print("内容をリロードしました")
end

-- アクションを実行する関数
function execute_action()
  print("アクションが実行されました")
  -- ここに実際のアクションコードを記述
end

-- コマンドを登録
vim.api.nvim_create_user_command(
  'FloatWindow',
  function()
    create_float_window()
  end,
  {}
)

フロートウインドウをluaで作成し、coc.nvimで実行できるみたい。

// TypeScript (coc.nvim plugin)
import { workspace } from 'coc.nvim';

export async function activate(context: ExtensionContext): Promise<void> {
  context.subscriptions.push(
    workspace.registerCommand('example.callLuaFunction', async () => {
      const nvim = workspace.nvim;

      // Lua関数を呼び出す
      const result = await nvim.call('luaeval', ['require("my_module").create_float_window()']);

      // 結果を処理
      workspace.showMessage(`Luaから返された結果: ${result}`);
    })
  );
}

結局作らなかった。

理由はluaで書き直したほうが、UI周りが好きなように設定できそうだと感じたから。

nodejsのエコシステムを使えるのはすごい利点だけど。
coc.nvimはUIまわりを作るのが面倒だと感じた。

フローティングウインドウを自作しCocの低レベルAPIを使えばなんとかなると回答されたけど。
うーん...。

そこで結局luaで書き直しすることにした。

なにかの参考になるのかな。
一応共有

Discussion