bibtex-ruby 1.2.1 → 1.3.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/Gemfile +6 -1
- data/Gemfile.lock +48 -5
- data/History.txt +16 -1
- data/Manifest +43 -19
- data/README.md +178 -167
- data/Rakefile +26 -5
- data/auto.watchr +6 -0
- data/bibtex-ruby.gemspec +8 -5
- data/examples/bib2html.rb +28 -18
- data/features/bibtex.feature +96 -0
- data/features/entries.feature +67 -0
- data/features/issues/slash_keys.feature +21 -0
- data/features/names.feature +72 -0
- data/features/preambles.feature +27 -0
- data/features/query.feature +56 -0
- data/features/replacement.feature +68 -0
- data/features/step_definitions/bibtex_steps.rb +74 -0
- data/features/step_definitions/name_steps.rb +13 -0
- data/features/strings.feature +52 -0
- data/features/support/env.rb +7 -0
- data/lib/bibtex.rb +5 -1
- data/lib/bibtex/bibliography.rb +218 -95
- data/lib/bibtex/bibtex.y +18 -15
- data/lib/bibtex/elements.rb +130 -136
- data/lib/bibtex/entry.rb +133 -69
- data/lib/bibtex/extensions.rb +0 -35
- data/lib/bibtex/lexer.rb +9 -9
- data/lib/bibtex/name_parser.output +464 -0
- data/lib/bibtex/name_parser.rb +490 -0
- data/lib/bibtex/names.rb +162 -0
- data/lib/bibtex/names.y +196 -0
- data/lib/bibtex/parser.output +5 -5
- data/lib/bibtex/parser.rb +19 -16
- data/lib/bibtex/replaceable.rb +52 -0
- data/lib/bibtex/utilities.rb +23 -5
- data/lib/bibtex/value.rb +201 -0
- data/lib/bibtex/version.rb +1 -1
- data/test/benchmark.rb +52 -0
- data/test/bibtex/test_bibliography.rb +141 -0
- data/test/bibtex/test_elements.rb +40 -0
- data/test/bibtex/test_entry.rb +99 -0
- data/test/bibtex/test_names.rb +23 -0
- data/test/bibtex/test_parser.rb +79 -0
- data/test/bibtex/test_string.rb +83 -0
- data/test/bibtex/test_utilities.rb +34 -0
- data/test/bibtex/test_value.rb +70 -0
- data/test/{bib/10_bibdesk.bib → fixtures/bibdesk.bib} +1 -1
- data/test/{bib/05_comment.bib → fixtures/comment.bib} +0 -0
- data/test/{bib/08_decoret.bib → fixtures/decoret.bib} +0 -0
- data/test/{bib/00_empty.bib → fixtures/empty.bib} +0 -0
- data/test/{bib/07_entry.bib → fixtures/entry.bib} +0 -0
- data/test/{bib/09_errors.bib → fixtures/errors.bib} +0 -0
- data/test/{bib/01_no_bibtex.bib → fixtures/no_bibtex.bib} +0 -0
- data/test/{bib/06_preamble.bib → fixtures/preamble.bib} +1 -1
- data/test/{bib/11_roundtrip.bib → fixtures/roundtrip.bib} +1 -1
- data/test/helper.rb +17 -2
- data/test/test_bibtex.rb +87 -93
- data/test/test_export.rb +18 -22
- metadata +85 -30
- data/test/bib/02_string.bib +0 -1
- data/test/bib/03_string.bib +0 -25
- data/test/bib/04_string_replacement.bib +0 -16
- data/test/test_comment.rb +0 -21
- data/test/test_entry.rb +0 -98
- data/test/test_preamble.rb +0 -39
- data/test/test_string.rb +0 -97
- data/test/test_utilities.rb +0 -36
@@ -0,0 +1,52 @@
|
|
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
|
+
#
|
22
|
+
# The Replaceable module provides methods that expose a Value attribute
|
23
|
+
# and the ability to join or replace the contained BibTeX symbols.
|
24
|
+
#
|
25
|
+
module Replaceable
|
26
|
+
extend Forwardable
|
27
|
+
|
28
|
+
attr_reader :value
|
29
|
+
|
30
|
+
def value=(value)
|
31
|
+
@value = Value.new(value)
|
32
|
+
end
|
33
|
+
|
34
|
+
def replace(*arguments)
|
35
|
+
@value.replace(*arguments)
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def join
|
40
|
+
@value.join
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def <<(value)
|
45
|
+
@value << value
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
alias :v :value
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
data/lib/bibtex/utilities.rb
CHANGED
@@ -19,20 +19,38 @@
|
|
19
19
|
module BibTeX
|
20
20
|
|
21
21
|
class << self
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
|
23
|
+
# Opens a BibTeX file or URI and returns a corresponding +Bibliography+
|
24
|
+
# object or, if a block is given, yields the Bibliography to the block,
|
25
|
+
# ensuring that the file is saved.
|
26
|
+
def open(file, options = {}, &block)
|
27
|
+
Bibliography.open(file, options, &block)
|
25
28
|
end
|
26
29
|
|
27
30
|
# Parses the given string and returns a corresponding +Bibliography+ object.
|
28
|
-
|
29
|
-
|
31
|
+
# Delegates to BibTeX.open if the string is a filename or URI.
|
32
|
+
def parse(string, options = {}, &block)
|
33
|
+
if File.exists?(string) || string =~ /^[a-z]+:\/\//i
|
34
|
+
open(string, options, &block)
|
35
|
+
else
|
36
|
+
Bibliography.parse(string, options)
|
37
|
+
end
|
30
38
|
end
|
31
39
|
|
32
40
|
# Returns true if the given file is a valid BibTeX bibliography.
|
33
41
|
def valid?(file)
|
34
42
|
Bibliography.open(file).valid?
|
35
43
|
end
|
44
|
+
|
45
|
+
# Parses the given string as a BibTeX name value and returns a Names object.
|
46
|
+
def names(string)
|
47
|
+
Names.parse(string)
|
48
|
+
end
|
49
|
+
|
50
|
+
alias :name :names
|
51
|
+
alias :parse_name :names
|
52
|
+
alias :parse_names :names
|
53
|
+
|
36
54
|
end
|
37
55
|
|
38
56
|
end
|
data/lib/bibtex/value.rb
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
#--
|
2
|
+
# BibTeX-Ruby
|
3
|
+
# Copyright (C) 2010-2011 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 'forwardable'
|
20
|
+
|
21
|
+
module BibTeX
|
22
|
+
|
23
|
+
#
|
24
|
+
# A BibTeX Value is something very much like a string. In BibTeX files it
|
25
|
+
# can appear on the right hand side of @string or @entry field assignments
|
26
|
+
# or as @preamble contents. In the example below [VALUE] indicates possible
|
27
|
+
# occurences of values in BibTeX:
|
28
|
+
#
|
29
|
+
# @preamble{ "foo" [VALUE] }
|
30
|
+
# @string{ foo = "foo" [VALUE] }
|
31
|
+
# @book{id,
|
32
|
+
# author = {John Doe} [VALUE],
|
33
|
+
# title = foo # "bar" [VALUE]
|
34
|
+
# }
|
35
|
+
#
|
36
|
+
# All Values have in common that they can be simple strings in curly braces
|
37
|
+
# or double quotes or complex BibTeX string-concatenations (using the '#'
|
38
|
+
# symbol).
|
39
|
+
#
|
40
|
+
# Generally, Values try to behave as much as normal Ruby strings as possible;
|
41
|
+
# If you do not require any of the advanced BibTeX functionality (string
|
42
|
+
# replacement or concatentaion) you can simply convert them to strings using
|
43
|
+
# +to_s+. Note that BibTeX Names are special instances of Values which
|
44
|
+
# currently do not support string concatenation or replacement.
|
45
|
+
#
|
46
|
+
class Value
|
47
|
+
extend Forwardable
|
48
|
+
include Comparable
|
49
|
+
|
50
|
+
attr_reader :tokens
|
51
|
+
alias :to_a :tokens
|
52
|
+
|
53
|
+
def_delegators :to_s, :empty?, :=~, :match, :intern, :to_sym, :to_i, :to_f, :end_with?, :start_with?, :include?, :upcase, :downcase, :reverse, :chop, :chomp, :rstrip, :gsub, :sub, :size, :strip, :succ, :to_c, :to_r, :to_str, :split, :each_byte, :each_char, :each_line
|
54
|
+
def_delegators :@tokens, :[], :length
|
55
|
+
|
56
|
+
def initialize(*arguments)
|
57
|
+
@tokens = []
|
58
|
+
arguments.flatten.compact.each do |argument|
|
59
|
+
add(argument)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def initialize_copy(other)
|
64
|
+
@tokens = other.tokens.dup
|
65
|
+
end
|
66
|
+
|
67
|
+
def add(argument)
|
68
|
+
case argument
|
69
|
+
when Value
|
70
|
+
@tokens += argument.tokens.dup
|
71
|
+
when ::String
|
72
|
+
@tokens << argument
|
73
|
+
when Symbol
|
74
|
+
@tokens << argument
|
75
|
+
else
|
76
|
+
raise(ArgumentError, "Failed to create Value from argument #{ argument.inspect }; expected String, Symbol or Value instance.")
|
77
|
+
end
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
alias :<< :add
|
82
|
+
alias :push :add
|
83
|
+
|
84
|
+
[:strip!, :upcase!, :downcase!, :sub!, :gsub!, :chop!, :chomp!, :rstrip!].each do |method_id|
|
85
|
+
define_method(method_id) do |*arguments, &block|
|
86
|
+
@tokens.each do |part|
|
87
|
+
part.send(method_id, *arguments, &block)
|
88
|
+
end
|
89
|
+
self
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def replace(*arguments)
|
94
|
+
return self unless has_symbol?
|
95
|
+
arguments.flatten.each do |argument|
|
96
|
+
case argument
|
97
|
+
when ::String # simulates Ruby's String#replace
|
98
|
+
@tokens = [argument]
|
99
|
+
when String
|
100
|
+
@tokens = @tokens.map { |v| argument.key == v ? argument.value.tokens : v }.flatten
|
101
|
+
when Hash
|
102
|
+
@tokens = @tokens.map { |v| argument[v] || v }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# Returns the Value instance with all consecutive String tokens joined.
|
110
|
+
#
|
111
|
+
# call-seq:
|
112
|
+
# Value.new('foo', 'bar').join #=> <'foobar'>
|
113
|
+
# Value.new(:foo, 'bar').join #=> <:foo, 'bar'>
|
114
|
+
#
|
115
|
+
def join
|
116
|
+
@tokens = @tokens.inject([]) do |a,b|
|
117
|
+
a[-1].is_a?(::String) && b.is_a?(::String) ? a[-1] += b : a << b; a
|
118
|
+
end
|
119
|
+
self
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns a the Value as a string. @see #value; the only difference is
|
123
|
+
# that single symbols are returned as String, too.
|
124
|
+
# If the Value is atomic and the option :quotes is given, the string
|
125
|
+
# will be quoted using the quote symbols specified.
|
126
|
+
#
|
127
|
+
# call-seq:
|
128
|
+
# Value.new('foo').to_s #=> "foo"
|
129
|
+
# Value.new(:foo).to_s #=> "foo"
|
130
|
+
# Value.new('foo').to_s(:quotes => '"') #=> "\"foo\""
|
131
|
+
# Value.new('foo').to_s(:quotes => ['"','"']) #=> "\"foo\""
|
132
|
+
# Value.new('foo').to_s(:quotes => ['{','}']) #=> "{foo}"
|
133
|
+
# Value.new(:foo, 'bar').to_s #=> "foo # \"bar\""
|
134
|
+
# Value.new('foo', 'bar').to_s #=> "\"foo\" # \"bar\""
|
135
|
+
#
|
136
|
+
def to_s(options = {})
|
137
|
+
return value.to_s unless options.has_key?(:quotes) && atomic?
|
138
|
+
*q = options[:quotes]
|
139
|
+
[q[0], value, q[-1]].compact.join
|
140
|
+
end
|
141
|
+
|
142
|
+
# Returns the Value as a string or, if it consists of a single symbol, as
|
143
|
+
# a Symbol instance. If the Value contains multiple tokens, they will be
|
144
|
+
# joined by a '#', additionally, all string tokens will be turned into
|
145
|
+
# string literals (i.e., delimitted by quotes).
|
146
|
+
def value
|
147
|
+
atomic? ? @tokens[0] : @tokens.map { |v| v.is_a?(::String) ? v.inspect : v }.join(' # ')
|
148
|
+
end
|
149
|
+
|
150
|
+
alias :v :value
|
151
|
+
|
152
|
+
def inspect
|
153
|
+
'<' + @tokens.map(&:inspect).join(', ') + '>'
|
154
|
+
end
|
155
|
+
|
156
|
+
# Returns true if the Value is empty or consists of a single token.
|
157
|
+
def atomic?
|
158
|
+
@tokens.length < 2
|
159
|
+
end
|
160
|
+
|
161
|
+
# Returns true if the Value looks like a BibTeX name value.
|
162
|
+
def name?
|
163
|
+
end
|
164
|
+
|
165
|
+
alias :names? :name?
|
166
|
+
alias :is_name? :name?
|
167
|
+
|
168
|
+
def to_name
|
169
|
+
Names.parse(to_s)
|
170
|
+
end
|
171
|
+
|
172
|
+
alias :to_names :to_name
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
# Returns true if the Value's content is numeric.
|
177
|
+
def numeric?
|
178
|
+
to_s =~ /^\s*[+-]?\d+[\/\.]?\d*\s*$/
|
179
|
+
end
|
180
|
+
|
181
|
+
alias :is_numeric? :numeric?
|
182
|
+
|
183
|
+
# Returns true if the Value contains at least one symbol.
|
184
|
+
def symbol?
|
185
|
+
@tokens.detect { |v| v.is_a?(Symbol) }
|
186
|
+
end
|
187
|
+
|
188
|
+
alias :has_symbol? :symbol?
|
189
|
+
|
190
|
+
# Returns all symbols contained in the Value.
|
191
|
+
def symbols
|
192
|
+
@tokens.select { |v| v.is_a?(Symbol) }
|
193
|
+
end
|
194
|
+
|
195
|
+
def <=>(other)
|
196
|
+
to_s <=> other.to_s
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
data/lib/bibtex/version.rb
CHANGED
data/test/benchmark.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path('../../lib/bibtex.rb', __FILE__)
|
2
|
+
require 'profile'
|
3
|
+
|
4
|
+
module BibTeX
|
5
|
+
module Benchmark
|
6
|
+
def self.open
|
7
|
+
BibTeX.parse <<-END
|
8
|
+
@book{rails,
|
9
|
+
Address = {Raleigh, North Carolina},
|
10
|
+
Author = {Ruby, Sam, and Thomas, Dave, and Hansson Heinemeier, David},
|
11
|
+
Booktitle = {Agile Web Development with Rails},
|
12
|
+
Date-Added = {2010-08-05 10:01:36 +0200},
|
13
|
+
Date-Modified = {2010-08-05 10:06:46 +0200},
|
14
|
+
Edition = {third},
|
15
|
+
Isbn = {978-1-9343561-6-6},
|
16
|
+
Keywords = {ruby, rails},
|
17
|
+
Publisher = {The Pragmatic Bookshelf},
|
18
|
+
Series = {The Facets of Ruby},
|
19
|
+
Title = {Agile Web Development with Rails},
|
20
|
+
Year = {2009}
|
21
|
+
}
|
22
|
+
|
23
|
+
@book{dragon,
|
24
|
+
Address = {Boston},
|
25
|
+
Author = {Aho, Alfred V., and Lam, Monica S., and Ullman, Jeffrey D.},
|
26
|
+
Booktitle = {Compilers: Principles, Techniques, and Tools},
|
27
|
+
Date-Added = {2010-08-05 09:57:15 +0200},
|
28
|
+
Date-Modified = {2010-08-05 10:06:32 +0200},
|
29
|
+
Edition = {second},
|
30
|
+
Keywords = {compiler, lex, yacc},
|
31
|
+
Publisher = {Addison Wesley},
|
32
|
+
Title = {Compilers: Principles, Techniques, and Tools},
|
33
|
+
Year = {2007}
|
34
|
+
}
|
35
|
+
|
36
|
+
@book{pickaxe,
|
37
|
+
Address = {Raleigh, North Carolina},
|
38
|
+
Author = {Thomas, Dave, and Fowler, Chad, and Hunt, Andy},
|
39
|
+
Date-Added = {2010-08-05 09:54:07 +0200},
|
40
|
+
Date-Modified = {2010-08-05 10:07:01 +0200},
|
41
|
+
Keywords = {ruby},
|
42
|
+
Publisher = {The Pragmatic Bookshelf},
|
43
|
+
Series = {The Facets of Ruby},
|
44
|
+
Title = {Programming Ruby 1.9: The Pragmatic Programmer's Guide},
|
45
|
+
Year = {2009}
|
46
|
+
}
|
47
|
+
END
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
BibTeX::Benchmark.open
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module BibTeX
|
4
|
+
|
5
|
+
class BibliographyTest < MiniTest::Spec
|
6
|
+
|
7
|
+
context 'when newly created' do
|
8
|
+
should 'not be nil' do
|
9
|
+
assert Bibliography.new
|
10
|
+
end
|
11
|
+
should 'be empty' do
|
12
|
+
assert Bibliography.new.empty?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context '#open' do
|
17
|
+
should 'accept a block and save the file after execution' do
|
18
|
+
tmp = Tempfile.new('bibtex')
|
19
|
+
tmp.close
|
20
|
+
b = BibTeX.open(Test.fixtures(:bibdesk)).save_to(tmp.path)
|
21
|
+
|
22
|
+
BibTeX.open(tmp.path) do |bib|
|
23
|
+
bib.delete(:rails)
|
24
|
+
end
|
25
|
+
|
26
|
+
assert_equal b.length - 1, BibTeX.open(tmp.path).length
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'given a populated biliography' do
|
31
|
+
setup do
|
32
|
+
@bib = BibTeX.parse <<-END
|
33
|
+
@book{rails,
|
34
|
+
address = {Raleigh, North Carolina},
|
35
|
+
author = {Ruby, Sam, and Thomas, Dave, and Hansson Heinemeier, David},
|
36
|
+
booktitle = {Agile Web Development with Rails},
|
37
|
+
edition = {third},
|
38
|
+
keywords = {ruby, rails},
|
39
|
+
publisher = {The Pragmatic Bookshelf},
|
40
|
+
series = {The Facets of Ruby},
|
41
|
+
title = {Agile Web Development with Rails},
|
42
|
+
year = {2009}
|
43
|
+
}
|
44
|
+
@book{flanagan2008,
|
45
|
+
title={{The ruby programming language}},
|
46
|
+
author={Flanagan, D. and Matsumoto, Y.},
|
47
|
+
keywords = {ruby},
|
48
|
+
year={2008},
|
49
|
+
publisher={O'Reilly}
|
50
|
+
}
|
51
|
+
@article{segaran2007,
|
52
|
+
title={{Programming collective intelligence}},
|
53
|
+
author={Segaran, T.},
|
54
|
+
year={2007},
|
55
|
+
publisher={O'Reilly}
|
56
|
+
}
|
57
|
+
END
|
58
|
+
end
|
59
|
+
|
60
|
+
should 'support access by index' do
|
61
|
+
assert_equal 'ruby', @bib[1].keywords
|
62
|
+
end
|
63
|
+
|
64
|
+
should 'support access by range' do
|
65
|
+
assert_equal %w{2008 2007}, @bib[1..2].map(&:year)
|
66
|
+
end
|
67
|
+
|
68
|
+
should 'support access by index and offset' do
|
69
|
+
assert_equal %w{2008 2007}, @bib[1,2].map(&:year)
|
70
|
+
end
|
71
|
+
|
72
|
+
should 'support queries by symbol key' do
|
73
|
+
refute_nil @bib[:rails]
|
74
|
+
assert_nil @bib[:ruby]
|
75
|
+
end
|
76
|
+
|
77
|
+
should 'support queries by symbol key and selector' do
|
78
|
+
assert_equal 1, @bib.q(:all, :rails).length
|
79
|
+
refute_nil @bib.q(:first, :rails)
|
80
|
+
assert_nil @bib.q(:first, :railss)
|
81
|
+
end
|
82
|
+
|
83
|
+
should 'support queries by string key' do
|
84
|
+
assert_equal 1, @bib['rails'].length
|
85
|
+
assert_equal 0, @bib['ruby'].length
|
86
|
+
end
|
87
|
+
|
88
|
+
should 'support queries by type string' do
|
89
|
+
assert_equal 2, @bib['@book'].length
|
90
|
+
assert_equal 1, @bib['@article'].length
|
91
|
+
assert_equal 0, @bib['@collection'].length
|
92
|
+
end
|
93
|
+
|
94
|
+
should 'support queries by type string and selector' do
|
95
|
+
assert_equal 2, @bib.q(:all, '@book').length
|
96
|
+
refute_nil @bib.q(:first, '@book')
|
97
|
+
assert_equal 1, @bib.q(:all, '@article').length
|
98
|
+
refute_nil @bib.q(:first, '@article')
|
99
|
+
assert_equal 0, @bib.q(:all, '@collection').length
|
100
|
+
assert_nil @bib.q(:first, '@collection')
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
should 'support queries by pattern' do
|
105
|
+
assert_equal 0, @bib[/reilly/].length
|
106
|
+
assert_equal 2, @bib[/reilly/i].length
|
107
|
+
end
|
108
|
+
|
109
|
+
should 'support queries by type string and conditions' do
|
110
|
+
assert_equal 1, @bib['@book[keywords=ruby]'].length
|
111
|
+
end
|
112
|
+
|
113
|
+
should 'support queries by bibtex element' do
|
114
|
+
entry = Entry.parse(<<-END).first
|
115
|
+
@article{segaran2007,
|
116
|
+
title = {{Programming collective intelligence}},
|
117
|
+
author = {Segaran, T.},
|
118
|
+
year = {2007},
|
119
|
+
publisher = {O'Reilly}
|
120
|
+
}
|
121
|
+
END
|
122
|
+
assert_equal 1, @bib[entry].length
|
123
|
+
entry.year = '2006'
|
124
|
+
assert_equal 0, @bib[entry].length
|
125
|
+
end
|
126
|
+
|
127
|
+
should 'support query and additional block' do
|
128
|
+
assert_equal 1, @bib.q('@book') { |e| e.keywords.split(/,/).length > 1 }.length
|
129
|
+
end
|
130
|
+
|
131
|
+
should 'support saving the bibliography to a file' do
|
132
|
+
tmp = Tempfile.new('bibtex')
|
133
|
+
tmp.close
|
134
|
+
@bib.save_to(tmp.path)
|
135
|
+
assert_equal @bib, BibTeX.open(tmp.path)
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|