LoginSignup
0

More than 3 years have passed since last update.

システム環境設定にあるキーボードショートカットを設定するJXA

Posted at

2年ぐらい前にポストした「システム環境設定にあるキーボードショートカットを設定するAppleScript」のJXA版です。

OS標準のショートカット設定では、設定をインポート/エクスポートができないため、それを補完する感じでJSONファイルで設定を書いて無理やり取り込むスクリプトです。インポートができれば設定ファイルが残るため、エクスポートは「ええやろ」という考えなのでエクスポートのスクリプトはありません。

High Sierra(10.13.6)で動作確認しています。

使い方

  1. 環境設定 → セキュリティとプライバシー → プライバシー の「アクセシビリティ」で、スクリプトエディタ.appにコンピュータの操作を許可する
  2. JSONファイルをこしらえる(:point_right_tone2: JSONの書き方
  3. :point_right_tone2: 下記のスクリプトを「スクリプトエディタ」にコピペする(言語はJavaScriptを選択してください)
  4. スクリプトエディタのツールバーにある右向きの三角で実行(ショートカット:Cmd + R)すると、ダイアログが表示されるので、こしらえたJSONファイルを選択する
  5. あとは無事終わるまで眺める(スクリプトでGUIを操作しているので、文字通り眺めてください)

「アプリケーション」フォルダ直下にないアプリをJSONのappNameで指定している場合、4でダイアログが表示されるので、appNameと同じアプリを選択してください。

  • スクリプトエディタ.appは、「アプリケーション/ユーティリティ」の中にあります。
  • 「アプリケーション」フォルダは、FinderでCmd + Shift + Aで表示されるフォルダです。

JSONの書き方

次のように記述します。

[
    {
        "appName": "Sketch.app",
        "shortcut": [
            {
                "menu": "Flatten Selection to Bitmap",
                "key": "e",
                "modifier": [ "command", "control", "shift" ]
            }
        ]
    }
]
appName:
アプリケーション名です。アプリケーションフォルダ内の名前を正確に入力してください。
shortcut:
menu:
アプリのメニュー項目を正確に入力してください。同じ項目名が複数ある場合は、親のメニュー項目を「->」でつなぎます。
例:Use Defaultという項目がかぶる場合、Kern->Use DefaultLigature->Use Defaultと入力する。
key:
キーボードで文字が入力できるキーを1文字を小文字で指定してください。例外的に矢印キーは「up」「right」「down」「left」と指定できます。Fキーは要望があれば対応します。
modifier:
Command・Control・Shift・Optionキーを指定します。CommandまたはControlのどちらかは必ず含めてください。

サンプル

スクリプト

"use strict";

var app = Application.currentApplication();
app.includeStandardAdditions = true;

// ローカライズ
var langList = app.doShellScript("defaults read NSGlobalDomain AppleLanguages | awk '{gsub(/[^a-zA-Z-]/,\"\");print}' | grep -v '^$'");
var langs = langList.split('\r');

var chooseJSONLabel = 'Please select a JSON file:';
var shortcutLabel = 'App Shortcuts';
var menuItemLabel = 'Menu Title:';
var addButtonLabel = 'Add';
switch (langs[0].substr(0, 2)) {
    case 'ja':
        chooseJSONLabel = 'JSONファイルを選択してください。';
        shortcutLabel = 'アプリケーション';
        menuItemLabel = 'メニュータイトル:';
        addButtonLabel = '追加';
        break;
}

var appList = app.doShellScript('ls /Applications').split('\r');

// 設定ファイルを読み込んでJSONへパース
var chooseFile = app.chooseFile({
        withPrompt: chooseJSONLabel
    })
var json = JSON.parse(readFile(chooseFile));

// 環境設定を起動してキーボードを選択し、ショートカットタブを表示する
var pref = Application('com.apple.systempreferences');
pref.panes['com.apple.preference.keyboard'].anchors['shortcutsTab'].reveal();
pref.activate();
delay(2);

// 左のリストから「アプリケーション」を選択
var sysEvent = Application('System Events');
var prefKeyboard = sysEvent.processes['System Preferences'].windows[0];
var rows = prefKeyboard.tabGroups[0].splitterGroups[0].scrollAreas[0].tables[0].rows();
var shortcutPosition = 0;
for (let i = 0; i < rows.length; i++) {
    console.log(rows[i].staticTexts[0].name());
    if (shortcutLabel === rows[i].staticTexts[0].name()) {
        shortcutPosition = i;
        break;
    }
}
rows[shortcutPosition].select();

// ショートカットを設定
for (let i = 0; i < json.length; i++) {
    let appName = json[i].appName;
    let appExist = false;
    appList.some(function (obj) {
        if (appName === obj) {
            appExist = true;
            return true;
        }
    });

    let appSelected = false;

    for (let j = 0; j < json[i].shortcut.length; j++) {
        // [+]ボタンをクリックしてダイアログシートを表示
        prefKeyboard.tabGroups[0].groups[0].buttons[0].click();
        let settingSheet = prefKeyboard.sheets[0];

        // アプリケーションを設定
        if (!appSelected) {
            if (appExist) {
                settingSheet.popUpButtons[0].click().menus[0].menuItems[appName].click();
            } else {
                // ポップアップの中にアプリがない場合
                let appListItems = settingSheet.popUpButtons[0].click().menus[0].menuItems.length;
                settingSheet.popUpButtons[0].menus[0].menuItems[appListItems - 1].click();

                // アプリが選択されるまで待つ
                while (!appExist) {
                    if(appName == settingSheet.popUpButtons[0].value()) {
                        appExist = true;
                    } else {
                        delay(2);
                    }
                }
            }
            appSelected = true;
        }

        // メニュー項目を設定
        settingSheet.textFields[menuItemLabel].value = json[i].shortcut[j].menu;

        // タブキーでフォーカスを移動
        sysEvent.keyCode(48);

        // ショートカットキーを設定
        let pressKey;
        switch (json[i].shortcut[j].key) {
            case 'left':
                pressKey = 123;
                break;
            case 'right':
                pressKey = 124;
                break;
            case 'up':
                pressKey = 125;
                break;
            case 'down':
                pressKey = 125;
                break;
            default:
                pressKey = json[i].shortcut[j].key
                break;
        }
        setShortcut(pressKey, json[i].shortcut[j].modifier);

        // 追加ボタンをクリック
        settingSheet.buttons[addButtonLabel].click();
    }
    appSelected = false;
}


// Helpers
function readFile(file) {
    var fileString = file.toString();
    return app.read(Path(fileString));
}

function setShortcut(key, mod) {
    for (var i = 0; i < mod.length; i++) {
        mod[i] = mod[i] + ' down';
    }
    if (isNaN(key)) {
        sysEvent.keystroke(key, {using: mod});
    } else {
        sysEvent.keyCode(key, {using: mod});
    }
}

トラブルシューティング

エラー処理はあまり考えてないので、そこは大目にみてください :bow_tone2:

1回実行した後にエラーが出て再実行できない

スクリプトエディタでハンマーのアイコンをクリックしてみてください。ショートカットはCmd + Kです。

アプリを選択したが進まない

JSONのappNameで指定した名前が間違っている可能性がありますので、確認してください。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0