Last active
September 10, 2018 01:25
-
-
Save mcoster/7c8837167df8b6fbb3a38e2de52ad0f4 to your computer and use it in GitHub Desktop.
bib2hugoac - a python script that takes a .bib file and generates a directory full of .md files for use with the Hugo Academic theme
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
""" | |
This script takes a BibTeX .bib file and outputs a series of .md files for use | |
in the Academic theme for Hugo, a general-purpose, static-site generating web | |
framework. Each file incorporates the data for a single publication. | |
Written for and tested using python 3.6.1 | |
Requires: bibtexparser | |
Copyright (C) 2017 Mark Coster | |
""" | |
import argparse | |
import os | |
import bibtexparser | |
from bibtexparser.bparser import BibTexParser | |
from bibtexparser.customization import * | |
def main(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument("bib_file", help="BibTeXfile to convert") | |
parser.add_argument('dir', nargs='?', default='publication', | |
help="output directory") | |
parser.add_argument("-s", "--selected", help="publications 'selected = true'", | |
action="store_true") | |
parser.add_argument("-v", "--verbose", help="increase output verbosity", | |
action="store_true") | |
args = parser.parse_args() | |
if args.verbose: | |
print("Verbosity turned on") | |
print("Opening {}".format(args.bib_file)) | |
try: | |
with open(args.bib_file) as bib_file: | |
parser = BibTexParser() | |
parser.customization = customizations | |
bib_data = bibtexparser.load(bib_file, parser=parser) | |
except IOError: | |
print('There was a problem opening the file.') | |
if not os.path.exists(args.dir): | |
if args.verbose: | |
print("Creating directory '{}'".format(args.dir)) | |
os.makedirs(args.dir) | |
os.chdir(args.dir) | |
for index, entry in enumerate(bib_data.entries): | |
if args.verbose: | |
print("Making entry {0}: {1}".format(index + 1, entry['ID'])) | |
if entry['ENTRYTYPE'] != 'article': | |
continue | |
info = ['+++'] | |
abstract_clean = entry['abstract'].replace('"', '\\"') | |
info.append('abstract = "{}"'.format(abstract_clean)) | |
info.append('abstract_short = "{}"'.format(abstract_clean)) | |
authors = [] | |
for author in entry['author']: | |
authors.append('"{}"'.format(author)) | |
info.append('authors = [{}]'.format(', '.join(authors))) | |
info.append('date = "{}-01-01"'.format(entry['year'])) | |
info.append('image_preview = ""') | |
info.append('math = true') | |
info.append('publication_types = ["2"]') | |
journal_name = entry['journal']['name'].replace('\\', '') | |
info.append('publication = "{}"'.format(journal_name)) | |
if 'volume' in entry: | |
volume = entry['volume'] + ', ' | |
else: | |
volume = '' | |
info.append('publication_short = "{journal} {year}, {vol}{pages}"'.format( | |
journal=journal_name, | |
year=entry['year'], | |
vol=volume, | |
pages=entry['pages'])) | |
info.append('selected = {}'.format(str(args.selected).lower())) | |
info.append('title = "{}"'.format(entry['title'])) | |
info.append('\n\n+++') | |
pub_info = '\n'.join(info) | |
file_name = entry['ID'] + '.md' | |
try: | |
if args.verbose: | |
print("Saving '{}'".format(file_name)) | |
with open(file_name, 'w') as pub_file: | |
pub_file.write(pub_info) | |
except IOError: | |
print('There was a problem writing to the file.') | |
def customizations(record): | |
"""Use some functions delivered by the library | |
:param record: a record | |
:returns: -- customized record | |
""" | |
record = type(record) | |
record = author(record) | |
record = editor(record) | |
record = journal(record) | |
record = keyword(record) | |
record = link(record) | |
record = doi(record) | |
record = convert_to_unicode(record) | |
record = abstract(record) | |
record = pages(record) | |
return record | |
def abstract(record): | |
""" | |
Clean abstract string. | |
:param record: a record | |
:type record: dict | |
:return: dict -- the modified record | |
""" | |
record['abstract'] = record['abstract'].strip(' [on SciFinder(R)]') | |
return record | |
def pages(record): | |
""" | |
Convert double hyphen page range to single hyphen, | |
eg. '4703--4705' --> '4703-4705' | |
:param record: a record | |
:type record: dict | |
:return: dict -- the modified record | |
""" | |
record['pages'] = record['pages'].replace('--', '-') | |
return record | |
if __name__ == '__main__': | |
main() |
I'm pretty new to this too, but it looks like you're using python 2.7, whereas I wrote the script and tested it using python 3.6. If you haven't already, I'd highly recommend using virtual environments to do anything with python. Let me know how it goes and if you're still having problems, I'll look into it further!
@arturgower @EBucksJeff
I had a similar problem and it was because some of my bib entries lacked entries for page numbers (lines 136 and 80 in the gist assumes they are present). A few extra if statements will do the trick.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @mcoster,
thanks for writing this code, it will be super useful!
A few of us (@EBucksJeff) complete python noobs are trying to use your code, but get the error: