bibtex-ruby 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bibtex-ruby might be problematic. Click here for more details.
- data.tar.gz.sig +0 -0
- data/History.txt +3 -0
- data/LICENSE +621 -0
- data/Manifest +34 -0
- data/README.rdoc +152 -0
- data/Rakefile +54 -0
- data/bibtex-ruby.gemspec +36 -0
- data/examples/bib2html.rb +28 -0
- data/examples/markdown.bib +39 -0
- data/lib/bibtex.rb +51 -0
- data/lib/bibtex/bibliography.rb +175 -0
- data/lib/bibtex/bibtex.y +129 -0
- data/lib/bibtex/elements.rb +262 -0
- data/lib/bibtex/entry.rb +154 -0
- data/lib/bibtex/error.rb +37 -0
- data/lib/bibtex/lexer.rb +328 -0
- data/lib/bibtex/parser.output +578 -0
- data/lib/bibtex/parser.rb +467 -0
- data/lib/bibtex/string_replacement.rb +43 -0
- data/lib/extensions/core.rb +35 -0
- data/test/bib/00_empty.bib +0 -0
- data/test/bib/01_no_bibtex.bib +9 -0
- data/test/bib/02_string.bib +1 -0
- data/test/bib/03_string.bib +26 -0
- data/test/bib/04_string_replacement.bib +16 -0
- data/test/bib/05_comment.bib +15 -0
- data/test/bib/06_preamble.bib +12 -0
- data/test/bib/07_entry.bib +20 -0
- data/test/bib/08_decoret.bib +83 -0
- data/test/bib/09_errors.bib +67 -0
- data/test/bib/10_bibdesk.bib +47 -0
- data/test/test_bibtex.rb +58 -0
- data/test/test_comment.rb +24 -0
- data/test/test_entry.rb +35 -0
- data/test/test_preamble.rb +24 -0
- data/test/test_string.rb +77 -0
- metadata +155 -0
- metadata.gz.sig +0 -0
data/lib/bibtex/bibtex.y
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
#--
|
2
|
+
# BibTeX-Ruby
|
3
|
+
# Copyright (C) 2010 Sylvester Keil <http://sylvester.keil.or.at>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#++
|
18
|
+
#
|
19
|
+
# A BibTeX grammar for the parser generator +racc+
|
20
|
+
#
|
21
|
+
|
22
|
+
# -*- racc -*-
|
23
|
+
|
24
|
+
class BibTeX::Parser
|
25
|
+
|
26
|
+
token AT COMMA COMMENT CONTENT ERROR EQ LBRACE META_COMMENT
|
27
|
+
NAME NUMBER PREAMBLE RBRACE SHARP STRING STRING_LITERAL
|
28
|
+
|
29
|
+
expect 0
|
30
|
+
|
31
|
+
rule
|
32
|
+
|
33
|
+
bibliography : /* empty */ { result = Bibliography.new }
|
34
|
+
| objects { result = val[0] }
|
35
|
+
|
36
|
+
objects : object { result = Bibliography.new << val[0] }
|
37
|
+
| objects object { result << val[1] }
|
38
|
+
|
39
|
+
object : AT at_object { result = val[1] }
|
40
|
+
| META_COMMENT { result = BibTeX::MetaComment.new(val[0]) }
|
41
|
+
| ERROR { result = BibTeX::Error.new(val[0]) }
|
42
|
+
|
43
|
+
at_object : comment { result = val[0] }
|
44
|
+
| string { result = val[0] }
|
45
|
+
| preamble { result = val[0] }
|
46
|
+
| entry { result = val[0] }
|
47
|
+
|
48
|
+
comment : COMMENT LBRACE content RBRACE { result = BibTeX::Comment.new(val[2]) }
|
49
|
+
|
50
|
+
content : /* empty */ { result = '' }
|
51
|
+
| CONTENT { result = val[0] }
|
52
|
+
|
53
|
+
preamble : PREAMBLE LBRACE string_value RBRACE { result = BibTeX::Preamble.new(val[2]) }
|
54
|
+
|
55
|
+
string : STRING LBRACE string_assignment RBRACE { result = BibTeX::String.new(val[2][0],val[2][1]); }
|
56
|
+
|
57
|
+
string_assignment : NAME EQ string_value { result = [val[0].downcase.to_sym, val[2]] }
|
58
|
+
|
59
|
+
string_value : string_literal { result = [val[0]] }
|
60
|
+
| string_value SHARP string_literal { result << val[2] }
|
61
|
+
|
62
|
+
string_literal : NAME { result = val[0].downcase.to_sym }
|
63
|
+
| STRING_LITERAL { result = val[0] }
|
64
|
+
|
65
|
+
entry : entry_head assignments RBRACE { result = val[0] << val[1] }
|
66
|
+
| entry_head assignments COMMA RBRACE { result = val[0] << val[1] }
|
67
|
+
| entry_head RBRACE { result = val[0] }
|
68
|
+
|
69
|
+
entry_head : NAME LBRACE key COMMA { result = BibTeX::Entry.new(val[0].downcase.to_sym,val[2]) }
|
70
|
+
|
71
|
+
key : NAME { result = val[0] }
|
72
|
+
| NUMBER { result = val[0] }
|
73
|
+
|
74
|
+
assignments : assignment { result = val[0] }
|
75
|
+
| assignments COMMA assignment { result.merge!(val[2]) }
|
76
|
+
|
77
|
+
assignment : NAME EQ value { result = { val[0].downcase.to_sym => val[2] } }
|
78
|
+
|
79
|
+
value : string_value { result = val[0] }
|
80
|
+
| NUMBER { result = val[0] }
|
81
|
+
| LBRACE content RBRACE { result = val[1] }
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
---- header
|
86
|
+
require 'bibtex/lexer'
|
87
|
+
|
88
|
+
---- inner
|
89
|
+
|
90
|
+
attr_reader :lexer
|
91
|
+
|
92
|
+
def initialize(options={})
|
93
|
+
@options = options
|
94
|
+
@options[:include] ||= [:errors]
|
95
|
+
@lexer = Lexer.new(options)
|
96
|
+
end
|
97
|
+
|
98
|
+
def parse(input)
|
99
|
+
@yydebug = self.debug?
|
100
|
+
|
101
|
+
self.lexer.src = input
|
102
|
+
self.lexer.analyse
|
103
|
+
|
104
|
+
do_parse
|
105
|
+
end
|
106
|
+
|
107
|
+
def next_token
|
108
|
+
token = self.lexer.next_token
|
109
|
+
if token[0] == :ERROR
|
110
|
+
self.include_errors? ? token : next_token
|
111
|
+
else
|
112
|
+
[token[0],token[1][0]]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def debug?
|
117
|
+
@options[:debug] == true || ENV['DEBUG'] == true
|
118
|
+
end
|
119
|
+
|
120
|
+
def include_errors?
|
121
|
+
@options[:include].include?(:errors)
|
122
|
+
end
|
123
|
+
|
124
|
+
def on_error(tid, val, vstack)
|
125
|
+
#raise(ParseError, "Failed to parse BibTeX on value %s (%s) %s" % [val.inspect, token_to_str(tid) || '?', vstack.inspect])
|
126
|
+
Log.error("Failed to parse BibTeX on value %s (%s) %s" % [val.inspect, token_to_str(tid) || '?', vstack.inspect])
|
127
|
+
end
|
128
|
+
|
129
|
+
# -*- racc -*-
|
@@ -0,0 +1,262 @@
|
|
1
|
+
#--
|
2
|
+
# BibTeX-Ruby
|
3
|
+
# Copyright (C) 2010 Sylvester Keil <sylvester.keil.or.at>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#++
|
18
|
+
|
19
|
+
require 'json'
|
20
|
+
require 'rexml/document'
|
21
|
+
require 'yaml'
|
22
|
+
|
23
|
+
module BibTeX
|
24
|
+
|
25
|
+
#
|
26
|
+
# The base class for BibTeX objects.
|
27
|
+
#
|
28
|
+
class Element
|
29
|
+
|
30
|
+
attr_reader :bibliography
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@bibliography = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a string containing the object's content.
|
37
|
+
def content
|
38
|
+
""
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns a string representation of the object.
|
42
|
+
def to_s
|
43
|
+
self.content
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_hash
|
47
|
+
{ self.class.name.downcase => content }
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_yaml
|
51
|
+
self.to_hash.to_yaml
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_json
|
55
|
+
self.to_hash.to_json
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_xml
|
59
|
+
xml = REXML::Element.new(self.class.name.downcase)
|
60
|
+
xml.text = self.content
|
61
|
+
xml
|
62
|
+
end
|
63
|
+
|
64
|
+
# Called when the element was added to a bibliography.
|
65
|
+
def added_to_bibliography(bibliography)
|
66
|
+
@bibliography = bibliography
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
# Called when the element was removed from a bibliography.
|
71
|
+
def removed_from_bibliography(bibliography)
|
72
|
+
@bibliography = nil
|
73
|
+
self
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
#
|
79
|
+
# Represents a @string object.
|
80
|
+
#
|
81
|
+
# In BibTeX @string objects contain a single string constant
|
82
|
+
# assignment. For example, @string{ foo = "bar" } defines the
|
83
|
+
# constant `foo'; this constant can be used (using BibTeX's
|
84
|
+
# string concatenation syntax) in susbsequent
|
85
|
+
# @string and @preamble objects, as well as in field values
|
86
|
+
# of regular entries.
|
87
|
+
#
|
88
|
+
class String < Element
|
89
|
+
attr_reader :key, :value
|
90
|
+
|
91
|
+
# Creates a new instance.
|
92
|
+
def initialize(key=nil,value=nil)
|
93
|
+
self.key = key.to_sym unless key.nil?
|
94
|
+
self.value = value unless value.nil?
|
95
|
+
end
|
96
|
+
|
97
|
+
# Sets the string's key (i.e., the name of the constant)
|
98
|
+
def key=(key)
|
99
|
+
raise(ArgumentError, "BibTeX::String key must be of type Symbol; was: #{key.class.name}.") unless key.kind_of?(Symbol)
|
100
|
+
@key = key
|
101
|
+
end
|
102
|
+
|
103
|
+
# Sets the string's value (i.e., the string literal defined by the constant)
|
104
|
+
def value=(value)
|
105
|
+
raise(ArgumentError, "BibTeX::String value must be of type Array, Symbol, or String; was: #{value.class.name}.") unless [Array,::String,Symbol].map { |k| value.kind_of?(k) }.inject { |sum,n| sum || n }
|
106
|
+
@value = value.kind_of?(Array) ? value : [value]
|
107
|
+
end
|
108
|
+
|
109
|
+
# Replaces all constants in this string's value which are defined in +hsh+.
|
110
|
+
# Returns the new value (the @string object itself remains unchanged).
|
111
|
+
#
|
112
|
+
# call-seq:
|
113
|
+
# s.to_s
|
114
|
+
# => "@string{ foobar = foo # "bar"}"
|
115
|
+
# s.replace({:foo => 'foo'})
|
116
|
+
# => ["foo","bar"]
|
117
|
+
# s.to_s
|
118
|
+
# => "@string{ foobar = foo # "bar"}"
|
119
|
+
def replace(hsh)
|
120
|
+
StringReplacement.replace(@value,hsh)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Replaces all constants in this string's value which are defined in +hsh+.
|
124
|
+
# Returns the new value (the @string object itself is changed as well).
|
125
|
+
#
|
126
|
+
# call-seq:
|
127
|
+
# s.to_s
|
128
|
+
# => "@string{ foobar = foo # "bar"}"
|
129
|
+
# s.replace({:foo => 'foo'})
|
130
|
+
# => ["foo","bar"]
|
131
|
+
# s.to_s
|
132
|
+
# => "@string{ foobar = "foo" # "bar"}"
|
133
|
+
def replace!(hsh)
|
134
|
+
@value = replace(hsh)
|
135
|
+
@bibliography.strings[@key] = value unless @bibliography.nil?
|
136
|
+
end
|
137
|
+
|
138
|
+
# Adds either a string constant or literal to the current value. The
|
139
|
+
# values will be concatenated using the `#' symbol.
|
140
|
+
def <<(value)
|
141
|
+
raise(ArgumentError, "BibTeX::String value can contain only instances of Symbol or String; was: #{value.class.name}.") unless [::String,Symbol].map { |k| value.kind_of?(k) }.inject { |sum,n| sum || n }
|
142
|
+
@value << value
|
143
|
+
end
|
144
|
+
|
145
|
+
# Called when the element was added to a bibliography.
|
146
|
+
def added_to_bibliography(bibliography)
|
147
|
+
super(bibliography)
|
148
|
+
bibliography.strings[@key] = @value
|
149
|
+
self
|
150
|
+
end
|
151
|
+
|
152
|
+
# Called when the element was removed from a bibliography.
|
153
|
+
def removed_from_bibliography(bibliography)
|
154
|
+
super(bibliography)
|
155
|
+
bibliography.strings[@key] = nil
|
156
|
+
self
|
157
|
+
end
|
158
|
+
|
159
|
+
# Returns a string representation of the @string's content.
|
160
|
+
def content
|
161
|
+
[@key.to_s,' = ',StringReplacement.to_s(@value)].join
|
162
|
+
end
|
163
|
+
|
164
|
+
# Returns a string representation of the @string object.
|
165
|
+
def to_s
|
166
|
+
['@string{ ',content,'}'].join
|
167
|
+
end
|
168
|
+
|
169
|
+
def to_hash
|
170
|
+
{ 'string' => { @key.to_s => StringReplacement.to_s(@value) } }
|
171
|
+
end
|
172
|
+
|
173
|
+
def to_xml
|
174
|
+
xml = REXML::Element.new('string')
|
175
|
+
key = REXML::Element.new('key')
|
176
|
+
val = REXML::Element.new('value')
|
177
|
+
key.text = @key.to_s
|
178
|
+
val.text = @value.to_s
|
179
|
+
xml
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
#
|
184
|
+
# Represents a @preamble object.
|
185
|
+
#
|
186
|
+
# In BibTeX an @preamble object contains a single string literal,
|
187
|
+
# a single constant, or a concatenation of string literals and
|
188
|
+
# constants.
|
189
|
+
class Preamble < Element
|
190
|
+
attr_reader :value
|
191
|
+
|
192
|
+
# Creates a new instance.
|
193
|
+
def initialize(value=[])
|
194
|
+
self.value = value
|
195
|
+
end
|
196
|
+
|
197
|
+
def value=(value)
|
198
|
+
raise(ArgumentError, "BibTeX::Preamble value must be of type Array, Symbol, or String; was: #{value.class.name}.") unless [Array,::String,Symbol].map { |k| value.kind_of?(k) }.inject { |sum,n| sum || n }
|
199
|
+
@value = value.kind_of?(Array) ? value : [value]
|
200
|
+
end
|
201
|
+
|
202
|
+
def replace(hsh)
|
203
|
+
StringReplacement.replace(@value,hsh)
|
204
|
+
end
|
205
|
+
|
206
|
+
def replace!(hsh)
|
207
|
+
@value = replace(hsh)
|
208
|
+
@bibliography.strings[@key] = @value unless @bibliography.nil?
|
209
|
+
end
|
210
|
+
|
211
|
+
# Returns a string representation of the @preamble's content.
|
212
|
+
def content
|
213
|
+
StringReplacement.to_s(@value)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Returns a string representation of the @preamble object
|
217
|
+
def to_s
|
218
|
+
['@preamble{ ',content,'}'].join
|
219
|
+
end
|
220
|
+
|
221
|
+
def to_hash
|
222
|
+
{ 'preamble' => StringReplacement.to_s(@value) }
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# Represents a @comment object.
|
227
|
+
class Comment < Element
|
228
|
+
|
229
|
+
def initialize(content='')
|
230
|
+
self.content = content
|
231
|
+
end
|
232
|
+
|
233
|
+
def content=(content)
|
234
|
+
raise(ArgumentError, "BibTeX::#{self.class.name} content must be of type String; was: #{content.class.name}.") unless content.kind_of?(::String)
|
235
|
+
@content = content
|
236
|
+
end
|
237
|
+
|
238
|
+
def content
|
239
|
+
@content
|
240
|
+
end
|
241
|
+
|
242
|
+
def to_s
|
243
|
+
['@comment{ ',content,'}'].join
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
# Represents text in a `.bib' file, but outside of an
|
249
|
+
# actual BibTeX object; typically, such text is treated
|
250
|
+
# as a comment and is ignored by the parser.
|
251
|
+
# BibTeX-Ruby offers this class to allows for
|
252
|
+
# post-processing of this type of `meta' comment. If you
|
253
|
+
# want the parser to include +MetaComment+ objects, you
|
254
|
+
# need to add +:meta_comments+ to the parser's +:include+
|
255
|
+
# option.
|
256
|
+
class MetaComment < Comment
|
257
|
+
def to_s
|
258
|
+
@content
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
data/lib/bibtex/entry.rb
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
#--
|
2
|
+
# BibTeX-Ruby
|
3
|
+
# Copyright (C) 2010 Sylvester Keil <sylvester.keil.or.at>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#++
|
18
|
+
|
19
|
+
module BibTeX
|
20
|
+
#
|
21
|
+
# Represents a regular BibTeX entry.
|
22
|
+
#
|
23
|
+
class Entry < Element
|
24
|
+
attr_reader :key, :type, :fields
|
25
|
+
|
26
|
+
# Hash containing the required fields of the standard entry types
|
27
|
+
@@RequiredFields = Hash.new([])
|
28
|
+
@@RequiredFields.merge!({
|
29
|
+
:article => [:author,:title,:journal,:year],
|
30
|
+
:book => [[:author,:editor],:title,:publisher,:year],
|
31
|
+
:booklet => [:title],
|
32
|
+
:conference => [:author,:title,:booktitle,:year],
|
33
|
+
:inbook => [[:author,:editor],:title,[:chapter,:pages],:publisher,:year],
|
34
|
+
:incollection => [:author,:title,:booktitle,:publisher,:year],
|
35
|
+
:inproceedings => [:author,:title,:booktitle,:year],
|
36
|
+
:manual => [:title],
|
37
|
+
:mastersthesis => [:author,:title,:school,:year],
|
38
|
+
:misc => [],
|
39
|
+
:phdthesis => [:author,:title,:school,:year],
|
40
|
+
:proceedings => [:title,:year],
|
41
|
+
:techreport => [:author,:title,:institution,:year],
|
42
|
+
:unpublished => [:author,:title,:note]
|
43
|
+
})
|
44
|
+
|
45
|
+
# Creates a new instance of a given +type+ (e.g., :article, :book, etc.)
|
46
|
+
# identified by a +key+.
|
47
|
+
def initialize(type=nil, key=nil)
|
48
|
+
self.key = key.to_s unless key.nil?
|
49
|
+
self.type = type.to_sym unless type.nil?
|
50
|
+
@fields = {}
|
51
|
+
end
|
52
|
+
|
53
|
+
# Sets the key of the entry
|
54
|
+
def key=(key)
|
55
|
+
raise(ArgumentError, "BibTeX::Entry key must be of type String; was: #{key.class.name}.") unless key.kind_of?(::String)
|
56
|
+
@key = key
|
57
|
+
end
|
58
|
+
|
59
|
+
# Sets the type of the entry.
|
60
|
+
def type=(type)
|
61
|
+
raise(ArgumentError, "BibTeX::Entry type must be of type Symbol; was: #{type.class.name}.") unless type.kind_of?(Symbol)
|
62
|
+
@type = type
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the value of the field with the given name.
|
66
|
+
def [](name)
|
67
|
+
@fields[name.to_sym]
|
68
|
+
end
|
69
|
+
|
70
|
+
# Adds a new field (name-value pair) to the entry.
|
71
|
+
# Returns the new value.
|
72
|
+
def []=(name,value)
|
73
|
+
add(name,value)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Adds a new field (name-value pair) to the entry.
|
77
|
+
# Returns the new value.
|
78
|
+
def add(name,value)
|
79
|
+
raise(ArgumentError, "BibTeX::Entry field name must be of type Symbol; was: #{name.class.name}.") unless name.kind_of?(Symbol)
|
80
|
+
raise(ArgumentError, "BibTeX::Entry field value must be of type Array, Symbol, or String; was: #{value.class.name}.") unless [Array,::String,Symbol].map { |k| value.kind_of?(k) }.inject { |sum,n| sum || n }
|
81
|
+
@fields[name] = value.kind_of?(Array) ? value : [value]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Removes the field with a given name from the entry.
|
85
|
+
# Returns the value of the deleted field; nil if the field was not set.
|
86
|
+
def delete(name)
|
87
|
+
@fields.delete(name.to_sym)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Adds all the fields contained in a given hash to the entry.
|
91
|
+
def <<(fields)
|
92
|
+
raise(ArgumentError, "BibTeX::Entry fields must be of type Hash; was: #{fields.class.name}.") unless fields.kind_of?(Hash)
|
93
|
+
fields.each { |n,v| add(n,v) }
|
94
|
+
self
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns true if the entry currently contains no field.
|
98
|
+
def empty?
|
99
|
+
@fields.empty?
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns false if the entry is one of the standard entry types and does not have
|
103
|
+
# definitions of all the required fields for that type.
|
104
|
+
def valid?
|
105
|
+
!@@RequiredFields[@type].map { |f|
|
106
|
+
f.kind_of?(Array) ? !(f & @fields.keys).empty? : !@fields[f].nil?
|
107
|
+
}.include?(false)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Called when the element was added to a bibliography.
|
111
|
+
def added_to_bibliography(bibliography)
|
112
|
+
super(bibliography)
|
113
|
+
bibliography.entries[@key] = self
|
114
|
+
self
|
115
|
+
end
|
116
|
+
|
117
|
+
# Called when the element was removed from a bibliography.
|
118
|
+
def removed_from_bibliography(bibliography)
|
119
|
+
super(bibliography)
|
120
|
+
bibliography.entries[@key] = nil
|
121
|
+
self
|
122
|
+
end
|
123
|
+
|
124
|
+
# Replaces all constants in this entry's field values which are defined in +hsh+.
|
125
|
+
def replace!(hsh)
|
126
|
+
@fields.keys.each { |k| @fields[k] = StringReplacement.replace(@fields[k],hsh) }
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns a string of all the entry's fields.
|
130
|
+
def content
|
131
|
+
@fields.keys.map { |k| "#{k} = #{StringReplacement.to_s(@fields[k], :delimiter => ['{','}'])}" }.join(",\n")
|
132
|
+
end
|
133
|
+
|
134
|
+
# Returns a string representation of the entry.
|
135
|
+
def to_s
|
136
|
+
["@#{type}{#{key},",content.gsub(/^/,' '),"}\n"].join("\n")
|
137
|
+
end
|
138
|
+
|
139
|
+
def to_hash
|
140
|
+
{ @type.to_s => @fields.keys.map { |k| { k.to_s => StringReplacement.to_s(@fields[k], :delimiter => ['{','}']) } }.inject({ 'key' => @key }) { |sum,n| sum.merge(n) } }.to_yaml
|
141
|
+
end
|
142
|
+
|
143
|
+
def to_xml
|
144
|
+
xml = REXML::Element.new(@type.to_s)
|
145
|
+
xml.attributes['key'] = @key
|
146
|
+
@fields.each do |k,v|
|
147
|
+
e = REXML::Element.new(k.to_s)
|
148
|
+
e.text = StringReplacement.to_s(v, :delimiter => ['',''])
|
149
|
+
xml.add_element(e)
|
150
|
+
end
|
151
|
+
xml
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|