Posted at

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

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で指定した名前が間違っている可能性がありますので、確認してください。