Class: BibTeX::Bibliography

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Comparable, Enumerable
Defined in:
lib/bibtex/bibliography.rb

Overview

The Bibliography class models a BibTeX bibliography; typically, it corresponds to a ‘.bib’ file.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data = []) ⇒ Bibliography

Creates a new bibliography; empty if no data attribute is specified.



86
87
88
89
90
91
# File 'lib/bibtex/bibliography.rb', line 86

def initialize(data = [])
  @data = []
  @strings = {}
  @entries = {}
  add(data)
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



76
77
78
# File 'lib/bibtex/bibliography.rb', line 76

def data
  @data
end

#entriesObject (readonly)

Returns the value of attribute entries.



76
77
78
# File 'lib/bibtex/bibliography.rb', line 76

def entries
  @entries
end

#errorsObject (readonly)

Returns all objects which could not be parsed successfully.



184
185
186
# File 'lib/bibtex/bibliography.rb', line 184

def errors
  @errors
end

#pathObject

Returns the value of attribute path.



75
76
77
# File 'lib/bibtex/bibliography.rb', line 75

def path
  @path
end

#stringsObject (readonly)

Returns the value of attribute strings.



76
77
78
# File 'lib/bibtex/bibliography.rb', line 76

def strings
  @strings
end

Class Method Details

.attr_by_type(*arguments) ⇒ Object

Defines a new accessor that selects elements by type.



67
68
69
70
71
72
# File 'lib/bibtex/bibliography.rb', line 67

def attr_by_type(*arguments)
  arguments.each do |type|
    method_id = "#{type}s"
    define_method(method_id) { find_by_type(type) } unless respond_to?(method_id)
  end
end

.open(path, options = {}) ⇒ Object

Opens and parses the ‘.bib’ file at the given path. Returns a new Bibliography instance corresponding to the file, or, if a block is given, yields the instance to the block, ensuring that the file is saved after the block’s execution (use the :out option if you want to specify a save path other than the path from where the file is loaded).

The options argument is passed on to BibTeX::Parser.new.



45
46
47
48
49
50
51
52
53
54
# File 'lib/bibtex/bibliography.rb', line 45

def open(path, options = {})
  b = parse(Kernel.open(path).read, options)
  return b unless !b.nil? and block_given?

  begin
    yield b
  ensure
    b.save_to(options[:out] || path)
  end
end

.parse(bibtex, options = {}) ⇒ Object

Parses the given string and returns a corresponding Bibliography instance.



57
58
59
60
61
62
# File 'lib/bibtex/bibliography.rb', line 57

def parse(bibtex, options = {})
  b = Parser.new(options).parse(bibtex)
  b.parse_names unless b.nil? || options[:parse_names] == false
  b.parse_months unless b.nil? || options[:parse_months] == false
  b
end

Instance Method Details

#<=>(other) ⇒ Object



311
312
313
# File 'lib/bibtex/bibliography.rb', line 311

def <=>(other)
  other.respond_to?(:to_a) ? to_a <=> other.to_a : nil
end

#[](*arguments) ⇒ Object

Returns an element or a list of elements according to the given index, range, or query. Contrary to the Bibliography#query this method does not yield to a block for additional refinement of the query.

call-seq: >> bib

> Returns the last element of the Bibliography or nil

>> bib

> Returns the second and third elements or nil

>> bib >> Same as above >> bib

> Returns the first entry with key ‘key’ or nil

>> bib

> Returns all entries with key ‘key’ or []

>> bib

> Returns all entries of type ‘article’ or []

>> bib

> Returns all preamble objects (this is the same as Bibliography#preambles) or []

>> bib

> Returns all objects that match ‘ruby’ anywhere or []

>> bib[‘@book’]

> Returns all books whose keywords attribute equals ‘ruby’ or []

Raises:

  • (ArgumentError)


170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/bibtex/bibliography.rb', line 170

def [](*arguments)
  raise(ArgumentError, "wrong number of arguments (#{arguments.length} for 1..2)") unless arguments.length.between?(1,2)

  case
  when !([Range, Numeric] & arguments[0].class.ancestors).empty?
    @data[*arguments] 
  when arguments.length == 1 && arguments[0].is_a?(Symbol)
    @entries[arguments[0]]
  else
    query(*arguments)
  end
end

#add(*arguments) ⇒ Object Also known as: <<, push

Adds a new element, or a list of new elements to the bibliography. Returns the Bibliography for chainability.



95
96
97
98
99
100
101
# File 'lib/bibtex/bibliography.rb', line 95

def add(*arguments)
  arguments.flatten.each do |element|
    raise(ArgumentError, "Failed to add #{ element.inspect } to Bibliography; instance of BibTeX::Element expected.") unless element.is_a?(Element)
    @data << element.added_to_bibliography(self)
  end
  self
end

#delete(*arguments, &block) ⇒ Object Also known as: remove, rm

Deletes an object, or a list of objects from the bibliography. If a list of objects is to be deleted, you can either supply the list of objects or use a query or block to define the list.

Returns the object (or the list of objects) that were deleted; nil if the object was not part of the bibliography.



136
137
138
139
140
# File 'lib/bibtex/bibliography.rb', line 136

def delete(*arguments, &block)
  objects = q(*arguments, &block).map { |o| o.removed_from_bibliography(self) }
  @data = @data - objects
  objects.length == 1 ? objects[0] : objects
end

#errors?Boolean

Returns true if there are object which could not be parsed.

Returns:

  • (Boolean)


189
190
191
# File 'lib/bibtex/bibliography.rb', line 189

def errors?
  !errors.empty?
end

#find_by_type(*types, &block) ⇒ Object Also known as: find_by_types



305
306
307
# File 'lib/bibtex/bibliography.rb', line 305

def find_by_type(*types, &block)
  q(types.flatten.compact.map { |t| "@#{t}" }.join(', '), &block)
end

#join(filter = '') ⇒ Object Also known as: join_strings



219
220
221
222
# File 'lib/bibtex/bibliography.rb', line 219

def join(filter = '')
  q(filter, &:join)
  self
end

#parse_monthsObject



123
124
125
126
# File 'lib/bibtex/bibliography.rb', line 123

def parse_months
  q('@entry') { |e| e.parse_month }
  self
end

#parse_namesObject



118
119
120
121
# File 'lib/bibtex/bibliography.rb', line 118

def parse_names
  q('@entry') { |e| e.parse_names }
  self
end

#query(*arguments, &block) ⇒ Object Also known as: q

Returns objects in the Bibliography which match the given selector and, optionally, the conditions specified in the given block.

call-seq: bib.query() #=> returns all objects bib.query(:all) #=> returns all objects bib.query(:first) #=> returns the first object bib.query(‘@book’) #=> returns all books bib.query(:first, ‘@book, @article’) #=> returns the first book or article bib.query(‘@book, @article) #=> returns all books published in 2011 and all articles bib.query(’@book, @article) { |o| o.year == ‘2011’ } #=> returns all books and articles published in 2011 bib.query(‘@book, @article) #=> same as above without using a block

Raises:

  • (ArgumentError)


294
295
296
297
298
299
300
301
# File 'lib/bibtex/bibliography.rb', line 294

def query(*arguments, &block)
  raise(ArgumentError, "wrong number of arguments (#{arguments.length} for 0..2)") unless arguments.length.between?(0,2)

  q, selector = arguments.reverse
  filter = block ? Proc.new { |e| e.match?(q) && block.call(e) } : Proc.new { |e| e.match?(q) }

  send(query_handler(selector), &filter)
end

#rename(*arguments, &block) ⇒ Object



226
227
228
229
# File 'lib/bibtex/bibliography.rb', line 226

def rename(*arguments, &block)
  q('@entry') { |e| e.rename(*arguments, &block) }
  self
end

#replace(filter = '') ⇒ Object Also known as: replace_strings

Replaces all string symbols which are defined in the bibliography.

By default symbols in @string, @preamble and entries are replaced; this behaviour can be changed using the optional query parameter.

Note that strings are replaced in the order in which they occur in the bibliography.

call-seq: bib.replace #=> replaces all symbols bib.replace(‘@string, @preamble’) #=> replaces only symbols in @string and @preamble objects



212
213
214
215
# File 'lib/bibtex/bibliography.rb', line 212

def replace(filter = '')
  q(filter) { |e| e.replace(@strings.values) }
  self
end

#save(options = {}) ⇒ Object

Saves the bibliography to the current path.



107
108
109
# File 'lib/bibtex/bibliography.rb', line 107

def save(options = {})
  save_to(@path, options)
end

#save_to(path, options = {}) ⇒ Object

Saves the bibliography to a file at the given path. Returns the bibliography.



112
113
114
115
116
# File 'lib/bibtex/bibliography.rb', line 112

def save_to(path, options = {})
  options[:quotes] ||= %w({ })
  File.open(path, "w") { |f| f.write(to_s(options)) }
  self
end

#sort(*arguments, &block) ⇒ Object



231
232
233
234
# File 'lib/bibtex/bibliography.rb', line 231

def sort(*arguments, &block)
  @data.sort(*arguments, &block)
  self
end

#to_a(options = {}) ⇒ Object



241
242
243
# File 'lib/bibtex/bibliography.rb', line 241

def to_a(options = {})
  map { |o| o.to_hash(options) }
end

#to_citeproc(options = {}) ⇒ Object

Returns a CiteProc JSON representation of the bibliography. Only BibTeX enrties are exported.



261
262
263
# File 'lib/bibtex/bibliography.rb', line 261

def to_citeproc(options = {})
  q('@entry').map { |o| o.to_citeproc(options) }
end

#to_hash(options = {}) ⇒ Object

Returns a Ruby hash representation of the bibliography.



246
247
248
# File 'lib/bibtex/bibliography.rb', line 246

def to_hash(options = {})
  { :bibliography => map { |o| o.to_hash(options) } }
end

#to_json(options = {}) ⇒ Object

Returns a JSON representation of the bibliography.



256
257
258
# File 'lib/bibtex/bibliography.rb', line 256

def to_json(options = {})
  to_a(options).to_json
end

#to_s(options = {}) ⇒ Object

Returns a string representation of the bibliography.



237
238
239
# File 'lib/bibtex/bibliography.rb', line 237

def to_s(options = {})
  map { |o| o.to_s(options) }.join
end

#to_xmlObject

Returns an XML representation of the bibliography. Only BibTeX entries are exported.



266
267
268
269
270
271
272
273
274
275
# File 'lib/bibtex/bibliography.rb', line 266

def to_xml
  require 'rexml/document'
 
  xml = REXML::Document.new
  xml << REXML::XMLDecl.new('1.0','UTF-8')
  root = REXML::Element.new('bibliography')
  each { |e| root.add_element(e.to_xml) }
  xml << root
  xml
end

#to_yaml(options = {}) ⇒ Object

Returns a YAML representation of the bibliography.



251
252
253
# File 'lib/bibtex/bibliography.rb', line 251

def to_yaml(options = {})
  to_a(options).to_yaml
end

#valid?Boolean

Returns true if the Bibliography contains no errors and only valid BibTeX objects (meta content is ignored).

Returns:

  • (Boolean)


195
196
197
# File 'lib/bibtex/bibliography.rb', line 195

def valid?
  !errors? && @entries.values.all?(&:valid?)
end