2020/04/26

MacOS Automator で選択範囲のテキストにフィルタをかける

Automator を使ってクリップボードを編集する方法の紹介です。

このブログは性格上、頻繁にコードスニペットを貼り付けています。コードスニペットは Google Code Prettify を使って綺麗に表示させています。Google Code Prettify を使うには、以下のように、<pre> タグで囲んであげる必要があります。
<pre class="prettyprint">
public static void main(final String[] args) {
  System.out.println("Hello, World!");
}
</pre><br />

しかし、このブログで使っている Blogger の記事編集画面には、任意のタグに任意のクラスを指定したブロックを作る機能は無いので、HTML 編集画面の方で手で書いてあげる必要があります。

<pre> タグで囲むくらいなら、としばらく我慢して手で書いていましたが、実はそれだけではダメで、<, > などをエスケープしてあげないといけないことに気付きました。これはさすがに人間様が手作業でやることではない、と思い、省力化を試みました。

仕様

いろいろ考えたり、試行錯誤した結果、以下のような使い方をすることになりました。
  • コードスニペットを選択して、Command+C でコピー
  • Command+Shift+V で Automator クイックアクションを呼び出し、クリップボード内にフィルタを適用する
  • Blogger の HTML 編集画面に Command+V でペースト
本当はフィルタ+ペーストを1アクションでやれるようにしたかったのですが、Automator からペーストするのがどうしてもうまく出来ず、あきらめて2アクションになりました。
あとは、クリップボードの中身にフィルタを掛けるのか、選択範囲についてフィルタを掛けるのかで悩みましたが、後者は範囲選択アクションが増えてしまうので、前者にしました。後者の方が挙動が分かりやすい気はしましたが、頻繁にやるので、手間の削減を優先しました。

フィルタ仕様は、以下の通りです。
  • & は &amp; にエスケープ
  • <, >, " は &lt;, &gt;, &quot; にエスケープ
  • 全体を <pre class="prettyprint">...</pre> で囲む

作り方

作り方が分かると応用が効くと思うので、説明します。

Automator クイックアクションの新規作成

まず、Automator を起動します。次のようなウィンドウが出てくると思います。
今回は「新規書類」をクリックします。次のような画面が開きますので、「クイックアクション」を選んで「選択」を押しましょう。クイックアクションとして作ると、サービスメニューに追加され、右クリックやショートカットキーで呼び出すことができます。
ここまで進むと、次の画面に到達します。この画面が Automator のワークフロー編集画面です。ここで自動化したい処理を作っていきます。

Automator ワークフローの編集

最終的に、以下のような状態にします。
順を追って説明します。
まず、上部のワークフローの設定は次のようにします。
  • ワークフローが受け取る項目: 入力なし
    • クリップボードの中身を編集するので、それが入力のようなものなのですが、Automator ではクリップボードの中身は入力ではないので、ここでは「入力なし」とします
  • 他は初期値のまま
    • 特に挙動に関係してこないので、そのままで大丈夫です
次に、ライブラリ (左側の一覧) から ユーティリティ - シェルスクリプトを実行 を探して、右側にドラッグ&ドロップしてください。シェルは /bin/bash にしてください。入力の引き渡しの方法は stdin へ のままで良いです。その下のテキストエリアには、以下のように書きます。
function filter() {
 echo -n '<pre class="prettyprint">'
 perl -pe 's/&/&amp;/g; s/</&lt;/g; s/>/&gt;/g; s/"/&quot;/g;'
 echo '</pre><br />'
}
pbpaste | filter | pbcopy

(補足) このスクリプトの解説

filter() というシェルスクリプト関数を定義しています。標準入力を編集して標準出力する、いわゆる UNIX 的なフィルタの挙動をする関数になっています。

今回は filter() の中で、まず <pre class="prettyprint"> を出力しています。echo に -n が付いていますが、これは最後に改行コードを出力しないことを意味します。<pre> タグの後ろに改行があると、最初に空行が入ってしまうためです。Blogger は勝手に取り除いてくれますが、念の為そうしています。
次に標準入力を perl で編集しています。-pe は、標準入力を1行ずつ後ろの perl コードに渡して、その結果を標準出力に出すことを指示するオプションです。perl でフィルタを書くときに便利なオプションです。あとは s/正規表現/置換後の文字列/g; の構文を繰り返し適用して、エスケープ処理をしています。最後の g は反復適用の指示です。これを付けないと、1行ごとに1回マッチした時点で処理をやめてしまいます。
最後に </pre><br /> を出力して終わりです。

この filter() にクリップボードの中身を渡して、クリップボードに戻す処理が最後の行に書かれています。
pbpaste コマンドは、クリップボードの中身を取得して標準出力に出します。
パイプで filter につなぎ、さらにパイプで pbcopy コマンドに渡します。pbcopy は標準入力をクリップボードに入れます。

保存

ここまで出来たら、Command+S で保存します。名前を聞かれるので、付けてあげてください。私は PrettyPrint としました。~/Library/Services に保存されます。

ショートカットキーの割り当て

作成した Automator クイックアクションにショートカットキーを割り当てるには、システム環境設定を起動します。
起動したら、キーボード の ショートカットを選択してください。
下のような画面になりますので、左側から「サービス」を選ぶと、右側の「一般」の下に保存した名前でクイックアクションが見つかるはずです (私は PrettyPrint としました)。
クイックアクション名を選択すると、「ショートカットを追加」と出てくるので、そこを押すと、入力待ちのようになります。この状態で割り当てたいショートカットキーを押してください。私は Command+Shift+V としました。 
私は Chrome で Blogger 記事を書いているので、割り当てるショートカットキーは、Chrome で使われているキーを避ける必要があります。そうしないと効きません。

動作の様子