Poof — macOS テキストスニペット展開ツール
概要
PoofはmacOS上で動作するテキストスニペット(定型文)展開ツールです。ユーザーが設定したトリガー文字列を入力すると、それを指定のプレースホルダやテキストに置き換えることができます。グローバルに入力を監視しているため、どのアプリケーションでも動作する点が特徴です。展開の挙動には「区切り文字で確定する」モードと「トリガー入力完了で即時展開」モードの2種類があり、用途に応じて使い分けられます。設定はTOML形式のファイルで管理され、ユーザーが好きなディレクトリから読み込めるため、dotfilesで一元管理する運用にも向いています。
リポジトリの統計情報
- スター数: 8
- フォーク数: 0
- ウォッチャー数: 8
- コミット数: 15
- ファイル数: 15
- メインの言語: Swift
主な特徴
- グローバルなスニペット展開:どのアプリケーションでもトリガーに応じて展開可能。
- 2つの展開モード:区切り文字確定型と即時展開型をサポートし、用途に応じて切替可能。
- TOMLベースの設定:[[snippets]] エントリでトリガー・置換・説明を定義し、任意ディレクトリから読み込み可。
- dotfilesフレンドリー:設定ファイルを好きな場所に置けるため、設定のバージョン管理や同期が容易。
技術的なポイント
PoofはSwiftで実装されており、プロジェクトにPackage.resolvedが含まれていることからSwift Package Manager(SPM)との連携が想定されます。グローバルなテキスト展開を実現するにはシステム全体の入力を監視する必要があるため、一般にmacOSのアクセシビリティAPIやイベントタップ(CGEventTap)を使ったキー監視/注入の仕組みが用いられます。設定はTOMLファイルで記述され、[[snippets]]配列でtrigger/replace/descriptionを定義するシンプルな構造です。区切り文字モードでは、トリガー後に特定の区切り(スペースやタブなど)を検出して展開するため誤爆が抑えられ、即時モードは入力の利便性を優先します。実装面では、文字列マッチングの効率化(末尾一致や最長一致の判定)、入力イベントのバッファ管理、クリップボードや入力ソースへの影響を最小限にするテキスト置換ロジックが重要になります。また、設定ファイルを任意のディレクトリから読み込めるため、ファイル監視(変更検知)やパース処理(TOMLライブラリの利用)、エラーハンドリング(不正なTOMLや重複トリガーの検出)も実装上の注目点です。セキュリティ面では、グローバル入力を扱う特性上、macOSの権限設定(アクセシビリティ権限)やサンドボックスの制約に配慮した設計が求められ、配布時の権限案内やユーザーへの説明が必要になります。CI/ビルド関連ではJustfileや.suite.ymlが含まれており、開発・テスト・ビルドの自動化に対応していることが伺えます。
プロジェクトの構成
主要なファイルとディレクトリ:
- .gitignore: file
- .suite.yml: file
- CHANGELOG.md: file
- Justfile: file
- Package.resolved: file
…他 10 ファイル
まとめ
軽量で設定が分かりやすく、dotfiles管理に向いたmacOS用スニペット展開ツール。
リポジトリ情報:
- 名前: Poof
- 説明: macOS text snippet expander
- スター数: 8
- 言語: Swift
- URL: https://github.com/mikker/Poof
- オーナー: mikker
- アバター: https://avatars.githubusercontent.com/u/2819?v=4
READMEの抜粋:

Poof is a macOS text snippet expander.
- Global snippet expansion via typed triggers
- Two modes:
- Delimiter mode: expand after trigger + delimiter
- Immediate mode: expand as soon as trigger is fully typed
- TOML-driven config from a user-selectable directory (keep in your dotfiles)
TOML config format
Use [[snippets]] entries in any .toml file:
[[snippets]]
trigger = ":date"
replace = "{{date}}"
description = "Current date"
...