diff --git a/src/BibTeX.jl b/src/BibTeX.jl index d7f036c..3aee2b7 100644 --- a/src/BibTeX.jl +++ b/src/BibTeX.jl @@ -1,5 +1,5 @@ module BibTeX -export Bib, BibItem +export Bibliography, Citation include("parser.jl") include("bibitem.jl") diff --git a/src/bib.jl b/src/bib.jl index 3eb5ab8..8d727dc 100644 --- a/src/bib.jl +++ b/src/bib.jl @@ -1,39 +1,39 @@ -struct Bib <: Associative{String,BibItem} +struct Bibliography <: Associative{String,Citation} preamble::String - data::Dict{String,BibItem} + data::Dict{String,Citation} end """ - Bib(bibtex::String) - Bib(io::IO) + Bibliography(bibtex::String) + Bibliography(io::IO) Given a string (or IO stream) of bibtex-format bibliography data, -parses the data and returns a `Dict`-like object `b::Bib` that +parses the data and returns a `Dict`-like object `b::Bibliography` that behaves as a dictionary mapping strings to bibliography items -[`BibItem`](@ref). +[`Citation`](@ref). """ -function Bib(bibtex::String) +function Bibliography(bibtex::String) preamble, data = parse_bibtex(bibtex) - return Bib(preamble, Dict(k=>BibItem!(v) for (k,v) in data)) + return Bibliography(preamble, Dict(k=>Citation!(v) for (k,v) in data)) end -Bib(io::IO) = Bib(readstring(io)) -Base.open(::Type{Bib}, args...) = open(io -> Bib(io), args...) +Bibliography(io::IO) = Bibliography(readstring(io)) +Base.open(::Type{Bibliography}, args...) = open(io -> Bibliography(io), args...) -Base.similar(b::Bib) = Bib("", Dict{String,BibItem}()) -Base.rehash!(b::Bib, n=length(b.data)) = begin rehash!(b.data, n); b; end -Base.sizehint!(b::Bib, n) = begin sizehint!(b.data, n); b; end -Base.empty!(b::Bib) = begin empty!(b.data); b; end -Base.copy(b::Bib) = Bib(b.preamble, copy(b.data)) +Base.similar(b::Bibliography) = Bibliography("", Dict{String,Citation}()) +Base.rehash!(b::Bibliography, n=length(b.data)) = begin Base.rehash!(b.data, n); b; end +Base.sizehint!(b::Bibliography, n) = begin sizehint!(b.data, n); b; end +Base.empty!(b::Bibliography) = begin empty!(b.data); b; end +Base.copy(b::Bibliography) = Bibliography(b.preamble, copy(b.data)) -function Base.setindex!(b::Bib, v::BibItem, k::AbstractString) - setindex!(b.data[String(k)], v) +function Base.setindex!(b::Bibliography, v::Citation, k::AbstractString) + b.data[String(k)] = v return b end -Base.get(b::Bib, k::AbstractString, default) = get(b.data, String(k), default) +Base.get(b::Bibliography, k::AbstractString, default) = get(b.data, String(k), default) -Base.start(b::Bib) = start(b.data) -Base.done(b::Bib, i) = done(b.data, i) -Base.next(b::Bib, i) = next(b.data, i) -Base.length(b::Bib) = length(b.data) +Base.start(b::Bibliography) = start(b.data) +Base.done(b::Bibliography, i) = done(b.data, i) +Base.next(b::Bibliography, i) = next(b.data, i) +Base.length(b::Bibliography) = length(b.data) # todo: add specialized Base.show methods for MIME"text/bibtex" etc. diff --git a/src/bibitem.jl b/src/bibitem.jl index 2f1f755..b5b230a 100644 --- a/src/bibitem.jl +++ b/src/bibitem.jl @@ -1,41 +1,42 @@ """ - BibItem{S}(data::Dict{String,String}) + Citation{S}(data::Dict{String,String}) A bibliography item in a bibTeX database, based on a dictionary of strings to values. It is parameterized by a symbol `S` giving the -type of the item (`:article` etcetera). A `b::BibItem` supports +type of the item (`:article` etcetera). A `b::Citation` supports `b[key]` access to retrieve the data and in general acts like a dictionary from `String` to `String`. """ -struct BibItem{S} <: Associative{String,String} +struct Citation{S} <: Associative{String,String} data::Dict{String,String} end +Citation{S}() where {S} = Citation{S}(Dict{String,String}()) -function BibItem!(data::Dict{String,String}) +function Citation!(data::Dict{String,String}) S = Symbol(pop!(data, "__type__")) - return BibItem{S}(data) + return Citation{S}(data) end -Base.similar(b::BibItem{S}) where {S} = BibItem{S}(Dict{String,String}()) -Base.rehash!(b::BibItem, n=length(b.data)) = begin rehash!(b.data, n); b; end -Base.sizehint!(b::BibItem, n) = begin sizehint!(b.data, n); b; end -Base.empty!(b::BibItem) = begin empty!(b.data); b; end -Base.copy(b::BibItem{S}) where {S} = BibItem{S}(copy(b.data)) +Base.similar(b::Citation{S}) where {S} = Citation{S}(Dict{String,String}()) +Base.rehash!(b::Citation, n=length(b.data)) = begin rehash!(b.data, n); b; end +Base.sizehint!(b::Citation, n) = begin sizehint!(b.data, n); b; end +Base.empty!(b::Citation) = begin empty!(b.data); b; end +Base.copy(b::Citation{S}) where {S} = Citation{S}(copy(b.data)) -Base.get(b::BibItem, k::AbstractString, default) = get(b.data, String(k), default) -Base.getindex(b::BibItem, k::AbstractString) = getindex(b.data, String(k)) -function Base.setindex!(b::BibItem, v::AbstractString, k::AbstractString) +Base.get(b::Citation, k::AbstractString, default) = get(b.data, String(k), default) +Base.getindex(b::Citation, k::AbstractString) = getindex(b.data, String(k)) +function Base.setindex!(b::Citation, v::AbstractString, k::AbstractString) b.data[String(k)] = String(v) return b end -Base.start(b::BibItem) = start(b.data) -Base.done(b::BibItem, i) = done(b.data, i) -Base.next(b::BibItem, i) = next(b.data, i) -Base.length(b::BibItem) = length(b.data) +Base.start(b::Citation) = start(b.data) +Base.done(b::Citation, i) = done(b.data, i) +Base.next(b::Citation, i) = next(b.data, i) +Base.length(b::Citation) = length(b.data) -function Base.show{S}(io::IO, b::BibItem{S}) - print(io, "BibItem{:$S}(", length(b), " entries)") +function Base.show{S}(io::IO, b::Citation{S}) + print(io, "Citation{:$S}(", length(b), " entries)") end # TODO: add Base.show text/plain and text/markdown for formatted citation diff --git a/test/runtests.jl b/test/runtests.jl index ba1ee3e..a04dac2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,7 +14,29 @@ Documenter.makedocs( ) @testset "examples.bib" begin - b = open(Bib, joinpath("..", "example", "examples.bib"), "r") + b = open(Bibliography, joinpath("..", "example", "examples.bib"), "r") @test length(b) == 92 - @test (b["angenendt"]::BibItem{:article})["date"] == "2002" + @test (b["angenendt"]::Citation{:article})["date"] == "2002" +end + +@testset "small bib" begin + b = Bibliography(""" + @article{foo, bar=baz} + @book{bar, foobar=1} + """) + @test get(b, "foobar", nothing) === nothing + @test get(b["foo"], "blah", nothing) === nothing + + @test string(b["foo"]) == "Citation{:article}(1 entries)" + + Base.rehash!(b) + b2 = copy(b) + @test isempty(sizehint!(empty!(b2),10)) + @test isempty(similar(b)) + b2["x"] = Citation{:foo}() + b2["x"]["bar"] = "blah" + @test length(b2) == length(b2["x"]) == 1 + @test b2["x"]["bar"] == "blah" + @test collect(b2)[1][2] == b2["x"] + @test collect(b2["x"])[1] == ("bar"=>"blah") end