bibtex-ruby 2.0.7 → 2.0.8

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 CHANGED
@@ -1,6 +1,9 @@
1
1
  source :rubygems
2
2
  gemspec
3
3
 
4
+ # RDF Export
5
+ gem 'rdf', '~>0.3'
6
+
4
7
  group :debug do
5
8
  gem 'debugger', :platforms => [:mri_19]
6
9
  gem 'ruby-debug', :platforms => [:mri_18]
@@ -1,13 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bibtex-ruby (2.0.6)
4
+ bibtex-ruby (2.0.8)
5
5
  latex-decode (>= 0.0.6)
6
6
  multi_json (~> 1.3)
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
+ addressable (2.2.7)
11
12
  autowatchr (0.1.5)
12
13
  watchr
13
14
  builder (3.0.0)
@@ -39,7 +40,7 @@ GEM
39
40
  linecache (0.46)
40
41
  rbx-require-relative (> 0.0.4)
41
42
  minitest (2.11.3)
42
- multi_json (1.3.2)
43
+ multi_json (1.3.4)
43
44
  mynyml-redgreen (0.7.1)
44
45
  term-ansicolor (>= 1.0.4)
45
46
  racc (1.4.8)
@@ -52,6 +53,8 @@ GEM
52
53
  columnize
53
54
  rbx-linecache (~> 1.3)
54
55
  rbx-require-relative (>= 0.0.4)
56
+ rdf (0.3.5.2)
57
+ addressable (>= 2.2.6)
55
58
  rdoc (3.12)
56
59
  json (~> 1.4)
57
60
  ruby-debug (0.10.4)
@@ -79,6 +82,7 @@ DEPENDENCIES
79
82
  racc (~> 1.4)
80
83
  rake (~> 0.9)
81
84
  rbx-trepanning
85
+ rdf (~> 0.3)
82
86
  rdoc (~> 3.9)
83
87
  ruby-debug
84
88
  ruby-prof (~> 0.10)
@@ -1,3 +1,9 @@
1
+ 2.0.8 / 2012-05-11
2
+ ==================
3
+
4
+ * Added extend_initials feature for names
5
+ * Added experimental RDF export (using BIBO ontology)
6
+
1
7
  2.0.7 / 2012-04-30
2
8
  ==================
3
9
 
data/README.md CHANGED
@@ -35,7 +35,7 @@ Select a BibTeX entry and access individual fields:
35
35
  b[:pickaxe].author.length
36
36
  #=> 3
37
37
  b[:pickaxe].author.to_s
38
- #=> "Thomas, Dave and Fowler, Chad and Hunt, Andy"
38
+ #=> "Thomas, D. and Fowler, Chad and Hunt, Andy"
39
39
  b[:pickaxe].author[2].first
40
40
  #=> "Andy"
41
41
 
@@ -48,6 +48,12 @@ Query a bibliography:
48
48
  b['@book[year=2009]'].length
49
49
  #=> 1 - the number of books published in 2009
50
50
 
51
+ Extend first name initials throughout your bibliography:
52
+
53
+ b.extend_initials ['Dave', 'Thomas']
54
+ b[:pickaxe].author.to_s
55
+ #=> "Thomas, Dave and Fowler, Chad and Hunt, Andy"
56
+
51
57
  Render your bibliography in one of
52
58
  [many different citation styles](https://github.com/citation-style-language/styles)
53
59
  (requires the **citeproc-ruby** gem):
data/Rakefile CHANGED
@@ -80,6 +80,8 @@ end
80
80
 
81
81
  desc 'Pushes the gem file to rubygems.org'
82
82
  task :release => ['build'] do
83
+ system %Q{git tag "#{BibTeX::Version::STRING}"}
84
+ system "git push --tags"
83
85
  system "gem push bibtex-ruby-#{BibTeX::Version::STRING}.gem"
84
86
  end
85
87
 
@@ -89,8 +89,9 @@ module BibTeX
89
89
  :comment, :meta_content
90
90
 
91
91
  def_delegators :@data, :length, :size, :empty?
92
- def_delegators :@entries, :key?, :has_key?
92
+ def_delegators :@entries, :key?, :has_key?, :values_at
93
93
 
94
+ alias entries_at values_at
94
95
 
95
96
  # Creates a new bibliography.
96
97
  def initialize(options = {})
@@ -285,6 +286,17 @@ module BibTeX
285
286
  self
286
287
  end
287
288
 
289
+ # call-seq:
290
+ # b.extend_initials(['Edgar Allen', 'Poe'], ['Nathaniel', 'Hawthorne'])
291
+ # #=> Extends the initials in names like 'E.A. Poe' or 'Hawethorne, N.'
292
+ # in the bibliography.
293
+ def extend_initials(*arguments)
294
+ arguments.each do |with_first, for_last|
295
+ names.each do |name|
296
+ name.extend_initials(with_first, for_last)
297
+ end
298
+ end
299
+ end
288
300
 
289
301
  def sort(*arguments, &block)
290
302
  data.sort(*arguments, &block)
@@ -341,6 +353,22 @@ module BibTeX
341
353
  xml
342
354
  end
343
355
 
356
+ # Returns an RDF::Graph representation of the bibliography. The graph
357
+ # can be serialized using any of the RDF serializer plugins.
358
+ def to_rdf(options = {})
359
+ require 'rdf'
360
+
361
+ graph = RDF::Graph.new
362
+
363
+ q('@entry').each do |entry|
364
+ graph << entry.to_rdf(options)
365
+ end
366
+
367
+ graph
368
+ rescue LoadError
369
+ BibTeX.log.error "Please gem install rdf for RDF support."
370
+ end
371
+
344
372
  # call-seq:
345
373
  # bib.query() #=> returns all elements
346
374
  # bib.query('@book') #=> returns all books
@@ -107,6 +107,35 @@ module BibTeX
107
107
  article article-journal
108
108
  }.map(&:intern)]).freeze
109
109
 
110
+ BIBO_FIELDS = Hash[*%w{
111
+ pages pages
112
+ number issue
113
+ isbn isbn
114
+ issn issn
115
+ doi doi
116
+ edition edition
117
+ abstract abstract
118
+ volume volume
119
+ }.map(&:intern)].freeze
120
+
121
+ BIBO_TYPES = Hash.new(:Document).merge(Hash[*%w{
122
+ booklet Book
123
+ book Book
124
+ conference Conference
125
+ inbook Article
126
+ incollection Article
127
+ inproceedings Article
128
+ manual Manual
129
+ mastersthesis Thesis
130
+ phdthesis Thesis
131
+ proceedings Proceedings
132
+ techreport Report
133
+ journal Journal
134
+ periodical Periodical
135
+ unpublished Manuscript
136
+ article Article
137
+ }.map(&:intern)]).freeze
138
+
110
139
 
111
140
  attr_reader :fields, :type
112
141
 
@@ -198,20 +227,33 @@ module BibTeX
198
227
  alias type? has_type?
199
228
 
200
229
 
201
- def has_field?(name)
202
- name.respond_to?(:to_sym) ? fields.has_key?(name.to_sym) : false
230
+ def has_field?(*names)
231
+ names.flatten.any? do |name|
232
+ name.respond_to?(:to_sym) ? fields.has_key?(name.to_sym) : false
233
+ end
203
234
  end
204
235
 
205
236
  alias field? has_field?
206
237
 
207
- def inherits?(name)
208
- !has_field(name) && has_parent? && parent.provides?(name)
238
+ def inherits?(*names)
239
+ names.flatten.any? do |name|
240
+ !has_field(name) && has_parent? && parent.provides?(name)
241
+ end
209
242
  end
210
243
 
211
- # Returns true if the Entry has a field (or alias) for the passed-in name.
212
- def provides?(name)
213
- return nil unless name.respond_to?(:to_sym)
214
- has_field?(name) || has_field?(aliases[name.to_sym])
244
+ # Returns true if the Entry has a field (or alias) for any of the passed-in names.
245
+ def provides?(*names)
246
+ names.flatten.any? do |name|
247
+ if name.respond_to?(:to_sym)
248
+ has_field?(name) || has_field?(aliases[name.to_sym])
249
+ else
250
+ false
251
+ end
252
+ end
253
+ end
254
+
255
+ def provides_or_inherits?(*names)
256
+ provides?(names) || inherits?(names)
215
257
  end
216
258
 
217
259
  # Returns the field value referenced by the passed-in name.
@@ -327,6 +369,16 @@ module BibTeX
327
369
  add(name.to_sym, value)
328
370
  end
329
371
 
372
+ # Author, Editor and Translator readers
373
+ NAME_FIELDS.each do |contributor|
374
+ define_method(contributor) do
375
+ get(contributor)
376
+ end
377
+
378
+ alias_method "#{contributor}s", contributor
379
+ end
380
+
381
+
330
382
  # Adds a new field (name-value pair) or multiple fields to the entry.
331
383
  # Returns the entry for chainability.
332
384
  #
@@ -364,6 +416,19 @@ module BibTeX
364
416
  Digest::MD5.hexdigest(field_names(filter).map { |k| [k, fields[k]] }.flatten.join)
365
417
  end
366
418
 
419
+ def identifier
420
+ case
421
+ when provides?(:doi)
422
+ "info:doi/#{get(:doi)}"
423
+ when provides?(:isbn)
424
+ "urn:isbn:#{get(:isbn)}"
425
+ when provides?(:issn)
426
+ "urn:issn:#{get(:issn)}"
427
+ else
428
+ "urn:bibtex:#{key}"
429
+ end
430
+ end
431
+
367
432
  # Called when the element was added to a bibliography.
368
433
  def added_to_bibliography(bibliography)
369
434
  super
@@ -431,6 +496,9 @@ module BibTeX
431
496
 
432
497
  alias parse_months parse_month
433
498
 
499
+ def date
500
+ get(:date) || get(:year)
501
+ end
434
502
 
435
503
  # Parses all name values of the entry. Tries to replace and join the
436
504
  # value prior to parsing.
@@ -494,6 +562,43 @@ module BibTeX
494
562
 
495
563
  alias cross_referenced_by children
496
564
 
565
+ def container_title
566
+ get(:booktitle) || get(:journal) || get(:container)
567
+ end
568
+
569
+ def pages_from
570
+ fetch(:pages, '').split(/\D+/)[0]
571
+ end
572
+
573
+ def pages_to
574
+ fetch(:pages, '').split(/\D+/)[-1]
575
+ end
576
+
577
+ # Returns true if this entry is published inside a book, collection or journal
578
+ def contained?
579
+ has_field?(:booktitle, :container, :journal)
580
+ end
581
+
582
+
583
+ # Returns a duplicate entry with all values converted using the filter.
584
+ # If an optional block is given, only those values will be converted where
585
+ # the block returns true (the block will be called with each key-value pair).
586
+ #
587
+ # @see #convert!
588
+ def convert(filter)
589
+ block_given? ? dup.convert!(filter, &Proc.new) : dup.convert!(filter)
590
+ end
591
+
592
+ # In-place variant of @see #convert
593
+ def convert!(filter)
594
+ fields.each_pair { |k,v| !block_given? || yield(k,v) ? v.convert!(filter) : v }
595
+ self
596
+ end
597
+
598
+ def <=>(other)
599
+ type != other.type ? type <=> other.type : key != other.key ? key <=> other.key : to_s <=> other.to_s
600
+ end
601
+
497
602
 
498
603
  # Returns a string of all the entry's fields.
499
604
  def content(options = {})
@@ -562,24 +667,106 @@ module BibTeX
562
667
  xml
563
668
  end
564
669
 
565
- # Returns a duplicate entry with all values converted using the filter.
566
- # If an optional block is given, only those values will be converted where
567
- # the block returns true (the block will be called with each key-value pair).
568
- #
569
- # @see #convert!
570
- def convert(filter)
571
- block_given? ? dup.convert!(filter, &Proc.new) : dup.convert!(filter)
670
+ # Returns a RDF::Graph representation of the entry using the BIBO ontology.
671
+ # TODO: improve level of detail captured by export
672
+ def to_rdf(options = {})
673
+ require 'rdf'
674
+
675
+ bibo = RDF::Vocabulary.new('http://purl.org/ontology/bibo/')
676
+
677
+ graph = RDF::Graph.new
678
+ entry = RDF::URI.new(identifier)
679
+
680
+ graph << [entry, RDF.type, bibo[BIBO_TYPES[type]]]
681
+
682
+ [:title, :language].each do |key|
683
+ graph << [entry, RDF::DC[key], get(key).to_s] if field?(key)
684
+ end
685
+
686
+ graph << [entry, RDF::DC.date, get(:year).to_s] if field?(:year)
687
+
688
+ if field?(:publisher)
689
+ address = RDF::Vocabulary.new('http://schemas.talis.com/2005/address/schema#')
690
+ pub = RDF::Node.new
691
+
692
+ graph << [pub, RDF.type, RDF::FOAF[:Organization]]
693
+ graph << [pub, RDF::FOAF.name, get(:publisher)]
694
+
695
+ graph << [pub, address[:localityName], get(:address)] if field?(:address)
696
+
697
+ graph << [entry, RDF::DC.published, pub]
698
+ end
699
+
700
+ [:doi, :edition, :volume].each do |key|
701
+ graph << [entry, bibo[key], get(key).to_s] if field?(key)
702
+ end
703
+
704
+ if has_field?(:pages)
705
+ if get(:pages).to_s =~ /^\s*(\d+)\s*-+\s*(\d+)\s*$/
706
+ graph << [entry, bibo[:pageStart], $1]
707
+ graph << [entry, bibo[:pageEnd], $2]
708
+ else
709
+ graph << [entry, bibo[:pages], get(:pages).to_s]
710
+ end
711
+ end
712
+
713
+ if has_field?(:author)
714
+ seq = RDF::Node.new
715
+
716
+ graph << [seq, RDF.type, RDF[:Seq]]
717
+ graph << [entry, bibo[:authorList], seq]
718
+
719
+ authors.each do |author|
720
+ a = RDF::Node.new
721
+
722
+ graph << [a, RDF.type, RDF::FOAF[:Person]]
723
+
724
+ if author.is_a?(Name)
725
+ [:given, :family, :prefix, :suffix].each do |part|
726
+ graph << [a, bibo["#{part}Name"], author.send(part).to_s]
727
+ end
728
+ else
729
+ graph << [a, RDF::FOAF.name, author.to_s]
730
+ end
731
+
732
+ graph << [entry, RDF::DC.creator, a]
733
+ graph << [seq, RDF.li, a]
734
+ end
735
+ end
736
+
737
+ if has_field?(:editor)
738
+ seq = RDF::Node.new
739
+
740
+ graph << [seq, RDF.type, RDF[:Seq]]
741
+ graph << [entry, bibo[:editorList], seq]
742
+
743
+ editors.each do |editor|
744
+ e = RDF::Node.new
745
+
746
+ graph << [e, RDF.type, RDF::FOAF[:Person]]
747
+
748
+ if editor.is_a?(Name)
749
+ [:given, :family, :prefix, :suffix].each do |part|
750
+ graph << [e, bibo["#{part}Name"], editor.send(part).to_s]
751
+ end
752
+ else
753
+ graph << [e, RDF::FOAF.name, editor.to_s]
754
+ end
755
+
756
+ graph << [entry, bibo.editor, a]
757
+ graph << [seq, RDF.li, e]
758
+ end
759
+ end
760
+
761
+ graph
762
+ rescue LoadError
763
+ BibTeX.log.error "Please gem install rdf for RDF support."
572
764
  end
573
765
 
574
- # In-place variant of @see #convert
575
- def convert!(filter)
576
- fields.each_pair { |k,v| !block_given? || yield(k,v) ? v.convert!(filter) : v }
577
- self
578
- end
766
+ alias to_bibo to_rdf
579
767
 
580
- def <=>(other)
581
- type != other.type ? type <=> other.type : key != other.key ? key <=> other.key : to_s <=> other.to_s
582
- end
768
+
769
+
583
770
 
584
771
  private
585
772
 
@@ -594,5 +781,6 @@ module BibTeX
594
781
  k
595
782
  end
596
783
 
784
+
597
785
  end
598
786
  end
@@ -20,6 +20,7 @@ require 'forwardable'
20
20
 
21
21
  module BibTeX
22
22
 
23
+ # A BibTeX Names value is an ordered list of name values.
23
24
  class Names < Value
24
25
  include Enumerable
25
26
 
@@ -27,9 +28,9 @@ module BibTeX
27
28
 
28
29
  def self.parse(string)
29
30
  new(NameParser.new.parse(string))
30
- rescue => e
31
- BibTeX.log.info(e.message)
32
- nil
31
+ rescue => e
32
+ BibTeX.log.info(e.message)
33
+ nil
33
34
  end
34
35
 
35
36
  def initialize(*arguments)
@@ -39,12 +40,16 @@ module BibTeX
39
40
  end
40
41
  end
41
42
 
42
- def replace(*arguments); self; end
43
+ def replace(*arguments)
44
+ self
45
+ end
43
46
 
44
- def join; self; end
47
+ def join
48
+ self
49
+ end
45
50
 
46
- def value
47
- @tokens.join(' and ')
51
+ def value(options = {})
52
+ @tokens.map { |n| n.to_s(options) }.join(' and ')
48
53
  end
49
54
 
50
55
  def to_s(options = {})
@@ -53,14 +58,24 @@ module BibTeX
53
58
  [q[0], value, q[-1]].compact.join
54
59
  end
55
60
 
56
- def name?; true; end
57
- def numeric?; false; end
58
- def atomic?; true; end
61
+ def name?
62
+ true
63
+ end
64
+
65
+ def numeric?
66
+ false
67
+ end
59
68
 
60
- alias :names? :name?
61
- alias :symbol? :numeric?
69
+ def atomic?
70
+ true
71
+ end
62
72
 
63
- def to_name; self; end
73
+ alias names? name?
74
+ alias symbol? numeric?
75
+
76
+ def to_name
77
+ self
78
+ end
64
79
 
65
80
  def to_citeproc(options = {})
66
81
  map { |n| n.to_citeproc(options) }
@@ -82,13 +97,14 @@ module BibTeX
82
97
  self
83
98
  end
84
99
 
85
- alias :<< :add
86
- alias :push :add
100
+ alias << add
101
+ alias push add
87
102
 
88
- # Converts all string values according to the given filter.
89
- def convert! (filter)
90
- tokens.each { |t| t.convert!(filter) }
91
- self
103
+ [:convert!, :rename_if, :rename_unless, :extend_initials].each do |method_id|
104
+ define_method(method_id) do |*arguments|
105
+ tokens.each { |t| t.send(method_id, *arguments) }
106
+ self
107
+ end
92
108
  end
93
109
 
94
110
  def <=>(other)
@@ -97,20 +113,21 @@ module BibTeX
97
113
 
98
114
  end
99
115
 
116
+ # A Name comprises individual name parts (first, last, prefix and suffix),
117
+ # but behaves almost like an atomic string value.
100
118
  class Name < Struct.new(:first, :last, :prefix, :suffix)
101
119
  extend Forwardable
102
-
103
120
  include Comparable
104
-
121
+
105
122
  BibTeXML = {
106
- :first => :first,
107
- :last => :last,
108
- :prefix => :prelast,
109
- :suffix => :lineage
110
- }.freeze
111
-
123
+ :first => :first,
124
+ :last => :last,
125
+ :prefix => :prelast,
126
+ :suffix => :lineage
127
+ }.freeze
128
+
112
129
  def_delegators :to_s, :=~, :===,
113
- *String.instance_methods(false).reject { |m| m =~ /^\W|to_s|replace|each|first|last|!$/ }
130
+ *String.instance_methods(false).reject { |m| m =~ /^\W|to_s|replace|each|first|last|!$/ }
114
131
 
115
132
  class << self
116
133
  def parse(string)
@@ -125,53 +142,114 @@ module BibTeX
125
142
  end
126
143
 
127
144
  def initialize(attributes = {})
128
- attributes.each do |key,value|
129
- send("#{key}=", value) if respond_to?(key)
130
- end
145
+ set(attributes)
131
146
  end
132
147
 
133
148
  def initalize_copy(other)
134
- each_pair { |k,v| self[k] = v }
149
+ each_pair { |k,v| self[k] = v.dup }
150
+ end
151
+
152
+ # Set the name tokens to the values defined in the passed-in hash.
153
+ def set(attributes = {})
154
+ attributes.each do |key, value|
155
+ send("#{key}=", value) if respond_to?(key)
156
+ end
157
+
158
+ self
135
159
  end
136
160
 
137
161
  def blank?
138
162
  to_a.compact.empty?
139
163
  end
164
+
165
+ # Returns the first name (or the passed-in string) as initials.
166
+ def initials(token = first)
167
+ token.to_s.gsub(/([[:upper:]])[[:lower:]]+\s*/, '\1.')
168
+ end
140
169
 
141
- def display_order
142
- [prefix, last, first, suffix].compact.join(' ')
170
+ # Returns true if the first name consists solely of initials.
171
+ def initials?
172
+ !(first.nil? || first.empty? || first.to_s =~ /[[:alpha:]]{2,}[^\.]/)
173
+ end
174
+
175
+ # Sets the name's first name to the passed-in name if the last name equals
176
+ # for_last and the current first name has the same initials as with_first.
177
+ def extend_initials(with_first, for_last)
178
+ rename_if :first => with_first do |name|
179
+ name.last == for_last && name.initials.gsub(/\s+/, '') == initials(with_first).gsub(/\s+/, '')
180
+ end
181
+ end
182
+
183
+ # Renames the tokens according to the passed-in attributes if all of the
184
+ # conditions match or if the given block returns true.
185
+ def rename_if(attributes, conditions = {})
186
+ if block_given?
187
+ set(attributes) if yield self
188
+ else
189
+ set(attributes) if conditions.all? do |key, value|
190
+ respond_to?(key) && send(key) == value
191
+ end
192
+ end
193
+
194
+ self
195
+ end
196
+
197
+ def rename_unless(attributes, conditions = {})
198
+ if block_given?
199
+ set(attributes) unless yield self
200
+ else
201
+ set(attributes) unless conditions.all? do |key, value|
202
+ respond_to?(key) && send(key) == value
203
+ end
204
+ end
205
+
206
+ self
207
+ end
208
+
209
+ # call-seq:
210
+ # name.display_order #=> 'Edgar Allen Poe'
211
+ # name.display_order :initials => true #=> 'E.A. Poe'
212
+ #
213
+ # Returns the name as a string in display order.
214
+ def display_order(options = {})
215
+ [options[:initials] ? initials : first, prefix, last, suffix].compact.join(' ')
143
216
  end
144
217
 
145
218
  alias display display_order
146
219
 
147
- def sort_order
148
- [[prefix,last].compact.join(' '), suffix, first].compact.join(', ')
220
+ # call-seq:
221
+ # name.sort_order #=> 'Poe, Edgar Allen'
222
+ # name.sort_order :initials => true #=> 'Poe, E.A.'
223
+ #
224
+ # Returns the name as a string in sort order.
225
+ def sort_order(options = {})
226
+ [[prefix, last].compact.join(' '), suffix, options[:initials] ? initials : first].compact.join(', ')
149
227
  end
150
228
 
151
229
  alias to_s sort_order
152
-
230
+
153
231
  def <=>(other)
154
- other.is_a?(Name) ? [last, prefix, first, suffix].compact.join(' ') <=> [other.last, other.prefix, other.first, other.suffix].compact.join(' ') : super
232
+ other.is_a?(Name) ? sort_order <=> other.sort_order : super
155
233
  end
156
234
 
157
235
  def to_hash
158
236
  Hash[each_pair.to_a]
159
237
  end
160
238
 
161
- def to_xml
162
- require 'rexml/document'
163
- xml = REXML::Element.new('bibtex:person')
239
+ def to_xml
240
+ require 'rexml/document'
241
+ xml = REXML::Element.new('bibtex:person')
164
242
 
165
- each_pair do |part, text|
166
- unless text.nil?
167
- element = REXML::Element.new("bibtex:#{BibTeXML[part]}")
168
- element.text = text
169
- xml.add_element(element)
170
- end
171
- end
172
-
173
- xml
174
- end
243
+ each_pair do |part, text|
244
+ unless text.nil?
245
+ element = REXML::Element.new("bibtex:#{BibTeXML[part]}")
246
+ element.text = text
247
+ xml.add_element(element)
248
+ end
249
+ end
250
+
251
+ xml
252
+ end
175
253
 
176
254
  [:strip!, :upcase!, :downcase!, :sub!, :gsub!, :chop!, :chomp!, :rstrip!].each do |method_id|
177
255
  define_method(method_id) do |*arguments, &block|
@@ -182,20 +260,20 @@ module BibTeX
182
260
  end
183
261
  end
184
262
 
185
- def convert(filter)
186
- dup.convert!(filter)
187
- end
188
-
189
- def convert!(filter)
190
- if f = Filters.resolve(filter)
191
- each_pair { |k,v| self[k] = f.apply(v) unless v.nil? }
192
- else
193
- raise ArgumentError, "Failed to load filter #{filter.inspect}"
194
- end
263
+ def convert(filter)
264
+ dup.convert!(filter)
265
+ end
266
+
267
+ def convert!(filter)
268
+ if f = Filters.resolve(filter)
269
+ each_pair { |k,v| self[k] = f.apply(v) unless v.nil? }
270
+ else
271
+ raise ArgumentError, "Failed to load filter #{filter.inspect}"
272
+ end
195
273
 
196
- self
197
- end
198
-
274
+ self
275
+ end
276
+
199
277
  def to_citeproc(options = {})
200
278
  hash = {}
201
279
  hash['family'] = family unless family.nil?
@@ -213,6 +291,6 @@ module BibTeX
213
291
  alias jr= suffix=
214
292
  alias von prefix
215
293
  alias von= prefix=
216
-
294
+
217
295
  end
218
296
  end
@@ -18,6 +18,6 @@
18
18
 
19
19
  module BibTeX
20
20
  module Version
21
- STRING = '2.0.7'.freeze
21
+ STRING = '2.0.8'.freeze
22
22
  end
23
23
  end
@@ -71,6 +71,20 @@ module BibTeX
71
71
  END
72
72
  end
73
73
 
74
+ describe '#entries_at' do
75
+ it 'returns a list of all entries identified by the passed-in keys' do
76
+ assert_equal [@bib['segaran2007'], @bib['rails']], @bib.entries_at('segaran2007', :rails)
77
+ end
78
+ end
79
+
80
+ describe '#extend_initials' do
81
+ it 'extends the initials in matching names' do
82
+ @bib.names.map(&:to_s).wont_include 'Flanagan, Dave'
83
+ @bib.extend_initials(['Dave', 'Flanagan'])
84
+ @bib.names.map(&:to_s).must_include 'Flanagan, Dave'
85
+ end
86
+ end
87
+
74
88
  it 'supports access by index' do
75
89
  assert_equal 'ruby', @bib[1].keywords
76
90
  end
@@ -5,6 +5,10 @@ require 'helper'
5
5
  module BibTeX
6
6
  class NamesTest < MiniTest::Spec
7
7
 
8
+ before do
9
+ @poe = Name.new(:first => 'Edgar Allen', :last => 'Poe')
10
+ end
11
+
8
12
  describe 'string behaviour' do
9
13
  before do
10
14
  @name = Name.new(:first => 'Charles Louis Xavier Joseph', :prefix => 'de la', :last => 'Vallee Poussin', :suffix => 'Jr.')
@@ -18,7 +22,85 @@ module BibTeX
18
22
  it 'should implement gsub!' do
19
23
  assert_equal 'dX la VallXX PoussXn, Jr., CharlXs LouXs XavXXr JosXph', @name.gsub!(/[ei]/, 'X').to_s
20
24
  end
25
+ end
26
+
27
+ describe '#display_order' do
28
+ it 'returns the name as "first last"' do
29
+ @poe.display_order.must_be :==, 'Edgar Allen Poe'
30
+ end
31
+
32
+ it 'accepts the :initials option' do
33
+ @poe.display_order(:initials => true).must_be :==, 'E.A. Poe'
34
+ end
35
+ end
36
+
37
+ describe '#sort_order' do
38
+ it 'returns the name as "last, first"' do
39
+ @poe.sort_order.must_be :==, 'Poe, Edgar Allen'
40
+ end
41
+
42
+ it 'accepts the :initials option' do
43
+ @poe.sort_order(:initials => true).must_be :==, 'Poe, E.A.'
44
+ end
45
+ end
46
+
47
+ describe '#initials?' do
48
+ it 'returns true if the name contains a solely initials as a first name' do
49
+ @poe.initials?.must_equal false
50
+
51
+ @poe.first = 'Edgar A.'
52
+ @poe.initials?.must_equal false
53
+
54
+ @poe.first = 'E.A.'
55
+ @poe.initials?.must_equal true
56
+
57
+ @poe.first = ''
58
+ @poe.initials?.must_equal false
59
+
60
+ @poe.first = nil
61
+ @poe.initials?.must_equal false
62
+ end
63
+ end
64
+
65
+ describe '#rename_if' do
66
+ it 'renames the name to the given attributes if no condition is given' do
67
+ @poe.rename_if({ :first => 'E.A.' }).first.must_equal 'E.A.'
68
+ end
69
+
70
+ it 'renames the name to the given attributes if all conditions match' do
71
+ @poe.rename_if({ :first => 'E.A.' }, { :last => @poe.last }).first.must_equal 'E.A.'
72
+ @poe.rename_if({ :first => 'E.A.' }, { :last => @poe.last, :first => @poe.first }).first.must_equal 'E.A.'
73
+ end
74
+
75
+ it 'renames the name to the given attributes if the block returns true' do
76
+ @poe.rename_if({ :first => 'E.A.' }) {|n| true}.first.must_equal 'E.A.'
77
+ end
78
+
79
+ it 'does not rename the name to the given attributes if at least one condition does not match' do
80
+ @poe.rename_if({ :first => 'E.A.' }, { :last => 'foo' }).first.wont_equal 'E.A.'
81
+ @poe.rename_if({ :first => 'E.A.' }, { :last => 'foo', :first => @poe.first }).first.wont_equal 'E.A.'
82
+ @poe.rename_if({ :first => 'E.A.' }, { :last => @poe.last, :first => 'foo' }).first.wont_equal 'E.A.'
83
+ end
84
+
85
+ it 'does not rename the name to the given attributes if the block returns false' do
86
+ @poe.rename_if({ :first => 'E.A.' }) {|n| false}.first.wont_equal 'E.A.'
87
+ end
88
+ end
89
+
90
+ describe '#extend_initials' do
91
+ it 'extends the first name if the last name and initials match' do
92
+ Name.new(:first => 'E.A.', :last => 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
93
+ Name.new(:first => 'Edgar A.', :last => 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
94
+ Name.new(:first => 'E. A.', :last => 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
95
+ Name.new(:first => 'E. Allen', :last => 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
96
+ Name.new(:first => 'E.A.', :last => 'Poe').extend_initials('Edgar A.', 'Poe').first.must_equal 'Edgar A.'
97
+ end
21
98
 
99
+ it 'does not extend the first name if the last name or initials do not match' do
100
+ Name.new(:first => 'E.A.', :last => 'Poe').extend_initials('Edgar Allen', 'Poser').first.wont_equal 'Edgar Allen'
101
+ Name.new(:first => 'E.A.', :last => 'Poe').extend_initials('Edgar Ellen', 'Poe').first.wont_equal 'Edgar Ellen'
102
+ Name.new(:first => 'E.R.', :last => 'Poe').extend_initials('Edgar Allen', 'Poe').first.wont_equal 'Edgar Allen'
103
+ end
22
104
  end
23
105
 
24
106
  describe "conversions" do
@@ -39,8 +121,8 @@ module BibTeX
39
121
  Names.parse("S{\\o}ren Kirkegaard and Emmanuel L\\'evinas").convert(:latex).to_s.must_be :==, 'Kirkegaard, Søren and Lévinas, Emmanuel'
40
122
  end
41
123
  end
42
-
43
124
  end
44
125
 
45
126
  end
127
+
46
128
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bibtex-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.7
4
+ version: 2.0.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-30 00:00:00.000000000 Z
12
+ date: 2012-05-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: latex-decode
16
- requirement: &70149186709340 !ruby/object:Gem::Requirement
16
+ requirement: &70229986220740 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.0.6
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70149186709340
24
+ version_requirements: *70229986220740
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: multi_json
27
- requirement: &70149186708580 !ruby/object:Gem::Requirement
27
+ requirement: &70229986220220 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '1.3'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70149186708580
35
+ version_requirements: *70229986220220
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &70149186708040 !ruby/object:Gem::Requirement
38
+ requirement: &70229986219680 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0.9'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70149186708040
46
+ version_requirements: *70229986219680
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: racc
49
- requirement: &70149186707340 !ruby/object:Gem::Requirement
49
+ requirement: &70229986219200 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '1.4'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70149186707340
57
+ version_requirements: *70229986219200
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rdoc
60
- requirement: &70149186706200 !ruby/object:Gem::Requirement
60
+ requirement: &70229986218720 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '3.9'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70149186706200
68
+ version_requirements: *70229986218720
69
69
  description: ! "\t\tBibTeX-Ruby is the Rubyist's swiss-army-knife for all things BibTeX.
70
70
  It\n includes a parser for all common BibTeX objects (@string, @preamble,\n @comment
71
71
  and regular entries) and a sophisticated name parser that\n tokenizes correctly
@@ -180,12 +180,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
180
180
  - - ! '>='
181
181
  - !ruby/object:Gem::Version
182
182
  version: '0'
183
+ segments:
184
+ - 0
185
+ hash: -4363834808819370688
183
186
  required_rubygems_version: !ruby/object:Gem::Requirement
184
187
  none: false
185
188
  requirements:
186
189
  - - ! '>='
187
190
  - !ruby/object:Gem::Version
188
191
  version: '0'
192
+ segments:
193
+ - 0
194
+ hash: -4363834808819370688
189
195
  requirements: []
190
196
  rubyforge_project:
191
197
  rubygems_version: 1.8.10