summaryrefslogtreecommitdiff
path: root/qutebrowser/api/hook.py
blob: 9a1a7bc9cc522ca2e098a74907fbdba8527fa372 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# SPDX-FileCopyrightText: Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# SPDX-License-Identifier: GPL-3.0-or-later

# pylint: disable=invalid-name

"""Hooks for extensions."""

import importlib
from typing import Callable, Any


from qutebrowser.extensions import loader


def _add_module_info(func: Callable[..., Any]) -> loader.ModuleInfo:
    """Add module info to the given function."""
    module = importlib.import_module(func.__module__)
    return loader.add_module_info(module)


class init:

    """Decorator to mark a function to run when initializing.

    The decorated function gets called with a
    :class:`qutebrowser.api.apitypes.InitContext` as argument.

    Example::

        @hook.init()
        def init(_context):
            message.info("Extension initialized.")
    """

    def __call__(self, func: loader.InitHookType) -> loader.InitHookType:
        info = _add_module_info(func)
        if info.init_hook is not None:
            raise ValueError("init hook is already registered!")
        info.init_hook = func
        return func


class config_changed:

    """Decorator to get notified about changed configs.

    By default, the decorated function is called when any change in the config
    occurs::

        @hook.config_changed()
        def on_config_changed():
            ...

    When an option name is passed, it's only called when the given option was
    changed::

        @hook.config_changed('content.javascript.enabled')
        def on_config_changed():
            ...

    Alternatively, a part of an option name can be specified. In the following
    snippet, ``on_config_changed`` gets called when either
    ``bindings.commands`` or ``bindings.key_mappings`` have changed::

        @hook.config_changed('bindings')
        def on_config_changed():
            ...
    """

    def __init__(self, option_filter: str = None) -> None:
        self._filter = option_filter

    def __call__(
        self,
        func: loader.ConfigChangedHookType,
    ) -> loader.ConfigChangedHookType:
        info = _add_module_info(func)
        info.config_changed_hooks.append((self._filter, func))
        return func