# Source code for decorators

    """
    Module containing various decorators
    """

    import common

    class RefreshWrapper(object):
        def __init__(self):
            self.core = None

        def conditional(self, func):
            """
            Decorator to refresh the UI if the wrapped function
            returns True
            """
            def wrap(*args, **kwargs):
                ret = func(*args, **kwargs)
                if self.core and ret:
                    self.core.refresh_window()
                return ret
            return wrap

        def always(self, func):
            """
            Decorator that refreshs the UI no matter what after the function
            """
            def wrap(*args, **kwargs):
                ret = func(*args, **kwargs)
                if self.core:
                    self.core.refresh_window()
                return ret
            return wrap

        def update(self, func):
            """
            Decorator that only updates the screen
            """
            def wrap(*args, **kwargs):
                ret = func(*args, **kwargs)
                if self.core:
                    self.core.doupdate()
                return ret
            return wrap

    refresh_wrapper = RefreshWrapper()

    class CommandArgParser(object):
        """Modify the string argument of the function into a list of strings
        containing the right number of extracted arguments, or None if we don’t
        have enough.
        """
        @staticmethod
        def raw(func):
            """Just call the function with a single string, which is the original string
            untouched
            """
            def wrap(self, args, *a, **kw):
                return func(self, args, *a, **kw)
            return wrap

        @staticmethod
        def ignored(func):
            """
            Call the function without any argument
            """
            def wrap(self, args, *a, **kw):
                return func(self, *a, **kw)
            return wrap

        @staticmethod
        def quoted(mandatory, optional=0, defaults=[],
                   ignore_trailing_arguments=False):

            """The function receives a list with a number of arguments that is between
            the numbers `mandatory` and `optional`.

            If the string doesn’t contain at least `mandatory` arguments, we return
            None because the given arguments  are invalid.

            If there are any remaining arguments after `mandatory` and `optional`
            arguments have been found (and “ignore_trailing_arguments" is not True),
            we happen them to the last argument of the list.

            An argument is a string (with or without whitespaces) between to quotes
            ("), or a whitespace separated word (if not inside quotes).

            The argument `defaults` is a list of strings that are used when an
            optional argument is missing.  For example if we accept one optional
            argument, zero is available but we have one value in the `defaults`
            list, we use that string inplace. The `defaults` list can only
            replace missing optional arguments, not mandatory ones. And it
            should not contain more than `mandatory` values. Also you cannot

            Example:
            This method needs at least one argument, and accepts up to 3
            arguments

            >> @command_args_parser.quoted(1, 2, ['default for first arg'], False)
            >> def f(args):
            >>     print(args)

            >> f('coucou les amis') # We have one mandatory and two optional
            ['coucou', 'les', 'amis']
            >> f('"coucou les amis" "PROUT PROUT"') # One mandator and only one optional,
                                                    # no default for the second
            ['coucou les amis', 'PROUT PROUT']
            >> f('')                # Not enough args for mandatory number
            None
            >> f('"coucou les potes"') # One mandatory, and use the default value
                                       # for the first optional
            ['coucou les potes, 'default for first arg']
            >> f('"un et demi" deux trois quatre cinq six') # We have three trailing arguments
            ['un et demi', 'deux', 'trois quatre cinq six']

            """
            def first(func):
                def second(self, args, *a, **kw):
                    default_args = defaults
                    args = common.shell_split(args)
                    if len(args) < mandatory:
                        return func(self, None, *a, **kw)
                    res, args = args[:mandatory], args[mandatory:]
                    if optional == -1:
                        opt_args = args[:]
                    else:
                        opt_args = args[:optional]

                    if opt_args:
                        res += opt_args
                        args = args[len(opt_args):]
                        default_args = default_args[len(opt_args):]
                    res += default_args
                    if args and res and not ignore_trailing_arguments:
                        res[-1] += " " + " ".join(args)
                    return func(self, res, *a, **kw)
                return second
            return first

    command_args_parser = CommandArgParser()