AppleScriptでなくすmicro-toil

# Background
株式会社AbemaTVでABEMAの広告プロダクト開発チームでSREをしているKosakaと言います。
元々はデザイナー・サーバサイドエンジニアをしていましたが、最近はクラウドネイティブな技術やパブリッククラウドと戯れています。
さて、ABEMAやアメーバをはじめ、サイバーエージェントが運営する各メディアをプラットフォームとした広告プロダクト・広告配信システムを開発しているチームが社内にはいくつかあります。
それらを横軸で束ねる、PTA（Publisher adTech Associations）というアライアンスが立ち上がり、所属エンジニアやビジネス職のメンバーを中心に、広告配信を支える技術や広告業界のドメイン知識に関する情報共有、勉強会、[公開イベント](https://cyberagent.connpass.com/event/195409/)などを定期的に開催しています。
今回はその[PTAのアドベントカレンダー2020](https://adventar.org/calendars/5741)のエントリとして小ネタ記事を書きたいと思います。

# Introduction
### Prerequisites
- この記事の内容は、非エンジニアを含め、全macOSユーザを対象としています
- ちなみにABEMAを含むサイバーエージェントでは、エンジニアの8〜9割ぐらいがMacで開発をしています（デフォルトはMacですが、もちろん選べます）
- 今回の例ではiTermを挙げていますが、iTermは[Python API](https://iterm2.com/python-api/)を提供することでAppleScriptのサポートを無くす方向のようです
- しかしながら、他のアプリケーションでも同じ戦略が使える場合が多いため、適宜読み替えて試してみてください
- [Alfred](https://www.alfredapp.com/)などのランチャーを使っているとさらに便利かと思います

### Goals
- AppleScriptの普及
- 極小かつ繰り返し発生する手作業（micro-toil）に対して、減らせないだろうか？と考えてみるきっかけにして欲しい
- 人々の日々のストレスフルな作業・操作を少しでも減らす
- 1日30秒節約できれば1年間でおよそ3時間の節約になります（映画1本多く観られますね！）
- 現実的には時間的効果は実感できないと思いますが…
- ストレス軽減効果を考えると時間以上にメリットがあるかもしれません
- 何よりも、これが解消できた！という喜び・達成感が大事

# Motivation
今回、AppleScriptを使おうと思った動機を以下で述べます。

- マルチディスプレイ環境+複数デスクトップを行き来して作業することが多い
- 既に起動しているアプリケーションの新規ウィンドウを開きたいことが多々ある（ターミナル etc）

このような場合、通常であれば以下のような操作になるかと思います。
説明のために、2つのデスクトップ、デスクトップAとデスクトップBがあるとし、デスクトップAでiTermが開いている状況を考えます。

1. デスクトップBで作業中にiTermのウィンドウが欲しくなった（ウェブサイト見ながらコマンド試したいとか、ありますよね？あるんです）
2. デスクトップAに移動する（コマンド+TabでもMission Controlでもなんでもいいです）
3. 既に開いているiTermウィンドウにフォーカス
4. 新規ウィンドウを開く
5. 新規ウィンドウをデスクトップBに持っていく

これが1日に何度もあると操作が面倒になってきます。コンピュータを使っているのだから、こういうのは機械がやって欲しいものです。
そこでAppleScriptの出番です。
今回は、上で述べた手順の2〜5を無くしてしまおうと思います。

# AppleScript
AppleScriptはSystem 7といういにしえのOSで採用されたMac用のスクリプト言語です。
アプリケーション操作の自動化などを行うことができます。構文は若干古い印象を受けますが、今回のようなライトな使用目的に限れば、学習コストはかなり小さく済むのではないでしょうか。
macOSに標準でインストールされているスクリプトエディタで記述するのが一般的かと思います。もちろん、使い慣れたエディタを使うこともできます。VSCodeのプラグインもあります。
完成したスクリプトは.app形式にビルドすることもできます。

# Hands-On
さて、ここから実際にAppleScriptを使って実装をしていきます。
まずはスクリプトエディタを起動します。ユーティリティの中にあると思います。
ランチャーからの起動なら一瞬です。
![Screen Shot 2020-12-02 at 18.54.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19487/5b83609a-b285-dd58-be5f-0b7d15a04c80.png)

以下の操作の自動化を実装していきます。

1. iTermが起動していなければ起動する
2. iTermの新規ウィンドウをデフォルトプロファイルで作成する
3. 作成したウィンドウをフォーカス状態にする

結論から掲載してしまいますが、以下のようなコードになります。

```#AppleScript
if application "iTerm" is not running then
	activate application "iTerm"
else
	tell application "iTerm"
		create window with default profile
		activate
	end tell
end if
```

![Screen Shot 2020-12-02 at 18.59.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19487/a79942fb-35cc-83e9-e209-1c27f6f2f8c3.png)

スクリプトエディタの実行ボタンを押すとiTermの新規ウィンドウが開きます。

ここで特に注目したいのが、`create window with default profile` の部分です。
「iTermのデフォルトのプロファイルで新規ウィンドウを作る」という命令ですが、これはiTerm固有の命令です。
2行目の`activate application "iTerm"`などはmacOSのGUIアプリケーションに共通した命令であり、AppleScriptのリファレンスで引くことができます。
しかし、iTerm固有の命令にどのようなものがあるのかをどのように知ることができるのでしょうか？
  
サポートの充実したアプリケーションであれば、ウェブ上でドキュメントを公開している場合もありますが、公開されていない場合も多いです。また、AppleScriptをサポートしていないアプリケーションもあります。
AppleScriptをサポートしているアプリケーションは`/Applications/<app name>.app/Contents/Resource`配下に`<app name>.sdef`という辞書ファイルを持っています。
スクリプトエディタの`File > Open Dictionary`メニューでsdefファイルをもつアプリケーションの一覧を見ることができ、ここから目的のアプリケーションを選択することで開くことができます。
言い換えれば、このリストにあるアプリケーションはAppleScriptに対応しているということです。

![Screen Shot 2020-12-02 at 19.16.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19487/478eac4b-73a4-7282-0822-f87afcd61814.png)

iTermのものもありました。

![Screen Shot 2020-12-02 at 19.19.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19487/1236813e-87d2-ad18-4b8b-dca4aa5f7254.png)

これによると、`command <text>`でシェルにコマンドを渡して実行することができそうですね。そこで、開いたiTermの新規ウィンドウでvimを実行してみたいと思います。
次のようにスクリプトを修正します。

```#AppleScript
if application "iTerm" is not running then
	activate application "iTerm"
else
	tell application "iTerm"
		create window with default profile command "vim"
		activate
	end tell
end if
```

実行ボタンを押すと、vimを起動した状態のiTermの新規ウィンドウが開きました！

![Screen Shot 2020-12-02 at 19.32.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19487/6657a2ea-55ef-ecc0-ab25-88bb02268f48.png)

辞書ファイルの次の項目を見ると、`write`コマンドというものもあります。これにテキストを渡すとシェルでの入力を模倣できるようです。少し複雑な操作も自動化できそうですね。そこで、`~/Desktop/vim`フォルダに日時を名前に持つテキストファイルを作成し、それをvimで開くという操作をさせてみました。

```#AppleScript
if application "iTerm" is not running then
	activate application "iTerm"
else
	tell application "iTerm"
		set w to create window with default profile
		activate
		tell current session of w
			write text "mkdir -p ~/Desktop/vim && vim ~/Desktop/vim/`date +%Y%m%d%H%M%S`.txt"
		end tell
	end tell
end if
```

とっさにメモを取りたいときに役立ちそうです！

いろいろ試してみたくなるところですが、一旦、iTermの新規ウィンドウを開くスクリプトに戻ります。
AppleScriptの項で述べた通り、スクリプトは.app形式にビルドすることができます。`File > Export`でapp形式で書き出すだけなので、お手軽です。Windowsで言うところのbatファイルのようなものでしょうか。

![Screen Shot 2020-12-02 at 19.42.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19487/2d2cac10-c604-eebc-6ada-4fa6e8b022c6.png)

書き出したファイルに`NewiTermWindow.app`などと名前をつけて、パスが通っているところに置いておけば、Alfredなどのランチャーから実行することができ、書き出したアプリケーションファイル名の先頭数文字、この場合では`new`と入力するだけで、現在のデスクトップにiTermの新規ウィンドウを作成することができます。

![Screen Shot 2020-12-02 at 19.48.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19487/c0ab416d-d196-775b-5a2a-6029909bef65.png)

これにより目的は達成されました！お疲れ様でした。

# Conclusion
まとめです。
存在すら知られていないかもしれないAppleScriptですが、かゆいところに手が届くので、同じ操作を繰り返しているな？と気づいた際に思い出してもらえれば嬉しいです。
年末年始のステイホーム時間で遊んでみてください！
SREとしてチームのtoil削減も考えなければいけませんが、自分の作業環境におけるmicro-toilとそれに伴うストレスを無くすことも必要なことだと思っています。
広告の話を全くしませんでしたね…。いいんでしたっけ？