DTPab

DTPにまつわるあれこれ

テキストをJSで評価・実行するJXA

はじめに

前の記事でめんたいこ師匠のネタ的なJXA(ネタと言ってもすごく使えるTipsが満載)を紹介しました。

uske-s.hatenablog.com

そうしたらご本人から改めてAutomatorを使ったテキスト展開に関するQiitaの記事を紹介してもらいました。

qiita.com

これはPythonを使って、テキストを評価してPythonとして実行してしまおうという「天才かよ…」と思わず脱帽してしまったアイディアでした。天才かよ。

JavaScriptでチャレンジ

そんな天才に触発されたので、僕も似たような処理をJavaScriptで実装しようと思ってやってみたのがこちら。

f:id:uske_S:20190530013513g:plain

単純にJavaScriptとして実行するだけでなく、クリップボードもいじれるようにしてみた。

Automatorの設定

まずはAutomatorの設定(サービスとして作成)。

f:id:uske_S:20190530013745p:plain

クリップボードの内容を取得、JavaScriptを実行、の2つのみ。例によって「選択されたテキストを出力で置き換える」をチェックしておいてください。
名前は適当に「evalScript」としました。

JXAのコード

コードはこんな感じ。

function run(input, parameters) {
    var tmpAry = input.toString().split(/;\n/);
    var CB = tmpAry.pop();
    var input = tmpAry;
    return eval("(function(CB){"+input+"})(CB);");
}

選択したテキストとクリップボードの中身をどうしても区別して取得したくて、ちょっと面倒な実装をしています(後述)。ここのところ、もっといい方法があったら教えてほしい…。

コードの説明

クリップボードに何かテキストを入れておき、さらにエディタなどでテキストを選択した状態でサービスを実行します。そうすると「選択したテキスト情報+改行+クリップボードの中身」という形で引数inputに渡されるようです。
これを利用すれば選択したテキストの情報と、クリップボードの情報を切り分けられそうと考えました。

コードをテキストとして記述しておき、最後に;を付けておきます。それを目印に、inputの前半を選択したテキスト、後半をクリップボードの内容と区別します。
ここで問題だったのが「クリップボードに;\nがあったらどうする?」だったのですが、そこは目を瞑りました…(なのでもっといい実装があったら教えてくれ)。
今後の課題ということにしておきます。

とりあえずそんなわけで、クリップボードになにかしたいという要求にも応えます*1

使い方

単純にJavaScriptのコードを実行させてもよし。ただし、先程のコードの通り匿名関数内で実行しているため、戻り値は明確にreturnしてください

e.g.1 偶数を取り出す

前掲のGIFのひとつめ、「指定した数値までの偶数を取り出す」のはこんな感じです。

i=0,r=[];while(i<=20){if(i%2===0){r.push(i)}i++};return r.toString();

while(i<20)の部分でいくつまでの偶数が欲しいか決めてください。もちろん、奇数が欲しければi%2===0i%2===1にしてもらえればOKです。

e.g.2 テキストの順序を入れ替える

前掲のGIFのふたつめ、クリップボード内のテキストを、まるっとひっくり返します。コードはこちら。

return CB.split("\n").reverse().join("\n");

ここでなんの前触れもなく登場するCBですが、これはJXA側でクリップボードを格納した変数です。変数CBに対してテキスト処理すれば、そのままクリップボードの内容をいじれます。

e.g.3 ファイルパスのエンコード

前回の記事で書きましたが、これもこのJXAでできます。以下のようなテキストを選択してサービスを実行してください。

return encodeURI("~/desktop/ほげ.txt");

~/desktop/%E3%81%BB%E3%81%92.txtと書き換えられます。
また、クリップボードにファイルパスが入っている場合は

return encodeURI(CB);

で同じことができます。これ便利〜。

e.g.4 クリップボードから前後の空白を削除する

クリップボードに適当な文字列 あいう   などを送っておき、以下のテキストに対してサービスを実行します。

return CB.trim();

クリップボードの あいう   が無事にあいうになりました。

さいごに

とまぁこんな感じで無理やりテキスト処理できるようにJXAで遊んでみました。試行錯誤する過程は本当に楽しいですね。
実装がやっぱり今ひとつなので、もう少し合理的なやり方を考えてみたいと思います。

*1:長年愛用してきたClipMenuというアプリの開発が進んでいないようで、クリップボードをマクロでいじれるアプリを探していました。が、正直この方法でもそこそこ使えるかなーと思い始めてきました。