cursor_open.nvim - Neovimから Cursor を起動するプラグインの紹介
cursor_open.nvim - Neovimから Cursor を起動するプラグインの紹介
はじめに
Neovimを開発でもよく使っているのですが、最近はCursorがかなり便利でよく使っています。
コーディングやドキュメント編集はメインのNeovimで行いつつ、CursorのAI機能周りを併用したいと言う気持ちでneovimからcursorを開けるコマンドを作成しました。
cursor_open.nvim
cursor_open.nvim というプラグインを作成しました。同じ悩みを持つvimmerの方などに使ってもらえると嬉しいです(;p;)!
主な機能
- 現在編集中のファイルをCursorで開く
- Gitリポジトリを検出して、ルートとして開く機能
- 既存のCursorウィンドウを再利用するか新規ウィンドウで開くかを選択可能
インストール方法
packer.nvim を使用する場合
use 'yuucu/cursor_open.nvim'
lazy.nvim を使用する場合
{
'yuucu/cursor_open.nvim',
cmd = { 'CursorOpen' },
keys = {
{ '<leader>oc', ':CursorOpen<CR>', desc = '[O]pen in [C]ursor' },
{ '<leader>oC', ':CursorOpen!<CR>', desc = '[O]pen in [C]ursor (new window)' },
},
config = function()
require('cursor_open').setup()
end
}
実際の風景
実装したもの
- 現在編集中のファイルをCursorで開くコマンド
- Gitリポジトリのルートを検出し、適切なワークスペースで開く機能
- 既存のCursorウィンドウを再利用するオプション
- 新しいウィンドウで強制的に開くオプション
実装
以下が実装したプラグインのコードです。
local M = {}
-- デフォルト設定
local defaults = {
keymaps = {
open = '<leader>oc',
open_new = '<leader>oC',
},
}
-- 設定
local config = {}
-- Git リポジトリルートを取得する関数
local function get_git_root(path)
local result = vim.fn.system('git -C ' .. vim.fn.shellescape(path) .. ' rev-parse --show-toplevel 2>/dev/null')
if vim.v.shell_error ~= 0 then
return nil
end
return result:gsub('\n', '')
end
-- 現在のファイルを Cursor で開く
local function open_in_cursor(opts)
opts = opts or {}
local force_new = opts.bang or false
local file_path = vim.fn.expand('%:p')
local line_num = vim.fn.line('.')
local col_num = vim.fn.col('.')
-- Git リポジトリルートを取得(可能な場合)
local git_root = get_git_root(vim.fn.expand('%:p:h'))
local cursor_args = {}
-- フラグの設定
if force_new then
table.insert(cursor_args, '-n') -- 新しいウィンドウを強制
elseif git_root then
-- 強制フラグがない場合は既存のワークスペースを再利用
table.insert(cursor_args, '-r')
end
-- ワークスペースとファイルの設定
if git_root then
table.insert(cursor_args, git_root)
end
-- ファイル位置の指定
table.insert(cursor_args, '-g')
table.insert(cursor_args, string.format('%s:%s:%s', file_path, line_num, col_num))
-- コマンドの実行
local cmd = 'cursor ' .. table.concat(cursor_args, ' ')
local job_id = vim.fn.jobstart(cmd, { detach = true })
if job_id <= 0 then
vim.notify('Cursorの起動に失敗しました', vim.log.levels.ERROR)
end
end
-- プラグインの初期化
function M.setup(opts)
-- デフォルト設定とユーザー設定のマージ
config = vim.tbl_deep_extend('force', defaults, opts or {})
-- CursorOpen コマンドの作成
vim.api.nvim_create_user_command('CursorOpen', function(cmd_opts)
open_in_cursor({ bang = cmd_opts.bang })
end, { bang = true })
-- キーマッピングの設定
if config.keymaps.open then
vim.keymap.set('n', config.keymaps.open, ':CursorOpen<CR>',
{ desc = '[O]pen in [C]ursor', noremap = true, silent = true })
end
if config.keymaps.open_new then
vim.keymap.set('n', config.keymaps.open_new, ':CursorOpen!<CR>',
{ desc = '[O]pen in [C]ursor (new window)', noremap = true, silent = true })
end
end
return M
実装の解説
Gitリポジトリの検出
local function get_git_root(path)
local result = vim.fn.system('git -C ' .. vim.fn.shellescape(path) .. ' rev-parse --show-toplevel 2>/dev/null')
if vim.v.shell_error ~= 0 then
return nil
end
return result:gsub('\n', '')
end
この関数は指定されたパスに対してGitリポジトリのルートディレクトリを検出します。リポジトリが見つからない場合はnil
を返します。
Cursorを開く機能
open_in_cursor
関数は、Neovimで開いているファイルをCursorで開くための中核機能です。いくつかの部分に分けて見ていきます。
1. カーソル位置情報の取得
local function open_in_cursor(opts)
opts = opts or {}
local force_new = opts.bang or false
local file_path = vim.fn.expand('%:p') -- 現在のファイルの絶対パス
local line_num = vim.fn.line('.') -- 現在のカーソル行
local col_num = vim.fn.col('.') -- 現在のカーソル列
-- Git リポジトリルートを取得
local git_root = get_git_root(vim.fn.expand('%:p:h'))
local cursor_args = {}
現在編集中のファイルのパスとカーソル位置を取得します。また、そのファイルが存在するディレクトリのGitリポジトリルートも検出します。
2. コマンド引数の構築
-- ウィンドウモードの設定
if force_new then
table.insert(cursor_args, '-n') -- 新しいウィンドウを強制
elseif git_root then
table.insert(cursor_args, '-r') -- 既存ワークスペースを再利用
end
-- ワークスペースとファイル位置の指定
if git_root then
table.insert(cursor_args, git_root) -- Gitリポジトリをワークスペースとして指定
end
table.insert(cursor_args, '-g')
table.insert(cursor_args, string.format('%s:%s:%s', file_path, line_num, col_num))
ここでは、コマンドライン引数を条件に応じて構築しています。force_new
フラグが設定されていれば新しいウィンドウを開き、Gitリポジトリが見つかった場合はそのルートパスをワークスペースとして指定します。そして、ファイルパスと行・列の位置を指定します。
3. Cursorの起動
-- 非同期でCursorを起動
local cmd = 'cursor ' .. table.concat(cursor_args, ' ')
local job_id = vim.fn.jobstart(cmd, { detach = true })
if job_id <= 0 then
vim.notify('Cursorの起動に失敗しました', vim.log.levels.ERROR)
end
end
最後に、構築したコマンドを vim.fn.jobstart()
を使って非同期に実行します。detach = true
オプションにより、NeovimはCursorの終了を待たずに操作を続けることができます。
仕組み
この機能は以下のように動作します:
- 現在編集中のファイルのパスとカーソル位置を取得
- ファイルが属するGitリポジトリのルートを検出
- コマンドのオプションに応じて適切なCursorの起動引数を構築
-
vim.fn.jobstart()
を使って非同期にCursorを起動
Cursorが起動すると、指定されたファイルが開かれ、Neovimでのカーソルと同じ位置にカーソルが移動します。
まとめ
この実装により、Neovimとの快適な連携が可能になりました...!
neovimを使いつつ、cursorを連携することで開発がより豊かになると思います!
ぜひプラグインをよろしくお願いします。
Discussion