from typing import Optional
from typing import List
import re


def sub_general(text_in: str, patterns: Optional[List[List[str]]]) -> str:
    """ substitutions general

    Performs general substitutions from regex expression.

    Parameters
    ----------
    text_in: str
        text to modify
    patterns: list[list[str]]
        Pattern and replacement values
        example:
        [
            # [search pattern, substitution value]
            ["^[a-zA-Z;,.: /]*", ""],  # remove text at front of strings
            ["(?<=[^a-zA-Z])at([^a-zA-Z])", " @ "],  # replace at with @
        ]

    Returns
    -------
    text: str

    """
    # guard statement
    if patterns is None or patterns == []:
        return text_in

    if isinstance(patterns, list):
        if isinstance(patterns[0], list):
            for pattern in patterns:
                text_in = re.sub(pattern[0], pattern[1], text_in)

            return text_in.strip()

    raise TypeError("Patterns must be a List[List[pattern, substitution]].")