Mac OSXの純正アプリケーション「Automator」では、自動でいくつかの処理を行うことが出来ます。
develop or drink ? photo by tea © その中でも新規ワークフローでjavascriptを実行
を使って、AppleScriptで利用できるjavascript 1.0を書いて実行することができます。ちなみに、ES6(ES2015)は使えません。
今回はjavascriptを使って、ターミナルを起動し、コマンドを自動入力させる方法をまとめてみたいと思います。
検索欄で「javascript」と入力すると、javascriptを実行が選択できる ©
目次
スクリプトエディタでjavascriptをデバッグする
まず、デバッグ環境について説明したいと思います。
Automatorで記述していくjavascriptは、Mac OSXの純正アプリケーション「スクリプトエディタ」でも実行やデバッグすることができます。
スクリプトエディタでデバッグできる ©
javascriptを使う際には、左上にあるAppleScript
をJavascript
に予め変更しておきましょう。
また、console.log()
で値を確認したい時には、スクリプトエディタ > 表示 > ログを隠す
でログを表示させる事ができるので、そこで値を確認することができます。
Automatorでターミナルを起動する
ターミナルをAutomatorから起動させるには、以下のスクリプトを記述します。
terminal-run.jsa1 2 3 4 5 6
| function run(input, parameters) { var Terminal = Application('Terminal') Terminal.activate() var terW1 = Terminal.windows[0] return input; }
|
terW1
で起動したターミナルウインドウを取得します。
また、ターミナルを一旦閉じてしまうと、ターミナルが起動した状態でありながら、ターミナル・ウインドウが1つもない状態となってしまいます。こういった状態の場合に、上記のコードを実行するとエラーとなります。
このような場合には、ウインドウのプロパティを取得してエラーが発生した際に、ターミナルの新規ウインドウを作成すると、回避する事ができます。
terminal-run.jsa1 2 3 4 5 6 7 8 9 10 11 12
| function run(input, parameters) { var Terminal = Application('Terminal') Terminal.activate() var terW1 = Terminal.windows[0] try{ console.log(terW1.selectedTab.properties()) }catch(e){ Terminal.doScript("echo 'Hi terminal window 1'"); terW1 = Terminal.windows[0] } return input; }
|
ターミナルのコマンド実行中は待機する
ターミナルのコマンドが実行中に、次のコマンドを入力するとエラーが発生します。
その為、ターミナルが実行中はスクリプトの実行を待機する必要があります。下記のサンプルコードでは、コマンドが終了するまでスクリプトを停止させるwaitDelay
を追加してみました。
terminal-run2.jsa1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| function run(input, parameters) { var Terminal = Application('Terminal') Terminal.activate() var terW1 = Terminal.windows[0] try{ console.log(terW1.selectedTab.properties()) }catch(e){ Terminal.doScript("echo 'Hi terminal window 1'"); terW1 = Terminal.windows[0] } waitDelay(terW1) return input; }
function waitDelay(inTerminalWindow){ delay(1) while( inTerminalWindow.selectedTab.busy() ){ delay(1) console.log("待機中") } }
|
Automatorからターミナルコマンドを実行する
Automatorからコマンドを実行するには、doScript()
を使います。
例えば、ディレクトリを変更する場合には以下のようなコードを記述していきます。
terminal-cd.jsa1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| function run(input, parameters) { var Terminal = Application('Terminal') Terminal.activate() var terW1 = Terminal.windows[0] try{ console.log(terW1.selectedTab.properties()) }catch(e){ Terminal.doScript("echo 'Hi terminal window 1'"); terW1 = Terminal.windows[0] } waitDelay(terW1) Terminal.doScript( 'cd \"$HOME/Desktop/your-dir\"' , {in: terW1} ) waitDelay(terW1) return input; }
function waitDelay(inTerminalWindow){ delay(1) while( inTerminalWindow.selectedTab.busy() ){ delay(1) console.log("待機中") } }
|
なお、コマンドラインの基礎に関しては、以下をご覧ください。
自身のブログ
コマンドラインを使ってみよう!Hexoの使い方と始め方
Automatorから複数のコマンドを実行していく
順番に2件以上のコマンドを実行していくには、waitDelay()
を挟みながら、doScript()
メソッド内でコマンドを書いていきます。
例えば、Automatorでnode.jsのプロジェクトを最新に更新して、コードを実行させるには次のように記述していきます。
terminal-commands.jsa1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| function run(input, parameters) { var Terminal = Application('Terminal') Terminal.activate() var terW1 = Terminal.windows[0] try{ console.log(terW1.selectedTab.properties()) }catch(e){ Terminal.doScript("echo 'Hi terminal window 1'"); terW1 = Terminal.windows[0] } waitDelay(terW1) Terminal.doScript( 'cd \"$HOME/Desktop/your-dir\"' , {in: terW1} ) waitDelay(terW1) Terminal.doScript( 'git pull origin master' , {in: terW1} ) waitDelay(terW1) Terminal.doScript( 'nvm use 4.3.0' , {in: terW1} ) waitDelay(terW1) Terminal.doScript( 'node index.js' , {in: terW1} ) waitDelay(terW1) return input; }
function waitDelay(inTerminalWindow){ delay(1) while( inTerminalWindow.selectedTab.busy() ){ delay(1) console.log("待機中") } }
|
Automatorから起動したターミナルでキーボード入力させる
Automatorから起動したターミナルでキーの入力(例えば^C
など)させるには、次のgistが参考になります。
gist
jiaaro/hotkey_helpers.js
上記のコードを利用すると、press()
でキーボード入力を行うことができます。
例えば、以下のコードでは、サーバーを起動させ、5分後にサーバーを停止させるサンプルコードです。
terminal-server.jsa1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| function run(input, parameters) { var Terminal = Application('Terminal') Terminal.activate() var terW1 = Terminal.windows[0] try{ console.log(terW1.selectedTab.properties()) }catch(e){ Terminal.doScript("echo 'Hi terminal window 1'"); terW1 = Terminal.windows[0] } waitDelay(terW1) Terminal.doScript( 'cd \"$HOME/Desktop/your-dir\"' , {in: terW1} ) waitDelay(terW1) Terminal.doScript( 'hexo s' , {in: terW1} ) delay(300) press("^c") return input; }
function waitDelay(inTerminalWindow){ delay(1) while( inTerminalWindow.selectedTab.busy() ){ delay(1) console.log("待機中") } }
var key_codes = { "→": 124, "←": 123, "↑": 126, "↓": 125, "⏎": 36 };
var modifiers = { "⌘": "command down", "^": "control down", "⌥": "option down", "⇧": "shift down" };
function press(hotkey) { var using = []; while (hotkey.length > 1) { if (modifiers[hotkey[0]] == undefined) { throw new Error(hotkey[0] + " is not a recognized modifier key"); } using.push(modifiers[hotkey[0]]); hotkey = hotkey.slice(1); } if (key_codes[hotkey] != undefined) { sys.keyCode(key_codes[hotkey], {using: using}); } else { sys.keystroke(hotkey.toLowerCase(), {using: using}); } } function type(text) { for (var i=0; i < text.length; i++) { sys.keystroke(text[i]); } } function menu_item() { if (!arguments.length) return; var process = sys.processes.whose({"frontmost": true})[0]; var menu_bar = process.menuBars[0].menuBarItems[arguments[0]]; var menu_item = menu_bar; for (var i=1; i < arguments.length; i++) { menu_item = menu_item.menus[0].menuItems[arguments[i]]; } menu_item.click(); }
|
Automatorから複数のターミナルウインドウを新規作成する
複数の新規ターミナルウインドウを作成するには、doScript()
に第2引数(操作したいウインドウ)を指定せずに実行します。
以下は、3つのターミナルウインドウを作成するサンプルコードです。
terminal-create-windows.jsa1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| function run(input, parameters) { var Terminal = Application('Terminal') Terminal.activate() var terW1 = Terminal.windows[0] try{ console.log(terW1.selectedTab.properties()) }catch(e){ Terminal.doScript("echo 'Hi terminal window 1'"); terW1 = Terminal.windows[0] } waitDelay(terW1) Terminal.doScript("echo 'Hi terminal window 2'"); var terW2 = Terminal.windows[0] waitDelay(terW2) Terminal.doScript("echo 'Hi terminal window 3'"); var terW3 = Terminal.windows[0] waitDelay(terW3) return input; }
function waitDelay(inTerminalWindow){ delay(1) while( inTerminalWindow.selectedTab.busy() ){ delay(1) console.log("待機中") } }
|
各ウインドウに対して、コマンドを実行するには次のように記述します。
ここで注意点ですが、手前のウインドウから奥のウインドウに向かって、0番目〜2番目となっているので、ウインドウの変数を扱う際に気をつけて下さい。
terminal-create-windows2.jsa1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| function run(input, parameters) { var Terminal = Application('Terminal') Terminal.activate() var terW1 = Terminal.windows[0] try{ console.log(terW1.selectedTab.properties()) }catch(e){ Terminal.doScript("echo 'Hi terminal window 1'"); terW1 = Terminal.windows[0] } waitDelay(terW1) Terminal.doScript("echo 'Hi terminal window 2'"); var terW2 = Terminal.windows[0] waitDelay(terW2) Terminal.doScript("echo 'Hi terminal window 3'"); var terW3 = Terminal.windows[0] waitDelay(terW3) terW3 = Terminal.windows[0] terW2 = Terminal.windows[1] terW1 = Terminal.windows[2] Terminal.doScript( 'echo "created window 1"' , {in: terW1} ) waitDelay(terW1) Terminal.doScript( 'echo "created window 2"' , {in: terW2} ) waitDelay(terW2) Terminal.doScript( 'echo "created window 3"' , {in: terW3} ) waitDelay(terW3) return input; }
function waitDelay(inTerminalWindow){ delay(1) while( inTerminalWindow.selectedTab.busy() ){ delay(1) console.log("待機中") } }
|
ということで
今回はMac OSX純正アプリの「Automator」から実行できるAppleScript対応のjavascriptで、ターミナルを実行する方法をまとめました。
コマンドをアプリ1クリックで、自動的に色々な処理を走らせることができて大変便利です。サンプルコードではコマンドを逐次実行する方法や、複数ウインドウの作成方法を解説しました。よろしければ参考にしてください。
参考資料
以下の記事を一部参考にさせていただきました。ありがとうございます。
Qiita
Terminalで「すぐに消せ」ごっこ (Mac, JXA)