AppleScriptでなくすmicro-toil


Background

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

Introduction

Prerequisites

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

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を使って実装をしていきます。
まずはスクリプトエディタを起動します。ユーティリティの中にあると思います。
ランチャーからの起動なら一瞬です。

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

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

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

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

スクリプトエディタの実行ボタンを押すと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に対応しているということです。

iTermのものもありました。

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

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の新規ウィンドウが開きました!

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

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ファイルのようなものでしょうか。

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

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

Conclusion

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