VSCode May 2020 (version 1.46) に Selection Anchor が導入されたので xyzzy 風のリージョン操作ができるようにした

VSCode が May 2020 (version 1.46) にアップデートされる前は拡張機能 Emacs Friendly Keymap を導入して Emacs 風のキーバインドを使っていたが、次の点が不満だった。

  • C-SPC でマークをセットしたあと、リージョンの終わりに検索でカーソルを移動できない
  • 別の拡張機能 Clipboard History に kill-ring の内容が反映されない

そこで今回搭載されたキーボードでの選択を補助するための次の機能を使ってこれを改善した。また、クリップボード履歴の拡張機能を Multiple Clipboards for VSCode に変更した。

  • Set Selection Anchor (Ctrl+K Ctrl+B)
  • Select From Anchor to Cursor (Ctrl+K Ctrl+K)
  • Cancel Selection Anchor (Escape)
  • Go to Selection Anchor

この動作をするためには拡張機能 multi-command が必要。これは一つのキーバインドで複数のコマンドを実行するためのものだ。

設定内容

  • C-Space (set-mark-command) 相当
    • カーソル位置にアンカーを設定する
  • M-w (copy-region-as-kill) 相当
    • アンカーからカーソル位置までを選択し、クリップボードにコピーする
    • コピー後は選択を解除する
    • アンカーを設定せずにこのコマンドを実行すると、カーソル位置の行をコピーする(editor.emptySelectionClipboard がオンの場合)
  • C-w (kill-region) 相当
    • アンカーからカーソル位置までを選択し、クリップボードにカットする
    • アンカーを設定せずにこのコマンドを実行すると、カーソル位置の行をカットする(editor.emptySelectionClipboard がオンの場合)
  • C-y (yank) 相当
  • C-c C-y
    • Clipboard History から貼り付け

settings.json

    "multiCommand.commands": [
        {
            "command": "emacs.copy-region",
            "sequence": [
                "editor.action.selectFromAnchorToCursor",
                "multiclip.copy",
                "cancelSelection"
            ]
        },
        {
            "command": "emacs.kill-region",
            "sequence": [
                "editor.action.selectFromAnchorToCursor",
                "multiclip.cut"
            ]
        },
        {
            "command": "emacs.paste",
            "sequence": ["editor.action.clipboardPasteAction"]
        },
        {
            "command": "emacs.expand-selection",
            "sequence": [
                "editor.action.cancelSelectionAnchor",
                "editor.action.smartSelect.expand"
            ]
        }
    ],

keybindings.json

	{
		"key": "ctrl+space",
		"command": "editor.action.setSelectionAnchor",
		"when": "editorTextFocus"
	},
	{
		"key": "alt+w",
		"command": "emacs.copy-region",
		"when": "editorTextFocus"
	},
	{
		"key": "ctrl+w",
		"command": "emacs.kill-region",
		"when": "editorTextFocus"
	},
	{
		"key": "ctrl+y",
		"command": "emacs.paste",
		"when": "editorTextFocus && !editorReadonly"
	},
	{
		"key": "ctrl+c ctrl+y",
		"command": "multiclip.list",
		"when": "editorTextFocus && !editorReadonly"
	},