Clip Hold の「項目を変更してコピー」にテキスト置換機能を実装した【Clip Hold 開発日記】

みなさんこんにちは、たいくんです。
私のクリップボードマネージャーであるClip Holdには特定の履歴や定型文をベースに、変更を加えて新たにコピーすることができる「項目を変更してコピー」機能があるのですが、そこにメモやテキストエディタのようなテキスト置換機能があったら便利だなと思ったので、実装した時の話をご紹介します(次回のアップデートで搭載予定)。

広告

項目を変更してコピー機能について

もともとClip Holdに搭載されていた項目を変更してコピー機能は非常にシンプルなもので、特定の履歴や定型文があらかじめ入力された状態でテキストを編集してコピーするだけの機能でした。

私はクリップボードを毎日のように活用しているのですが、コピーしたテキストの一部分をちょっと変えてからペーストしたい、という場面が多くあります。
この機能を実装する前はペーストしてからテキストを編集するか、一旦メモのような場所に貼り付け、一部を編集してカットする、といったことを繰り返すことが多く、地味に面倒な作業でした。コピー履歴を変更したいのが1度だけであれば貼り付けてから編集でも問題ありませんが、変更した後のテキストを何度か使い回したい場合はまたコピーし直す必要があるので、そんな作業をしているときにこの機能(項目を変更してコピー)を思いつきました。

最初にこの機能を実装した時はそこまで高度なことをしないだろうと思い、シンプルな機能として実装していましたが、その後もしばらく使い続けていると様々な場面で(特に長いテキストをコピーした時)「繰り返し登場するテキストを一括で変更できたら…」「パターンを手軽に変更できたら…」と思うことが増えてきたため、テキスト置換機能を次期バージョンの1.7.0に搭載しようと思い実装することにしました。

デザインを考える

私はプログラミングの知識がないため、Clip Holdを始めとする自作アプリの開発には生成AIが必須なのですが、私はデザイン作業は得意で、UIデザインには非常に強いこだわりを持っています。
作りたい機能は、頭に思い浮かんでいる機能を言葉でまとめて生成AIに投げれば概ね出来上がりますが、生成AIが出力するUIデザインは私のこだわりからは大きくかけ離れたものになってしまうことが多いです。
しかも、比較的シンプルなUIであれば言葉だけでも概ねレイアウトできますが、少々複雑なレイアウトや機能を含む場合、言葉だけではなかなか想像通りのものになる事は少なく、後から何度も細かい修正を繰り返さなければならないことがあります。

そこで、私が少し前から行っている、最初から想定に近いデザインになるようにする対策があります。それは「UIデザインのモックアップを作成してその画像をAIに見せること」です。
最近の生成AIは画像認識能力がかなり高く、画像に含まれるテキストだけでなく、配置や色、大きさなどをかなり高精度で読み取ってくれるので、想定しているUIの画像を読み取って再現してくれます(まるでデザイナーとプログラマーの共同作業かのようw)。
それに、実装前にデザインを考えることで途中で追加すべき機能を思いついたり、オプションの配置場所について気づきを得たりすることができるため、最初からノープランで考えながら実装していくよりも、初回での完成度の高さにも貢献します。

広告

Keynoteでデザインする

私は、モックアップUIデザインをApple Keynoteで作成することにしました。

私が主に使用しているデザインソフトは「Affinity」で、そちらの方がより高度なデザインを作成することができますが、結構大型のソフトなので、なんとなく気合が必要です…w
「気合が必要」というのは使い方や操作が難しいという意味ではなく(むしろ個人的にはAdobe Illustratorより使いやすい)、「よし、これからちゃんと仕事をするぞ」と意気込むような若干のハードルの高さを感じます。緻密なデザインや本格的なしっかりとしたデザインを作りたいときには大変重宝しますが、もっと気軽に使いたいときにはあまり向いていない感じがあります。
一方で、Keynoteはプレゼン作成ソフトですが、動作が非常に軽量で、高度なエフェクトなどを使用する事はできないものの、様々な図形を組み合わせた本格的なグラフィックを作成することができ、AIに渡すような簡単なモックアップデザインであれば十分な仕事をこなしてくれます。メモ帳感覚のような気楽さでデザインできるため、Keynoteを使用しました。
今思えばフリーボードでもほぼ同じ事はできると思いますが、Keynoteであればスライドのサイズで大きさを決めて複数の画像を一度に書き出すことができるため、この作業はKeynoteの方が向いているように思います。

実際にKeynoteでデザインした画面がこんな感じです。ボタンをどのように配置すれば使いやすいか良いかを考えながらデザインしていたので少し時間がかかってしまいました(3時間くらい?)が、実際にこんなレイアウトになれば使いやすいだろうと思います。

実装作業を行う生成AIに私の想定や機能についてより良く理解してもらえるよう、様々なパターンの画像5枚を作成しました。これが2枚目。

3枚目。

4枚目。

これが最後の5枚目です。

テキスト置換機能には2種類のモードを用意することにしました。
1つ目がよくある、テキストを検索して別のテキストに置き換える検索モード、2つ目がより高度な、特定のパターンを正規表現で検索して別のパターンに置き換えられる正規表現モードです。

広告

Apple Intelligence機能を実装しようとしたが…

実は、私が正規表現モードを実装しようとした理由として、Apple Intelligenceのオンデバイスモデルを使って、自然言語でAIに正規表現パターンを作成してもらう機能を作ろうと思っていたからです。私自身、正規表現に詳しくなく、言葉で説明して簡単に生成してくれたら便利だなと感じました。
最初は「置換履歴」ボタンの代わりに「Apple Intelligence」ボタンを配置して、そこで説明画面を開こうと考えていたのですが、実装に入る前にオンデバイスモデルの性能をテストしておこうと思い、ショートカットアプリの「モデルを使用」ブロックを使ってモデルの能力を試してみることにしました。

モデルに渡すプロンプトは以下のものを使用しました。

利用可能な置換モード: 検索, 正規表現
利用可能なオプション:
⚬ ignore_case: 大文字・小文字を無視(true / false)
⚬ multiline: 行ごとに検索(true / false)
⚬ dot_matches_all: ドットが改行にも一致(true / false)
入力欄: 検索欄または正規表現欄, 置き換え欄
指示内容とテキストを分析し、どのツールを使い、どのオプションを有効にし、各入力欄に何を入力するかを出力してください。
出力形式は必ず以下のJSONフォーマットのみとしてください。
{
    "tool": "検索 または 正規表現",
    "options": {
        "ignore_case": false,
        "multiline": false,
        "dot_matches_all": false
    },
    "search_field": "検索文字列または正規表現パターン",
    "replace_field": "置換後のテキスト(正規表現の場合は$1等の参照を含む)"
}

変更を要求するテキスト:
[user_id: 1001, name: "Alice Smith", role: "admin"], active: true
[user_id: 1002, name: "Bob Johnson", role: "editor"], active: false
[user_id: 1003, name: "Charlie Brown", role: "viewer"], active: true
[user_id: 1004, name: "Diana Prince", role: "editor"], active: true
[user_id: 1005, name: "Edward Norton", role: "admin"], active: false

ユーザが求めている変更:
「[」から始まって「]」で終わる部分だけをJSON形式にして、user_idはidに変更したい。アクティブは変更しない。

出力を辞書形式にして試してみたのですが…

なんとも残念なことに、オンデバイスモデルでは正規表現の組み立てが全くできないようでした。

出力結果:

{
  "options" : {
    "dot_matches_all" : false,
    "ignore_case" : false,
    "multiline" : false
  },
  "tool" : "正規表現",
  "search_field" : "\\[",
  "replace_field" : "\\1"
}

正規表現を使おうという意思は感じますが、モデルの性能が全く足りず、正規表現の適切なパターンを出力することはできませんでした。

広告

そこで、アプリには実装できないものの、試しにモデルの性能が少し高いであろうプライベートクラウドコンピューティングモデルに切り替えて試してみたところ、こちらも残念なことに、適切なパターンを出力できませんでした。

出力結果:

{
  "options" : {
    "dot_matches_all" : false,
    "ignore_case" : false,
    "multiline" : false
  },
  "tool" : "正規表現",
  "search_field" : "\\[([^\\]]+)\\]",
  "replace_field" : "{\"id\": $1, \"name\": $2, \"role\": $3}"
}

オンデバイスモデルよりは若干改善されているような感じはしますが、全く使えません。

念のため、拡張のChatGPTモデルを試してみたところ、やはり大きな高性能モデルであるため、こちらは適切に出力することができました。

出力結果:

{
  "tool" : "正規表現",
  "options" : {
    "dot_matches_all" : false,
    "ignore_case" : false,
    "multiline" : true
  },
  "search_field" : "\\[user_id: (\\d+), name: \"([^\"]+)\", role: \"([^\"]+)\"\\]",
  "replace_field" : "{\"id\": $1, \"name\": \"$2\", \"role\": \"$3\"}"
}

これらの検証から、Appleのオンデバイスおよびプライベートクラウドコンピューティングモデルは文章の解析と作成に特化したモデルであり、プログラミングや正規表現パターンの出力のような複雑なリクエストには完全に対応していないようであることがわかりました。
ただし、これは2026年8月現在のmacOS Tahoeで検証した結果であり、WWDC26で発表されたmacOS Golden Gate以降で使用できる進化したオンデバイスモデルであるAFM 3 CoreとAFM 3 Core AdvancedおよびプライベートクラウドコンピューティングモデルであるAFM 3 CloudとAFM 3 Cloud Proでは結果が異なる可能性があります。
そのため、現時点ではApple Intelligenceを使った検索パターンの組み立て機能を実装する事は諦め、また今度オンデバイスモデルが進化したとき試してみたいと思います。

広告

完成した機能

こちらが実際に出来上がった項目を変更してコピー画面です。
さすがに画像送って一発目では完璧とまではいかなかったものの、ボタンのレイアウトや基本機能は想定通りでした。ただし、ボタンのサイズやポップオーバーの見た目が異なっていた(スクリーンショットを撮り忘れてしまいましたが…)ため、細かいデザインの修正を何度か繰り返しましたが、デザインの改善とパフォーマンスの改善を行い、良い感じに実装することができました。

こちらが正規表現モードと置換履歴のポップオーバー画面です。
最初のデザインからの改善として各履歴項目を削除できるようにしたり、空白文字を薄く記号で表示したりといった変更は加えましたが、ほとんど当初想定していたレイアウト通りで使いやすそうです。
今後のさらなる開発中に操作のテストを何度か行うと思いますので、その時に改善を思いついたら変更を加える可能性があります。

バージョン1.7.0は開発中です

今回紹介した内容は、Clip Holdの次期バージョンである1.7.0に搭載される予定です。なお、1.7.0は開発中であり、この記事で紹介した内容は1.7.0の正式リリースまでに変更される可能性があります。

Clip Holdのアップデート情報のお知らせは私のXアカウント(@i_am_taikun)で行いますので、ぜひフォローしていただけると幸いです。

最後まで読んでくださりありがとうございました。それでは、また!

広告

コメントはこちらから!

記事について気になるところや質問、ご指摘など、以下のコメント欄から気軽にコメントしていただけるとうれしいです!

※コメントの投稿には、無料で作成できるGitHubアカウントが必要です。コメント欄が表示されない場合はページを再読み込みしてみてください。

コメント欄ではMarkdown記法が使用でき、画像を挿入することもできます。ここで使用できるMarkdown記法の詳しい使い方は、入力欄の右下にあるアイコンをクリックすることで確認することができます。