Macで実行もできるFileMakerコード管理 その2

FileMaker Proに集めたスクリプトのメモをそのまま実行環境にしてしまった話の続き、具体的にいきます。

前回のあらすじ

どこかで見つけたコマンドやスクリプトなどのコードをコピペしてメモっていると散在して探しにくくなってきたのでFileMakerで一元管理。一元管理だけに留まらず、簡単な小技を使うことでコマンド発射装置として育った…

実際に作ってみて手元にある「CodeManagement.fmp12」というファイルをネタにして具体的に行きます。

メモっておくコード・実行させるコード

CodeManagement.fmp12で扱う内容と目的はこうです。

ターミナルのコマンドやAppleScriptのスクリプトのコード、その他のメモ保管

最初の目的は「コマンドやスクリプトをメモっておく」ことに過ぎませんでした。その目的の根っこは何も変わりません。ただのマイリファレンスです。

スクリプトを実行させる装置

メモのうち、ターミナルコマンドやAppleScriptのスクリプトを実行させます。例えばスクリーンショットの名前や場所を変更したり、TimeMachineの速度アップをONOFFしたり、Macの設定を行ったりします。

通常「えーと、スクリーンショットのコマンド、どんなだっけ」と思って調べますね、マイリファレンスにすでに載ってます。それを一旦何かにコピペして必要項目を書き換えた後にターミナルにコピペして実行させますが、マイリファレンスで調べたそのときに実行できてしまうという、そういう便利さを実現します。

主に以上が本ポストで扱うファイルメーカー書類の目的です。他に似た意味の少し異なる目的もあります。

AppleScript をFileMakerで使用するときのリファレンスとして

ファイル情報を得ることなんかは当然Finderでやるほうが手っ取り早いのですが、FileMaker書類の中でファイルに関する操作を行うことがよくあるんです。ファイルをデータベースに登録したり、その際、ファイルサイズや作成日をセットしたりします。登録後はそれをFinderで表示させたりもします。こうしたFileMaker内部でよく行う処理のリファレンス、コピペ用ネタとしても利用しています。

フィールド

CodeManagement.fmp12の主なフィールドです。

メインのフィールド

codeTemplate

codeTemplateと名付けたフィールドです。スクリプトやコマンドなど、メモったコードを書き溜めるメインのテキストフィールドです。

メモに留まらず、コマンドを実際に実行させたいのでマイルールを設けます。それは、変数の入る箇所に、変数である事を示す決まった文字列を採用することです。その決まった文字列を、後に実際の文言と置き換えます。

ここではその文字列を「$変数1」「$変数2」のようにしています。

実行用に成形するフィールド

codeFinalと名付けたフィールドです。コードを実行できる形に整形します。タイプは計算式です。

If ( PatternCount ( category ; "メモ" ) ; "" ;
 Substitute ( CodeTemplate ;
 [ "$変数1" ; 変数1 ] ;
 [ "$変数2" ; 変数2 ] ;
 [ "$変数3" ; 変数3 ] ;
 [ "$変数4" ; 変数4 ] ;
 [ "@FileMaker" ; システム::FileMakerName ] ) )

フィールドの計算式はこのようになってます。「$変数1」という文字列を変数1フィールドで置き換えるといった単純な計算式です。

変数+Template
変数とcodeTemplate こんな感じの画面に仕立てます
codeFinal
codeFinalの計算式でこうなる

あと、ちょっと補足が必要ですか。

・カテゴリーを用意していて、「メモ」ならファイナルのフィールドに何も書かないということにしています。

・フィールドFileMakerName は、使用中のFileMakerのアプリケーション名を返します。AppleScript で必要なときがありますので。FileMakerはバージョンによってアプリ名が変わるから、カスタム関数を使って起動FimeMakerの名前を取得しています。

計算式の形に成形するオマケ的フィールド

codeFormulaと名付けたフィールドです。codeFinalを計算式に整形させたものを格納します。

FileMakerのファイル内でコマンドやスクリプトを実行させる時、たまに計算式の中に仕込む必要があります。そのとき、 ” ” で囲ったり ¶ を加えたり、もともとの ” ” を \” の形にしたり、いろいろ変形しなければなりません。そうした整形を行うスクリプトを用意して結果を格納します。

フィールドの計算式ではなくFileMakerのスクリプトで整形を行い、ボタンに割り当て、通常と式の形とをトグルで表示できるようにしました。

やや乱暴な条件分岐のスクリプトはこんな感じ。

式の変換スクリプト

変数を置き換えるフィールド(複数)

メインとなるフィールド内に「$変数1」文字列があれば、フィールド「変数1」の内容で置換します。その置換するための、変数フィールドです。

ひとつのコードに、多分3つくらい変数があれば十分だと思うので三つ用意しています。

リレーションを使って変数をフレキシブルに扱おうとしてみたこともありましたが、手続きが面倒すぎてやめました。シンプルにフィールドを複数個用意したほうがアナログっぽくて扱いが簡単です。

他のフィールド

実例としてCodeManagement.fmp12と名付けたファイルを挙げていますが、このファイルのフィールド定義はこんな感じです。

フィールド定義
あれ?変数フィールド3つと書いたのに4つあるじゃん

categoryフィールド:ターミナルのコマンドやAppleScriptのスクリプトやメモが混在していますから、それを分別します。この分別によって、後にFileMakerスクリプトの処理を変えていきます。

分別は手動で付けてもいいし、codeTemplateの内容から推察することができることがあるので半自動にしています。

Case (
 PatternCount ( codeTemplate ; "end tell" ) ; "AppleScript" ;
 PatternCount ( codeTemplate ; "sudo" ) ; "Terminal" ;
 Left ( Code::codeFinal ; 8 ) ="https://" ; "URL" ;
 Left ( Code::codeFinal ; 7 ) ="http://" ; "URL"
; "" )

こんな感じです。

結果フィールド:結果を返すタイプのAppleScriptを使用時に、それを格納するフィールド。

objectフィールド:このファイルの中で、フォルダやファイルを選択するボタンを用意しています。フォルダ選択はいいのですがファイル選択するためにオブジェクトを挿入することを行っていまして、そのためのフィールドです。やや無理矢理。

繰り返し:実験的にバッチ処理みたいなことができないか試してみているので、その利用をするかしないかのチェックフィールド。繰り返し処理は試作レベルなので適当です。いずれはAutomatorみたいに「組み立てる」も作ってみたいと思っていましたが、それを構築することが難しそうで本末転倒になる前にパス。

スクリプト

codeFinalに書かれたコードを実行させる仕組みをFileMakerスクリプトで作ります。「AppleScriptを実行」スクリプトステップを使います。

ターミナルコマンドを実行させるスクリプト

ターミナルを起動させてアクティブにしてcodeFinalの内容を実行させます。

AppleScriptではコマンドを実行させることができます。

do script with command "ここにコマンド"

これです。これを使えばいいのですが問題もあります。””のエスケープ処理など、整形させる必要がありますし、改行して連続してコードを送り込みたいときに1行では済みません。

もっと簡単にコマンドやスクリプトを実行させる

いろいろ考えた末に、もっと簡単で直感的で馬鹿らしい方法に落ち着きました。即ち、コードをコピペします。

そもそもターミナルのコマンドをメモってはコピペで使っていました。ですのでコピペを再現するだけです。do script みたいなわけわからんコードを使う必要もありません。

FileMakerのスクリプトでこうします。

  1. codeFinalをコピーします
  2. ターミナルをアクティブにして念のために新規ウインドウ
  3. ペーストします

もうちょっと詳しく書くとこうです。

1. スクリプトステップ「コピー」でcodeFinalの内容をコピー

2.「AppleScriptを実行」ステップでターミナルを起動

tell application "ターミナル"
activate
end tell

さらに念のためターミナルに新規ウインドウ。新規ウインドウを作成するコードなんか知らないので「コマンド+N」しています。

tell application "System Eventes"
key code 45 using {command down}
end tell

3. 一呼吸置いてから(一時停止1秒)ペーストします。もちろんペーストするコードなんか知らないので「コマンド+V」させるだけです。

tell application "System Eventes"
key code 9 using {command down}
end tell

なんという馬鹿馬鹿しく原始的で直感的かつストレートなスクリプトステップでありましょうか。

ところでメモった AppleScript のスクリプトを実行させるときは単に「AppleScriptを実行」ステップで codeFinal を指定するだけです。

カテゴリーで「Terminal」「AppleScript」「memo」「URL」などと分けていますから、スクリプトではカテゴリーに応じた処理を書き分けます。

実行ボタンスクリプト
メモを実行させるスクリプト

そんなわけで基本は以上です。「コードをメモったフィールドと変数フィールド」「それらを元に整形したフィールド」「実行させるボタンに割り当てるスクリプト」があれば事足ります。

ですがFileMakerでこういうのを作ってるとどんどん本筋から離れた仕組みを付け加えたくなります。実例 CodeManagement.fmp12 にはそうしたオマケ機能もいくつか用意しています。

履歴を保存するスクリプト

変数にセットした内容を履歴として保存します。履歴に保存された項目はポップアップメニューから選択することができるようになり、使い回しの利便性が上がります。

準備として履歴用のテーブルを作ります。

履歴テーブルにはメインとのリレーション用IDフィールド、タイトル、それから変数の履歴フィールドを用意します。

余計なことに履歴フィールドは「PATH」と「NAME」に振り分け、変数の内容に応じて振り分けたりしています。あとで「DATE」も必要だったかも思い当たり、自動的に振り分ける困難さに「分けなければ良かった・・・」とちょっと思ったという。

IDでリレーションを組んで、メインテーブルにスクリプトをひとつ作ります。変数フィールドにトリガーとして割り当てて使いましょう。

流れとしては、そのフィールドに内容が入力され確定されたときに履歴に保存させます。

  1. 空ならスクリプト終了
  2. 変数をセット ID、title と、$item Get(アクティブフィールド内容)
  3. 条件分岐で$itemがパスなのか名前なのか日付なのか振り分ける
  4. 履歴ウインドウを開き $itemを検索。すでにあるかどうかチェック、なければ新規レコードでID、タイトルと共に変数の種類に応じたフィールドに格納してウインドウを閉じる

こんな感じ。これを変数フィールドにトリガとしてセット。OnObjectSaveとOnObjectExitの両方にセットします。二重に働きますが、フィールドを触るだけで履歴が保存されます。あれ?じゃあExitだけに割り当てれば良いのか。そうかも。

他、値一覧を作ります。履歴フィールドから取得し、動的値一覧にしておきます。動的にするとレコードに関連する履歴のみが一覧されますね。簡単に「動的一覧」などと言ってますが私はこれを理解するのに長い年月がかかりました。

この値一覧を使ってポップアップメニューを作り、履歴にアクセスできるようにします。同じような仕組みを使って「検索窓の履歴」も残したりしています。

参考:FileMakerでメディア管理 2-3 小ネタ:快適操作

やや説明が雑でしたが履歴についてでした。

繰り返し処理の試作

複雑なバッチ処理は難しいですが単純なものなら出来るかもしれないと試作しています。

新たなテーブルに必要フィールドと「変数リスト」フィールドを作って処理します。

そもそもはTimeMachineのローカルスナップショットを削除したいというところが出発点でした。

こっそり作られるTimeMachineのローカルスナップショット、これを確認するには

sudo tmutil listlocalsnapshots /

を使います。パスワードを入れた後、こんなふうにリストされます。

com.apple.TimeMachine.2021-05-16-150139
com.apple.TimeMachine.2021-05-16-155746
com.apple.TimeMachine.2021-05-16-170133
com.apple.TimeMachine.2021-05-16-180027
com.apple.TimeMachine.2021-05-16-185802
com.apple.TimeMachine.2021-05-16-200525
com.apple.TimeMachine.2021-05-16-215709
com.apple.TimeMachine.2021-05-16-230136
com.apple.TimeMachine.2021-05-17-000202
com.apple.TimeMachine.2021-05-17-010145
com.apple.TimeMachine.2021-05-17-020125

これをコピーして繰り返し処理に持っていきます。

 

繰り返しの準備

ポイントは「変数リスト」ですね。ペーストしたあとは、検索・置換の便利フィールドを使って日付の部分のみ残します。

置換を使って日付部分のみに

これをリストにして処理します。レイアウトをこしらえて、このリストをループで回しcodeFinalを一個ずつ新規作成していきます。

リストスクリプト

こういうスクリプトですが、これだけ見たって何のことやらわからないですよねえ。

まあ、とにかく別テーブルにてこんなふうに作って連続で処理するテストは上手くいきました。

繰り返し処理画面

試作レベルなので「変数1」にしか対応しておらず、複雑なことはできません。

ここまで雑な説明を続けてきて今思いつきましたが、この試作ファイルをダウンロードできるようにしておきます。もっとスマートなやり口に改造したり、余計な機能を足したり引いたりしてお好きなように使っていただければいいんじゃないかと。

.CodeManagement.fmp12

ということで、実行もできるコードメモ管理でした。