Decorator to declare custom function or custom class as a new textops op

    the custom function/class will receive the whole raw input text at once.

    Examples:

        >>> @add_textop
        ... def repeat(text, n, *args,**kwargs):
        ...     return text * n
        >>> 'hello' | repeat(3)
        'hellohellohello'

        >>> @add_textop
        ... class cool(TextOp):
        ...     @classmethod
        ...     def op(cls, text, *args,**kwargs):
        ...         return text + ' is cool.'
        >>> 'textops' | cool()
        'textops is cool.'

def add_textop(class_or_func):
    """Decorator to declare custom function or custom class as a new textops op

    the custom function/class will receive the whole raw input text at once.

    Examples:

        >>> @add_textop
        ... def repeat(text, n, *args,**kwargs):
        ...     return text * n
        >>> 'hello' | repeat(3)
        'hellohellohello'

        >>> @add_textop
        ... class cool(TextOp):
        ...     @classmethod
        ...     def op(cls, text, *args,**kwargs):
        ...         return text + ' is cool.'
        >>> 'textops' | cool()
        'textops is cool.'
    """
    if isinstance(class_or_func,type):
        op = class_or_func
    else:
        op = type(class_or_func.__name__,(TextOp,), {'fn':staticmethod(class_or_func)})

    setattr(textops.ops,class_or_func.__name__,op)
    return op