# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_snake.ipynb.

# %% auto 0
__all__ = ['BASIC_WORDS_TO_SNAKE', 'WORDS_TO_SNAKE_WITH_UPPERCASE', 'CAMEL_TO_SNAKE', 'PASCAL_TO_SNAKE', 'SUNDER', 'DUNDER',
           'SUB_SUNDER', 'SNAKE_PATTERNS', 'swapall', 'joinall', 'to_snake', 'py_to_snake']

# %% ../nbs/01_snake.ipynb 4
import re

# %% ../nbs/01_snake.ipynb 8
BASIC_WORDS_TO_SNAKE = re.compile(
    r'[A-Z]?[a-z]+'                     # A possible uppercase followed by lowercase letters
    r'|[A-Z]{2,}(?=[A-Z][a-z]|\d|\W|$)' # Two or more consecutive uppercase letters
    r'|\d+'                             # One or more digits
)

# %% ../nbs/01_snake.ipynb 9
WORDS_TO_SNAKE_WITH_UPPERCASE = re.compile(
    r'[A-Z]?[a-z]+'                     # A possible uppercase followed by lowercase letters
    r'|[A-Z]{2,}(?=[A-Z][a-z]|\d|\W|$)' # Two or more consecutive uppercase letters
    r'|\d+'                             # One or more digits
    r'|[A-Z]{2,}'                       # Two or more consecutive uppercase letters
    r'|[A-Z]$'                          # Uppercase letter at end of string
)

# %% ../nbs/01_snake.ipynb 13
CAMEL_TO_SNAKE = re.compile(
    r'(?<=[a-z0-9])[A-Z]'          # An uppercase letter after a lowercase letter / digit
    r'|(?<![A-Z_])[A-Z](?=[a-z])'  # An uppercase letter before a lowercase letter AND 
                                   # not after an uppercase letter or underscore
)

# %% ../nbs/01_snake.ipynb 17
PASCAL_TO_SNAKE = re.compile(
    r'(?!^)(?<!_)[A-Z][a-z]+'     # An uppercase letter not at the start and not after an underscore, 
                                  # followed by one or more lowercase letters (captures beginning of PascalCase words)
    r'|(?<=[a-z0-9])[A-Z]'        # An uppercase letter after a lowercase letter or digit 
                                  # (captures transition in camelCase)
)

# %% ../nbs/01_snake.ipynb 20
SUNDER = '_'
DUNDER = '__'

SUB_SUNDER = rf'{SUNDER}\1'

# %% ../nbs/01_snake.ipynb 21
def swapall(s: str, pattern: str, repl: str = SUB_SUNDER) -> str:
    '''Replace all occurences of the pattern in string with repl'''
    return re.sub(pattern, repl, s)

def joinall(s: str, pattern: str, repl: str = SUNDER) -> str:
    '''Join all occurrences of the pattern in string with repl'''
    matches = re.findall(pattern, s)
    return repl.join(matches)

# %% ../nbs/01_snake.ipynb 22
def to_snake(s: str) -> str:
    '''Convert a string to snake_case'''
    return joinall(s, WORDS_TO_SNAKE_WITH_UPPERCASE, SUNDER).lower()
    
def py_to_snake(s: str) -> str:    
    _precap = [f'_{c.lower()}' if c.isupper() else c for c in s]
    return ''.join(_precap).lstrip(SUNDER)

# %% ../nbs/01_snake.ipynb 23
SNAKE_PATTERNS = (BASIC_WORDS_TO_SNAKE, WORDS_TO_SNAKE_WITH_UPPERCASE, CAMEL_TO_SNAKE, PASCAL_TO_SNAKE,)
