# Copyright (c) 2006-2021 Andrey Golovizin # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import unicode_literals import re from pybtex.py3compat import fix_unicode_literals_in_doctest from pybtex.utils import deprecated terminators = '.', '?', '!' delimiter_re = re.compile(r'([\s\-])') whitespace_re = re.compile(r'\s+') @deprecated('0.19', 'use str.capitalize() instead') def capfirst(s): return s[0].upper() + s[1:] if s else s def is_terminated(text): """ Return True if text ends with a terminating character. >>> is_terminated('') False >>> is_terminated('.') True >>> is_terminated('Done') False >>> is_terminated('Done. ') False >>> is_terminated('Done.') True >>> is_terminated('Done...') True >>> is_terminated('Done!') True >>> is_terminated('Done?') True >>> is_terminated('Done?!') True """ return text.endswith(terminators) def add_period(text): """Add a period to the end of text, if needed. >>> print(add_period('')) >>> print(add_period('.')) . >>> print(add_period('Done')) Done. >>> print(add_period('Done. ')) Done. . >>> print(add_period('Done.')) Done. >>> print(add_period('Done...')) Done... >>> print(add_period('Done!')) Done! >>> print(add_period('Done?')) Done? >>> print(add_period('Done?!')) Done?! """ if text and not is_terminated(text): return text + '.' return text @fix_unicode_literals_in_doctest def abbreviate(text, split=delimiter_re.split): """Abbreviate the given text. >> abbreviate('Name') u'N' >> abbreviate('Some words') u'S. w.' >>> abbreviate('First-Second') u'F.-S.' """ def abbreviate(part): if part.isalpha(): return part[0] + '.' else: return part return ''.join(abbreviate(part) for part in split(text)) def normalize_whitespace(string): r""" Replace every sequence of whitespace characters with a single space. >>> print(normalize_whitespace('abc')) abc >>> print(normalize_whitespace('Abc def.')) Abc def. >>> print(normalize_whitespace(' Abc def.')) Abc def. >>> print(normalize_whitespace('Abc\ndef.')) Abc def. >>> print(normalize_whitespace('Abc\r\ndef.')) Abc def. >>> print(normalize_whitespace('Abc \r\n\tdef.')) Abc def. >>> print(normalize_whitespace(' \nAbc\r\ndef.')) Abc def. """ return whitespace_re.sub(' ', string.strip()) def width(string): r""" Get the width of the typeset string, in relative units. Similar to BibTeX's width$, but does not care about any "special characters". >>> width('') 0 >>> width('abc') 1500 >>> width('ab{c}') 2500 >>> width(r"ab{\'c}") 3278 >>> width(r"ab{\'c{}}") 4278 >>> width(r"ab{\'c{}") 3778 >>> width(r"ab{\'c{d}}") 4834 """ from pybtex.charwidths import charwidths return sum(charwidths.get(char, 0) for char in string) def tie_or_space(word, tie='~', space=' ', enough_chars=3, other_word=None): n_chars = len(word) if other_word is not None: n_chars = min(n_chars, len(other_word)) if n_chars < enough_chars: return tie else: return space