You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
6.4 KiB
182 lines
6.4 KiB
8 months ago
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
# Copyright (c) 2006-2019 Andrey Golovigin
|
||
|
#
|
||
|
# 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 absolute_import, unicode_literals
|
||
|
|
||
|
import re
|
||
|
import sys
|
||
|
import unicodedata
|
||
|
|
||
|
import six
|
||
|
from pybtex.style.labels import BaseLabelStyle
|
||
|
from pybtex.textutils import abbreviate
|
||
|
|
||
|
if sys.version_info < (2, 7):
|
||
|
from counter import Counter
|
||
|
else:
|
||
|
from collections import Counter
|
||
|
|
||
|
|
||
|
|
||
|
_nonalnum_pattern = re.compile('[^A-Za-z0-9]+', re.UNICODE)
|
||
|
|
||
|
def _strip_accents(s):
|
||
|
return u''.join(
|
||
|
(c for c in unicodedata.normalize('NFD', s)
|
||
|
if not unicodedata.combining(c)))
|
||
|
|
||
|
def _strip_nonalnum(parts):
|
||
|
"""Strip all non-alphanumerical characters from a list of strings.
|
||
|
|
||
|
>>> print(_strip_nonalnum([u"ÅA. B. Testing 12+}[.@~_", u" 3%"]))
|
||
|
AABTesting123
|
||
|
"""
|
||
|
s = u''.join(parts)
|
||
|
return _nonalnum_pattern.sub(u'', _strip_accents(s))
|
||
|
|
||
|
def _abbr(parts):
|
||
|
return (abbreviate(part) for part in parts)
|
||
|
|
||
|
|
||
|
class LabelStyle(BaseLabelStyle):
|
||
|
|
||
|
def format_labels(self, sorted_entries):
|
||
|
labels = [self.format_label(entry) for entry in sorted_entries]
|
||
|
count = Counter(labels)
|
||
|
counted = Counter()
|
||
|
for label in labels:
|
||
|
if count[label] == 1:
|
||
|
yield label
|
||
|
else:
|
||
|
yield label + chr(ord('a') + counted[label])
|
||
|
counted.update([label])
|
||
|
|
||
|
# note: this currently closely follows the alpha.bst code
|
||
|
# we should eventually refactor it
|
||
|
|
||
|
def format_label(self, entry):
|
||
|
# see alpha.bst calc.label
|
||
|
if entry.type == "book" or entry.type == "inbook":
|
||
|
label = self.author_editor_key_label(entry)
|
||
|
elif entry.type == "proceedings":
|
||
|
label = self.editor_key_organization_label(entry)
|
||
|
elif entry.type == "manual":
|
||
|
label = self.author_key_organization_label(entry)
|
||
|
else:
|
||
|
label = self.author_key_label(entry)
|
||
|
if "year" in entry.fields:
|
||
|
return label + entry.fields["year"][-2:]
|
||
|
else:
|
||
|
return label
|
||
|
# bst additionally sets sort.label
|
||
|
|
||
|
def author_key_label(self, entry):
|
||
|
# see alpha.bst author.key.label
|
||
|
if not "author" in entry.persons:
|
||
|
if not "key" in entry.fields:
|
||
|
return entry.key[:3] # entry.key is bst cite$
|
||
|
else:
|
||
|
# for entry.key, bst actually uses text.prefix$
|
||
|
return entry.fields["key"][:3]
|
||
|
else:
|
||
|
return self.format_lab_names(entry.persons["author"])
|
||
|
|
||
|
def author_editor_key_label(self, entry):
|
||
|
# see alpha.bst author.editor.key.label
|
||
|
if not "author" in entry.persons:
|
||
|
if not "editor" in entry.persons:
|
||
|
if not "key" in entry.fields:
|
||
|
return entry.key[:3] # entry.key is bst cite$
|
||
|
else:
|
||
|
# for entry.key, bst actually uses text.prefix$
|
||
|
return entry.fields["key"][:3]
|
||
|
else:
|
||
|
return self.format_lab_names(entry.persons["editor"])
|
||
|
else:
|
||
|
return self.format_lab_names(entry.persons["author"])
|
||
|
|
||
|
def author_key_organization_label(self, entry):
|
||
|
if not "author" in entry.persons:
|
||
|
if not "key" in entry.fields:
|
||
|
if not "organization" in entry.fields:
|
||
|
return entry.key[:3] # entry.key is bst cite$
|
||
|
else:
|
||
|
result = entry.fields["organization"]
|
||
|
if result.startswith("The "):
|
||
|
result = result[4:]
|
||
|
return result
|
||
|
else:
|
||
|
return entry.fields["key"][:3]
|
||
|
else:
|
||
|
return self.format_lab_names(entry.persons["author"])
|
||
|
|
||
|
def editor_key_organization_label(self, entry):
|
||
|
if not "editor" in entry.persons:
|
||
|
if not "key" in entry.fields:
|
||
|
if not "organization" in entry.fields:
|
||
|
return entry.key[:3] # entry.key is bst cite$
|
||
|
else:
|
||
|
result = entry.fields["organization"]
|
||
|
if result.startswith("The "):
|
||
|
result = result[4:]
|
||
|
return result
|
||
|
else:
|
||
|
return entry.fields["key"][:3]
|
||
|
else:
|
||
|
return self.format_lab_names(entry.persons["editor"])
|
||
|
|
||
|
def format_lab_names(self, persons):
|
||
|
# see alpha.bst format.lab.names
|
||
|
# s = persons
|
||
|
numnames = len(persons)
|
||
|
if numnames > 1:
|
||
|
if numnames > 4:
|
||
|
namesleft = 3
|
||
|
else:
|
||
|
namesleft = numnames
|
||
|
result = ""
|
||
|
nameptr = 1
|
||
|
while namesleft:
|
||
|
person = persons[nameptr - 1]
|
||
|
if nameptr == numnames:
|
||
|
if six.text_type(person) == "others":
|
||
|
result += "+"
|
||
|
else:
|
||
|
result += _strip_nonalnum(_abbr(
|
||
|
person.prelast_names + person.last_names))
|
||
|
else:
|
||
|
result += _strip_nonalnum(_abbr(
|
||
|
person.prelast_names + person.last_names))
|
||
|
nameptr += 1
|
||
|
namesleft -= 1
|
||
|
if numnames > 4:
|
||
|
result += "+"
|
||
|
else:
|
||
|
person = persons[0]
|
||
|
result = _strip_nonalnum(_abbr(
|
||
|
person.prelast_names + person.last_names))
|
||
|
if len(result) < 2:
|
||
|
result = _strip_nonalnum(person.last_names)[:3]
|
||
|
return result
|