0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?