summaryrefslogtreecommitdiff
path: root/poezio/decorators.py
diff options
context:
space:
mode:
authorEmmanuel Gil Peyrot <linkmauve@linkmauve.fr>2016-03-31 18:54:41 +0100
committerEmmanuel Gil Peyrot <linkmauve@linkmauve.fr>2016-06-11 20:49:43 +0100
commit332a5c2553db41de777473a1e1be9cd1522c9496 (patch)
tree3ee06a59f147ccc4009b35cccfbe2461bcd18310 /poezio/decorators.py
parentcf44cf7cdec9fdb35caa372563d57e7045dc29dd (diff)
downloadpoezio-332a5c2553db41de777473a1e1be9cd1522c9496.tar.gz
poezio-332a5c2553db41de777473a1e1be9cd1522c9496.tar.bz2
poezio-332a5c2553db41de777473a1e1be9cd1522c9496.tar.xz
poezio-332a5c2553db41de777473a1e1be9cd1522c9496.zip
Move the src directory to poezio, for better cython compatibility.
Diffstat (limited to 'poezio/decorators.py')
-rw-r--r--poezio/decorators.py139
1 files changed, 139 insertions, 0 deletions
diff --git a/poezio/decorators.py b/poezio/decorators.py
new file mode 100644
index 00000000..c4ea6563
--- /dev/null
+++ b/poezio/decorators.py
@@ -0,0 +1,139 @@
+"""
+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()