238 lines
7.5 KiB
Python
238 lines
7.5 KiB
Python
# -*- coding: utf-8 -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
|
|
"""Des fonctions pour gérer les phrases et les mots.
|
|
"""
|
|
|
|
__all__ = ('enplural', 'plural',
|
|
'splitcc', 'joincc', 'splitus', 'joinus',
|
|
's2cc', 'cc2s',
|
|
's2us', 'us2s',
|
|
'cc2us', 'us2cc',
|
|
)
|
|
|
|
import string, re
|
|
|
|
from .base import isseq
|
|
|
|
RE_LAST_LETTER = re.compile(r'([a-zA-Z])[^a-zA-Z]*$')
|
|
RE_UPPERCASE = re.compile('[A-Z]')
|
|
def __caseof(s, ref):
|
|
"""Transformer s en majuscules ou en minuscules suivant la casse de la
|
|
dernière lettre de la chaine ref. si ref ne contient aucune lettre,
|
|
transformer s en minuscules
|
|
"""
|
|
mo = RE_LAST_LETTER.search(ref)
|
|
if mo is None: return s.lower()
|
|
if RE_UPPERCASE.match(mo.group(1)) is not None:
|
|
# majuscule
|
|
return s.upper()
|
|
else:
|
|
return s.lower()
|
|
|
|
RE_CHILD = re.compile(r'(?i)child$')
|
|
RE_Y = re.compile(r'(?i)y$')
|
|
RE_X = re.compile(r'(?i)x$')
|
|
RE_S = re.compile(r'(?i)s$')
|
|
def enplural(word):
|
|
"""Retourner la forme plurielle du mot anglais word
|
|
|
|
cas particuliers:
|
|
child --> children
|
|
*y --> *ies
|
|
*x --> *xes
|
|
*s --> *ses
|
|
|
|
sinon, on se contente de rajouter un s
|
|
|
|
XXX la règle est un peu plus compliquée que cela. l'implémenter
|
|
correctement. http://en.wikipedia.org/wiki/English_plural
|
|
"""
|
|
if RE_CHILD.match(word): return word + __caseof('ren', word)
|
|
elif RE_Y.search(word): return word[:-1] + __caseof('ies', word)
|
|
elif RE_X.search(word): return word + __caseof('es', word)
|
|
elif RE_S.search(word): return word + __caseof('es', word)
|
|
else: return word + __caseof('s', word)
|
|
|
|
RE_PLURAL = re.compile(r'%(?:<([^#<>]*))?(?:>([^#<>]*))?#')
|
|
|
|
def plural(text, count, format=True):
|
|
"""Dans text, remplacer des marqueurs de pluralité par la chaine appropriée
|
|
en fonction de la valeur de count.
|
|
|
|
Un marqueur de pluralité est de la forme %[<sing][>plur]#
|
|
Par défaut, sing == '' et plur == 's'
|
|
|
|
Si count > 1, les marqueurs sont remplacés par plur, sinon ils sont
|
|
remplacés par sing.
|
|
|
|
Si format==True et que text contienne une occurence de %i, le formater avec
|
|
text % count.
|
|
"""
|
|
pos = 0
|
|
while True:
|
|
mo = RE_PLURAL.search(text, pos)
|
|
if mo is None: break
|
|
before = text[:mo.start(0)]
|
|
after = text[mo.end(0):]
|
|
if count > 1:
|
|
plural = mo.group(2)
|
|
if plural is None: plural = "s"
|
|
else:
|
|
plural = mo.group(1)
|
|
if plural is None: plural = ""
|
|
pos = len(before) + len(plural)
|
|
text = before + plural + after
|
|
if format and text.find("%i") != -1:
|
|
text = text % count
|
|
return text
|
|
|
|
def __split_maybe(s, sep=None):
|
|
if not isseq(s): s = s.split(sep)
|
|
return s
|
|
|
|
ALL_UPPERCASE_PATTERN = re.compile(r'[A-Z0-9]+$')
|
|
UNDERSCORE_PATTERN = re.compile(r'_+')
|
|
UPPERCASE_PATTERN = re.compile(r'([A-Z]+)?([^A-Z]*)')
|
|
|
|
def splitcc(src, plural=False):
|
|
"""Spliter des mots écrits en CamelCase. La casse des mots n'est pas
|
|
modifiée.
|
|
|
|
Si plural==True, utiliser enplural pour mettre au pluriel le dernier mot.
|
|
|
|
e.g.
|
|
splitcc('camelCase') --> ['camel', 'Case']
|
|
splitcc('URClass') --> ['UR', 'Class']
|
|
"""
|
|
src = src.strip()
|
|
if not src: return []
|
|
|
|
parts = UPPERCASE_PATTERN.findall(src)
|
|
if parts[ - 1] == ('', ''): parts = parts[: - 1]
|
|
|
|
dests = []
|
|
for prefix, suffix in parts:
|
|
if prefix == "":
|
|
dests.append(suffix)
|
|
elif len(prefix) == 1:
|
|
dests.append(prefix + suffix)
|
|
else:
|
|
# len(prefix) > 1
|
|
dests.append(prefix[: - 1])
|
|
dests.append(prefix[ - 1] + suffix)
|
|
|
|
if dests and plural: dests[-1] = enplural(dests[-1])
|
|
return dests
|
|
|
|
def joincc(src, firstcap=False, plural=False):
|
|
"""Joindre des mots en camelCase. Si les mots sont tout en majuscules, il ne
|
|
sont pas modifiés. Sinon, il sont transformés en minuscule, et la première
|
|
lettre est capitalisée au besoin.
|
|
|
|
Si plural==True, utiliser enplural pour mettre au pluriel le dernier mot.
|
|
|
|
e.g.
|
|
joincc('hello world') --> 'helloWorld'
|
|
joincc(['hello', 'world']) --> 'helloWorld'
|
|
joincc('Hello world') --> 'helloWorld'
|
|
joincc('Hello World') --> 'helloWorld'
|
|
joincc('HELLO WORLD') --> 'HELLOWORLD'
|
|
joincc('Hello world', true) --> 'HelloWorld'
|
|
joincc('Hello World', true) --> 'HelloWorld'
|
|
joincc('HELLO WORLD', true) --> 'HELLOWORLD'
|
|
"""
|
|
dests = []
|
|
first = True
|
|
for s in __split_maybe(src):
|
|
if ALL_UPPERCASE_PATTERN.match(s) is None:
|
|
if first and not firstcap:
|
|
s = s.lower()
|
|
else:
|
|
s = s.capitalize()
|
|
dests.append(s)
|
|
first = False
|
|
|
|
if dests and plural: dests[-1] = enplural(dests[-1])
|
|
return ''.join(dests)
|
|
|
|
def splitus(src, plural=False):
|
|
"""Splitter des mots écrits séparés par des '_'. La casse des mots n'est pas
|
|
modifiée.
|
|
|
|
Si plural==True, utiliser enplural pour mettre au pluriel le dernier mot.
|
|
|
|
e.g.
|
|
splitus('under_score') --> ['under', 'score']
|
|
splitus('UR_CLASS') --> ['UR', 'CLASS']
|
|
"""
|
|
src = src.strip()
|
|
if not src: return []
|
|
|
|
dests = UNDERSCORE_PATTERN.split(src)
|
|
if dests and plural: dests[-1] = enplural(dests[-1])
|
|
return dests
|
|
|
|
def joinus(src, plural=False):
|
|
"""Joindre des mots en les séparant par des '_'. Si les mots sont tout en
|
|
majuscules, il ne sont pas modifiés. Sinon, il sont transformés en
|
|
minuscule avant d'être séparés par '_'.
|
|
|
|
Si plural==True, utiliser enplural pour mettre au pluriel le dernier mot.
|
|
|
|
e.g.
|
|
joinus('hello world') --> 'hello_world'
|
|
joinus(['hello', 'world']) --> 'hello_world'
|
|
joinus('Hello world') --> 'hello_world'
|
|
joinus('Hello World') --> 'hello_world'
|
|
joinus('HELLO WORLD') --> 'HELLO_WORLD'
|
|
"""
|
|
dests = []
|
|
for s in __split_maybe(src):
|
|
if ALL_UPPERCASE_PATTERN.match(s) is None:
|
|
s = s.lower()
|
|
dests.append(s)
|
|
|
|
if dests and plural: dests[-1] = enplural(dests[-1])
|
|
return '_'.join(dests)
|
|
|
|
|
|
def s2cc(s, firstcap=False, sep=None, plural=False):
|
|
"""Transformer une suite de mots séparés par sep en une suite de mots en camelCase.
|
|
e.g. s2cc('hello world') --> 'helloWorld'
|
|
"""
|
|
dests = __split_maybe(s, sep)
|
|
if dests and plural: dests[-1] = enplural(dests[-1])
|
|
return joincc(dests, firstcap)
|
|
|
|
def cc2s(cc, sep=None, plural=False):
|
|
"""Transformer une suite de mots en camelCase en une suite de mots séparés par sep.
|
|
e.g. cc2s('helloWorld') --> 'hello world'
|
|
"""
|
|
return (sep or ' ').join(map(string.lower, splitcc(cc, plural)))
|
|
|
|
def s2us(s, sep=None, plural=False):
|
|
"""Transformer une suite de mots séparés par sep en une suite de mots séparés par '_'.
|
|
e.g. s2cc('hello world') --> 'hello_world'
|
|
"""
|
|
dests = __split_maybe(s, sep)
|
|
if dests and plural: dests[-1] = enplural(dests[-1])
|
|
return joinus(dests)
|
|
|
|
def us2s(us, sep=None, plural=False):
|
|
"""Transformer une suite de mots séparés par '_' en une suite de mots séparés par sep.
|
|
e.g. cc2s('hello_world') --> 'hello world'
|
|
"""
|
|
return (sep or ' ').join(map(string.lower, splitus(us, plural)))
|
|
|
|
def cc2us(cc, plural=False):
|
|
"""Transformer une suite de mots en camelCase en une suite de mots séparés par '_'.
|
|
e.g. cc2s('helloWorld') --> 'hello_world'
|
|
"""
|
|
return joinus(splitcc(cc, plural))
|
|
|
|
def us2cc(us, firstcap=False, plural=False):
|
|
"""Transformer une suite de mots séparés par '_' en une suite de mots en camelCase.
|
|
e.g. cc2s('hello_world') --> 'helloWorld'
|
|
"""
|
|
return joincc(splitus(us, plural), firstcap)
|