diff --git a/anki/hooks.py b/anki/hooks.py new file mode 100644 index 000000000..e3dbed778 --- /dev/null +++ b/anki/hooks.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright: Damien Elmes +# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html + +"""\ +Hooks - hook management and tools for extending Anki +============================================================================== + +To find available hooks, grep for runHook in the source code. + +Instrumenting allows you to modify functions that don't have hooks available. +If you call wrap() with pos='around', the original function will not be called +automatically but can be called with _old(). +""" + +# Hooks +############################################################################## + +_hooks = {} + +def runHook(hook, *args): + "Run all functions on hook." + hook = _hooks.get(hook, None) + if hook: + for func in hook: + func(*args) + +def addHook(hook, func): + "Add a function to hook. Ignore if already on hook." + if not _hooks.get(hook, None): + _hooks[hook] = [] + if func not in _hooks[hook]: + _hooks[hook].append(func) + +def removeHook(hook, func): + "Remove a function if is on hook." + hook = _hooks.get(hook, []) + if func in hook: + hook.remove(func) + +# Instrumenting +############################################################################## + +def wrap(old, new, pos="after"): + "Override an existing function." + def repl(*args, **kwargs): + if pos == "after": + old(*args, **kwargs) + new(*args, **kwargs) + elif pos == "before": + new(*args, **kwargs) + old(*args, **kwargs) + else: + new(_old=old, *args, **kwargs) + return repl