bibtex-ruby 1.3.12 → 2.0.0pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bibtex-ruby might be problematic. Click here for more details.
- data/Gemfile +7 -0
- data/Gemfile.lock +12 -13
- data/Manifest +1 -1
- data/README.md +114 -22
- data/bibtex-ruby.gemspec +13 -7
- data/features/issues/crossref.feature +62 -0
- data/features/names.feature +1 -1
- data/features/step_definitions/bibtex_steps.rb +2 -2
- data/lib/bibtex.rb +3 -1
- data/lib/bibtex/bibliography.rb +84 -32
- data/lib/bibtex/elements.rb +49 -30
- data/lib/bibtex/entry.rb +243 -72
- data/lib/bibtex/error.rb +11 -2
- data/lib/bibtex/lexer.rb +8 -8
- data/lib/bibtex/names.rb +29 -4
- data/lib/bibtex/value.rb +9 -9
- data/lib/bibtex/version.rb +1 -1
- data/lib/bibtex/version.rbc +2 -2
- data/test/bibtex/test_bibliography.rb +59 -31
- data/test/bibtex/test_elements.rb +31 -7
- data/test/bibtex/test_entry.rb +220 -41
- data/test/bibtex/test_filters.rb +6 -6
- data/test/bibtex/test_lexer.rb +1 -1
- data/test/bibtex/test_name_parser.rb +4 -4
- data/test/bibtex/test_names.rb +5 -5
- data/test/bibtex/test_parser.rb +23 -23
- data/test/bibtex/test_string.rb +6 -6
- data/test/bibtex/test_value.rb +32 -32
- data/test/helper.rb +0 -1
- data/test/test_bibtex.rb +5 -6
- data/test/test_export.rb +2 -3
- metadata +32 -72
- data/profile.png +0 -0
data/Gemfile
CHANGED
@@ -7,6 +7,13 @@ group :debug do
|
|
7
7
|
gem 'rbx-trepanning', :platforms => [:rbx]
|
8
8
|
end
|
9
9
|
|
10
|
+
group :test do
|
11
|
+
gem 'minitest', :platforms => [:ruby_18, :jruby, :rbx]
|
12
|
+
gem 'mynyml-redgreen', ['~>0.7']
|
13
|
+
gem 'autowatchr', ['~>0.1']
|
14
|
+
gem 'cucumber', ['~>1.0']
|
15
|
+
end
|
16
|
+
|
10
17
|
group :profile do
|
11
18
|
gem 'ruby-prof', ['~>0.10']
|
12
19
|
gem 'gnuplot', ['~>2.3']
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bibtex-ruby (
|
4
|
+
bibtex-ruby (2.0.0pre1)
|
5
5
|
latex-decode (>= 0.0.3)
|
6
|
+
multi_json (~> 1.0)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: http://rubygems.org/
|
@@ -12,29 +13,28 @@ GEM
|
|
12
13
|
watchr
|
13
14
|
builder (3.0.0)
|
14
15
|
columnize (0.3.4)
|
15
|
-
cucumber (0.
|
16
|
+
cucumber (1.0.2)
|
16
17
|
builder (>= 2.1.2)
|
17
18
|
diff-lcs (>= 1.1.2)
|
18
|
-
gherkin (~> 2.4.
|
19
|
+
gherkin (~> 2.4.5)
|
19
20
|
json (>= 1.4.6)
|
20
21
|
term-ansicolor (>= 1.0.5)
|
21
22
|
diff-lcs (1.1.2)
|
22
|
-
gherkin (2.4.
|
23
|
+
gherkin (2.4.18)
|
23
24
|
json (>= 1.4.6)
|
24
|
-
gherkin (2.4.
|
25
|
+
gherkin (2.4.18-java)
|
25
26
|
json (>= 1.4.6)
|
26
27
|
gnuplot (2.3.6)
|
27
|
-
json (1.5.
|
28
|
-
json (1.5.
|
28
|
+
json (1.5.4)
|
29
|
+
json (1.5.4-java)
|
29
30
|
latex-decode (0.0.3)
|
30
31
|
unicode (>= 0.4)
|
31
32
|
linecache (0.46)
|
32
33
|
rbx-require-relative (> 0.0.4)
|
33
34
|
linecache19 (0.5.12)
|
34
35
|
ruby_core_source (>= 0.1.4)
|
35
|
-
|
36
|
-
|
37
|
-
minitest (2.1.0)
|
36
|
+
minitest (2.3.1)
|
37
|
+
multi_json (1.0.3)
|
38
38
|
mynyml-redgreen (0.7.1)
|
39
39
|
term-ansicolor (>= 1.0.4)
|
40
40
|
racc (1.4.6)
|
@@ -75,10 +75,9 @@ PLATFORMS
|
|
75
75
|
DEPENDENCIES
|
76
76
|
autowatchr (~> 0.1)
|
77
77
|
bibtex-ruby!
|
78
|
-
cucumber (~> 0
|
78
|
+
cucumber (~> 1.0)
|
79
79
|
gnuplot (~> 2.3)
|
80
|
-
|
81
|
-
mini_shoulda (~> 0.3)
|
80
|
+
minitest
|
82
81
|
mynyml-redgreen (~> 0.7)
|
83
82
|
racc (~> 1.4)
|
84
83
|
rake (~> 0.9)
|
data/Manifest
CHANGED
@@ -17,6 +17,7 @@ features/bibtex.feature
|
|
17
17
|
features/entries.feature
|
18
18
|
features/issues
|
19
19
|
features/issues/braced_strings.feature
|
20
|
+
features/issues/crossref.feature
|
20
21
|
features/issues/latex_filter.feature
|
21
22
|
features/issues/number_keys.feature
|
22
23
|
features/issues/parse_months.feature
|
@@ -75,7 +76,6 @@ lib/bibtex/version.rb
|
|
75
76
|
lib/bibtex/version.rbc
|
76
77
|
lib/bibtex.rb
|
77
78
|
lib/bibtex.rbc
|
78
|
-
profile.png
|
79
79
|
test
|
80
80
|
test/benchmark.rb
|
81
81
|
test/bibtex
|
data/README.md
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
BibTeX-Ruby
|
2
2
|
===========
|
3
3
|
|
4
|
-
BibTeX-Ruby is
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
BibTeX-Ruby is the Rubyist's swiss-army-knife for all things BibTeX. It
|
5
|
+
includes a parser for all common BibTeX objects (@string, @preamble,
|
6
|
+
@comment and regular entries) and a sophisticated name parser that
|
7
|
+
tokenizes correctly formatted names; BibTeX-Ruby recognizes BibTeX string
|
8
|
+
replacements, joins values containing multiple strings or variables,
|
9
|
+
supports cross-references, and decodes common LaTeX formatting
|
10
|
+
instructions to unicode; if you are in a hurry, it also allows for easy
|
11
|
+
export/conversion to formats such as YAML, JSON, CiteProc, and XML (BibTeXML).
|
12
|
+
|
13
|
+
For a list of projects using BibTeX-Ruby, see
|
14
|
+
[the project wiki](https://github.com/inukshuk/bibtex-ruby/wiki/Projects-Using-BibTeX-Ruby).
|
12
15
|
|
13
16
|
|
14
17
|
Quickstart
|
@@ -19,9 +22,9 @@ Quickstart
|
|
19
22
|
>> require 'bibtex'
|
20
23
|
=> true
|
21
24
|
>> b = BibTeX.open('./ruby.bib')
|
22
|
-
>> b[
|
25
|
+
>> b['pickaxe']
|
23
26
|
=> "2009"
|
24
|
-
>> b[
|
27
|
+
>> b['pickaxe'].title
|
25
28
|
=> "Programming Ruby 1.9: The Pragmatic Programmer's Guide"
|
26
29
|
>> b[:pickaxe].author.length
|
27
30
|
=> 3
|
@@ -39,7 +42,8 @@ Quickstart
|
|
39
42
|
BibTeX-Ruby helps you convert your bibliography to JSON, XML, or YAML;
|
40
43
|
alternatively, you can export to the JSON format used by
|
41
44
|
[CSL](http://citationstyles.org) processors and render the bibliography in
|
42
|
-
many styles
|
45
|
+
one of [many different styles](https://github.com/citation-style-language/styles)
|
46
|
+
([previews](http://www.zotero.org/styles/)):
|
43
47
|
|
44
48
|
>> require 'citeproc' # requires the citeproc-ruby gem
|
45
49
|
=> true
|
@@ -80,10 +84,9 @@ Requirements
|
|
80
84
|
|
81
85
|
* The parser generator [racc](http://i.loveruby.net/en/projects/racc/) is
|
82
86
|
required to generate the BibTeX parser and the name parser.
|
83
|
-
* The **json** gem is required on older Ruby versions for JSON export.
|
84
87
|
|
85
|
-
The
|
86
|
-
been confirmed to work with REE
|
88
|
+
The BibTeX-Ruby gem has been tested on Ruby versions 1.8.7 and 1.9.2; it has
|
89
|
+
been confirmed to work with REE, JRuby, and Rubinius;
|
87
90
|
however, there have been some [issues](https://github.com/inukshuk/bibtex-ruby/issues)
|
88
91
|
with MacRuby implementations.
|
89
92
|
|
@@ -139,6 +142,27 @@ Instead of parsing strings you can also create BibTeX elements directly in Ruby:
|
|
139
142
|
> book.key = :mybook
|
140
143
|
> bib << book
|
141
144
|
|
145
|
+
### Cross References
|
146
|
+
|
147
|
+
From version 2.0, BibTeX-Ruby correctly resolves entry cross-references, which are commonly used for entries with type `inbook`, `incollection`, and `inproceedings`. When an entry has a valid citation key in field `crossref`, BibTeX-Ruby will return any fields inherited from the parent entry:
|
148
|
+
|
149
|
+
> b = BibTeX.parse <<-END
|
150
|
+
@inbook{fraassen_1989b,
|
151
|
+
Crossref = {fraassen_1989},
|
152
|
+
Pages = {40-64},
|
153
|
+
Title = {Ideal Science: David Lewis's Account of Laws},
|
154
|
+
}
|
155
|
+
|
156
|
+
@book{fraassen_1989,
|
157
|
+
Address = {Oxford},
|
158
|
+
Author = {Bas C. van Fraassen},
|
159
|
+
Publisher = {Oxford University Press},
|
160
|
+
Title = {Laws and Symmetry},
|
161
|
+
Year = 1989
|
162
|
+
}
|
163
|
+
END
|
164
|
+
> b['fraassen_1989b'].booktitle
|
165
|
+
=> <"Laws and Symmetry">
|
142
166
|
|
143
167
|
### Queries
|
144
168
|
|
@@ -274,21 +298,22 @@ Conditional conversions are also supported:
|
|
274
298
|
>> faust1 = '@book{faust1, title = {Faust: Der Trag\"odie Erster Teil}}'
|
275
299
|
>> faust2 = '@book{faust2, title = {Faust: Der Trag\"odie Zweiter Teil}}'
|
276
300
|
>> p BibTeX.parse(faust1 + faust2).convert(:latex) { |e| e.key == :faust2 }.to_s
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
301
|
+
@book{faust1,
|
302
|
+
title = {Faust: Der Trag\"odie Erster Teil}
|
303
|
+
}
|
304
|
+
@book{faust2,
|
305
|
+
title = {Faust: Der Tragödie Zweiter Teil}
|
306
|
+
}
|
283
307
|
|
284
308
|
If you need to express a condition on the basis of individual fields, use the
|
285
309
|
conversion methods of BibTeX::Entry with a block instead (the block will be
|
286
310
|
passed the key and value of each field prior to conversion).
|
287
311
|
|
288
|
-
###
|
312
|
+
### Exports
|
289
313
|
|
290
314
|
Furthermore, BibTeX-Ruby allows you to export your bibliography for processing
|
291
315
|
by other tools. Currently supported formats include YAML, JSON, and XML.
|
316
|
+
|
292
317
|
Of course, you can also export your bibliography back to BibTeX; if you include
|
293
318
|
`:meta_content', your export should be identical to the original '.bib' file,
|
294
319
|
except for whitespace, blank lines and letter case (BibTeX-Ruby will downcase
|
@@ -300,6 +325,52 @@ BibTeX to YAML converter:
|
|
300
325
|
|
301
326
|
>> BibTeX.open('example.bib').to_yaml
|
302
327
|
|
328
|
+
Starting with version 2.0, BibTeX-Ruby's `#to_xml` exports your bibliography
|
329
|
+
to the [BibTeXML](http//bibtexml.sf.net/) format. By passing the option
|
330
|
+
`:extended => true` you can make use of the BibTeXML's extended format which
|
331
|
+
will return individual person elements and name tokens (provided you have
|
332
|
+
successfully parsed the names of your bibliography).
|
333
|
+
|
334
|
+
> BibTeX.parse(<<-END).to_xml(:extended => true).write($stdout, 2)
|
335
|
+
" @book{pickaxe,
|
336
|
+
" Address = {Raleigh, North Carolina},
|
337
|
+
" Author = {Thomas, Dave, and Fowler, Chad, and Hunt, Andy},
|
338
|
+
" Publisher = {The Pragmatic Bookshelf},
|
339
|
+
" Title = {Programming Ruby 1.9: The Pragmatic Programmer's Guide},
|
340
|
+
" Year = {2009}
|
341
|
+
" }
|
342
|
+
" END
|
343
|
+
|
344
|
+
This example parse a BibTeX entry, formats it as extended BibTeXML,
|
345
|
+
and writes the following XML to standard out:
|
346
|
+
|
347
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
348
|
+
<bibtex:file xmlns:bibtex='http://bibtexml.sf.net/'>
|
349
|
+
<bibtex:entry id='pickaxe'>
|
350
|
+
<bibtex:book>
|
351
|
+
<bibtex:address>Raleigh, North Carolina</bibtex:address>
|
352
|
+
<bibtex:person>
|
353
|
+
<bibtex:first>Dave</bibtex:first>
|
354
|
+
<bibtex:last>Thomas</bibtex:last>
|
355
|
+
</bibtex:person>
|
356
|
+
<bibtex:person>
|
357
|
+
<bibtex:first>Chad</bibtex:first>
|
358
|
+
<bibtex:last>Fowler</bibtex:last>
|
359
|
+
</bibtex:person>
|
360
|
+
<bibtex:person>
|
361
|
+
<bibtex:first>Andy</bibtex:first>
|
362
|
+
<bibtex:last>Hunt</bibtex:last>
|
363
|
+
</bibtex:person>
|
364
|
+
<bibtex:author/>
|
365
|
+
<bibtex:publisher>The Pragmatic Bookshelf</bibtex:publisher>
|
366
|
+
<bibtex:title>
|
367
|
+
Programming Ruby 1.9: The Pragmatic Programmer's Guide
|
368
|
+
</bibtex:title>
|
369
|
+
<bibtex:year>2009</bibtex:year>
|
370
|
+
</bibtex:book>
|
371
|
+
</bibtex:entry>
|
372
|
+
</bibtex:file>
|
373
|
+
|
303
374
|
Look at the 'examples' directory for more elaborate examples of a BibTeX to YAML
|
304
375
|
and a BibTeX to HTML converter using **#to_citeproc** to format a bibliography
|
305
376
|
using [CSL](http://citationstyles.org/).
|
@@ -345,20 +416,41 @@ quotes; therefore you can simply add the :quotes option with an empty string:
|
|
345
416
|
:title=>"Programming Ruby 1.9: The Pragmatic Programmer's Guide",
|
346
417
|
:year=>"2009"}]
|
347
418
|
|
419
|
+
|
348
420
|
The Parser
|
349
421
|
----------
|
350
422
|
|
351
423
|
The BibTeX-Ruby parser is generated using the awesome
|
352
424
|
[racc](http://i.loveruby.net/en/projects/racc/) parser generator. You can take
|
353
|
-
look at the grammar
|
425
|
+
look at the LALR grammar in the file
|
354
426
|
[lib/bibtex/bibtex.y](https://github.com/inukshuk/bibtex-ruby/blob/master/lib/bibtex/bibtex.y).
|
355
427
|
|
356
428
|
For more information about the BibTeX format and the parser's idiosyncrasies
|
357
429
|
[refer to the project wiki](https://github.com/inukshuk/bibtex-ruby/wiki/The-BibTeX-Format).
|
358
430
|
|
431
|
+
Contributing
|
432
|
+
------------
|
433
|
+
|
434
|
+
The BibTeX-Ruby source code is
|
435
|
+
[hosted on GitHub](http://github.com/inukshuk/bibtex-ruby/).
|
436
|
+
You can check out a copy of the latest code using Git:
|
437
|
+
|
438
|
+
$ git clone https://github.com/inukshuk/bibtex-ruby.git
|
439
|
+
|
440
|
+
If you've found a bug or have a question, please open an issue on the
|
441
|
+
[BibTeX-Ruby issue tracker](http://github.com/inukshuk/bibtex-ruby/issues).
|
442
|
+
Or, for extra credit, clone the BibTeX-Ruby repository, write a failing
|
443
|
+
example, or cucumber feature, fix the bug and submit a pull request (for
|
444
|
+
useful examples, take a look at the cucumber features in the
|
445
|
+
[features/issues/](https://github.com/inukshuk/bibtex-ruby/blob/master/features/issues)
|
446
|
+
directory).
|
447
|
+
|
359
448
|
|
360
449
|
Credits
|
361
450
|
-------
|
362
451
|
|
363
452
|
The BibTeX-Ruby package was written by [Sylvester Keil](http://sylvester.keil.or.at/);
|
364
453
|
kudos and thanks to all [contributors](https://github.com/inukshuk/bibtex-ruby/contributors)!
|
454
|
+
|
455
|
+
BibTeX-Ruby is distributed under the terms and conditions of the GPL. See
|
456
|
+
LICENSE for details.
|
data/bibtex-ruby.gemspec
CHANGED
@@ -11,19 +11,25 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.authors = ['Sylvester Keil']
|
12
12
|
s.email = ['http://sylvester.keil.or.at']
|
13
13
|
s.homepage = 'http://inukshuk.github.com/bibtex-ruby'
|
14
|
-
s.summary = 'A BibTeX parser and converter written in Ruby.'
|
15
|
-
s.description = 'A (fairly complete) BibTeX library and parser written in Ruby. Includes a name parser and supports regular BibTeX entries, @comments, string replacement via @string. Allows for easy export/conversion to formats such as YAML, JSON, and XML.'
|
16
14
|
s.license = 'GPL-3'
|
17
15
|
|
16
|
+
s.summary = 'A BibTeX parser, converter and API for Ruby.'
|
17
|
+
s.description = <<-END_DESCRIPTION
|
18
|
+
BibTeX-Ruby is the Rubyist's swiss-army-knife for all things BibTeX. It
|
19
|
+
includes a parser for all common BibTeX objects (@string, @preamble,
|
20
|
+
@comment and regular entries) and a sophisticated name parser that
|
21
|
+
tokenizes correctly formatted names; BibTeX-Ruby recognizes BibTeX string
|
22
|
+
replacements, joins values containing multiple strings or variables,
|
23
|
+
supports cross-references, and decodes common LaTeX formatting
|
24
|
+
instructions to unicode; if you are in a hurry, it also allows for easy
|
25
|
+
export/conversion to formats such as YAML, JSON, CSL, and XML (BibTeXML).
|
26
|
+
END_DESCRIPTION
|
27
|
+
|
18
28
|
s.add_runtime_dependency('latex-decode', ['>=0.0.3'])
|
29
|
+
s.add_runtime_dependency('multi_json', ['~>1.0'])
|
19
30
|
|
20
31
|
s.add_development_dependency('rake', ['~>0.9'])
|
21
32
|
s.add_development_dependency('racc', ['~>1.4'])
|
22
|
-
s.add_development_dependency('mini_shoulda', ['~>0.3'])
|
23
|
-
s.add_development_dependency('mynyml-redgreen', ['~>0.7'])
|
24
|
-
s.add_development_dependency('autowatchr', ['~>0.1'])
|
25
|
-
s.add_development_dependency('cucumber', ['~>0.10'])
|
26
|
-
s.add_development_dependency('json', ['~>1.5'])
|
27
33
|
s.add_development_dependency('rdoc', ['~>3.9'])
|
28
34
|
|
29
35
|
s.files = File.open('Manifest').readlines.map(&:chomp)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
Feature: Parse BibTeX cross-references
|
2
|
+
As a hacker who works with bibliographies
|
3
|
+
I want to be able to parse BibTeX files with cross-referenced entries
|
4
|
+
|
5
|
+
@wip
|
6
|
+
Scenario: A BibTeX file with six entries and three cross-references
|
7
|
+
When I parse the following file:
|
8
|
+
"""
|
9
|
+
@book{zimmerman_2004,
|
10
|
+
Address = {Oxford},
|
11
|
+
Author = {Dean W. Zimmerman},
|
12
|
+
Editor = {Dean W. Zimmerman},
|
13
|
+
Keywords = {Metaphysics},
|
14
|
+
Publisher = {Oxford University Press},
|
15
|
+
Title = {Oxford Studies in Metaphysics},
|
16
|
+
Volume = {1},
|
17
|
+
Year = {2004}
|
18
|
+
}
|
19
|
+
|
20
|
+
@incollection{hall_2004b,
|
21
|
+
Author = {Ned Hall},
|
22
|
+
Crossref = {zimmerman_2004},
|
23
|
+
Keywords = {Causation},
|
24
|
+
Pages = {255-299},
|
25
|
+
Title = {The Intrinsic Character of Causation}
|
26
|
+
}
|
27
|
+
|
28
|
+
@proceedings{weingartner_1989,
|
29
|
+
Address = {Vienna},
|
30
|
+
Editor = {Paul Weingartner and Gerhard Schurz},
|
31
|
+
Keywords = {Anthology},
|
32
|
+
Publisher = {Verlag H{\"o}lder-Pichter Tempsky},
|
33
|
+
Title = {Philosophy of the Natural Sciences: Proceedings of the 13th International Wittgenstein Symposium},
|
34
|
+
Year = {1989}}
|
35
|
+
|
36
|
+
@inproceedings{cartwright_1989a,
|
37
|
+
Author = {Nancy Cartwright},
|
38
|
+
Crossref = {weingartner_1989},
|
39
|
+
Keywords = {Causation; Quantum Mechanics},
|
40
|
+
Pages = {120-127},
|
41
|
+
Title = {Quantum Causes: The Lesson of the Bell Inequalities}}
|
42
|
+
|
43
|
+
@inbook{fraassen_1989b,
|
44
|
+
Crossref = {fraassen_1989},
|
45
|
+
Pages = {40-64},
|
46
|
+
Title = {Ideal Science: David Lewis's Account of Laws},
|
47
|
+
Url = {http://dx.doi.org/10.1093/0198248601.003.0003}
|
48
|
+
}
|
49
|
+
|
50
|
+
@book{fraassen_1989,
|
51
|
+
Address = {Oxford},
|
52
|
+
Author = {Bas C. van Fraassen},
|
53
|
+
Keywords = {Laws; Lewis},
|
54
|
+
Publisher = {Oxford University Press},
|
55
|
+
Title = {Laws and Symmetry},
|
56
|
+
Url = {http://dx.doi.org/10.1093/0198248601.001.0001},
|
57
|
+
Year = 1989
|
58
|
+
}
|
59
|
+
"""
|
60
|
+
Then the entry with key "fraassen_1989b" should have a field "Booktitle" with the value "Laws and Symmetry"
|
61
|
+
And the entry with key "hall_2004b" should have a field "Editor" with the value "Zimmerman, Dean W."
|
62
|
+
And the entry with key "cartwright_1989a" should have a field "Year" with the value "1989"
|
data/features/names.feature
CHANGED
@@ -61,7 +61,7 @@ end
|
|
61
61
|
|
62
62
|
Then /^my bibliography should contain an entry with (?:key|id) "([^"]*)" and a?n? (\w+) value of "([^"]*)"$/ do |key,field,value|
|
63
63
|
refute_nil @bibliography[key.to_s]
|
64
|
-
assert_equal value, @bibliography[key.to_s][field].to_s
|
64
|
+
assert_equal value, @bibliography[key.to_s][field.downcase.to_sym].to_s
|
65
65
|
end
|
66
66
|
|
67
67
|
|
@@ -91,5 +91,5 @@ Then /^the string "([^"]*)" should be "([^"]*)"$/ do |key, value|
|
|
91
91
|
end
|
92
92
|
|
93
93
|
Then /^the entry with key "([^"]*)" should have a field "([^"]*)" with the value "([^"]*)"$/ do |key, field, value|
|
94
|
-
assert_equal value, @bibliography[key
|
94
|
+
assert_equal value, @bibliography[key][field.downcase.to_sym].to_s
|
95
95
|
end
|
data/lib/bibtex.rb
CHANGED
@@ -19,11 +19,13 @@
|
|
19
19
|
$:.unshift(File.dirname(__FILE__)) unless
|
20
20
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
21
21
|
|
22
|
-
require '
|
22
|
+
require 'digest/md5'
|
23
23
|
|
24
24
|
require 'bibtex/version'
|
25
25
|
require 'logger'
|
26
26
|
|
27
|
+
require 'multi_json'
|
28
|
+
|
27
29
|
# = BibTeX
|
28
30
|
#
|
29
31
|
# This module encompasses a parser for BibTeX files and
|
data/lib/bibtex/bibliography.rb
CHANGED
@@ -31,10 +31,12 @@ module BibTeX
|
|
31
31
|
include Enumerable
|
32
32
|
include Comparable
|
33
33
|
|
34
|
-
|
34
|
+
@defaults = { :parse_names => true, :parse_months => true }.freeze
|
35
35
|
|
36
36
|
class << self
|
37
37
|
|
38
|
+
attr_reader :defaults
|
39
|
+
|
38
40
|
# Opens and parses the `.bib' file at the given +path+. Returns
|
39
41
|
# a new Bibliography instance corresponding to the file, or, if a block
|
40
42
|
# is given, yields the instance to the block, ensuring that the file
|
@@ -50,7 +52,8 @@ module BibTeX
|
|
50
52
|
# -:filter: convert all entries using the sepcified filter (not set by default)
|
51
53
|
#
|
52
54
|
def open(path, options = {})
|
53
|
-
b = parse(Kernel.open(path).read, options)
|
55
|
+
b = parse(Kernel.open(path, 'r:UTF-8').read, options)
|
56
|
+
b.path = path
|
54
57
|
return b unless block_given?
|
55
58
|
|
56
59
|
begin
|
@@ -61,13 +64,16 @@ module BibTeX
|
|
61
64
|
end
|
62
65
|
|
63
66
|
# Parses the given string and returns a corresponding Bibliography instance.
|
64
|
-
def parse(
|
65
|
-
|
67
|
+
def parse(input, options = {})
|
68
|
+
case input
|
69
|
+
when Array, Hash, Element
|
70
|
+
Bibliography.new(options).add(input)
|
71
|
+
else
|
72
|
+
Parser.new(options).parse(input) || Bibliography.new(options)
|
73
|
+
end
|
66
74
|
end
|
67
75
|
|
68
|
-
#
|
69
76
|
# Defines a new accessor that selects elements by type.
|
70
|
-
#
|
71
77
|
def attr_by_type(*arguments)
|
72
78
|
arguments.each do |type|
|
73
79
|
method_id = "#{type}s"
|
@@ -77,19 +83,21 @@ module BibTeX
|
|
77
83
|
end
|
78
84
|
|
79
85
|
attr_accessor :path
|
86
|
+
|
80
87
|
attr_reader :data, :strings, :entries, :errors, :options
|
81
88
|
|
82
|
-
attr_by_type :article, :book, :journal, :collection, :preamble, :comment,
|
89
|
+
attr_by_type :article, :book, :journal, :collection, :preamble, :comment,
|
90
|
+
:meta_content
|
83
91
|
|
84
|
-
def_delegators :@data, :length, :size, :each, :empty
|
85
|
-
|
92
|
+
def_delegators :@data, :length, :size, :each, :empty?, :last
|
93
|
+
def_delegators :@entries, :has_key?
|
86
94
|
|
87
|
-
|
95
|
+
|
88
96
|
# Creates a new bibliography.
|
89
|
-
#
|
90
97
|
def initialize(options = {})
|
91
|
-
@options =
|
92
|
-
@data, @strings
|
98
|
+
@options = Bibliography.defaults.merge(options)
|
99
|
+
@data, @strings = [], {}
|
100
|
+
@entries = Hash.new { |h,k| h.fetch(k.to_s, nil) }
|
93
101
|
|
94
102
|
yield self if block_given?
|
95
103
|
end
|
@@ -97,9 +105,8 @@ module BibTeX
|
|
97
105
|
# Adds a new element, or a list of new elements to the bibliography.
|
98
106
|
# Returns the Bibliography for chainability.
|
99
107
|
def add(*arguments)
|
100
|
-
arguments.flatten.each do |element|
|
101
|
-
|
102
|
-
@data << element.added_to_bibliography(self)
|
108
|
+
Element.parse(arguments.flatten).each do |element|
|
109
|
+
data << element.added_to_bibliography(self)
|
103
110
|
end
|
104
111
|
self
|
105
112
|
end
|
@@ -107,6 +114,7 @@ module BibTeX
|
|
107
114
|
alias << add
|
108
115
|
alias push add
|
109
116
|
|
117
|
+
|
110
118
|
# Saves the bibliography to the current path.
|
111
119
|
def save(options = {})
|
112
120
|
save_to(@path, options)
|
@@ -115,19 +123,21 @@ module BibTeX
|
|
115
123
|
# Saves the bibliography to a file at the given path. Returns the bibliography.
|
116
124
|
def save_to(path, options = {})
|
117
125
|
options[:quotes] ||= %w({ })
|
118
|
-
File.open(path,
|
126
|
+
File.open(path, 'w:UTF-8') { |f| f.write(to_s(options)) }
|
119
127
|
self
|
120
128
|
end
|
121
129
|
|
130
|
+
|
122
131
|
def parse_names
|
123
132
|
@entries.each_value { |e| e.parse_names }
|
124
133
|
self
|
125
134
|
end
|
126
|
-
|
135
|
+
|
127
136
|
def parse_months
|
128
137
|
@entries.each_value { |e| e.parse_month }
|
129
138
|
self
|
130
139
|
end
|
140
|
+
|
131
141
|
|
132
142
|
# Converts all enties using the given filter. If an optional block is given
|
133
143
|
# the block is used as a condition (the block will be called with each
|
@@ -137,7 +147,7 @@ module BibTeX
|
|
137
147
|
self
|
138
148
|
end
|
139
149
|
|
140
|
-
|
150
|
+
|
141
151
|
# Deletes an object, or a list of objects from the bibliography.
|
142
152
|
# If a list of objects is to be deleted, you can either supply the list
|
143
153
|
# of objects or use a query or block to define the list.
|
@@ -169,7 +179,7 @@ module BibTeX
|
|
169
179
|
# >> bib[:key]
|
170
180
|
# => Returns the first entry with key 'key' or nil
|
171
181
|
# >> bib['key']
|
172
|
-
# =>
|
182
|
+
# => Same as above
|
173
183
|
# >> bib['@article']
|
174
184
|
# => Returns all entries of type 'article' or []
|
175
185
|
# >> bib['@preamble']
|
@@ -183,10 +193,21 @@ module BibTeX
|
|
183
193
|
raise(ArgumentError, "wrong number of arguments (#{arguments.length} for 1..2)") unless arguments.length.between?(1,2)
|
184
194
|
|
185
195
|
case
|
186
|
-
when
|
187
|
-
|
188
|
-
|
189
|
-
|
196
|
+
when arguments[0].is_a?(Numeric) || arguments[0].is_a?(Range)
|
197
|
+
data[*arguments]
|
198
|
+
when arguments.length == 1
|
199
|
+
case
|
200
|
+
when arguments[0].nil?
|
201
|
+
nil
|
202
|
+
when arguments[0].respond_to?(:empty?) && arguments[0].empty?
|
203
|
+
nil
|
204
|
+
when arguments[0].is_a?(Symbol)
|
205
|
+
entries[arguments[0]]
|
206
|
+
when arguments[0].respond_to?(:start_with?) && !arguments[0].start_with?('@')
|
207
|
+
entries[arguments[0]]
|
208
|
+
else
|
209
|
+
query(*arguments)
|
210
|
+
end
|
190
211
|
else
|
191
212
|
query(*arguments)
|
192
213
|
end
|
@@ -208,6 +229,11 @@ module BibTeX
|
|
208
229
|
!errors? && @entries.values.all?(&:valid?)
|
209
230
|
end
|
210
231
|
|
232
|
+
# Returns a list of the names of all authors, editors and translators in the Bibliography.
|
233
|
+
def names
|
234
|
+
map(&:names).flatten
|
235
|
+
end
|
236
|
+
|
211
237
|
# Replaces all string symbols which are defined in the bibliography.
|
212
238
|
#
|
213
239
|
# By default symbols in @string, @preamble and entries are replaced; this
|
@@ -266,7 +292,7 @@ module BibTeX
|
|
266
292
|
|
267
293
|
# Returns a JSON representation of the bibliography.
|
268
294
|
def to_json(options = {})
|
269
|
-
to_a(options)
|
295
|
+
MultiJson.encode(to_a(options))
|
270
296
|
end
|
271
297
|
|
272
298
|
# Returns a CiteProc JSON representation of the bibliography. Only BibTeX enrties are exported.
|
@@ -274,15 +300,20 @@ module BibTeX
|
|
274
300
|
q('@entry').map { |o| o.to_citeproc(options) }
|
275
301
|
end
|
276
302
|
|
277
|
-
# Returns
|
278
|
-
|
303
|
+
# Returns a REXML::Document representation of the bibliography using the
|
304
|
+
# BibTeXML format.
|
305
|
+
def to_xml(options = {})
|
279
306
|
require 'rexml/document'
|
280
307
|
|
281
|
-
xml =
|
308
|
+
xml = REXML::Document.new
|
282
309
|
xml << REXML::XMLDecl.new('1.0','UTF-8')
|
283
|
-
|
284
|
-
|
285
|
-
|
310
|
+
|
311
|
+
root = REXML::Element.new('bibtex:file')
|
312
|
+
root.add_namespace('bibtex', 'http://bibtexml.sf.net/')
|
313
|
+
|
314
|
+
each { |e| root.add_element(e.to_xml(options)) }
|
315
|
+
|
316
|
+
xml.add_element(root)
|
286
317
|
xml
|
287
318
|
end
|
288
319
|
|
@@ -307,7 +338,8 @@ module BibTeX
|
|
307
338
|
raise(ArgumentError, "wrong number of arguments (#{arguments.length} for 0..2)") unless arguments.length.between?(0,2)
|
308
339
|
|
309
340
|
q, selector = arguments.reverse
|
310
|
-
filter = block ? Proc.new { |e| e.match?(q) && block.call(e) } :
|
341
|
+
filter = block ? Proc.new { |e| e.match?(q) && block.call(e) } :
|
342
|
+
Proc.new { |e| e.match?(q) }
|
311
343
|
|
312
344
|
send(query_handler(selector), &filter)
|
313
345
|
end
|
@@ -324,6 +356,26 @@ module BibTeX
|
|
324
356
|
other.respond_to?(:to_a) ? to_a <=> other.to_a : nil
|
325
357
|
end
|
326
358
|
|
359
|
+
# TODO this should be faster than select_duplicates_by
|
360
|
+
# def detect_duplicates_by(*arguments)
|
361
|
+
# end
|
362
|
+
|
363
|
+
def select_duplicates_by(*arguments)
|
364
|
+
d, fs = Hash.new([]), arguments.flatten.map(&:to_sym)
|
365
|
+
q('@entry') do |e|
|
366
|
+
d[e.generate_hash(fs)] << e
|
367
|
+
end
|
368
|
+
|
369
|
+
d.values.dup
|
370
|
+
end
|
371
|
+
|
372
|
+
alias duplicates select_duplicates_by
|
373
|
+
|
374
|
+
def duplicates?
|
375
|
+
!select_duplicates_by?.empty?
|
376
|
+
end
|
377
|
+
|
378
|
+
|
327
379
|
private
|
328
380
|
|
329
381
|
def query_handler(selector)
|