alias.py 5.38 KB
Newer Older
1
"""
mathieui's avatar
mathieui committed
2 3 4 5 6 7 8 9 10 11
Usage
-----

This plugin defines two new global commands: :term:`/alias` and :term:`/unalias`.

.. glossary::

    /alias
        **Usage:** ``/alias <name> <command> [args]``

12 13 14 15 16
        This command will create a new command, named ``<name>`` (and callable
        with ``/name``), that runs ``/command``, with ``[args]`` as fixed
        args for the command.
        When you run the alias, you can also pass parameters to it, that will be
        given to the original command.
mathieui's avatar
mathieui committed
17 18 19

        Example: ::

20
            /alias toto say koin
mathieui's avatar
mathieui committed
21

22
        Will bind ``/say koin`` to ``/toto``, so this alias will work in any
mathieui's avatar
mathieui committed
23 24 25 26 27 28
        Chat tab. If someone calls it with ::

            /toto koin

        Poezio will then execute ``/say koin koin``.

29 30 31 32 33 34 35 36 37 38 39 40
        Also, you can rebind arguments arbitrarily, with the ``{}`` placeholder.
        For example, ::

            /alias toto say {} le {}
            /toto loulou coucou

        Will execute ``/say loulou le coucou``, because the ``{}`` are
        replaced with the command args, in the order they are given.

        Extra args are still added at the end of the command if provided
        (args used for the formatting are only used for the formatting).

mathieui's avatar
mathieui committed
41 42 43 44
    /unalias
        **Usage:** ``/unalias <name>``

        This command removes a defined alias.
45

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

Config
------

The aliases are stored inside the configuration file for the plugin.
You can either use the above commands or write it manually, and it
will be read when the plugin is loaded.


Example of the syntax:

.. code-block:: ini

    [alias]
    toto = say {} le {}
    j = join {}@conference.jabber.org/nick
    jp = say je proteste


65 66
"""

67 68 69



mathieui's avatar
mathieui committed
70
from plugin import BasePlugin
71
from common import shell_split
mathieui's avatar
mathieui committed
72

mathieui's avatar
mathieui committed
73 74 75

class Plugin(BasePlugin):
    def init(self):
76
        self.api.add_command('alias', self.command_alias,
77 78 79
                usage='<alias> <command> [args]',
                short='Create an alias command',
                help='Create an alias for <command> with [args].')
80
        self.api.add_command('unalias', self.command_unalias,
81 82 83 84
                usage='<alias>',
                help='Remove a previously created alias',
                short='Remove an alias',
                completion=self.completion_unalias)
mathieui's avatar
mathieui committed
85
        self.commands = {}
86 87 88 89 90 91 92 93
        self.load_conf()

    def load_conf(self):
        """
        load stored aliases on startup
        """
        for alias in self.config.options():
            full = self.config.get(alias, '')
mathieui's avatar
mathieui committed
94 95
            if full:
                self.command_alias(alias + ' ' + full)
mathieui's avatar
mathieui committed
96 97

    def command_alias(self, line):
98 99 100
        """
        /alias <alias> <command> [args]
        """
101 102
        arg = split_args(line)
        if not arg:
103
            self.api.information('Alias: Not enough parameters', 'Error')
mathieui's avatar
mathieui committed
104
            return
105
        alias, command, args = arg
mathieui's avatar
mathieui committed
106

107 108 109
        if alias in self.commands:
            update = True
        elif alias in self.core.commands:
110
            self.api.information('Alias: command already exists', 'Error')
mathieui's avatar
mathieui committed
111
            return
112 113 114 115 116 117 118
        else:
            update = False

        self.config.set(alias, command + ' ' + args)
        self.commands[alias] = command_wrapper(generic_command, lambda: self.get_command(command), args)
        self.api.del_command(alias)
        self.api.add_command(alias, self.commands[alias], 'This command is an alias for /%s %s' %(alias, command))
119

120 121 122 123
        if update:
            self.api.information('Alias /%s updated' % alias, 'Info')
        else:
            self.api.information('Alias /%s successfuly created' % alias, 'Info')
mathieui's avatar
mathieui committed
124 125

    def command_unalias(self, alias):
126 127 128
        """
        /unalias <existing alias>
        """
mathieui's avatar
mathieui committed
129 130
        if alias in self.commands:
            del self.commands[alias]
131
            self.api.del_command(alias)
mathieui's avatar
mathieui committed
132 133
            self.config.set(alias, '')
            self.config.write()
134
            self.api.information('Alias /%s successfuly deleted' % alias, 'Info')
mathieui's avatar
mathieui committed
135

136
    def completion_unalias(self, the_input):
137
        "Completion for /unalias"
138 139 140 141
        aliases = [alias for alias in self.commands]
        aliases.sort()
        return the_input.auto_completion(aliases, '', quotify=False)

mathieui's avatar
mathieui committed
142 143 144 145 146 147 148
    def get_command(self, name):
        """Returns the function associated with a command"""
        def dummy(args):
            """Dummy function called if the command doesn’t exist"""
            pass
        if name in self.core.commands:
            return self.core.commands[name][0]
149 150
        elif name in self.api.current_tab().commands:
            return self.api.current_tab().commands[name][0]
mathieui's avatar
mathieui committed
151
        return dummy
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

def split_args(line):
    """
    Extract the relevant vars from the command line
    """
    arg = line.split()
    if len(arg) < 2:
        return None
    alias_pos = line.find(' ')
    alias = line[:alias_pos]
    end = line[alias_pos+1:]
    args_pos = end.find(' ')
    command = end[:args_pos]
    args = end[args_pos+1:]
    return (alias, command, args)

def generic_command(command, extra_args, args):
    """
    Function that will execute the command and set the relevant
    parameters (format string, etc).
    """
    args = shell_split(args)
    new_extra_args = extra_args.format(*args)
    count = extra_args.count('{}')
    args = args[count:]
    new_extra_args += ' '.join(args)
    return command()(new_extra_args)

def command_wrapper(func, command, extra_args):
    "set the predefined arguments"
    def wrapper(*args, **kwargs):
        return func(command, extra_args, *args, **kwargs)
    return wrapper