Anki は、アドオンを作成することで、標準機能を拡張したり、変更したりすることができます。このアドオンの作成を簡単にするために、Anki はフック (Hook) という機能を提供しています。フックを使うと標準機能の中に簡単に外部の関数を組み込むことができます。この記事では更に進んで Anki の標準のフックがない場所にカスタムのフックを追加し、機能拡張するアドオンを作成する方法を簡単に説明します。復習後、熟知になったノートにタグを付けるアドオンを開発します。オフィシャルドキュメント「Anki 2.0 アドオンの作成」を補足する内容です。
この記事は、АnkiWeb に公開済みの Аnki アドオン (Add-on) Mature Tagを例にとって、解説します。
完成品をインストールして動作させることができますし、ソースコードを見ることもできます。最後に作成したアドオンを AnkiWeb の共有アドオン一覧に登録する方法を紹介します。
アドオンのインストール方法は、Ankiの共有リソースを使ってみるで紹介しています。
また、ソースコードの表示方法は、インストールが完了した後、メニューバーの[ツール]-[アドオン]-[Mature_Tag]-[編集…]を選択してください。
目次
この記事の内容を理解するには、次の知識が必要です。
Anki の操作方法
特に、Anki というアプリケーションの機能を十分理解した上での操作方法の習熟は必須です。
Python による開発経験
他の開発言語の経験でも構いませんが、自分で資料を読み Python の開発方法を学べる能力は必要です。
Anki 2.0 アドオンの作成の内容理解
本文中のサンプルコードを実際に動かしてアドオンを作成する経験があると理解に役立ちます。
この記事の最後に Anki アドオン開発のおさらい という項目を設けて、必要な知識をまとめています。
まず最初にアドオンの要件を決めておきます。
「復習が終わったら、新たに設定した復習間隔を調べ、熟知なら “Mature” というタグをノートに追加し、それ以外なら “Mature” を削除します。」
最初に必要なモジュールをインポートします。
Anki の復習で解答した時の処理は sched.py の中のクラス Scheduler のメソッド answerCard で記述しています。
from anki.sched import Scheduler
残念ながら復習に関する処理の中にフック (Hook) は存在しません。そこで独自のフックをこのメソッドの最後に追加します。
フックの設置、呼び出しに必要なモジュールをインポートします。
from anki.hooks import addHook, runHook, wrap
もちろん answerCard を書き換えることもできますが、今回の様な条件では独自フックの設置したほうが簡単に記述できます。
まず、独自のフック “anseweredRevCard” を追加する関数 newAnswerCard() を定義します。
runHook() はフックを新たに設置する標準の関数です。
def newAnswerCard(self, card, ease):
runHook('anseweredRevCard', self, card)
次に標準の wrap() 関数を使って、answerCard の後に newAnswerCard の内容を追加する処理を記述します。
Scheduler.answerCard = wrap(Scheduler.answerCard, newAnswerCard)
すると answerCard の最後に次の行が追加されます。
runHook('anseweredRevCard', self, card)
これで、復習で解凍した後に処理を呼び出すフックを設置できました。
復習が終わったら、復習間隔を調べ 21 日以上であったら、”Mature” タグを追加し、それ以外の場合は削除する関数 matureCheck() を定義します。
熟知の基準日数は変数 threshold に、設定するタグ文字列は変数 MatureTag に設定しました。
タグをノートに追加するには Note クラスのメソッド addTag() を、削除するには delTag() を使います。
# Threshold interval for tagging
threshold = 21
# Tag string for mature note
MatureTag = u"Mature"
def matureCheck(self, card):
f = card.note()
if (card.ivl >= threshold):
f.addTag(MatureTag)
else:
f.delTag(MatureTag)
f.flush()
return True
最後に addHook() 関数を使って上で作成したカスタムフック “anseweredRevCard” で matureCheck() 関数を呼び出す設定をします。
addHook("anseweredRevCard", matureCheck)
これで、完成です。完成品は次の通りです。
from anki.hooks import addHook, runHook, wrap
from anki.sched import Scheduler
# Threshold interval for tagging
threshold = 21
# Tag string for mature note
MatureTag = u"Mature"
def matureCheck(self, card):
f = card.note()
if (card.ivl >= threshold):
f.addTag(MatureTag)
else:
f.delTag(MatureTag)
f.flush()
return True
def newAnswerCard(self, card, ease):
runHook('anseweredRevCard', self, card)
Scheduler.answerCard = wrap(Scheduler.answerCard, newAnswerCard)
addHook("anseweredRevCard", matureCheck)
実は、フックを設置せずに記述を簡略化できます。メソッドを上書きする方法です。
wrap() 関数で直接 matureCheck を指定します。
- def newAnswerCard(self, card, ease):
- runHook('anseweredRevCard', self, card)
- Scheduler.answerCard = wrap(Scheduler.answerCard, newAnswerCard)
+ Scheduler.answerCard = wrap(Scheduler.answerCard, matureCheck)
- addHook("anseweredRevCard", matureCheck)
この場合は、フックを使わないので、他の関数も追加で呼び出すような追加拡張はできません。
完成したファイル Mature_Tag.py を動作させるには、Documents/Anki/addons フォルダの中に保存します。Anki を再起動すると、この Python スクリプトファイルを読み込みます。
アドオンが読み込まれるとメニューバーに [ツール]-[アドオン]-[Mature_Tag] という項目が追加されます。
作成したアドオンを AnkiWeb に公開して、アドオン一覧に登録する方法を紹介します。
まず、共有アドオン一覧を開き、AnkiWeb にサインインします。
登録フォームは画面右上の [Upload Add-on] ボタンをクリックすると表示します。
このフォームでは次のように項目入力します。
Title: アドオンの名前を入力します。アドオン一覧に表示する名前にになります。
File: 登録したいアドオンの Python スクリプトを選択します。今回の例では Mature_Tag.py です。
Description アドオンユーザーのためにアドオンの機能や使い方の説明を入力します。
入力が済んだら [Upload] を押すと登録できます。特に AnkiWeb に障害がなければ即座に公開されます。
登録したアドオンのページに移動します。
公開したアドオンのページの下にある [Update] ボタンを押すと登録内容の編集ができ、[Remove] ボタンを押すとアドオンを削除することができます。
「Anki 2.0 アドオンの作成」で説明しているとおり、Anki が標準で用意しているフックを利用すると Anki の機能の修正や追加が簡単になります。フックが用意されていない箇所にも、この記事で紹介した方法で自分でカスタムのフックを自由に追加することができます。フックの使い方になれると Anki アドオン作成するを能力が向上し、Anki 自身の機能についても理解を深めることができます。
Anki のアドオンは、Python スクリプトで記述し、Documents/Anki/addons フォルダの中に保存します。
Anki に Python インタープリタが含まれているため、アドオンの開発に Python のインストールは必要ありません。
Anki は起動時に addons フォルダの中の .py ファイルを読み込みます。
従って、新たにアドオンファイルを追加した場合、再起動して初めて機能するようになります。
なお、シフトキーを押したまま Anki を起動すると、アドオンファイルの読み込みは行いません。
Anki には、WordPress のようにフック (Hook) という機能を提供していて、標準機能を拡張したり、変更したりするアドオン開発が容易にできます。Anki 自身もたくさんのフックを利用しています。
アドオンをつくるために Anki が用意している関数は次の通りです。
| 関数名 | 説明 |
|---|---|
| runHook | フックを実行する。値は返さない。 |
| runFilter | フィルターを実行し値を返す。 |
| addHook | フックを追加する。 |
| remHook | フックを削除する。 |
| wrap | 既存の関数を上書きする。第3引数でオリジナルの関数の位置を指定。既定はオリジナルの後にカスタム関数を実行する。 |
フックを見つけるには、Anki のソースコードを ”runHook”、”runFilter” で検索します。Anki 2.0.20 現在 36 のフックが存在します。
フックの使い方を詳しく知るには、Anki 2.0 アドオンの作成、および anki/hooks.py をお読みください。