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.

@@ -1,6 +1,15 @@
1
1
  module BibTeX
2
2
 
3
- class ParseError < StandardError; end
3
+ class BibTeXError < StandardError
4
+ attr_reader :orginal
5
+
6
+ def initialize(message = nil, original = $!)
7
+ super(message)
8
+ @original = original
9
+ end
10
+ end
11
+
12
+ class ParseError < BibTeXError; end
4
13
 
5
14
  #
6
15
  # Represents a lexical or syntactical error.
@@ -12,7 +21,7 @@ module BibTeX
12
21
  def initialize(trace=[])
13
22
  @trace = trace
14
23
  end
15
-
24
+
16
25
  def trace=(trace)
17
26
  raise(ArgumentError, "BibTeX::Error trace must be of type Array; was: #{trace.class.name}.") unless trace.kind_of?(Array)
18
27
  @trace = trace
@@ -95,10 +95,10 @@ module BibTeX
95
95
  def push(value)
96
96
  case value[0]
97
97
  when :CONTENT, :STRING_LITERAL
98
- if !@stack.empty? && value[0] == @stack[-1][0]
99
- @stack[-1][1] << value[1]
98
+ if !@stack.empty? && value[0] == @stack[-1][0]
99
+ @stack[-1][1] << value[1]
100
100
  else
101
- @stack.push(value)
101
+ @stack.push(value)
102
102
  end
103
103
  when :ERROR
104
104
  @stack.push(value) if @include_errors
@@ -119,10 +119,10 @@ module BibTeX
119
119
 
120
120
  self.data = string || @scanner.string
121
121
 
122
- until @scanner.eos?
123
- send("parse_#{MODE[@mode]}")
122
+ until @scanner.eos?
123
+ send("parse_#{MODE[@mode]}")
124
124
  end
125
-
125
+
126
126
  push([false, '$end'])
127
127
  end
128
128
 
@@ -130,7 +130,7 @@ module BibTeX
130
130
 
131
131
  def parse_bibtex
132
132
  case
133
- when @scanner.scan(/[\t\r\n\s]+/o)
133
+ when @scanner.scan(/[\s]+/o)
134
134
  when @scanner.scan(/\{/o)
135
135
  @brace_level += 1
136
136
  push([:LBRACE,'{'])
@@ -146,7 +146,7 @@ module BibTeX
146
146
  push([:COMMA,','])
147
147
  when @scanner.scan(/\d+/o)
148
148
  push([:NUMBER,@scanner.matched])
149
- when @scanner.scan(/[a-z\d \/:_!$\.%&*-]+/io)
149
+ when @scanner.scan(/[[:alpha:]\d \/:_!$\.%&*-]+/io)
150
150
  push([:NAME,@scanner.matched.rstrip])
151
151
  when @scanner.scan(/"/o)
152
152
  @mode = :literal
@@ -26,7 +26,10 @@ module BibTeX
26
26
  def_delegators :@tokens, :each, :sort
27
27
 
28
28
  def self.parse(string)
29
- Names.new(NameParser.new.parse(string))
29
+ new(NameParser.new.parse(string))
30
+ rescue => e
31
+ BibTeX.log.info(e.message)
32
+ nil
30
33
  end
31
34
 
32
35
  def initialize(*arguments)
@@ -49,7 +52,7 @@ module BibTeX
49
52
  q = [options[:quotes]].flatten
50
53
  [q[0], value, q[-1]].compact.join
51
54
  end
52
-
55
+
53
56
  def name?; true; end
54
57
  def numeric?; false; end
55
58
  def atomic?; true; end
@@ -91,8 +94,15 @@ module BibTeX
91
94
  class Name < Struct.new(:first, :last, :prefix, :suffix)
92
95
  extend Forwardable
93
96
  include Comparable
94
-
95
- def_delegators :to_s, :empty?, :=~, :casecmp, :match, :length, :intern, :to_sym, :end_with?, :start_with?, :include?, :upcase, :downcase, :reverse, :chop, :chomp, :rstrip, :gsub, :sub, :size, :strip, :succ, :to_str, :split, :each_byte, :each_char, :each_line
97
+
98
+ BibTeXML = {
99
+ :first => :first,
100
+ :last => :last,
101
+ :prefix => :prelast,
102
+ :suffix => :lineage
103
+ }.freeze
104
+
105
+ def_delegators :to_s, :=~, :===, *(String.instance_methods(false).reject { |m| m =~ /^\W|each|!$/ })
96
106
 
97
107
  class << self
98
108
  def parse(string)
@@ -140,6 +150,21 @@ module BibTeX
140
150
  Hash[each_pair.to_a]
141
151
  end
142
152
 
153
+ def to_xml
154
+ require 'rexml/document'
155
+ xml = REXML::Element.new('bibtex:person')
156
+
157
+ each_pair do |part, text|
158
+ unless text.nil?
159
+ element = REXML::Element.new("bibtex:#{BibTeXML[part]}")
160
+ element.text = text
161
+ xml.add_element(element)
162
+ end
163
+ end
164
+
165
+ xml
166
+ end
167
+
143
168
  [:strip!, :upcase!, :downcase!, :sub!, :gsub!, :chop!, :chomp!, :rstrip!].each do |method_id|
144
169
  define_method(method_id) do |*arguments, &block|
145
170
  each do |part|
@@ -52,7 +52,7 @@ module BibTeX
52
52
  attr_reader :tokens
53
53
  alias to_a tokens
54
54
 
55
- 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
55
+ def_delegators :to_s, :=~, :===, *String.instance_methods(false).reject { |m| m =~ /^\W|^length$|!$/ }
56
56
  def_delegators :@tokens, :[], :length
57
57
 
58
58
  def initialize(*arguments)
@@ -236,19 +236,19 @@ module BibTeX
236
236
  self
237
237
  end
238
238
 
239
- def method_missing (name, *args)
240
- if name.to_s =~ /^(?:convert|from)_([a-z]+)(!)?$/
241
- return $2 ? convert!($1) : convert($1)
242
- end
243
-
244
- super
239
+ def method_missing (name, *args)
240
+ case
241
+ when name.to_s =~ /^(?:convert|from)_([a-z]+)(!)?$/
242
+ $2 ? convert!($1) : convert($1)
243
+ else
244
+ super
245
+ end
245
246
  end
246
247
 
247
248
  def respond_to? (method)
248
249
  method =~ /^(?:convert|from)_([a-z]+)(!)?$/ || super
249
250
  end
250
-
251
-
251
+
252
252
  def <=> (other)
253
253
  to_s <=> other.to_s
254
254
  end
@@ -18,6 +18,6 @@
18
18
 
19
19
  module BibTeX
20
20
  module Version
21
- STRING = '1.3.12'.freeze
21
+ STRING = '2.0.0pre1'.freeze
22
22
  end
23
23
  end
@@ -1,5 +1,5 @@
1
1
  !RBIX
2
- 9595534255132031488
2
+ 16846133056282117387
3
3
  x
4
4
  M
5
5
  1
@@ -155,7 +155,7 @@ x
155
155
  STRING
156
156
  s
157
157
  6
158
- 1.3.11
158
+ 1.3.12
159
159
  x
160
160
  6
161
161
  freeze
@@ -1,20 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+
1
3
  require 'helper'
2
4
 
3
5
  module BibTeX
4
6
 
5
7
  class BibliographyTest < MiniTest::Spec
6
8
 
7
- context 'when newly created' do
8
- should 'not be nil' do
9
+ describe 'when newly created' do
10
+ it 'should not be nil' do
9
11
  assert Bibliography.new
10
12
  end
11
- should 'be empty' do
13
+ it 'should be empty' do
12
14
  assert Bibliography.new.empty?
13
15
  end
14
16
  end
15
17
 
16
- context '#open' do
17
- should 'accept a block and save the file after execution' do
18
+ describe '.open' do
19
+ it 'should accept a block and save the file after execution' do
18
20
  tmp = Tempfile.new('bibtex')
19
21
  tmp.close
20
22
  b = BibTeX.open(Test.fixtures(:bibdesk)).save_to(tmp.path)
@@ -25,10 +27,17 @@ module BibTeX
25
27
 
26
28
  assert_equal b.length - 1, BibTeX.open(tmp.path).length
27
29
  end
30
+
28
31
  end
32
+
33
+ describe '.parse' do
34
+ it 'should accept filters' do
35
+ Bibliography.parse("@misc{k, title = {\\''u}}", :filter => 'latex')[0].title.must_be :==, 'ü'
36
+ end
37
+ end
29
38
 
30
- context 'given a populated biliography' do
31
- setup do
39
+ describe 'given a populated biliography' do
40
+ before do
32
41
  @bib = BibTeX.parse <<-END
33
42
  @book{rails,
34
43
  address = {Raleigh, North Carolina},
@@ -57,41 +66,41 @@ module BibTeX
57
66
  END
58
67
  end
59
68
 
60
- should 'support access by index' do
69
+ it 'should support access by index' do
61
70
  assert_equal 'ruby', @bib[1].keywords
62
71
  end
63
72
 
64
- should 'support access by range' do
73
+ it 'should support access by range' do
65
74
  assert_equal %w{2008 2007}, @bib[1..2].map(&:year)
66
75
  end
67
76
 
68
- should 'support access by index and offset' do
77
+ it 'should support access by index and offset' do
69
78
  assert_equal %w{2008 2007}, @bib[1,2].map(&:year)
70
79
  end
71
80
 
72
- should 'support queries by symbol key' do
81
+ it 'should support queries by symbol key' do
73
82
  refute_nil @bib[:rails]
74
83
  assert_nil @bib[:ruby]
75
84
  end
76
85
 
77
- should 'support queries by symbol key and selector' do
86
+ it 'should support queries by symbol key and selector' do
78
87
  assert_equal 1, @bib.q(:all, :rails).length
79
88
  refute_nil @bib.q(:first, :rails)
80
89
  assert_nil @bib.q(:first, :railss)
81
90
  end
82
91
 
83
- should 'support queries by string key' do
84
- assert_equal 1, @bib['rails'].length
85
- assert_equal 0, @bib['ruby'].length
92
+ it 'should support queries by string key' do
93
+ refute_nil @bib['rails']
94
+ assert_nil @bib['ruby']
86
95
  end
87
96
 
88
- should 'support queries by type string' do
97
+ it 'should support queries by type string' do
89
98
  assert_equal 2, @bib['@book'].length
90
99
  assert_equal 1, @bib['@article'].length
91
100
  assert_equal 0, @bib['@collection'].length
92
101
  end
93
102
 
94
- should 'support queries by type string and selector' do
103
+ it 'should support queries by type string and selector' do
95
104
  assert_equal 2, @bib.q(:all, '@book').length
96
105
  refute_nil @bib.q(:first, '@book')
97
106
  assert_equal 1, @bib.q(:all, '@article').length
@@ -101,16 +110,16 @@ module BibTeX
101
110
  end
102
111
 
103
112
 
104
- should 'support queries by pattern' do
113
+ it 'should support queries by pattern' do
105
114
  assert_equal 0, @bib[/reilly/].length
106
115
  assert_equal 2, @bib[/reilly/i].length
107
116
  end
108
117
 
109
- should 'support queries by type string and conditions' do
118
+ it 'should support queries by type string and conditions' do
110
119
  assert_equal 1, @bib['@book[keywords=ruby]'].length
111
120
  end
112
121
 
113
- should 'support queries by bibtex element' do
122
+ it 'should support queries by bibtex element' do
114
123
  entry = Entry.parse(<<-END).first
115
124
  @article{segaran2007,
116
125
  title = {{Programming collective intelligence}},
@@ -124,40 +133,59 @@ module BibTeX
124
133
  assert_equal 0, @bib[entry].length
125
134
  end
126
135
 
127
- should 'support query and additional block' do
136
+ it 'should support query and additional block' do
128
137
  assert_equal 1, @bib.q('@book') { |e| e.keywords.split(/,/).length > 1 }.length
129
138
  end
130
139
 
131
- should 'support saving the bibliography to a file' do
140
+ it 'should support saving the bibliography to a file' do
132
141
  tmp = Tempfile.new('bibtex')
133
142
  tmp.close
134
143
  @bib.save_to(tmp.path)
135
- assert_equal @bib.to_s, BibTeX.open(tmp.path).to_s
144
+ assert_equal @bib.length, BibTeX.open(tmp.path).length
136
145
  end
137
146
 
138
- context 'given a filter' do
139
- setup do
147
+ describe 'given a filter' do
148
+ before do
140
149
  @filter = Object
141
150
  def @filter.apply (value); value.is_a?(::String) ? value.upcase : value; end
142
151
  end
143
152
 
144
- should 'support arbitrary conversions' do
153
+ it 'should support arbitrary conversions' do
145
154
  @bib.convert(@filter)
146
155
  assert_equal 'RUBY, RAILS', @bib[:rails].keywords
147
156
  end
148
157
 
149
- should 'support conditional arbitrary conversions' do
150
- @bib.convert(@filter) { |e| e.key != :rails }
158
+ it 'should support conditional arbitrary conversions' do
159
+ @bib.convert(@filter) { |e| e.key != 'rails' }
151
160
  assert_equal 'ruby, rails', @bib[:rails].keywords
152
161
  assert_equal 'RUBY', @bib[:flanagan2008].keywords
153
162
  end
154
163
 
155
164
  end
156
165
 
166
+ describe 'BibTeXML export' do
167
+ before { @bibtexml = Tempfile.new('bibtexml') }
168
+ after { @bibtexml.unlink }
169
+
170
+ it 'should support exporting to BibTeXML' do
171
+ @bib.to_xml.write(@bibtexml, 2)
172
+ @bibtexml.rewind
173
+ xml = REXML::Document.new(@bibtexml)
174
+ xml.root.namespace.must_be :==, 'http://bibtexml.sf.net/'
175
+ xml.root.get_elements('//bibtex:entry').wont_be_empty
176
+ end
177
+
178
+ it 'should support exporting to extended BibTeXML' do
179
+ @bib.to_xml(:extended => true).write(@bibtexml, 2)
180
+ @bibtexml.rewind
181
+ xml = REXML::Document.new(@bibtexml)
182
+ xml.root.namespace.must_be :==, 'http://bibtexml.sf.net/'
183
+ xml.root.get_elements('//bibtex:person').wont_be_empty
184
+ end
185
+
186
+ end
157
187
  end
158
-
159
-
160
-
188
+
161
189
 
162
190
  end
163
191
  end
@@ -2,31 +2,55 @@ require 'helper'
2
2
 
3
3
  module BibTeX
4
4
 
5
+ class ElementTest < MiniTest::Spec
6
+
7
+ describe '.parse' do
8
+
9
+ it 'accepts a BibTeX string' do
10
+ Element.parse('@misc{x,},@misc{y,}').length.must_be :==, 2
11
+ end
12
+
13
+ it 'accepts an Element' do
14
+ Element.parse(Comment.new('blah')).length.must_be :==, 1
15
+ end
16
+
17
+ it 'accepts a Hash and returns an Entry' do
18
+ Element.parse({ :type => :book })[0].type.must_be :==, :book
19
+ end
20
+
21
+ it 'accepts an array of hashes' do
22
+ Element.parse([{ :type => :book }, { :type => :misc }])[1].type.must_be :==, :misc
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
5
29
  class PreambleTest < MiniTest::Spec
6
30
 
7
- context 'a new preamble instance' do
8
- setup do
31
+ describe 'a new preamble instance' do
32
+ before do
9
33
  @preamble = Preamble.new
10
34
  end
11
35
 
12
- should 'not be nil' do
36
+ it 'should not be nil' do
13
37
  assert @preamble
14
38
  end
15
39
  end
16
40
 
17
- context 'given a set of @preambles' do
18
- setup do
41
+ describe 'given a set of @preambles' do
42
+ before do
19
43
  @bib = BibTeX.open(Test.fixtures(:preamble))
20
44
  @preambles = @bib.preambles
21
45
  end
22
46
 
23
- should 'support round-trips of all parsed preambles' do
47
+ it 'should support round-trips of all parsed preambles' do
24
48
  assert_equal %q[@preamble{ "This bibliography was created \today" }], @preambles[0].to_s
25
49
  assert_equal %q[@preamble{ "Bib\TeX" }], @preambles[1].to_s
26
50
  assert_equal %q[@preamble{ "Maintained by " # maintainer }], @preambles[2].to_s
27
51
  end
28
52
 
29
- should 'support string replacement of preamble contents' do
53
+ it 'should support string replacement of preamble contents' do
30
54
  assert_equal %q["Maintained by " # maintainer], @preambles[2].value.to_s
31
55
  @bib.replace_strings
32
56
  assert_equal %q["Maintained by " # "Myself"], @preambles[2].value.to_s
@@ -3,37 +3,171 @@ require 'helper.rb'
3
3
  module BibTeX
4
4
  class EntryTest < MiniTest::Spec
5
5
 
6
- context 'a new entry' do
7
- should 'not be nil' do
8
- assert Entry.new
6
+ describe 'a new entry' do
7
+ it "won't be nil" do
8
+ Entry.new.wont_be_nil
9
9
  end
10
10
  end
11
11
 
12
- context 'month conversion' do
13
- setup do
12
+ describe 'cross-references' do
13
+ it 'has no cross-reference by default' do
14
+ assert_equal false, Entry.new.has_cross_reference?
15
+ end
16
+
17
+ it 'is not cross-referenced by default' do
18
+ assert_equal false, Entry.new.cross_referenced?
19
+ Entry.new.cross_referenced_by.must_be_empty
20
+ end
21
+
22
+ describe 'given a bibliography with cross referenced entries' do
23
+ before do
24
+ @bib = Bibliography.parse <<-END
25
+ @book{a, editor = "A", title = "A"}
26
+ @incollection{a1, crossref = "a"}
27
+ @incollection{b1, crossref = "b"}
28
+ END
29
+ end
30
+
31
+ describe '#has_cross_reference?' do
32
+ it 'returns true if the entry has a valid cross-reference' do
33
+ assert_equal true, @bib['a1'].has_cross_reference?
34
+ end
35
+ it 'returns false if the entry has no valid cross-reference' do
36
+ assert_equal false, @bib['a'].has_cross_reference?
37
+ assert_equal false, @bib['b1'].has_cross_reference?
38
+ end
39
+ end
40
+
41
+ describe '#cross_referemced?' do
42
+ it 'returns true if the entry is cross-referenced by another entry' do
43
+ assert_equal true, @bib['a'].cross_referenced?
44
+ end
45
+ it 'returns false if the entry is not cross-referenced' do
46
+ assert_equal false, @bib['a1'].cross_referenced?
47
+ end
48
+ end
49
+
50
+ describe '#cross_referenced_by' do
51
+ it 'returns a list of all entries that cross-reference this entry' do
52
+ @bib['a'].cross_referenced_by.must_include(@bib['a1'])
53
+ end
54
+
55
+ it 'returns an empty list if there are no cross-references to this entry' do
56
+ @bib['a1'].cross_referenced_by.must_be_empty
57
+ end
58
+ end
59
+
60
+ describe 'resolve field values using array accessors #[]' do
61
+ describe 'when a "title" is set in the entry itself' do
62
+ before { @bib['a1'].title = 'A1' }
63
+ it 'returns the title' do
64
+ @bib['a1'].title.must_be :==, 'A1'
65
+ end
66
+ end
67
+
68
+ describe 'when "title" is undefined for the entry but defined in the reference' do
69
+ it 'returns the referenced title' do
70
+ @bib['a1'].title.must_be :==, @bib['a'].title
71
+ end
72
+ end
73
+
74
+ describe 'when "booktitle" is undefined for the entry but defined in the reference' do
75
+ before { @bib['a'].booktitle = "A Booktitle" }
76
+ it 'returns the referenced booktitle' do
77
+ @bib['a1'].booktitle.must_be :==, @bib['a'].booktitle
78
+ end
79
+ end
80
+
81
+ describe 'when "booktitle" is undefined for the entry and the reference but the reference has a "title"' do
82
+ it "returns the reference's title" do
83
+ @bib['a1'].booktitle.must_be :==, @bib['a'].title
84
+ end
85
+ end
86
+
87
+ it 'does not store referenced values permanently' do
88
+ refute_nil @bib['a1'].booktitle
89
+ assert_nil @bib['a1'].fields[:booktitle]
90
+ end
91
+
92
+ describe '#inherited_fields' do
93
+ it 'returns an empty list by default' do
94
+ Entry.new.inherited_fields.must_be_empty
95
+ end
96
+
97
+ it 'returns an empty list if this entry has no cross-reference' do
98
+ @bib['a'].inherited_fields.must_be_empty
99
+ end
100
+
101
+ it 'returns an empty list if this entry has a cross-reference but the reference does not exist in the bibliography' do
102
+ @bib['b1'].inherited_fields.must_be_empty
103
+ end
104
+
105
+ it 'returns a list of all fields not set in the field but in the reference' do
106
+ @bib['a1'].inherited_fields.must_be :==, [:booktitle, :editor, :title]
107
+ end
108
+ end
109
+
110
+ describe '#save_inherited_fields' do
111
+ it 'copies referenced values to the entry' do
112
+ @bib['a1'].title = 'a1'
113
+ @bib['a1'].save_inherited_fields
114
+ @bib['a1'].fields[:booktitle].must_be :==, @bib['a'].title
115
+ @bib['a1'].fields[:title].wont_be :==, @bib['a'].title
116
+ end
117
+ end
118
+ end
119
+
120
+ end
121
+ end
122
+
123
+ describe '#names' do
124
+ it 'returns an empty list by default' do
125
+ Entry.new.names.must_be :==, []
126
+ end
127
+
128
+ it 'returns the author (if set)' do
129
+ Entry.new(:author => 'A').names.must_be :==, %w{ A }
130
+ end
131
+
132
+ it 'returns all authors (if set)' do
133
+ Entry.new(:author => 'A B and C D').parse_names.names.length.must_be :==, 2
134
+ end
135
+
136
+ it 'returns the editor (if set)' do
137
+ Entry.new(:editor => 'A').names.must_be :==, %w{ A }
138
+ end
139
+
140
+ it 'returns the translator (if set)' do
141
+ Entry.new(:translator => 'A').names.must_be :==, %w{ A }
142
+ end
143
+
144
+ end
145
+
146
+ describe 'month conversion' do
147
+ before do
14
148
  @entry = Entry.new
15
149
  end
16
150
 
17
151
  [[:jan,'January'], [:feb,'February'], [:sep,'September']].each do |m|
18
- should 'convert english months' do
152
+ it 'should convert english months' do
19
153
  @entry.month = m[1]
20
154
  assert_equal m[0], @entry.month.v
21
155
  end
22
156
  end
23
157
 
24
158
  [[:jan,:jan], [:feb,:feb], [:sep,:sep]].each do |m|
25
- should 'convert bibtex abbreviations' do
159
+ it 'should convert bibtex abbreviations' do
26
160
  @entry.month = m[1]
27
161
  assert_equal m[0], @entry.month.v
28
162
  end
29
163
  end
30
164
 
31
165
  [[:jan,1], [:feb,2], [:sep,9]].each do |m|
32
- should 'convert numbers' do
166
+ it 'should convert numbers' do
33
167
  @entry.month = m[1]
34
168
  assert_equal m[0], @entry.month.v
35
169
  end
36
- should 'convert numbers when parsing' do
170
+ it 'should convert numbers when parsing' do
37
171
  @entry = Entry.parse("@misc{id, month = #{m[1]}}")[0]
38
172
  assert_equal m[0], @entry.month.v
39
173
  end
@@ -41,8 +175,8 @@ module BibTeX
41
175
 
42
176
  end
43
177
 
44
- context 'given an entry' do
45
- setup do
178
+ describe 'given an entry' do
179
+ before do
46
180
  @entry = Entry.new do |e|
47
181
  e.type = :book
48
182
  e.key = :key
@@ -56,13 +190,13 @@ module BibTeX
56
190
  end
57
191
  end
58
192
 
59
- should 'support renaming! of field attributes' do
193
+ it 'should support renaming! of field attributes' do
60
194
  @entry.rename!(:title => :foo)
61
195
  refute @entry.has_field?(:title)
62
196
  assert_equal 'Moby Dick', @entry[:foo]
63
197
  end
64
198
 
65
- should 'support renaming of field attributes' do
199
+ it 'should support renaming of field attributes' do
66
200
  e = @entry.rename(:title => :foo)
67
201
 
68
202
  assert @entry.has_field?(:title)
@@ -76,7 +210,7 @@ module BibTeX
76
210
  end
77
211
 
78
212
 
79
- should 'support citeproc export' do
213
+ it 'should support citeproc export' do
80
214
  e = @entry.to_citeproc
81
215
  assert_equal 'book', e['type']
82
216
  assert_equal 'New York', e['publisher-place']
@@ -86,30 +220,30 @@ module BibTeX
86
220
  assert_equal 'Melville', e['author'][0]['family']
87
221
  end
88
222
 
89
- context 'given a filter' do
90
- setup do
223
+ describe 'given a filter' do
224
+ before do
91
225
  @filter = Object.new
92
226
  def @filter.apply (value); value.is_a?(::String) ? value.upcase : value; end
93
227
  end
94
228
 
95
- should 'support arbitrary conversion' do
229
+ it 'should support arbitrary conversion' do
96
230
  e = @entry.convert(@filter)
97
231
  assert_equal 'MOBY DICK', e.title
98
232
  assert_equal 'Moby Dick', @entry.title
99
233
  end
100
234
 
101
- should 'support arbitrary in-place conversion' do
235
+ it 'should support arbitrary in-place conversion' do
102
236
  @entry.convert!(@filter)
103
237
  assert_equal 'MOBY DICK', @entry.title
104
238
  end
105
239
 
106
- should 'support conditional arbitrary in-place conversion' do
240
+ it 'should support conditional arbitrary in-place conversion' do
107
241
  @entry.convert!(@filter) { |k,v| k.to_s =~ /publisher/i }
108
242
  assert_equal 'Moby Dick', @entry.title
109
243
  assert_equal 'PENGUIN', @entry.publisher
110
244
  end
111
245
 
112
- should 'support conditional arbitrary conversion' do
246
+ it 'should support conditional arbitrary conversion' do
113
247
  e = @entry.convert(@filter) { |k,v| k.to_s =~ /publisher/i }
114
248
  assert_equal 'Moby Dick', e.title
115
249
  assert_equal 'PENGUIN', e.publisher
@@ -120,8 +254,8 @@ module BibTeX
120
254
 
121
255
  end
122
256
 
123
- context 'citeproc export' do
124
- setup do
257
+ describe 'citeproc export' do
258
+ before do
125
259
  @entry = Entry.new do |e|
126
260
  e.type = :book
127
261
  e.key = :key
@@ -130,11 +264,11 @@ module BibTeX
130
264
  end
131
265
  end
132
266
 
133
- should 'use dropping-particle by default' do
267
+ it 'should use dropping-particle by default' do
134
268
  assert_equal 'van', @entry.to_citeproc['author'][0]['dropping-particle']
135
269
  end
136
270
 
137
- should 'accept option to use non-dropping-particle' do
271
+ it 'should accept option to use non-dropping-particle' do
138
272
  assert_equal 'van', @entry.to_citeproc(:particle => 'non-dropping-particle')['author'][0]['non-dropping-particle']
139
273
  end
140
274
  end
@@ -145,9 +279,9 @@ module BibTeX
145
279
  assert_equal(BibTeX::Bibliography, bib.class)
146
280
  assert_equal(3, bib.data.length)
147
281
  assert_equal([BibTeX::Entry], bib.data.map(&:class).uniq)
148
- assert_equal(:'key:0', bib.data[0].key)
149
- assert_equal(:'key:1', bib.data[1].key)
150
- assert_equal(:'foo', bib.data[2].key)
282
+ assert_equal('key:0', bib.data[0].key)
283
+ assert_equal('key:1', bib.data[1].key)
284
+ assert_equal('foo', bib.data[2].key)
151
285
  assert_equal(:book, bib.data[0].type)
152
286
  assert_equal(:article, bib.data[1].type)
153
287
  assert_equal(:article, bib.data[2].type)
@@ -180,7 +314,7 @@ module BibTeX
180
314
  entry.title = 'The Raven'
181
315
 
182
316
  assert_equal :book, entry.type
183
- assert_equal :raven, entry.key
317
+ assert_equal 'raven', entry.key
184
318
  assert_equal 'Poe, Edgar A.', entry.author
185
319
  assert_equal 'The Raven', entry.title
186
320
  end
@@ -194,7 +328,7 @@ module BibTeX
194
328
  })
195
329
 
196
330
  assert_equal :book, entry.type
197
- assert_equal :raven, entry.key
331
+ assert_equal 'raven', entry.key
198
332
  assert_equal 'Poe, Edgar A.', entry.author
199
333
  assert_equal 'The Raven', entry.title
200
334
  end
@@ -202,36 +336,81 @@ module BibTeX
202
336
  def test_creation_from_block
203
337
  entry = BibTeX::Entry.new do |e|
204
338
  e.type = :book
205
- e.key = :raven
339
+ e.key = 'raven'
206
340
  e.author = 'Poe, Edgar A.'
207
341
  e.title = 'The Raven'
208
342
  end
209
343
 
210
344
  assert_equal :book, entry.type
211
- assert_equal :raven, entry.key
345
+ assert_equal 'raven', entry.key
212
346
  assert_equal 'Poe, Edgar A.', entry.author
213
347
  assert_equal 'The Raven', entry.title
214
348
  end
215
349
 
216
350
  def test_sorting
217
351
  entries = []
218
- entries << BibTeX::Entry.new({ :type => 'book', :key => 'raven3', :author => 'Poe, Edgar A.', :title => 'The Raven'})
219
- entries << BibTeX::Entry.new({ :type => 'book', :key => 'raven2', :author => 'Poe, Edgar A.', :title => 'The Raven'})
220
- entries << BibTeX::Entry.new({ :type => 'book', :key => 'raven1', :author => 'Poe, Edgar A.', :title => 'The Raven'})
221
- entries << BibTeX::Entry.new({ :type => 'book', :key => 'raven1', :author => 'Poe, Edgar A.', :title => 'The Aven'})
352
+ entries << Entry.new({ :type => 'book', :key => 'raven3', :author => 'Poe, Edgar A.', :title => 'The Raven'})
353
+ entries << Entry.new({ :type => 'book', :key => 'raven2', :author => 'Poe, Edgar A.', :title => 'The Raven'})
354
+ entries << Entry.new({ :type => 'book', :key => 'raven1', :author => 'Poe, Edgar A.', :title => 'The Raven'})
355
+ entries << Entry.new({ :type => 'book', :key => 'raven1', :author => 'Poe, Edgar A.', :title => 'The Aven'})
222
356
 
223
357
  entries.sort!
224
358
 
225
- assert_equal [:raven1, :raven1, :raven2, :raven3], entries.map(&:key)
359
+ assert_equal ['raven1', 'raven1', 'raven2', 'raven3'], entries.map(&:key)
226
360
  assert_equal ['The Aven', 'The Raven'], entries.map(&:title)[0,2]
227
361
 
228
362
  end
229
363
 
230
- def test_default_keys
231
- assert_equal :poe1996raven, Entry.new(:type => 'book', :author => 'Poe, Edgar A.', :title => 'The Raven', :year => 1996).key
232
- assert_equal :poe1996, Entry.new(:type => 'book', :author => 'Poe, Edgar A.', :year => 1996).key
233
- assert_equal :'1996raven', Entry.new(:type => 'book', :title => 'The Raven', :year => 1996).key
234
- assert_match /^\d+$/, Entry.new.key
364
+ describe 'default keys' do
365
+ before {
366
+ @e1 = Entry.new(:type => 'book', :author => 'Poe, Edgar A.', :title => 'The Raven', :editor => 'John Hopkins', :year => 1996)
367
+ @e2 = Entry.new(:type => 'book', :title => 'The Raven', :editor => 'John Hopkins', :year => 1996)
368
+ @e3 = Entry.new(:type => 'book', :author => 'Poe, Edgar A.', :title => 'The Raven', :editor => 'John Hopkins')
369
+ }
370
+
371
+ it 'should return "unknown-a" for an empty Entry' do
372
+ Entry.new.key.must_be :==, 'unknown-a'
373
+ end
374
+
375
+ it 'should return a key made up of author-year-a if all fields are present' do
376
+ @e1.key.must_be :==, 'poe1996a'
377
+ end
378
+
379
+ it 'should return a key made up of editor-year-a if there is no author' do
380
+ @e2.key.must_be :==, 'john1996a'
381
+ end
382
+
383
+ it 'should return use the last name if the author/editor names have been parsed' do
384
+ @e2.parse_names.key.must_be :==, 'hopkins1996a'
385
+ end
386
+
387
+ it 'skips the year if not present' do
388
+ @e3.key.must_be :==, 'poe-a'
389
+ end
390
+ end
391
+
392
+ describe 'when the entry is added to a Bibliography' do
393
+ before {
394
+ @e = Entry.new
395
+ @bib = Bibliography.new
396
+ }
397
+
398
+ it 'should register itself with its key' do
399
+ @bib << @e
400
+ @bib.entries.keys.must_include @e.key
401
+ end
402
+
403
+ describe "when there is already an element registered with the entry's key" do
404
+ before { @bib << Entry.new }
405
+
406
+ it "should find a suitable key" do
407
+ k = @e.key
408
+ @bib << @e
409
+ @bib.entries.keys.must_include @e.key
410
+ k.wont_be :==, @e.key
411
+ end
412
+
413
+ end
235
414
  end
236
415
 
237
416
  end