皆さんはVSCodeを使用していますでしょうか。 私は普段Vim(Neovim)ですが、誰かと共通の何かを作成するときはVSCodeを使用しています。 また、初心者の方に何かを教えるときは同じエディタを使わないと伝わりが良くないので、みんなが使ってるエディタを勧めることが多く、その上教える際も初心者に方にはこのボタンを押してみましょうみたいに教えるのでこうなってしまいますね。
そして、画面共有をしながらプログラミングして見せたりするのにコーディングをするわけですが、残念ながらVSCodeはそのままだと使い物になりません。 とはいえNeovimの拡張機能を入れてinit.luaを共通で使うというのもあんまりしたくありませんので、私はVSCodeの設定を別で管理することにしています。 今回はよく使う機能をショートカットに設定して、vimっぽく使おうということでお話していきます。
拡張機能を入れる
まずは拡張機能のvimを入れます。これがないと始まりません。
これでキーバインドがVimになって使いやすくなるのですが、これだけだと悲しい事件が起きてしまいます。 なので色々設定していきましょう。
設定 (settings.json)
まず、settings.jsonを開いて以下の設定を入れます。 leaderの設定とクリップボード共有の設定は入れておくといいでしょう。 また、Cursorにあるようなインラインなチャット入力の呼び出しもここで設定できます。(GitHub Copilot) (書き換えてDiffとってAcceptしたら書き換えてくれるやつのこと)
Macではこれを設定しなくてもCommand + iで呼べますが、Ubuntuの場合は設定しないとショートカットに割り当てられていません。今回は<C-i>に割り当てています。 他にもundoとredoもvscode由来のものを使用するように変更しています。これをしないとundo/redoしただけなのに未保存扱いになってしまい面倒です。 他にも色々書いていますが、興味があればKeyboard Shortcutsを開いてcommandsの部分を検索してみるとなんのことか解ると思います。
以下設定例です。
"vim.useSystemClipboard": true, "vim.hlsearch": true, "vim.incsearch": true, "vim.leader": ",", "vim.useCtrlKeys": true, // normal mode "vim.normalModeKeyBindingsNonRecursive": [ { "before": [ "<C-i>" ], // CopilotChat inline editor "commands": [ "interactiveEditor.start" ] },{ "before": [ "<leader>", "c" ], // CopilotChat "commands": [ "workbench.panel.chat.view.copilot.focus" ] },{ "before": [ "<leader>", "e" ], // open explorer "commands": [ "workbench.view.explorer" ] },{ "before": [ "<leader>", "u" ], // timeline "commands": [ "timeline.focus" ] },{ "before": [ "<leader>", "s", ], // find in files "commands": [ "workbench.action.findInFiles" ] },{ "before": [ "<leader>", "g", ], // open source control "commands": [ "workbench.view.scm" ] },{ "before": [ "<leader>", " ", ], // search highlight "commands": [ ":noh" ] },{ "before": [ "u", ], "commands": [ "undo" ] },{ "before": [ "<C-r>", ], "commands": [ "redo" ] },{ "before": [ "<leader>", "r", ], // search and replace "commands": [ "editor.action.startFindReplaceAction" ] },{ "before": [ "<leader>", "d", ], // git diff on current file "commands": [ "git.openChange" ] },{ "before": [ "<leader>", "f", ], // format document "commands": [ "editor.action.formatDocument" ] },{ "before": [ "K", ], // definition preview "commands": [ "editor.action.showDefinitionPreviewHover" ] },{ "before": [ "<C-t>", ], // jump to definition "commands": [ "editor.action.revealDefinition" ] } ], // visual mode "vim.visualModeKeyBindingsNonRecursive": [ { "before": [ "<C-i>" ], // CopilotChat inline editor "commands": [ "interactiveEditor.start" ] },{ "before": [ "<leader>", "c" ], // CopilotChat inline editor "commands": [ "workbench.panel.chat.view.copilot.focus" ] },{ "before": [ "<leader>", "e" ], // open explorer "commands": [ "workbench.view.explorer" ] },{ "before": [ "<leader>", "u" ], // timeline "commands": [ "timeline.focus" ] },{ "before": [ ">", ], "commands": [ "editor.action.indentLines" ] },{ "before": [ "<", ], "commands": [ "editor.action.outdentLines" ] } ], // insert mode "vim.insertModeKeyBindingsNonRecursive": [ { "before": [ "<C-i>" ], // CopilotChat inline editor "commands": [ "interactiveEditor.start" ] },{ "before": [ "<C-j>" ], // Copilot suggestion(next) "commands": [ "editor.action.inlineSuggest.showNext" ] },{ "before": [ "<C-k>" ], // Copilot suggestion(previous) "commands": [ "editor.action.inlineSuggest.showPrevious" ] } ],
あとはショートカットの設定を別途好みのものにすれば良いと思います。 これで結構使える感じになるのではないでしょうか。
おすすめの設定
ファイル名検索
開いているフォルダの中のファイルからファイル名検索
},{ "before": [ "<leader>", "s", "f", ], "commands": [ "workbench.action.quickOpen" ] },{
grep
開いているフォルダの中のファイルの中身をgrep
},{ "before": [ "<leader>", "g", "r", ], "commands": [ "workbench.action.findInFiles" ] },{
検索ハイライトを解除
},{ "before": [ "<leader>", " ", ], "commands": [ ":noh" ] },{
開いているバッファを表示(の代わり)
拡張機能のvimで:buffersをしようとするとPRヨロと言われるのでとりあえずこれで代用
},{ "before": [ "<leader>", "l", "s", ], "commands": [ "workbench.files.action.focusOpenEditorsView" ] },{
コメントイン/アウト
コレがないと生きられない
},{ "before": [ "g", "c", "c", ], commands": [ "editor.action.commentLine" ] },{
quick fix(Copilot)
次のエラーに飛んでインラインチャットでエラーメッセージを拾う
"before": [ "<leader>", "q", "f", ], "commands": [ "editor.action.marker.nextInFiles", "interactiveEditor.start", ]
ショートカット設定(keybindings.json)
併せてこちらも設定しておくといい感じになります。
Enterをctrl+m
、ESCをctrl+[
で出来るようにする
{ "key": "ctrl+m", "command": "type", "args": { "text": "\n" }, "when": "editorTextFocus" }, { "key": "ctrl+[", "command": "extension.vim_escape", },
Buffresの代わりに開いたOPEN EDITORS
の選択したファイルを閉じる
{ "key": "alt+x", "command": "workbench.action.closeActiveEditor" },
nvim-treeみたいにファイルの作成や削除をキー入力で出来るようにする(Explorerにフォーカスしているとき)
// create new file { "key": "a", "command": "explorer.newFile", "when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus" }, // create new dir { "key": "shift+a", "command": "explorer.newFolder", "when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus" }, // rename { "key": "r", "command": "renameFile", "when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus" }, // open with vertical split window { "key": "ctrl+v", "command": "explorer.openToSide", "when": "explorerViewletFocus && foldersViewVisible && !inputFocus" }, // delete file { "key": "d", "command": "moveFileToTrash", "when": "explorerResourceMoveableToTrash && filesExplorerFocus && foldersViewVisible && !explorerResourceReadonly && !inputFocus" },
ちなみに
NeovimでCopilotChat使いたいんだがって方はこちらを参照してください。
環境によっては「copilot.luaとか見つからないんだが?」って怒られる方もいると思います。
その場合はcopilot.luaとplugin.luaのimport os
の直下に
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
を追記すると使えるようになります。 copolot.luaとplugin.luaは
~/.local/share/nvim/lazy/CopilotChat.nvim/rplugin/python3
にあると思います。
また、根本解決したい場合は以下を実行するとよいです。
pip install pynvim==0.5.0
余談ですがnvimでcopilot chatを使用したquick fix(っぽいこと)をしたい場合はこんな感じになります。
local function quick_fix_next_error_with_ai() if vim.diagnostic.get(0, {severity = vim.diagnostic.severity.ERROR})[1] == nil then print("no error") return end -- jump to next error/warn vim.diagnostic.goto_next({severity = vim.diagnostic.severity.ERROR}) -- fix with Copilot -- copy diagnostic message and current line local diagnostic_message = vim.diagnostic.get(0, {severity = vim.diagnostic.severity.ERROR})[1].message local current_line_text = vim.api.nvim_get_current_line() -- open Copilot chat window vim.cmd("vertical rightbelow new") vim.cmd("setlocal filetype=markdown") vim.cmd("CopilotChat ".. "error message : " .. diagnostic_message .. " | current line text : " .. current_line_text .. " | your job : how to fix it?") end vim.keymap.set("n", "<leader>xn", vim.diagnostic.goto_next, {desc="Jump to Next Error/Warn"}) vim.keymap.set("n", "<leader>qf", quick_fix_next_error_with_ai, {desc="Jump to Next Error and fix with Copilot Chat"})