Scjrm.jl/src/bibliography.jl

105 lines
3.2 KiB
Julia

#=
Functions to manage the library
=#
using JSON, StringDistances
"""
Add `entry` to `bibliography` on key `id`
Defines `pre_add_to_bib` and `after_add_to_bib`.
"""
function addtobibliography!(bibliography::Bibliography, id::String, entry::Citation)
@hook :pre_add_to_bib
info("Here")
exists = id in keys(bibliography)
info("The id you are adding $(id) does " * (exists ? "" : "not ") * "exists")
if exists
oldentry = bibliography[id]
# TODO: run a Levenshtein distance on the two entry and decide
# what to do Options should be to merge/replace or keep both.
# In the latter the id must be modified (like id-$counter)
old = lowercase(get(oldentry,"title",""))
new = lowercase(get(entry,"title","-"))
differencepercent = compare(TokenMax(RatcliffObershelp()), old, new)
if differencepercent > 0.8
@hook :duplicated_paper
warn("The old and the new seems to be the same paper\n
(similarity is $(differencepercent))")
@show json(oldentry)
@show json(entry)
else
@hook :similar_paper
info("keeping both")
id = nextidnumber(bibliography,id)
end
end
bibliography[id] = entry
@hook :after_add_to_bib
end
""" Set `newbib` as a the bibliography, replacing `bibliography`.
"""
function setbibliography!(bibliography::Bibliography, newbib::Bibliography)
empty!(bibliography)
merge!(bibliography, newbib)
end
import Base.pop!
function pop!(bibliography::Bibliography, key::String)
copy = Dict(bibliography)
p = Base.pop!(copy, key) # FIXME: remove this Base.
empty!(bibliography)
foreach(k -> bibliography[k] = copy[k], keys(copy))
# Behaves like a real `pop`, returning the popped key value
p
end
# FIXME: find files?
"""Add all entries in a bibtex string to the current bibliography"""
function addbibtex!(bibliography, bibstring)
bibs = Bibliography(bibstring)
foreach(bib -> addtobibliography!(bibliography, createcitekey(bibs[bib]), bibs[bib]),
keys(bibs))
"ok"
end
function splitauthors(bib::Citation)
authors = split(bib["author"], " and ")
map(a -> (split(strip(a, ['}', '{']), ", ")),
authors)
end
"""Create the cite key given a bibtex object"""
function createcitekey(bib::Citation)
authors = splitauthors(bib)
firstauthor = length(authors) > 0 ? authors[1][1] : "Unnamed"
title = split(get(bib, "title", "Untitled"), " ")[1]
year = match(r"([0-9]{4})", get(bib, "year", get(bib, "date", "0000")))[1]
string(firstauthor, "_", title, "_", year) |> lowercase
end
"""Generates a new id, with the same key, but with a number at the end
(id-\$number) so that it is unique in the library. Fallback for
duplicates. """
function nextidnumber(bibliography::Bibliography,id::String)
num = 0
while true
nid = string(id, "-", num)
nid in keys(bibliography) || break
num += 1
end
nid
end
# """
# Apply some cleaning to the bibtex citation, namely fixing the key id.
# Useful when adding a bibtex directly to verify that it conforms to our "standard"
# """
# function cleancitation(cit)
# end