bibtex-ruby 2.0.1 → 2.0.2
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/Gemfile.lock +2 -2
- data/History.txt +5 -0
- data/lib/bibtex.rb +12 -12
- data/lib/bibtex/bibliography.rb +98 -81
- data/lib/bibtex/elements.rb +191 -191
- data/lib/bibtex/entry.rb +470 -445
- data/lib/bibtex/lexer.rb +5 -5
- data/lib/bibtex/names.rb +2 -1
- data/lib/bibtex/value.rb +40 -43
- data/lib/bibtex/version.rb +1 -1
- data/test/bibtex/test_bibliography.rb +49 -49
- data/test/bibtex/test_entry.rb +214 -208
- data/test/bibtex/test_name_parser.rb +2 -2
- metadata +12 -12
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bibtex-ruby (2.0.
|
4
|
+
bibtex-ruby (2.0.1)
|
5
5
|
latex-decode (>= 0.0.6)
|
6
6
|
multi_json (~> 1.0)
|
7
7
|
|
@@ -27,7 +27,7 @@ GEM
|
|
27
27
|
gnuplot (2.3.6)
|
28
28
|
json (1.5.4)
|
29
29
|
json (1.5.4-java)
|
30
|
-
latex-decode (0.0.
|
30
|
+
latex-decode (0.0.9)
|
31
31
|
unicode (~> 0.4)
|
32
32
|
linecache (0.46)
|
33
33
|
rbx-require-relative (> 0.0.4)
|
data/History.txt
CHANGED
data/lib/bibtex.rb
CHANGED
@@ -16,22 +16,20 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
#++
|
18
18
|
|
19
|
-
$:.unshift(File.dirname(__FILE__)) unless
|
20
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
21
|
-
|
22
19
|
require 'digest/md5'
|
23
|
-
|
24
|
-
require 'bibtex/version'
|
20
|
+
require 'forwardable'
|
25
21
|
require 'logger'
|
22
|
+
require 'open-uri'
|
26
23
|
|
27
24
|
require 'multi_json'
|
28
25
|
|
26
|
+
require 'bibtex/version'
|
27
|
+
|
29
28
|
# = BibTeX
|
30
29
|
#
|
31
30
|
# This module encompasses a parser for BibTeX files and
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# +Entry+.
|
31
|
+
# an API to the individual BibTeX objects: +String+,
|
32
|
+
# +Preamble+, +Comment+, and +Entry+.
|
35
33
|
#
|
36
34
|
# Author:: {Sylvester Keil}[http://sylvester.keil.or.at]
|
37
35
|
# Copyright:: Copyright (c) 2010-2011 Sylvester Keil
|
@@ -43,11 +41,13 @@ module BibTeX
|
|
43
41
|
# An instance of the Ruby core class +Logger+.
|
44
42
|
# Used for logging by BibTeX-Ruby.
|
45
43
|
#
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
@log = Logger.new(STDERR)
|
45
|
+
@log.level = ENV.has_key?('DEBUG') ? Logger::DEBUG : Logger::WARN
|
46
|
+
@log.datetime_format = '%Y-%m-%d %H:%M:%S'
|
49
47
|
|
50
|
-
|
48
|
+
class << self
|
49
|
+
attr_reader :log
|
50
|
+
end
|
51
51
|
|
52
52
|
end
|
53
53
|
|
data/lib/bibtex/bibliography.rb
CHANGED
@@ -16,9 +16,6 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
#++
|
18
18
|
|
19
|
-
require 'forwardable'
|
20
|
-
require 'open-uri'
|
21
|
-
|
22
19
|
module BibTeX
|
23
20
|
|
24
21
|
#
|
@@ -35,8 +32,8 @@ module BibTeX
|
|
35
32
|
|
36
33
|
class << self
|
37
34
|
|
38
|
-
|
39
|
-
|
35
|
+
attr_reader :defaults
|
36
|
+
|
40
37
|
# Opens and parses the `.bib' file at the given +path+. Returns
|
41
38
|
# a new Bibliography instance corresponding to the file, or, if a block
|
42
39
|
# is given, yields the instance to the block, ensuring that the file
|
@@ -53,7 +50,7 @@ module BibTeX
|
|
53
50
|
#
|
54
51
|
def open(path, options = {})
|
55
52
|
b = parse(Kernel.open(path, 'r:UTF-8').read, options)
|
56
|
-
|
53
|
+
b.path = path
|
57
54
|
return b unless block_given?
|
58
55
|
|
59
56
|
begin
|
@@ -65,14 +62,14 @@ module BibTeX
|
|
65
62
|
|
66
63
|
# Parses the given string and returns a corresponding Bibliography instance.
|
67
64
|
def parse(input, options = {})
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
65
|
+
case input
|
66
|
+
when Array, Hash, Element
|
67
|
+
Bibliography.new(options).add(input)
|
68
|
+
when ::String
|
69
|
+
Parser.new(options).parse(input) || Bibliography.new(options)
|
70
|
+
else
|
71
|
+
raise ArgumentError, "failed to parse #{input.inspect}"
|
72
|
+
end
|
76
73
|
end
|
77
74
|
|
78
75
|
# Defines a new accessor that selects elements by type.
|
@@ -88,22 +85,30 @@ module BibTeX
|
|
88
85
|
|
89
86
|
attr_reader :data, :strings, :entries, :errors, :options
|
90
87
|
|
91
|
-
attr_by_type :article, :book, :journal, :collection, :preamble,
|
92
|
-
|
88
|
+
attr_by_type :article, :book, :journal, :collection, :preamble,
|
89
|
+
:comment, :meta_content
|
93
90
|
|
94
|
-
def_delegators :@data, :length, :size, :
|
95
|
-
|
91
|
+
def_delegators :@data, :length, :size, :empty?
|
92
|
+
def_delegators :@entries, :key?, :has_key?
|
96
93
|
|
97
94
|
|
98
95
|
# Creates a new bibliography.
|
99
96
|
def initialize(options = {})
|
100
97
|
@options = Bibliography.defaults.merge(options)
|
101
|
-
@data, @strings = [], {}
|
102
|
-
|
98
|
+
@data, @strings, @errors = [], {}, []
|
99
|
+
@entries = Hash.new { |h,k| h.fetch(k.to_s, nil) }
|
103
100
|
|
104
101
|
yield self if block_given?
|
105
102
|
end
|
106
103
|
|
104
|
+
def initialize_copy(other)
|
105
|
+
@options = other.options.dup
|
106
|
+
@errors = other.errors.dup
|
107
|
+
@data, @strings = [], {}
|
108
|
+
@entries = Hash.new { |h,k| h.fetch(k.to_s, nil) }
|
109
|
+
add(other.data)
|
110
|
+
end
|
111
|
+
|
107
112
|
# Adds a new element, or a list of new elements to the bibliography.
|
108
113
|
# Returns the Bibliography for chainability.
|
109
114
|
def add(*arguments)
|
@@ -127,11 +132,21 @@ module BibTeX
|
|
127
132
|
options[:quotes] ||= %w({ })
|
128
133
|
|
129
134
|
File.open(path, 'w:UTF-8') do |f|
|
130
|
-
|
131
|
-
|
132
|
-
|
135
|
+
f.write(to_s(options))
|
136
|
+
end
|
137
|
+
|
133
138
|
self
|
134
139
|
end
|
140
|
+
|
141
|
+
|
142
|
+
def each
|
143
|
+
if block_given?
|
144
|
+
data.each(&Proc.new)
|
145
|
+
self
|
146
|
+
else
|
147
|
+
to_enum
|
148
|
+
end
|
149
|
+
end
|
135
150
|
|
136
151
|
|
137
152
|
def parse_names
|
@@ -150,12 +165,12 @@ module BibTeX
|
|
150
165
|
# entry). @see Entry#convert!
|
151
166
|
def convert (filter)
|
152
167
|
entries.each_value do |entry|
|
153
|
-
|
154
|
-
|
155
|
-
|
168
|
+
entry.convert!(filter) if !block_given? || yield(entry)
|
169
|
+
end
|
170
|
+
|
156
171
|
self
|
157
172
|
end
|
158
|
-
|
173
|
+
|
159
174
|
|
160
175
|
# Deletes an object, or a list of objects from the bibliography.
|
161
176
|
# If a list of objects is to be deleted, you can either supply the list
|
@@ -173,10 +188,6 @@ module BibTeX
|
|
173
188
|
alias rm delete
|
174
189
|
|
175
190
|
|
176
|
-
# Returns an element or a list of elements according to the given index,
|
177
|
-
# range, or query. Contrary to the Bibliography#query this method does
|
178
|
-
# not yield to a block for additional refinement of the query.
|
179
|
-
#
|
180
191
|
# call-seq:
|
181
192
|
# >> bib[-1]
|
182
193
|
# => Returns the last element of the Bibliography or nil
|
@@ -196,34 +207,35 @@ module BibTeX
|
|
196
207
|
# => Returns all objects that match 'ruby' anywhere or []
|
197
208
|
# >> bib['@book[keywords=ruby]']
|
198
209
|
# => Returns all books whose keywords attribute equals 'ruby' or []
|
210
|
+
#
|
211
|
+
# Returns an element or a list of elements according to the given index,
|
212
|
+
# range, or query. Contrary to the Bibliography#query this method does
|
213
|
+
# not yield to a block for additional refinement of the query.
|
214
|
+
#
|
199
215
|
def [](*arguments)
|
200
216
|
raise(ArgumentError, "wrong number of arguments (#{arguments.length} for 1..2)") unless arguments.length.between?(1,2)
|
201
217
|
|
202
218
|
case
|
203
219
|
when arguments[0].is_a?(Numeric) || arguments[0].is_a?(Range)
|
204
220
|
data[*arguments]
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
221
|
+
when arguments.length == 1
|
222
|
+
case
|
223
|
+
when arguments[0].nil?
|
224
|
+
nil
|
225
|
+
when arguments[0].respond_to?(:empty?) && arguments[0].empty?
|
226
|
+
nil
|
227
|
+
when arguments[0].is_a?(Symbol)
|
228
|
+
entries[arguments[0]]
|
229
|
+
when arguments[0].respond_to?(:start_with?) && !arguments[0].start_with?('@')
|
230
|
+
entries[arguments[0]]
|
231
|
+
else
|
232
|
+
query(*arguments)
|
233
|
+
end
|
218
234
|
else
|
219
235
|
query(*arguments)
|
220
236
|
end
|
221
237
|
end
|
222
238
|
|
223
|
-
# Returns all objects which could not be parsed successfully.
|
224
|
-
def errors
|
225
|
-
@errors ||= []
|
226
|
-
end
|
227
239
|
|
228
240
|
# Returns true if there are object which could not be parsed.
|
229
241
|
def errors?
|
@@ -233,14 +245,14 @@ module BibTeX
|
|
233
245
|
# Returns true if the +Bibliography+ contains no errors and only
|
234
246
|
# valid BibTeX objects (meta content is ignored).
|
235
247
|
def valid?
|
236
|
-
!errors? &&
|
248
|
+
!errors? && entries.values.all?(&:valid?)
|
249
|
+
end
|
250
|
+
|
251
|
+
# Returns a list of the names of all authors, editors and translators in the Bibliography.
|
252
|
+
def names
|
253
|
+
map(&:names).flatten
|
237
254
|
end
|
238
255
|
|
239
|
-
# Returns a list of the names of all authors, editors and translators in the Bibliography.
|
240
|
-
def names
|
241
|
-
map(&:names).flatten
|
242
|
-
end
|
243
|
-
|
244
256
|
# Replaces all string symbols which are defined in the bibliography.
|
245
257
|
#
|
246
258
|
# By default symbols in @string, @preamble and entries are replaced; this
|
@@ -273,8 +285,9 @@ module BibTeX
|
|
273
285
|
self
|
274
286
|
end
|
275
287
|
|
288
|
+
|
276
289
|
def sort(*arguments, &block)
|
277
|
-
|
290
|
+
data.sort(*arguments, &block)
|
278
291
|
self
|
279
292
|
end
|
280
293
|
|
@@ -283,6 +296,10 @@ module BibTeX
|
|
283
296
|
map { |o| o.to_s(options) }.join
|
284
297
|
end
|
285
298
|
|
299
|
+
def inspect
|
300
|
+
"#<#{self.class} data=[#{length}]>"
|
301
|
+
end
|
302
|
+
|
286
303
|
def to_a(options = {})
|
287
304
|
map { |o| o.to_hash(options) }
|
288
305
|
end
|
@@ -308,16 +325,16 @@ module BibTeX
|
|
308
325
|
end
|
309
326
|
|
310
327
|
# Returns a REXML::Document representation of the bibliography using the
|
311
|
-
|
328
|
+
# BibTeXML format.
|
312
329
|
def to_xml(options = {})
|
313
330
|
require 'rexml/document'
|
314
|
-
|
331
|
+
|
315
332
|
xml = REXML::Document.new
|
316
333
|
xml << REXML::XMLDecl.new('1.0','UTF-8')
|
317
334
|
|
318
335
|
root = REXML::Element.new('bibtex:file')
|
319
|
-
|
320
|
-
|
336
|
+
root.add_namespace('bibtex', 'http://bibtexml.sf.net/')
|
337
|
+
|
321
338
|
each { |e| root.add_element(e.to_xml(options)) }
|
322
339
|
|
323
340
|
xml.add_element(root)
|
@@ -342,11 +359,11 @@ module BibTeX
|
|
342
359
|
# #=> same as above without using a block
|
343
360
|
#
|
344
361
|
def query(*arguments, &block)
|
345
|
-
raise
|
362
|
+
raise ArgumentError, "wrong number of arguments (#{arguments.length} for 0..2)" unless arguments.length.between?(0,2)
|
346
363
|
|
347
364
|
q, selector = arguments.reverse
|
348
365
|
filter = block ? Proc.new { |e| e.match?(q) && block.call(e) } :
|
349
|
-
|
366
|
+
Proc.new { |e| e.match?(q) }
|
350
367
|
|
351
368
|
send(query_handler(selector), &filter)
|
352
369
|
end
|
@@ -363,26 +380,26 @@ module BibTeX
|
|
363
380
|
other.respond_to?(:to_a) ? to_a <=> other.to_a : nil
|
364
381
|
end
|
365
382
|
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
383
|
+
# TODO this should be faster than select_duplicates_by
|
384
|
+
# def detect_duplicates_by(*arguments)
|
385
|
+
# end
|
386
|
+
|
387
|
+
def select_duplicates_by(*arguments)
|
388
|
+
d, fs = Hash.new([]), arguments.flatten.map(&:to_sym)
|
389
|
+
q('@entry') do |e|
|
390
|
+
d[e.generate_hash(fs)] << e
|
391
|
+
end
|
392
|
+
|
393
|
+
d.values.dup
|
394
|
+
end
|
395
|
+
|
396
|
+
alias duplicates select_duplicates_by
|
397
|
+
|
398
|
+
def duplicates?
|
399
|
+
!select_duplicates_by?.empty?
|
400
|
+
end
|
401
|
+
|
402
|
+
|
386
403
|
private
|
387
404
|
|
388
405
|
def query_handler(selector)
|
data/lib/bibtex/elements.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#--
|
2
2
|
# BibTeX-Ruby
|
3
|
-
# Copyright (C) 2010-2011
|
3
|
+
# Copyright (C) 2010-2011 Sylvester Keil <sylvester.keil.or.at>
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
@@ -9,45 +9,45 @@
|
|
9
9
|
#
|
10
10
|
# This program is distributed in the hope that it will be useful,
|
11
11
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
13
|
# GNU General Public License for more details.
|
14
14
|
#
|
15
15
|
# You should have received a copy of the GNU General Public License
|
16
|
-
# along with this program.
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
#++
|
18
18
|
|
19
19
|
module BibTeX
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
#
|
22
|
+
# The base class for BibTeX objects.
|
23
|
+
#
|
24
|
+
class Element
|
25
25
|
include Comparable
|
26
26
|
|
27
27
|
attr_writer :id
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
attr_reader :bibliography
|
29
|
+
|
30
|
+
# Returns an array of BibTeX elements.
|
31
31
|
def self.parse(input, options = {})
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
32
|
+
case input
|
33
|
+
when Element
|
34
|
+
[input]
|
35
|
+
when Hash
|
36
|
+
[Entry.new(input)]
|
37
|
+
when Array
|
38
|
+
input.inject([]) { |s,a| s.concat(parse(a, options)) }
|
39
|
+
when ::String
|
40
|
+
Parser.new(options).parse(input).data.each do |e|
|
41
|
+
e.parse_names unless !e.respond_to?(:parse_names) || options[:parse_names] == false
|
42
|
+
e.parse_month unless !e.respond_to?(:parse_month) || options[:parse_months] == false
|
43
|
+
end
|
44
|
+
else
|
45
|
+
raise ArgumentError, "failed to parse Element from #{input.inspect}"
|
46
|
+
end
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
|
-
|
49
|
+
# Returns a string containing the object's content.
|
50
|
+
def content(options = {}); ''; end
|
51
51
|
|
52
52
|
# Invokes BibTeX string replacement on this element.
|
53
53
|
def replace(*arguments); self; end
|
@@ -63,19 +63,19 @@ module BibTeX
|
|
63
63
|
self.class.name.split(/::/).last.gsub(/([[:lower:]])([[:upper:]])/) { "#{$1}_#{$2}" }.downcase.intern
|
64
64
|
end
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
66
|
+
# Returns a list of names for that Element. All Elements except Entries return an empty list.
|
67
|
+
def names
|
68
|
+
[]
|
69
|
+
end
|
70
|
+
|
71
71
|
def has_type?(type)
|
72
72
|
self.type == type.intern || defined?(type) == 'constant' && is_a?(type)
|
73
73
|
end
|
74
74
|
|
75
75
|
[:entry, :book, :article, :collection, :string, :preamble, :comment]. each do |type|
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
method_id = "#{type}?"
|
77
|
+
define_method(method_id) { has_type?(type) } unless method_defined?(method_id)
|
78
|
+
end
|
79
79
|
|
80
80
|
# Returns true if the element matches the given query.
|
81
81
|
def matches?(query)
|
@@ -112,85 +112,85 @@ module BibTeX
|
|
112
112
|
|
113
113
|
alias meet? meets?
|
114
114
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
115
|
+
alias to_s content
|
116
|
+
|
117
|
+
def to_hash(options = {})
|
118
|
+
{ type => content }
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_yaml(options = {})
|
122
|
+
require 'yaml'
|
123
123
|
to_hash.to_yaml
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
124
|
+
end
|
125
|
+
|
126
|
+
def to_json(options = {})
|
127
|
+
MultiJson.encode(to_hash(options))
|
128
|
+
end
|
129
|
+
|
130
|
+
def to_xml(options = {})
|
131
|
+
require 'rexml/document'
|
132
|
+
xml = REXML::Element.new(type)
|
133
|
+
xml.text = content
|
134
|
+
xml
|
135
|
+
end
|
136
136
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
137
|
+
# Called when the element was added to a bibliography.
|
138
|
+
def added_to_bibliography(bibliography)
|
139
|
+
# raise BibTeXError, "failed to add element to Bibliography: already registered with another Bibliography" unless @bibliography.nil?
|
140
|
+
@bibliography = bibliography
|
141
|
+
self
|
142
|
+
end
|
143
|
+
|
144
|
+
# Called when the element was removed from a bibliography.
|
145
|
+
def removed_from_bibliography(bibliography)
|
146
|
+
@bibliography = nil
|
147
|
+
self
|
148
|
+
end
|
149
|
+
|
150
|
+
def <=>(other)
|
151
|
+
return nil unless other.respond_to? :type and other.respond_to? :to_s
|
152
|
+
[type, to_s] <=> [other.type, other.to_s]
|
153
|
+
end
|
154
|
+
|
155
|
+
# Returns the Element as a nicely formatted string.
|
156
|
+
def inspect
|
157
|
+
"#<#{self.class} #{content.gsub(/\n/, ' ')}>"
|
158
|
+
end
|
159
|
+
end
|
160
160
|
|
161
161
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
162
|
+
#
|
163
|
+
# Represents a @string object.
|
164
|
+
#
|
165
|
+
# In BibTeX @string objects contain a single string constant
|
166
|
+
# assignment. For example, @string{ foo = "bar" } defines the
|
167
|
+
# constant `foo'; this constant can be used (using BibTeX's
|
168
|
+
# string concatenation syntax) in susbsequent
|
169
|
+
# @string and @preamble objects, as well as in field values
|
170
|
+
# of regular entries.
|
171
|
+
#
|
172
|
+
class String < Element
|
173
173
|
include Replaceable
|
174
174
|
|
175
|
-
|
175
|
+
attr_reader :key
|
176
176
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
177
|
+
# Creates a new instance.
|
178
|
+
def initialize(key = nil, value = nil)
|
179
|
+
@key, @value = key.to_sym, Value.new(value)
|
180
|
+
yield self if block_given?
|
181
|
+
end
|
182
182
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
183
|
+
# Sets the string's key (i.e., the symbol identifying the constant).
|
184
|
+
def key=(key)
|
185
|
+
raise(ArgumentError, "keys must be convertible to Symbol; was: #{type.class.name}.") unless type.respond_to?(:to_sym)
|
186
|
+
|
187
|
+
unless bibliography.nil?
|
188
|
+
bibliography.strings.delete(@key)
|
189
|
+
bibliography.strings[key.to_sym] = self
|
190
|
+
end
|
191
191
|
|
192
|
-
|
193
|
-
|
192
|
+
@key = key.to_sym
|
193
|
+
end
|
194
194
|
|
195
195
|
# Retuns the string's value if parameter matches the key; nil otherwise.
|
196
196
|
def [](key)
|
@@ -198,104 +198,104 @@ module BibTeX
|
|
198
198
|
end
|
199
199
|
|
200
200
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
201
|
+
# Called when the element was added to a bibliography.
|
202
|
+
def added_to_bibliography(bibliography)
|
203
|
+
super
|
204
|
+
bibliography.strings[@key] = self
|
205
|
+
self
|
206
|
+
end
|
207
|
+
|
208
|
+
# Called when the element was removed from a bibliography.
|
209
|
+
def removed_from_bibliography(bibliography)
|
210
|
+
super
|
211
|
+
bibliography.strings[@key] = nil
|
212
|
+
self
|
213
|
+
end
|
214
214
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
215
|
+
# Returns a string representation of the @string's content.
|
216
|
+
def content
|
217
|
+
"#@key = #{@value.to_s(:quotes => '"')}"
|
218
|
+
end
|
219
219
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
220
|
+
# Returns a string representation of the @string object.
|
221
|
+
def to_s(options = {})
|
222
|
+
"@string{ #{content} }"
|
223
|
+
end
|
224
|
+
|
225
|
+
def to_hash(options = {})
|
226
|
+
{ :string => { @key => @value.to_s(:quotes => '"') } }
|
227
|
+
end
|
228
|
+
|
229
|
+
def to_xml(options = {})
|
230
|
+
require 'rexml/document'
|
231
|
+
|
232
|
+
xml = REXML::Element.new(:string)
|
233
|
+
|
234
|
+
k, v = REXML::Element.new(:key), REXML::Element.new(:value)
|
235
|
+
k.text = key.to_s
|
236
|
+
v.text = value.to_s(:quotes => '"')
|
237
|
+
|
238
|
+
xml.add_elements(k)
|
239
|
+
xml.add_elements(v)
|
240
|
+
|
241
|
+
xml
|
242
|
+
end
|
243
|
+
end
|
244
244
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
245
|
+
#
|
246
|
+
# Represents a @preamble object.
|
247
|
+
#
|
248
|
+
# In BibTeX an @preamble object contains a single string literal,
|
249
|
+
# a single constant, or a concatenation of string literals and
|
250
|
+
# constants.
|
251
|
+
class Preamble < Element
|
252
|
+
include Replaceable
|
253
253
|
|
254
|
-
|
255
|
-
|
254
|
+
# Creates a new instance.
|
255
|
+
def initialize(value = '')
|
256
256
|
@value = Value.new(value)
|
257
|
-
|
257
|
+
end
|
258
258
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
259
|
+
# Returns a string representation of the @preamble's content.
|
260
|
+
def content
|
261
|
+
@value.to_s(:quotes => '"')
|
262
|
+
end
|
263
263
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
264
|
+
# Returns a string representation of the @preamble object
|
265
|
+
def to_s(options = {})
|
266
|
+
"@preamble{ #{content} }"
|
267
|
+
end
|
268
|
+
end
|
269
269
|
|
270
|
-
|
271
|
-
|
270
|
+
# Represents a @comment object.
|
271
|
+
class Comment < Element
|
272
272
|
attr_accessor :content
|
273
273
|
|
274
|
-
|
275
|
-
|
276
|
-
|
274
|
+
def initialize(content = '')
|
275
|
+
@content = content
|
276
|
+
end
|
277
277
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
278
|
+
def to_s(options = {})
|
279
|
+
"@comment{ #@content }"
|
280
|
+
end
|
281
|
+
end
|
282
282
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
283
|
+
# Represents text in a `.bib' file, but outside of an
|
284
|
+
# actual BibTeX object; typically, such text is treated
|
285
|
+
# as a comment and is ignored by the parser.
|
286
|
+
# BibTeX-Ruby offers this class to allows for
|
287
|
+
# post-processing of this type of `meta' content. If you
|
288
|
+
# want the parser to include +MetaComment+ objects, you
|
289
|
+
# need to add +:meta_content+ to the parser's +:include+
|
290
|
+
# option.
|
291
|
+
class MetaContent < Element
|
292
|
+
attr_accessor :content
|
293
|
+
|
294
|
+
def initialize(content = '')
|
295
|
+
@content = content
|
296
|
+
end
|
297
297
|
|
298
|
-
|
299
|
-
|
298
|
+
def to_s(options = {}); @content; end
|
299
|
+
end
|
300
300
|
|
301
301
|
end
|