mirror of
https://github.com/TeachBooks/manual.git
synced 2026-11-12 22:35:51 +00:00
486 lines
16 KiB
Python
486 lines
16 KiB
Python
# -*- coding:Utf-8 -*-
|
|
from __future__ import unicode_literals
|
|
|
|
import re
|
|
import six
|
|
|
|
from pybtex.plugin import find_plugin
|
|
from pybtex.style.formatting import BaseStyle, toplevel
|
|
from pybtex.style.template import (
|
|
field, first_of, href, join, optional, optional_field, sentence, tag,
|
|
together, words, node, FieldIsMissing
|
|
)
|
|
|
|
from pybtex.richtext import Text, Symbol
|
|
|
|
|
|
firstlast = find_plugin('pybtex.style.names', 'lastfirst')()
|
|
|
|
if six.PY2:
|
|
def format_pages(text):
|
|
dash_re = re.compile(r'-+')
|
|
pages = Text(Symbol('ndash')).join(
|
|
re.split(dash_re, six.text_type(text)))
|
|
if re.search('[-‒–—―]', six.text_type(text)):
|
|
return Text("pp.", Symbol('nbsp'), pages)
|
|
return Text("p.", Symbol('nbsp'), pages)
|
|
else:
|
|
def format_pages(text):
|
|
dash_re = re.compile(r'-+')
|
|
pages = Text(Symbol('ndash')).join(text.split(dash_re))
|
|
if re.search('[-‒–—―]', str(text)):
|
|
return Text("pp.", Symbol('nbsp'), pages)
|
|
return Text("p.", Symbol('nbsp'), pages)
|
|
|
|
|
|
pages = field('pages', apply_func=format_pages)
|
|
date = words[field('year'), optional[", ", field('month')]]
|
|
|
|
|
|
@node
|
|
def apa_names(children, context, role, **kwargs):
|
|
"""
|
|
Returns formatted names as an APA compliant reference list citation.
|
|
"""
|
|
assert not children
|
|
|
|
try:
|
|
persons = context['entry'].persons[role]
|
|
except KeyError:
|
|
raise FieldIsMissing(role, context['entry'])
|
|
|
|
style = context['style']
|
|
|
|
if len(persons) > 7:
|
|
persons = persons[:6] + persons[-1:]
|
|
formatted_names = [style.format_name(
|
|
person, style.abbreviate_names) for person in persons]
|
|
return join(sep=', ', last_sep=', … ')[
|
|
formatted_names].format_data(context)
|
|
else:
|
|
formatted_names = [style.format_name(
|
|
person, style.abbreviate_names) for person in persons]
|
|
return join(sep=', ', sep2=', & ', last_sep=', & ')[
|
|
formatted_names].format_data(context)
|
|
|
|
|
|
@node
|
|
def editor_names(children, context, with_suffix=True, **kwargs):
|
|
"""
|
|
Returns formatted editor names for inbook.
|
|
"""
|
|
assert not children
|
|
|
|
try:
|
|
editors = context['entry'].persons['editor']
|
|
except KeyError:
|
|
raise FieldIsMissing('editor', context['entry'])
|
|
|
|
formatted_names = [
|
|
firstlast.format(editor, True) for editor in editors]
|
|
|
|
if with_suffix:
|
|
return words[
|
|
join(sep=', ', sep2=', & ', last_sep=', & ')[formatted_names],
|
|
"(Eds.)" if len(editors) > 1 else "(Ed.)"
|
|
].format_data(context)
|
|
|
|
return join(sep=', ', sep2=', & ', last_sep=', & ')[
|
|
formatted_names
|
|
].format_data(context)
|
|
|
|
|
|
class APAStyle(BaseStyle):
|
|
name = 'apa'
|
|
default_name_style = 'lastfirst'
|
|
default_sorting_style = 'author_year_title'
|
|
default_label_style = 'apa'
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(APAStyle, self).__init__(*args, **kwargs)
|
|
self.abbreviate_names = True
|
|
|
|
def format_names(self, role, as_sentence=True):
|
|
formatted_names = apa_names(role)
|
|
if as_sentence:
|
|
return sentence(capfirst=False)[formatted_names]
|
|
else:
|
|
return formatted_names
|
|
|
|
def format_author_or_editor_and_date(self, e):
|
|
if 'author' in e.persons and 'editor' in e.persons:
|
|
return sentence(sep=' ')[
|
|
self.format_names('author'), join["(", date, ")."],
|
|
self.format_editor(e, as_sentence=False)]
|
|
elif 'author' in e.persons:
|
|
return sentence(sep=' ')[
|
|
self.format_names('author'), join["(", date, ")"]]
|
|
else:
|
|
return sentence(sep=' ')[
|
|
self.format_editor(e, as_sentence=False),
|
|
join["(", date, ")"]]
|
|
|
|
def format_editor(self, e, as_sentence=True):
|
|
editors = self.format_names('editor', as_sentence=False)
|
|
if 'editor' not in e.persons:
|
|
# when parsing the template, a FieldIsMissing exception
|
|
# will be thrown anyway; no need to do anything now,
|
|
# just return the template that will throw the exception
|
|
return editors
|
|
if len(e.persons['editor']) > 1:
|
|
word = '(Eds.)'
|
|
else:
|
|
word = '(Ed.)'
|
|
result = join(sep=' ')[editors, word]
|
|
if as_sentence:
|
|
return sentence[result]
|
|
else:
|
|
return result
|
|
|
|
def format_volume(self, e, for_article=False):
|
|
prefix = "Vol."
|
|
if for_article:
|
|
return join[
|
|
tag('em')[field('volume')],
|
|
optional['(', field('number'), ')'],
|
|
]
|
|
else:
|
|
return optional[together[prefix, field('volume')]]
|
|
|
|
def format_title(self, e, which_field, as_sentence=True):
|
|
formatted_title = field(
|
|
which_field, apply_func=lambda text: text.capitalize()
|
|
)
|
|
if as_sentence:
|
|
return sentence[formatted_title]
|
|
else:
|
|
return formatted_title
|
|
|
|
def format_btitle(self, e, which_field, as_sentence=True):
|
|
formatted_title = tag('em')[field(which_field)]
|
|
if as_sentence:
|
|
return sentence[formatted_title]
|
|
else:
|
|
return formatted_title
|
|
|
|
def format_web_refs(self, e):
|
|
# Based on urlbst output.web.refs
|
|
return sentence(add_period=False)[
|
|
optional[self.format_url(e)],
|
|
optional[self.format_eprint(e)],
|
|
optional[self.format_pubmed(e)],
|
|
optional[self.format_doi(e)],
|
|
]
|
|
|
|
def format_url(self, e):
|
|
# Based on urlbst format.url
|
|
return words[
|
|
'URL:',
|
|
href[
|
|
field('url', raw=True),
|
|
field('url', raw=True)
|
|
]
|
|
]
|
|
|
|
def format_pubmed(self, e):
|
|
# Based on urlbst format.pubmed
|
|
return href[
|
|
join[
|
|
'https://www.ncbi.nlm.nih.gov/pubmed/',
|
|
field('pubmed', raw=True)
|
|
],
|
|
join[
|
|
'PMID:',
|
|
field('pubmed', raw=True)
|
|
]
|
|
]
|
|
|
|
def format_doi(self, e):
|
|
# Based on urlbst format.doi
|
|
return href[
|
|
join[
|
|
'https://doi.org/',
|
|
field('doi', raw=True)
|
|
],
|
|
join[
|
|
'doi:',
|
|
field('doi', raw=True)
|
|
]
|
|
]
|
|
|
|
def format_eprint(self, e):
|
|
# Based on urlbst format.eprint
|
|
return href[
|
|
join[
|
|
'https://arxiv.org/abs/',
|
|
field('eprint', raw=True)
|
|
],
|
|
join[
|
|
'arXiv:',
|
|
field('eprint', raw=True)
|
|
]
|
|
]
|
|
|
|
def get_article_template(self, e):
|
|
# Required fields: author, title, journal, year
|
|
# Optional fields: volume, number, pages, month, note, key
|
|
volume_and_pages = first_of[
|
|
# Volume and pages, with optional issue number
|
|
optional[
|
|
join[
|
|
self.format_volume(e, for_article=True),
|
|
optional[', ', field('pages')]
|
|
],
|
|
],
|
|
# Pages only
|
|
pages,
|
|
]
|
|
template = toplevel[
|
|
self.format_names('author'),
|
|
sentence[
|
|
join["(", date, ")"]
|
|
],
|
|
self.format_title(e, 'title'),
|
|
sentence[
|
|
tag('em')[field('journal')],
|
|
optional[volume_and_pages],
|
|
],
|
|
sentence[optional_field('note')],
|
|
self.format_web_refs(e),
|
|
]
|
|
return template
|
|
|
|
def get_book_template(self, e):
|
|
# Required fields: author/editor, title, publisher, year
|
|
# Optional fields: volume, series, address, edition, month, note, key,
|
|
# isbn
|
|
return toplevel[
|
|
self.format_author_or_editor_and_date(e),
|
|
sentence(sep=' ')[
|
|
self.format_btitle(e, 'title'),
|
|
optional[
|
|
sentence[
|
|
optional[field('edition'), ' ed.'],
|
|
self.format_volume(e),
|
|
]
|
|
]
|
|
],
|
|
sentence(sep=': ')[
|
|
optional_field('address'),
|
|
field('publisher'),
|
|
],
|
|
sentence[optional_field('note')],
|
|
]
|
|
|
|
def get_booklet_template(self, e):
|
|
# Required fields: title
|
|
# Optional fields: author, howpublished, address, month, year, note,
|
|
# key
|
|
return toplevel[
|
|
sentence(sep=' ')[
|
|
first_of[
|
|
optional[self.format_names(
|
|
'author', as_sentence=False)],
|
|
"None to claim their bones"
|
|
],
|
|
join["(", first_of[optional[date], "n.d."], ")"]
|
|
],
|
|
self.format_title(e, 'title'),
|
|
sentence[optional_field('address')],
|
|
sentence[optional_field('note')],
|
|
]
|
|
|
|
def get_inbook_template(self, e):
|
|
# Required fields: author/editor, title, chapter/pages, publisher, year
|
|
# Optional fields: volume, series, address, edition, month, note, key
|
|
return toplevel[
|
|
sentence(sep=' ')[
|
|
self.format_names('author'),
|
|
join["(", date, ")"]
|
|
],
|
|
self.format_title(e, 'title'),
|
|
sentence(sep=' ')[
|
|
optional[
|
|
"In ",
|
|
editor_names(),
|
|
","
|
|
],
|
|
self.format_btitle(e, 'booktitle', as_sentence=False),
|
|
optional[
|
|
join[
|
|
"(",
|
|
sentence(add_period=False)[
|
|
optional[field('edition'), ' ed.'],
|
|
self.format_volume(e),
|
|
pages,
|
|
],
|
|
")"
|
|
]
|
|
]
|
|
],
|
|
sentence(sep=': ')[
|
|
optional_field('address'),
|
|
field('publisher'),
|
|
],
|
|
sentence[optional_field('note')],
|
|
]
|
|
|
|
def get_incollection_template(self, e):
|
|
# Required fields: author, title, booktitle, year
|
|
# Optional fields: editor, pages, organization, publisher, address,
|
|
# month, note, key
|
|
return toplevel[
|
|
self.format_author_or_editor_and_date(e),
|
|
self.format_title(e, 'title'),
|
|
sentence(sep=' ')[
|
|
self.format_btitle(e, 'booktitle', as_sentence=False),
|
|
optional["(", pages, ")"]
|
|
],
|
|
sentence(sep=': ')[
|
|
optional_field('address'),
|
|
optional_field('publisher'),
|
|
],
|
|
sentence[optional_field('note')],
|
|
]
|
|
|
|
def get_inproceedings_template(self, e):
|
|
# Required fields: author, title, booktitle, year
|
|
# Optional fields: editor, pages, organization, publisher, address,
|
|
# month, note, key
|
|
return toplevel[
|
|
self.format_author_or_editor_and_date(e),
|
|
self.format_title(e, 'title'),
|
|
sentence(sep=' ')[
|
|
self.format_btitle(e, 'booktitle', as_sentence=False),
|
|
optional["(", pages, ")"]
|
|
],
|
|
sentence(sep=': ')[
|
|
optional_field('address'),
|
|
optional_field('publisher'),
|
|
],
|
|
sentence[optional_field('note')],
|
|
self.format_web_refs(e)
|
|
]
|
|
|
|
def get_manual_template(self, e):
|
|
# Required fields: title
|
|
# Optional fields: author, organization, address, edition, month, year,
|
|
# note, key
|
|
return toplevel[
|
|
sentence(sep=' ')[
|
|
first_of[
|
|
optional[self.format_names('author', as_sentence=False)],
|
|
optional_field('organization'),
|
|
"None to claim their bones"
|
|
],
|
|
join["(", first_of[optional[date], "n.d."], ")"]
|
|
],
|
|
self.format_btitle(e, 'title'),
|
|
sentence[optional_field('address')],
|
|
sentence[optional_field('note')],
|
|
self.format_web_refs(e)
|
|
]
|
|
|
|
def get_mastersthesis_template(self, e):
|
|
# Required fields: author, title, school, year
|
|
# Optional fields: address, month, note, key
|
|
return toplevel[
|
|
sentence(sep=' ')[
|
|
self.format_names('author'),
|
|
join["(", date, ")"]
|
|
],
|
|
sentence(sep=' ')[
|
|
self.format_btitle(e, 'title', as_sentence=False),
|
|
"(Master's thesis)"
|
|
],
|
|
sentence[
|
|
field('school'),
|
|
optional_field('address'),
|
|
],
|
|
sentence[optional_field('note')],
|
|
]
|
|
|
|
def get_misc_template(self, e):
|
|
# Required fields: aucun
|
|
# Optional fields: author, title, howpublished, month, year, note, key,
|
|
# type
|
|
template = toplevel[
|
|
sentence(sep=' ')[
|
|
first_of[
|
|
optional[self.format_names('author', as_sentence=False)],
|
|
optional_field('publisher'),
|
|
"None to claim their bones"
|
|
],
|
|
join["(", first_of[optional[date], "n.d."], ")"]
|
|
],
|
|
optional[self.format_title(e, 'title')],
|
|
sentence[optional_field('note')],
|
|
self.format_web_refs(e)
|
|
]
|
|
return template
|
|
|
|
def get_phdthesis_template(self, e):
|
|
# Required fields: author, title, school, year
|
|
# Optional fields: address, month, note, key
|
|
return toplevel[
|
|
sentence(sep=' ')[
|
|
self.format_names('author'),
|
|
join["(", date, ")"]
|
|
],
|
|
sentence(sep=' ')[
|
|
self.format_btitle(e, 'title', as_sentence=False),
|
|
"(Doctoral dissertation)"
|
|
],
|
|
sentence[
|
|
field('school'),
|
|
optional_field('address'),
|
|
],
|
|
sentence[optional_field('note')],
|
|
]
|
|
|
|
def get_proceedings_template(self, e):
|
|
# Required fields: title, year
|
|
# Optional fields: editor, publisher, organization, address, month,
|
|
# note, key
|
|
return toplevel[
|
|
sentence(sep=' ')[
|
|
first_of[
|
|
optional[self.format_editor(e, as_sentence=False)],
|
|
optional_field('organization'),
|
|
"None to claim their bones"
|
|
],
|
|
join["(", first_of[optional[date], "n.d."], ")"]
|
|
],
|
|
self.format_btitle(e, 'title'),
|
|
sentence(sep=': ')[
|
|
optional_field('address'),
|
|
optional_field('publisher'),
|
|
],
|
|
sentence[optional_field('note')],
|
|
]
|
|
|
|
def get_techreport_template(self, e):
|
|
# Required fields: author, title, institution, year
|
|
# Optional fields: type, number, address, month, note, key
|
|
return toplevel[
|
|
sentence(sep=' ')[
|
|
self.format_names('author', as_sentence=False),
|
|
join["(", date, ")"]
|
|
],
|
|
self.format_btitle(e, 'title'),
|
|
sentence[field('institution')],
|
|
sentence[optional_field('note')],
|
|
]
|
|
|
|
def get_unpublished_template(self, e):
|
|
# Required fields: author, title, note
|
|
# Optional fields: month, year, key
|
|
template = toplevel[
|
|
sentence(sep=' ')[
|
|
self.format_names('author', as_sentence=False),
|
|
join["(", first_of[optional[date], "n.d."], ")"]
|
|
],
|
|
self.format_btitle(e, 'title'),
|
|
sentence[field('note')],
|
|
]
|
|
return template
|