Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

emojiIME

CI

macOS 用の絵文字入力専用メソッド(IME)。 InputMethodKit フレームワークを使用し、キーワード入力で絵文字を検索・入力する。IME 切り替えで絵文字入力モードに移行する設計。

概要

  • IME を切り替えるだけで絵文字入力モードに移行、キーワードを入力すると即座に候補を表示
  • ローマ字入力で日本語と英語の両方から絵文字を検索(例: smile → 😀😊、neko → 🐱🐈)
  • SQLite3 ベースの絵文字データベース(CLDR データ利用、約 3,700 絵文字)
  • 使用頻度による学習機能(候補の並び順に反映)、メニューから学習データのリセットが可能
  • メニューバーにアイコンを表示(ダーク/ライトモード自動対応)
  • メニュー・ダイアログの多言語対応(日本語/英語)

動作環境

  • macOS 14.0 以降
  • Xcode 15.4 以降
  • Swift 5.0 / C++17 以降

キー操作

キー 状態 動作
英字 / - / _ 待機中 絵文字検索を開始、候補を逐次表示
英字 / - / _ 検索中 検索キーワードに追加、候補を逐次更新
Enter(候補あり) 検索中 先頭候補を確定
Space / Tab / ↓ 検索中 候補選択モードに遷移
Escape 検索中 検索をキャンセル
Delete 検索中 バッファ末尾を削除(空になったらキャンセル)
↓ / Space / Tab 候補選択中 次の候補へ移動
↑ / Shift+Space / Shift+Tab 候補選択中 前の候補へ移動
Enter 候補選択中 選択中の候補を確定(使用回数を記録)
Escape 候補選択中 検索モードに戻る
Delete 候補選択中 検索モードに戻り末尾を削除
マウスクリック 候補選択中 候補を直接選択・確定
Command+Enter 検索中/候補選択中 検索をキャンセル

入力例

英語キーワード:
  smile   → 😀😊😄 等の候補を表示
  heart   → ❤️💜💙 等の候補を表示
  cat     → 🐱🐈 等の候補を表示

日本語キーワード(ローマ字入力で日本語の絵文字名も検索):
  neko    → 🐱🐈 等
  egao    → 😀😃😄 等
  sakura  → 🌸
  sakana  → 🐟🐠🐡 等
  hana    → 💐🌸🌹 等
  inu     → 🐶🐕🐩 等
  kuruma  → 🚗🚕🚙 等
  ongaku  → 🎵🎶🎤 等
  taiyou  → 🌞🌅 等
  densha  → 🚃🚄🚅 等

初回セットアップ

絵文字データベース(emoji.db)とメニューバーアイコン(emoji_icon.tiff)はリポジトリに含まれているため、クローン後すぐにビルド・インストールできる。

./install.sh

絵文字 DB の再生成

CLDR データを更新したい場合や、対応ロケールを変更したい場合は build_db.sh で再生成できる。

./build_db.sh                    # デフォルト(ja en ロケール)
./build_db.sh --locales ja en zh  # ロケールを指定

build_db.sh は初回実行時に data/cldr-json/(約 1GB)と data/emoji-test.txt を自動取得する。これらの元データは .gitignore で除外されている。

メニューバーアイコンの再生成

swift tools/generate_icon.swift emojiIME/emoji_icon.tiff

ビルド・インストール

install.sh(推奨)

ビルド → インストール → プロセス再起動を一括実行するシェルスクリプト。

./install.sh           # Debug ビルド(デフォルト)
./install.sh Release   # Release ビルド

処理内容:

  1. xcodebuild でビルド
  2. rm -rfcp -R~/Library/Input Methods/ にインストール
  3. lsregister -f + TISRegisterInputSource で入力ソースキャッシュを更新
  4. pkill でプロセス再起動(macOS が自動的に再起動)

手動ビルド

cd emojiIME
xcodebuild -project emojiIME.xcodeproj -scheme emojiIME -configuration Debug build

Xcode の場合: emojiIME.xcodeproj を開き、Product → Build(⌘B)

ビルド成果物は build/Build/Products/Debug/emojiIME.app に生成される。

手動インストール

# 旧バージョンを削除(Info.plist を確実に更新するため rm -rf が必要)
rm -rf ~/Library/Input\ Methods/emojiIME.app

# ビルド成果物をコピー
cp -R build/Build/Products/Debug/emojiIME.app ~/Library/Input\ Methods/

入力ソースの追加手順(初回のみ)

インストール後、ログアウト → ログイン(または再起動)を行い、以下の手順で入力ソースを追加する。

  1. システム設定キーボード入力ソース編集...
  2. 左下の + ボタン
  3. その他 カテゴリから emojiIME を選択して追加

プロセスの再起動

IME プロセスは macOS によって自動管理されている。コード変更を反映するには、プロセスを終了して再起動させる必要がある。

方法 1: pkill(推奨)

pkill -f emojiIME

macOS が自動的にプロセスを再起動する。

方法 2: アクティビティモニタ

  1. アクティビティモニタを開く
  2. emojiIME を検索
  3. プロセスを選択して ×(強制終了)ボタン

方法 3: ログアウト / ログイン

確実にすべてのキャッシュをクリアしたい場合は、ログアウト→ログインを行う。Info.plist の変更(入力ソースカテゴリ変更等)を反映する場合はこの方法が必要。

注意事項

  • cp -R だけでは既存の .app バンドル内の Info.plist が正しく上書きされない場合がある。アップデート時は必ず rm -rfcp -R の順で行う
  • LaunchServices の登録情報は lsregister で更新できるが、入力ソースの表示名・カテゴリの変更はログアウト/ログインが必要な場合がある

プロジェクト構成

emojiIME/
├── emojiIME.xcodeproj/
│   └── project.pbxproj
├── emojiIME/
│   ├── AppDelegate.swift              # アプリエントリポイント、IMKServer 起動
│   ├── EmojiInputController.swift     # IMKInputController サブクラス(イベント処理・絵文字検索)
│   ├── RomajiConverter.swift          # C++ 実装の Swift ラッパー(二段検索用)
│   ├── RomajiConverter.cpp            # ローマ字→ひらがな変換エンジン(C++ 実装)
│   ├── RomajiConverter.h              # C 言語インターフェース(extern "C")
│   ├── EmojiDB.cpp                    # 絵文字 DB C++ 実装(EmojiDBImpl, ATTACH パターン)
│   ├── EmojiDB.h                      # 絵文字 DB extern "C" インターフェース
│   ├── EmojiDB.swift                  # 絵文字 DB Swift ラッパー
│   ├── emoji.db                       # 絵文字データベース(CLDR データ、ビルド時バンドル)
│   ├── emoji_icon.tiff                # メニューバーアイコン(SF Symbols から生成したテンプレートイメージ)
│   ├── emojiIME-Bridging-Header.h     # Swift-C ブリッジヘッダー
│   ├── en.lproj/
│   │   ├── InfoPlist.strings          # 入力ソース表示名(英語)
│   │   └── Localizable.strings        # UI 文字列(英語)
│   ├── ja.lproj/
│   │   ├── InfoPlist.strings          # 入力ソース表示名(日本語)
│   │   └── Localizable.strings        # UI 文字列(日本語)
│   ├── Info.plist                     # InputMethodKit 設定
│   └── emojiIME.entitlements          # Mach ポート登録権限
├── data/
│   ├── emoji-test.txt                 # Unicode 絵文字テストデータ(Emoji 15.1)
│   ├── cldr-json/                     # CLDR annotations(unicode-org/cldr-json リポジトリ)
│   └── keyword.txt                    # 全キーワードリスト(build_db.sh で自動生成)
├── tools/
│   ├── build_emoji_db.py              # 絵文字 DB 生成ツール(Python)
│   ├── tis_register.swift             # TISRegisterInputSource ヘルパー(Swift)
│   ├── tis_register                   # tis_register コンパイル済みバイナリ
│   └── generate_icon.swift            # SF Symbols → TIFF アイコン生成ツール(Swift)
├── install.sh                         # ビルド・インストール・キャッシュ更新・再起動スクリプト
└── build_db.sh                        # 絵文字 DB 生成スクリプト

アーキテクチャ

┌──────────────────────────────────────────────────────────┐
│  macOS InputMethodKit                                     │
│    └─ IMKServer / IMKInputController / IMKCandidates      │
├──────────────────────────────────────────────────────────┤
│  EmojiInputController.swift                               │
│    ├─ ステートマシン (none → emojiComposing → emojiSelecting) │
│    ├─ 二段検索 (ja: ひらがな + en: ローマ字)                │
│    └─ 候補選択・確定・学習                                │
├──────────────────────────────────────────────────────────┤
│  RomajiConverter.cpp (C++ 実装)                           │
│    ├─ RomajiConverterImpl クラス                          │
│    │   ├─ conversionTable (unordered_map)                │
│    │   └─ resolveBuffer() — バッファ解決ロジック            │
│    └─ extern "C" 関数群 (void* opaque pointer)           │
├──────────────────────────────────────────────────────────┤
│  EmojiDB.cpp (C++17 実装)                                 │
│    ├─ EmojiDBImpl クラス(SQLite3, ATTACH パターン)        │
│    │   ├─ search / searchPrefix — 完全一致・前方一致検索    │
│    │   ├─ recordUsage — 学習(使用回数記録)               │
│    │   └─ emoji.db (bundle) + emoji_user.db (user)       │
│    └─ extern "C" 関数群                                   │
└──────────────────────────────────────────────────────────┘

ステートマシン

                  ┌──────────────────────────────────────────┐
                  │                                          │
none ──(英字)──→ emojiComposing ──(Space/Tab/↓)──→ emojiSelecting
                  │                                    │
                  │←──────────(Escape/Delete)───────────┘
                  │
              (文字入力) → performEmojiSearch() → 候補リスト更新
                  │
              (Enter) → 先頭候補を確定

二段検索の仕組み

ユーザーのキー入力に対し、日本語と英語の両方で検索を行い結果をマージする。 日本語検索では、内部的に RomajiConverter(C++ 実装、hiragaIME から流用)でローマ字→ひらがな変換を行い、日本語 term を検索する。ユーザーの画面にはローマ字のまま表示され、ひらがなは見えない。

ユーザーが "smile" と入力:
  ├─ ① ローマ字バッファ "smile" → en 検索 → "smile" にヒット ✓
  └─ ② ひらがな変換結果 "すみぇ" → ja 検索 → ヒットなし ✗
  → ①の候補を表示(😀😊 等)

ユーザーが "neko" と入力:
  ├─ ① ローマ字バッファ "neko" → en 検索 → ヒットなし ✗
  └─ ② ひらがな変換結果 "ねこ" → ja 検索 → "ねこ" にヒット ✓
  → ②の候補を表示(🐱🐈 等)

日本語キーワードの到達可能性

日本語キーワードはローマ字入力→ひらがな変換を経由して検索される。そのため漢字・カタカナ・数字を含むキーワードにはローマ字入力から到達できない。

DB 内の日本語キーワード 5,168 件のうち、到達可能なのは約 1,411 件(ひらがなのみ)。

変換できる例(ひらがなのみの term_norm):

ローマ字入力 ひらがな変換 ヒットする絵文字
neko ねこ 🐱🐈
hana はな 💐🌸🌹
inu いぬ 🐶🐕🐩
sakura さくら 🌸
aisatsu あいさつ 👋
egao えがお 😀😃😄
azarashi あざらし 🦭

変換できない例(漢字・カタカナ・数字を含む term_norm):

term_raw term_norm 理由
2位 2位 数字+漢字
10時 10時 数字+漢字
0系新幹線 0系新幹線 数字+漢字
100点満点 100点満点 数字+漢字
2人でキス 2人できす 数字+漢字(term_norm にひらがな以外を含む)

現在到達できないキーワードも、将来の拡張(漢字変換対応、カタカナ入力対応等)に備えてデータベースに残している。

Info.plist 設定

InputMethodKit に必要な設定:

キー 説明
InputMethodConnectionName com.mitsuruk.inputmethod.emojiIME_Connection IMKServer の Mach ポート名
InputMethodServerControllerClass $(PRODUCT_MODULE_NAME).EmojiInputController コントローラクラス名
TISInputSourceLocalizedName emojiIME 入力ソースの表示名
tsInputModeScriptKey smUnicodeScript 入力ソースを「その他」カテゴリに配置
TISIntendedLanguage und 特定言語に紐付けない
tsInputMethodIconFileKey emoji_icon.tiff メニューバーアイコン
tsInputModeMenuIconFileKey emoji_icon.tiff 入力モードのメニューバーアイコン
tsInputMethodCharacterRepertoireKey Latn ラテン文字入力
LSUIElement true Dock に表示しない
CFBundleIdentifier com.mitsuruk.inputmethod.emojiIME .inputmethod. を含む必要あり

アイコン仕様

メニューバーアイコン (emoji_icon.tiff)

項目 仕様
ファイル形式 TIFF(PNG も可)
サイズ 16×16 pt(1x: 16×16px, 2x: 32×32px)
解像度 1x: 72dpi, 2x: 144dpi
カラー 黒一色 + 透明背景(テンプレートイメージ)
アルファ 必須(背景は透明)
色空間 sRGB / DeviceRGB
備考 macOS がダーク/ライトモードに応じて自動着色する。マルチ解像度(1x + 2x)を 1 つの TIFF にまとめるのが理想

配置先: emojiIME/emoji_icon.tiff → バンドルの Contents/Resources/ にコピーされる。

現在は tools/generate_icon.swift で SF Symbols number.square.fill から自動生成している。

swift tools/generate_icon.swift emojiIME/emoji_icon.tiff

カスタムアイコンに差し替える場合は、上記仕様に従った TIFF ファイルを emojiIME/emoji_icon.tiff に上書きする。

注意: メニューバーアイコンの変更を反映するには logout → login が必要(InputMethodKit の制約)。

設計判断

項目 選択 理由
イベント処理方式 handleEvent(_:client:) 修飾キーを含むすべてのキーイベントを制御可能
候補ウィンドウ IMKCandidates(システム提供) カスタムウィンドウより実装が簡潔
絵文字 DB エンジン C++17 + SQLite3 macOS フレームワーク非依存、高速検索
Swift-C++ 連携 Bridging Header + extern "C" Swift/C++ interop より広い互換性
検索方式 二段検索(ja + en) モード切替不要で日英両方の入力に対応
学習機能 use_count によるソート 頻繁に使う絵文字が上位に表示される
RomajiConverter 保持 二段検索に必要 hiragaIME のコードを流用し、ローマ字→ひらがな変換で日本語 term を検索
英字以外のパススルー return false 記号・数字等は通常入力として処理
クラス名属性 @objc(EmojiInputController) Swift 名前マングリングを回避

絵文字データベース

build_db.sh

絵文字データベース(emoji.db)を生成するシェルスクリプト。

./build_db.sh                    # デフォルト(ja en ロケール)
./build_db.sh --no-pykakasi      # pykakasi をスキップ
./build_db.sh --locales ja en zh  # ロケールを指定

処理内容:

  1. 元データの自動取得(data/emoji-test.txt, data/cldr-json/ が無い場合)
  2. tools/build_emoji_db.py を実行して emojiIME/emoji.db を生成
  3. 全キーワードリストを data/keyword.txt に出力

pykakasi は漢字→ひらがな変換を行う Python ライブラリ。CLDR の日本語キーワードには漢字を含むもの(例: "笑顔", "自動車")があり、pykakasi でひらがな読み("えがお", "じどうしゃ")を生成して DB に登録する。これにより、ローマ字入力から漢字キーワードにも到達できる。未インストールの場合は自動的にスキップされる(pip install pykakasi でインストール)。

生成後は ./install.sh で再ビルド・インストールする。

データベースの設計・スキーマ・データ取得方法の詳細は EmojiDB.md を参照。

hiragaIME との関係

本プロジェクトは 現時点では非公開のhiragaIME(実験中のプロジェクト)から絵文字入力機能のみを抽出して作成した。hiragaIME は macOS 用ひらがな入力 IME のプロトタイプであり、RomajiConverter や EmojiDB 等のコードを本プロジェクトで流用している。

項目 hiragaIME emojiIME
ローマ字→ひらがな変換 あり(画面に表示) 内部のみ(画面には非表示)
絵文字検索 : トリガー 即時検索(トリガー不要)
ステートマシン 5 状態(none, composing, selecting, emojiComposing, emojiSelecting) 3 状態(none, emojiComposing, emojiSelecting)
RomajiConverter ひらがな変換 + 二段検索 二段検索のみ
メニューバーアイコン 「ひ」 SF Symbols number.square.fill
バンドル識別子 com.mitsuruk.inputmethod.hiragaIME com.mitsuruk.inputmethod.emojiIME

学習リセット

メニューバーの emojiIME アイコンを クリック、Ctrl+クリック(または右クリック)すると、メニューが表示される。「絵文字の学習をリセット」(英語環境では "Reset Emoji Learning Data")を選択すると、確認ダイアログの後に使用頻度データ(emoji_user.db)をすべて削除できる。

メニューとダイアログの文字列は NSLocalizedString で多言語対応しており、日本語環境では日本語、それ以外の環境では英語で表示される。ローカライズファイルは en.lproj/Localizable.stringsja.lproj/Localizable.strings に配置されている。

CLDR データ

概要

本プロジェクトの絵文字キーワードは Unicode CLDR (Common Locale Data Repository) から取得している。CLDR は Unicode Consortium が管理する、世界最大のロケールデータリポジトリであり、Apple・Google・Microsoft・Meta 等が利用している。

本プロジェクトでは CLDR の annotations(絵文字に対するキーワードと短い説明文)を使用し、build_db.shunicode-org/cldr-json リポジトリから取得する。

使用しているデータ

データ 説明 取得元
cldr-annotations-full 絵文字のキーワード(tts, annotations) cldr-json/cldr-json/cldr-annotations-full/
cldr-annotations-derived-full 派生キーワード(skin tone 等のバリエーション) cldr-json/cldr-json/cldr-annotations-derived-full/

ライセンス

CLDR データは Unicode License V3(SPDX: Unicode-3.0)の下で提供されている。

  • 使用・コピー・改変・配布・販売が無償で許可される
  • 著作権表示とライセンス表示の保持が必要
  • 「AS IS」提供(無保証)

詳細: https://www.unicode.org/license.txt

About

絵文字入力 IME

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages