HippoBlog
Web開発に関する備忘録や
日々の雑記ブログ
  • #swift
  • 2023年12月3日
ENTRY TITLE

Xcode で VSCode のキーバインドを再現したい

TEXT BY @hippohack@hippohack
TEXT BY @hippohack@hippohack
  • このエントリーをはてなブックマークに追加

最近 iOSアプリを作りたくて Xcode を触り始めたのですが、キーバインドが辛いです。
辛いというのはこれまでずっと VSCode でコードを書いていましたので差がありすぎてやりたいことが全然できずに困っていました。
そもそも、VSCode で開発する方法もさぐってみたのですが自分が辿り着けていないだけかもしれません結果的にうまくいきませんでした。

この記事では、Xcode のキーバインドが辛いのでなるべく VSCode に寄せる設定を加えた際にやったことを残します。

設定方法

基本的にはこちらの Gist を参考にさせていただいてますので省略します。

躓いたこと

/Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Versions/A/Resources/IDETextKeyBindingSet.plist がロックされていて更新できませんでした。

結果的に、設定アプリの「プライバシーとセキュリティ」の「アプリ管理」からターミナルに権限を付与して、nano で編集して更新ができました。

sudo nano /Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Versions/A/Resources/IDETextKeyBindingSet.plist

Key Bindings Set を選択する

キャプチャだけですみません。

Delete Line は、cmd + x にしたい

これはひょっとすると自分の認識がずれているだけかもしれないのですが、行削除(厳密にはカット&コピー)は、ctrl + x ではなく cmd + x にしたいと思っていたので ChatGPT さんにご教授いただいて以下のように変更しました。

            <key>@x</key>
            <string>deleteLine:</string>

こちらに関しては、変更してはみましたが実際の挙動は思っているものにはなっていないことに後から気づきました。
本来は前述した通り、カーソルが当たっている行 or 選択状態のものをカット&コピーして欲しかったのですが、実際は選択状態のものをカットするのみという挙動をしています。
ここは改善ポイントです。もし良い方法あれば教えて欲しいです🙇‍♂️

最終的な VSCode.idekeybindings の XML

/Users/benzoh/Library/Developer/Xcode/UserData/KeyBindings/VSCode.idekeybindings

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Menu Key Bindings</key>
    <dict>
        <key>Key Bindings</key>
        <array>
            <dict>
                <key>Action</key>
                <string>cut:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandID</key>
                <string>Xcode.IDEKit.CmdDefinition.Cut</string>
                <key>Group</key>
                <string>Edit Menu</string>
                <key>GroupID</key>
                <string>Xcode.IDEKit.MenuDefinition.Main</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string>^x</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Title</key>
                <string>Cut</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>duplicate:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandID</key>
                <string>Xcode.IDEKit.CmdDefinition.Duplicate</string>
                <key>Group</key>
                <string>Edit Menu</string>
                <key>GroupID</key>
                <string>Xcode.IDEKit.MenuDefinition.Main</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string>~$</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Title</key>
                <string>Duplicate</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>openQuickly:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandID</key>
                <string>Xcode.IDEKit.CmdDefinition.OpenQuickly</string>
                <key>Group</key>
                <string>File Menu</string>
                <key>GroupID</key>
                <string>Xcode.IDEKit.MenuDefinition.Main</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string>@p</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Title</key>
                <string>Open Quickly…</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>runPageLayout:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandID</key>
                <string>Xcode.IDEKit.CmdDefinition.PageSetup</string>
                <key>Group</key>
                <string>File Menu</string>
                <key>GroupID</key>
                <string>Xcode.IDEKit.MenuDefinition.Main</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Title</key>
                <string>Page Setup…</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>printDocument:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandID</key>
                <string>Xcode.IDEKit.CmdDefinition.Print</string>
                <key>Group</key>
                <string>File Menu</string>
                <key>GroupID</key>
                <string>Xcode.IDEKit.MenuDefinition.Main</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Title</key>
                <string>Print…</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>showDocumentItemsMenu:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandID</key>
                <string>Xcode.IDEKit.CmdDefinition.ShowDocumentItemsMenu</string>
                <key>Group</key>
                <string>View Menu</string>
                <key>GroupID</key>
                <string>Xcode.IDEKit.MenuDefinition.Main</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string>$@O</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Editor</string>
                <key>Title</key>
                <string>Show Document Items</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>toggleBreakpointAtCurrentLine:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandID</key>
                <string>Xcode.IDEKit.CmdDefinition.ToggleBreakpointAtCurrentLine</string>
                <key>Group</key>
                <string>Debug Menu</string>
                <key>GroupID</key>
                <string>Xcode.IDEKit.MenuDefinition.Main</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string></string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Breakpoints</string>
                <key>Title</key>
                <string>Create Breakpoint at Current Line</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>moveCurrentLineDown:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandGroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineDown</string>
                <key>CommandID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineDown</string>
                <key>Group</key>
                <string>Editor Menu for Asset Catalog Comparison</string>
                <key>GroupID</key>
                <string>Xcode.DeltaComparisonEditor.MenuDefinition.Editor</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string>~</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Structure</string>
                <key>Title</key>
                <string>Move Line Down</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>moveCurrentLineDown:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandGroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineDown</string>
                <key>CommandID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineDown</string>
                <key>Group</key>
                <string>Editor Menu for Playground</string>
                <key>GroupID</key>
                <string>Xcode.IDEPlaygroundEditor.MenuDefinition.Editor</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string>~</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Structure</string>
                <key>Title</key>
                <string>Move Line Down</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>moveCurrentLineDown:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandGroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineDown</string>
                <key>CommandID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineDown</string>
                <key>Group</key>
                <string>Editor Menu for Source Code</string>
                <key>GroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.MenuDefinition.Editor</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string>~</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Structure</string>
                <key>Title</key>
                <string>Move Line Down</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>moveCurrentLineUp:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandGroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineUp</string>
                <key>CommandID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineUp</string>
                <key>Group</key>
                <string>Editor Menu for Asset Catalog Comparison</string>
                <key>GroupID</key>
                <string>Xcode.DeltaComparisonEditor.MenuDefinition.Editor</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string>~</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Structure</string>
                <key>Title</key>
                <string>Move Line Up</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>moveCurrentLineUp:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandGroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineUp</string>
                <key>CommandID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineUp</string>
                <key>Group</key>
                <string>Editor Menu for Playground</string>
                <key>GroupID</key>
                <string>Xcode.IDEPlaygroundEditor.MenuDefinition.Editor</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string>~</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Structure</string>
                <key>Title</key>
                <string>Move Line Up</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>moveCurrentLineUp:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandGroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineUp</string>
                <key>CommandID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.MoveLineUp</string>
                <key>Group</key>
                <string>Editor Menu for Source Code</string>
                <key>GroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.MenuDefinition.Editor</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string>~</string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Structure</string>
                <key>Title</key>
                <string>Move Line Up</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>renameRefactor:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandGroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.Refactor.Rename</string>
                <key>CommandID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.Refactor.Rename</string>
                <key>Group</key>
                <string>Editor Menu for Asset Catalog Comparison</string>
                <key>GroupID</key>
                <string>Xcode.DeltaComparisonEditor.MenuDefinition.Editor</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string></string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Refactor</string>
                <key>Title</key>
                <string>Rename…</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>renameRefactor:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandGroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.Refactor.Rename</string>
                <key>CommandID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.Refactor.Rename</string>
                <key>Group</key>
                <string>Editor Menu for Playground</string>
                <key>GroupID</key>
                <string>Xcode.IDEPlaygroundEditor.MenuDefinition.Editor</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string></string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Refactor</string>
                <key>Title</key>
                <string>Rename…</string>
            </dict>
            <dict>
                <key>Action</key>
                <string>renameRefactor:</string>
                <key>Alternate</key>
                <string>NO</string>
                <key>CommandGroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.Refactor.Rename</string>
                <key>CommandID</key>
                <string>Xcode.IDEPegasusSourceEditor.CmdDefinition.Refactor.Rename</string>
                <key>Group</key>
                <string>Editor Menu for Source Code</string>
                <key>GroupID</key>
                <string>Xcode.IDEPegasusSourceEditor.MenuDefinition.Editor</string>
                <key>GroupedAlternate</key>
                <string>NO</string>
                <key>Keyboard Shortcut</key>
                <string></string>
                <key>Navigation</key>
                <string>NO</string>
                <key>Parent Title</key>
                <string>Refactor</string>
                <key>Title</key>
                <string>Rename…</string>
            </dict>
        </array>
        <key>Version</key>
        <integer>3</integer>
    </dict>
    <key>Text Key Bindings</key>
    <dict>
        <key>Key Bindings</key>
        <dict>
            <key></key>
            <array>
                <string>moveParagraphBackwardAndModifySelection:</string>
                <string>moveParagraphForwardAndModifySelection:</string>
                <array>
                    <string>moveBackward:</string>
                    <string>moveToBeginningOfParagraph:</string>
                </array>
                <array>
                    <string>moveForward:</string>
                    <string>moveToEndOfParagraph:</string>
                </array>
                <string>selectToMark:</string>
                <string>swapWithMark:</string>
                <string>scrollToBeginningOfDocument:</string>
                <string>scrollToEndOfDocument:</string>
            </array>
            <key>@x</key>
            <string>deleteLine:</string>
            <key></key>
            <string>deleteForward:</string>
        </dict>
        <key>Version</key>
        <integer>3</integer>
    </dict>
</dict>
</plist>

追加で cmd + d

この方のおっしゃることにも完全に同意しましたので。同一テキストの複数選択を可能にする cmd + d を追加しました。
こちらは画面上から設定しました。

参考リンク


最後までお読みいただき、ありがとうございました。

ご意見などありましたら@hippohackへDMをお願いいたします。

  • このエントリーをはてなブックマークに追加