Skip to content

Instantly share code, notes, and snippets.

@mcoster
Last active September 10, 2018 01:25
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mcoster/7c8837167df8b6fbb3a38e2de52ad0f4 to your computer and use it in GitHub Desktop.
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
#!/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()
@arturgower
Copy link

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:

>python bib2hugoac.py MyPapers.bib -v
Verbosity turned on
Opening MyPapers.bib
Traceback (most recent call last):
  File "bib2hugoac.py", line 140, in <module>
    main()
  File "bib2hugoac.py", line 42, in main
    bib_data = bibtexparser.load(bib_file, parser=parser)
  File "/usr/local/lib/python2.7/dist-packages/bibtexparser/__init__.py", line 59, in load
    return parser.parse_file(bibtex_file)
  File "/usr/local/lib/python2.7/dist-packages/bibtexparser/bparser.py", line 130, in parse_file
    return self.parse(file.read())
  File "/usr/local/lib/python2.7/dist-packages/bibtexparser/bparser.py", line 119, in parse
    self._parse_records(customization=self.customization)
  File "/usr/local/lib/python2.7/dist-packages/bibtexparser/bparser.py", line 163, in _parse_records
    _add_parsed_record(record, records)
  File "/usr/local/lib/python2.7/dist-packages/bibtexparser/bparser.py", line 144, in _add_parsed_record
    parsed = self._parse_record(record, customization=customization)
  File "/usr/local/lib/python2.7/dist-packages/bibtexparser/bparser.py", line 310, in _parse_record
    return customization(d)
  File "bib2hugoac.py", line 110, in customizations
    record = pages(record)
  File "bib2hugoac.py", line 135, in pages
    record['pages'] = record['pages'].replace('--', '-')
KeyError: 'pages'

@mcoster
Copy link
Author

mcoster commented Jul 21, 2017

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

@jkkummerfeld
Copy link

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