bibtex-ruby 1.1.2 → 1.2.0

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/examples/bib2html.rb CHANGED
@@ -3,7 +3,7 @@ require 'bibtex'
3
3
 
4
4
 
5
5
  # Open a bibliography file
6
- bib = BibTeX::Bibliography.open(File.expand_path('../markdown.bib',__FILE__),
6
+ bib = BibTeX.open(File.expand_path('../markdown.bib',__FILE__),
7
7
  :include => [:meta_comments])
8
8
 
9
9
 
@@ -13,7 +13,7 @@ content = bib.data.map do |d|
13
13
 
14
14
  if d.class == BibTeX::Entry
15
15
  d.replace!(bib.strings)
16
- result = [d[:author], '. ', d[:title], '. ', d[:publisher], ': ', d[:address], ', ', d[:year], '.'].join
16
+ result = [d.author, '. ', d.title, '. ', d.publisher, ': ', d.address, ', ', d.year, '.'].join
17
17
  end
18
18
 
19
19
  if d.class == BibTeX::MetaComment
data/examples/bib2yaml.rb CHANGED
@@ -8,5 +8,5 @@ if ARGV.length < 1
8
8
  puts "Usage: #{$0} <bib> [<yml>]"
9
9
  else
10
10
  out = ARGV.length == 2 ? File.open(ARGV[1], 'w') : STDOUT
11
- out.puts BibTeX::Bibliography.open(ARGV[0]).to_yaml
11
+ out.puts BibTeX.open(ARGV[0]).to_yaml
12
12
  end
data/lib/bibtex.rb CHANGED
@@ -43,11 +43,16 @@ module BibTeX
43
43
  Log.level = ENV.has_key?('DEBUG') ? Logger::DEBUG : Logger::WARN
44
44
  Log.datetime_format = "%Y-%m-%d %H:%M:%S"
45
45
 
46
- require 'bibtex/string_replacement'
46
+ # Load debugger
47
+ # require 'ruby-debug'
48
+ # Debugger.start
49
+
50
+ require 'bibtex/extensions'
47
51
  require 'bibtex/elements'
48
52
  require 'bibtex/entry'
49
53
  require 'bibtex/error'
50
54
  require 'bibtex/parser'
51
55
  require 'bibtex/bibliography'
56
+ require 'bibtex/utilities'
52
57
 
53
58
  end
@@ -39,7 +39,7 @@ module BibTeX
39
39
  end
40
40
 
41
41
  #
42
- # Creates a new bibliography; empty if no path is specified, otherwise
42
+ # Creates a new bibliography; empty if no data attribute is specified, otherwise
43
43
  # by parsing the file at the given path.
44
44
  #
45
45
  def initialize(data=[])
@@ -53,8 +53,8 @@ module BibTeX
53
53
 
54
54
  # Adds a new element, or a list of new elements to the bibliography.
55
55
  def add(data)
56
- raise(ArgumentError,'BibTeX::Bibliography.add data expected to be enumerable or of type BibTeX::Element; was: ' + data.class.name) unless data.respond_to?(:each) || data.kind_of?(Element)
57
- data.kind_of?(Element) ? self << data : data.each { |d| self << d }
56
+ raise(ArgumentError,'BibTeX::Bibliography.add data expected to be enumerable or of type BibTeX::Element; was: ' + data.class.name) unless data.respond_to?(:each) || data.is_a?(Element)
57
+ data.is_a?(Element) ? self << data : data.each { |d| self << d }
58
58
  self
59
59
  end
60
60
 
@@ -70,7 +70,7 @@ module BibTeX
70
70
 
71
71
  # Add an object to the bibliography. Returns the bibliography.
72
72
  def <<(obj)
73
- raise(ArgumentError, 'A BibTeX::Bibliography can contain only BibTeX::Elements; was: ' + obj.class.name) unless obj.kind_of?(Element)
73
+ raise(ArgumentError, 'A BibTeX::Bibliography can contain only BibTeX::Elements; was: ' + obj.class.name) unless obj.is_a?(Element)
74
74
  @data << obj.added_to_bibliography(self)
75
75
  self
76
76
  end
@@ -95,7 +95,7 @@ module BibTeX
95
95
  def [](key)
96
96
  @entries[key.to_s]
97
97
  end
98
-
98
+
99
99
  # Returns all @comment objects.
100
100
  def comments
101
101
  find_by_type(BibTeX::Comment)
@@ -116,6 +116,12 @@ module BibTeX
116
116
  !errors.empty?
117
117
  end
118
118
 
119
+ # Returns true if the +Bibliography+ contains no errors and only
120
+ # valid BibTeX objects (meta comments are ignored).
121
+ def valid?
122
+ !errors? && !@entries.values.map(&:valid?).uniq.include?(false)
123
+ end
124
+
119
125
  # Replaces all string constants which are defined in the bibliography.
120
126
  #
121
127
  # By default constants in @string, @preamble and entries are defined; this
@@ -134,6 +140,11 @@ module BibTeX
134
140
  find_by_type(options[:include]).each { |e| e.replace!(@strings) if e.respond_to?(:replace!)}
135
141
  end
136
142
 
143
+ def join_strings(options={})
144
+ options[:include] ||= [BibTeX::String, BibTeX::Preamble, BibTeX::Entry]
145
+ find_by_type(options[:include]).each { |e| e.join! if e.respond_to?(:join!)}
146
+ end
147
+
137
148
  # Returns true if the bibliography is currently empty.
138
149
  def empty?
139
150
  @data.empty?
@@ -144,6 +155,11 @@ module BibTeX
144
155
  @data.length
145
156
  end
146
157
 
158
+ # Returns the bibliography as an array of +BibTeX::Element+
159
+ def to_a
160
+ @data
161
+ end
162
+
147
163
  # Returns a string representation of the bibliography.
148
164
  def to_s
149
165
  @data.map(&:to_s).join
@@ -172,9 +188,9 @@ module BibTeX
172
188
  private
173
189
 
174
190
  def find_by_type(type)
175
- @data.find_all { |x| type.respond_to?(:inject) ? type.inject(false) { |s,n| s || x.kind_of?(n) } : x.kind_of?(type) }
191
+ @data.find_all { |x| type.respond_to?(:inject) ? type.inject(false) { |s,n| s || x.is_a?(n) } : x.is_a?(type) }
176
192
  end
177
-
193
+
178
194
  def find_entry(key)
179
195
  entries.find { |e| e.key == key.to_s }
180
196
  end
data/lib/bibtex/bibtex.y CHANGED
@@ -66,7 +66,7 @@ rule
66
66
  | entry_head assignments COMMA RBRACE { result = val[0] << val[1] }
67
67
  | entry_head RBRACE { result = val[0] }
68
68
 
69
- entry_head : NAME LBRACE key COMMA { result = BibTeX::Entry.new(val[0].downcase.to_sym,val[2]) }
69
+ entry_head : NAME LBRACE key COMMA { result = BibTeX::Entry.new(:type => val[0].downcase.to_sym, :key => val[2]) }
70
70
 
71
71
  key : NAME { result = val[0] }
72
72
  | NUMBER { result = val[0] }
@@ -16,9 +16,6 @@
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  #++
18
18
 
19
- require 'rexml/document'
20
- require 'yaml'
21
-
22
19
  module BibTeX
23
20
 
24
21
  #
@@ -28,6 +25,11 @@ module BibTeX
28
25
 
29
26
  attr_reader :bibliography
30
27
 
28
+ # Returns an array of BibTeX elements.
29
+ def self.parse(string, options={})
30
+ BibTeX::Parser.new(options).parse(string).to_a
31
+ end
32
+
31
33
  def initialize
32
34
  @bibliography = nil
33
35
  end
@@ -47,7 +49,8 @@ module BibTeX
47
49
  end
48
50
 
49
51
  def to_yaml
50
- self.to_hash.to_yaml
52
+ require 'yaml'
53
+ self.to_hash.to_yaml
51
54
  end
52
55
 
53
56
  def to_json
@@ -56,6 +59,7 @@ module BibTeX
56
59
  end
57
60
 
58
61
  def to_xml
62
+ require 'rexml/document'
59
63
  xml = REXML::Element.new(self.class.name.downcase)
60
64
  xml.text = self.content
61
65
  xml
@@ -85,8 +89,8 @@ module BibTeX
85
89
  # @string and @preamble objects, as well as in field values
86
90
  # of regular entries.
87
91
  #
88
- class String < Element
89
- attr_reader :key, :value
92
+ class String < Element
93
+ attr_reader :key
90
94
 
91
95
  # Creates a new instance.
92
96
  def initialize(key=nil,value=nil)
@@ -96,28 +100,32 @@ module BibTeX
96
100
 
97
101
  # Sets the string's key (i.e., the name of the constant)
98
102
  def key=(key)
99
- raise(ArgumentError, "BibTeX::String key must be of type Symbol; was: #{key.class.name}.") unless key.kind_of?(Symbol)
103
+ raise(ArgumentError, "BibTeX::String key must be of type Symbol; was: #{key.class.name}.") unless key.is_a?(Symbol)
100
104
  @key = key
101
105
  end
102
106
 
103
107
  # Sets the string's value (i.e., the string literal defined by the constant)
104
108
  def value=(value)
105
- raise(ArgumentError, "BibTeX::String value must be of type Array, Symbol, or String; was: #{value.class.name}.") unless [Array,::String,Symbol].map { |k| value.kind_of?(k) }.inject { |sum,n| sum || n }
106
- @value = value.kind_of?(Array) ? value : [value]
109
+ raise(ArgumentError, "BibTeX::String value must be of type Array, Symbol, or String; was: #{value.class.name}.") unless [Array,::String,Symbol].map { |k| value.is_a?(k) }.inject { |sum,n| sum || n }
110
+ @value = Extensions.string_replacement(value.is_a?(Array) ? value : [value])
107
111
  end
108
-
109
- # Replaces all constants in this string's value which are defined in +hsh+.
112
+
113
+ def value
114
+ @value.to_s(:quotes => %w(" "))
115
+ end
116
+
117
+ # Replaces all constants in this string's value which are defined in +hash+.
110
118
  # Returns the new value (the @string object itself remains unchanged).
111
119
  #
112
120
  # call-seq:
113
121
  # s.to_s
114
122
  # => "@string{ foobar = foo # "bar"}"
115
- # s.replace({:foo => 'foo'})
116
- # => ["foo","bar"]
123
+ # s.replace({:foo => 'bar'})
124
+ # => "\"bar\" # \"bar\""
117
125
  # s.to_s
118
126
  # => "@string{ foobar = foo # "bar"}"
119
- def replace(hsh)
120
- StringReplacement.replace(@value,hsh)
127
+ def replace(hash)
128
+ @value.replace_strings(hash)
121
129
  end
122
130
 
123
131
  # Replaces all constants in this string's value which are defined in +hsh+.
@@ -126,19 +134,24 @@ module BibTeX
126
134
  # call-seq:
127
135
  # s.to_s
128
136
  # => "@string{ foobar = foo # "bar"}"
129
- # s.replace({:foo => 'foo'})
130
- # => ["foo","bar"]
137
+ # s.replace({:foo => 'bar'})
138
+ # => ["bar","bar"]
131
139
  # s.to_s
132
- # => "@string{ foobar = "foo" # "bar"}"
133
- def replace!(hsh)
134
- @value = replace(hsh)
135
- @bibliography.strings[@key] = value unless @bibliography.nil?
140
+ # => "@string{ foobar = "bar" # "bar"}"
141
+ def replace!(hash)
142
+ @value = @value.replace_strings(hash)
143
+ @bibliography.strings[@key] = @value unless @bibliography.nil?
136
144
  end
137
145
 
146
+ def join!
147
+ @value = @value.join_strings
148
+ @bibliography.strings[@key] = @value unless @bibliography.nil?
149
+ end
150
+
138
151
  # Adds either a string constant or literal to the current value. The
139
152
  # values will be concatenated using the `#' symbol.
140
153
  def <<(value)
141
- raise(ArgumentError, "BibTeX::String value can contain only instances of Symbol or String; was: #{value.class.name}.") unless [::String,Symbol].map { |k| value.kind_of?(k) }.inject { |sum,n| sum || n }
154
+ raise(ArgumentError, "BibTeX::String value can contain only instances of Symbol or String; was: #{value.class.name}.") unless [::String,Symbol].map { |k| value.is_a?(k) }.inject { |sum,n| sum || n }
142
155
  @value << value
143
156
  end
144
157
 
@@ -158,16 +171,16 @@ module BibTeX
158
171
 
159
172
  # Returns a string representation of the @string's content.
160
173
  def content
161
- [@key.to_s,' = ',StringReplacement.to_s(@value)].join
174
+ [@key.to_s, value].join(' = ')
162
175
  end
163
176
 
164
177
  # Returns a string representation of the @string object.
165
178
  def to_s
166
- ['@string{ ',content,'}'].join
179
+ "@string{ #{content} }"
167
180
  end
168
181
 
169
182
  def to_hash
170
- { 'string' => { @key.to_s => StringReplacement.to_s(@value) } }
183
+ { 'string' => { @key.to_s => @value.to_s(:quotes => %w(" ")) } }
171
184
  end
172
185
 
173
186
  def to_xml
@@ -175,7 +188,7 @@ module BibTeX
175
188
  key = REXML::Element.new('key')
176
189
  val = REXML::Element.new('value')
177
190
  key.text = @key.to_s
178
- val.text = @value.to_s
191
+ val.text = @value.to_s(:quotes => %w(" "))
179
192
  xml
180
193
  end
181
194
  end
@@ -187,40 +200,43 @@ module BibTeX
187
200
  # a single constant, or a concatenation of string literals and
188
201
  # constants.
189
202
  class Preamble < Element
190
- attr_reader :value
191
-
203
+
192
204
  # Creates a new instance.
193
205
  def initialize(value=[])
194
206
  self.value = value
195
207
  end
196
208
 
197
209
  def value=(value)
198
- raise(ArgumentError, "BibTeX::Preamble value must be of type Array, Symbol, or String; was: #{value.class.name}.") unless [Array,::String,Symbol].map { |k| value.kind_of?(k) }.inject { |sum,n| sum || n }
199
- @value = value.kind_of?(Array) ? value : [value]
210
+ raise(ArgumentError, "BibTeX::Preamble value must be of type Array, Symbol, or String; was: #{value.class.name}.") unless [Array,::String,Symbol].map { |k| value.is_a?(k) }.inject { |sum,n| sum || n }
211
+ @value = Extensions.string_replacement(value.is_a?(Array) ? value : [value])
200
212
  end
201
213
 
202
- def replace(hsh)
203
- StringReplacement.replace(@value,hsh)
214
+ def replace(hash)
215
+ @value.replace_strings(hash)
204
216
  end
205
217
 
206
- def replace!(hsh)
207
- @value = replace(hsh)
208
- @bibliography.strings[@key] = @value unless @bibliography.nil?
218
+ def replace!(hash)
219
+ @value = @value.replace_strings(hash)
209
220
  end
210
221
 
222
+ def join!
223
+ @value = @value.join_strings
224
+ end
225
+
226
+ def value
227
+ content
228
+ end
229
+
211
230
  # Returns a string representation of the @preamble's content.
212
231
  def content
213
- StringReplacement.to_s(@value)
232
+ @value.to_s(:quotes => %w(" "))
214
233
  end
215
234
 
216
235
  # Returns a string representation of the @preamble object
217
236
  def to_s
218
- ['@preamble{ ',content,'}'].join
237
+ "@preamble{ #{ content } }"
219
238
  end
220
239
 
221
- def to_hash
222
- { 'preamble' => StringReplacement.to_s(@value) }
223
- end
224
240
  end
225
241
 
226
242
  # Represents a @comment object.
@@ -231,7 +247,7 @@ module BibTeX
231
247
  end
232
248
 
233
249
  def content=(content)
234
- raise(ArgumentError, "BibTeX::#{self.class.name} content must be of type String; was: #{content.class.name}.") unless content.kind_of?(::String)
250
+ raise(ArgumentError, "BibTeX::#{self.class.name} content must be of type String; was: #{content.class.name}.") unless content.is_a?(::String)
235
251
  @content = content
236
252
  end
237
253
 
data/lib/bibtex/entry.rb CHANGED
@@ -21,6 +21,7 @@ module BibTeX
21
21
  # Represents a regular BibTeX entry.
22
22
  #
23
23
  class Entry < Element
24
+
24
25
  attr_reader :key, :type, :fields
25
26
 
26
27
  # Hash containing the required fields of the standard entry types
@@ -42,28 +43,30 @@ module BibTeX
42
43
  :unpublished => [:author,:title,:note]
43
44
  })
44
45
 
45
- # Creates a new instance of a given +type+ (e.g., :article, :book, etc.)
46
- # identified by a +key+.
47
- def initialize(type=nil, key=nil)
48
- self.key = key.to_s unless key.nil?
49
- self.type = type.to_sym unless type.nil?
46
+ # Creates a new instance. If a hash is given, the entry is populated accordingly.
47
+ def initialize(hash={})
50
48
  @fields = {}
49
+
50
+ self.type = hash.delete(:type) if hash.has_key?(:type)
51
+ self.key = hash.delete(:key) if hash.has_key?(:key)
52
+
53
+ hash.each { |k, v| add(k.to_sym, v) }
51
54
  end
52
55
 
53
56
  # Sets the key of the entry
54
57
  def key=(key)
55
- raise(ArgumentError, "BibTeX::Entry key must be of type String; was: #{key.class.name}.") unless key.kind_of?(::String)
58
+ raise(ArgumentError, "BibTeX::Entry key must be of type String; was: #{key.class.name}.") unless key.is_a?(::String)
56
59
  @key = key
57
60
  end
58
61
 
59
62
  # Sets the type of the entry.
60
63
  def type=(type)
61
- raise(ArgumentError, "BibTeX::Entry type must be of type Symbol; was: #{type.class.name}.") unless type.kind_of?(Symbol)
64
+ raise(ArgumentError, "BibTeX::Entry type must be of type Symbol; was: #{type.class.name}.") unless type.is_a?(Symbol)
62
65
  @type = type
63
66
  end
64
67
 
65
68
  def method_missing(name, *args)
66
- return @fields[name]if @fields.has_key?(name)
69
+ return self[name] if @fields.has_key?(name)
67
70
  return self.send(:add, name.to_s.chop.to_sym, args[0]) if name.match(/=$/)
68
71
  super
69
72
  end
@@ -74,21 +77,21 @@ module BibTeX
74
77
 
75
78
  # Returns the value of the field with the given name.
76
79
  def [](name)
77
- @fields[name.to_sym]
80
+ @fields[name.to_sym].to_s
78
81
  end
79
82
 
80
83
  # Adds a new field (name-value pair) to the entry.
81
84
  # Returns the new value.
82
- def []=(name,value)
83
- add(name,value)
85
+ def []=(name, value)
86
+ add(name.to_sym, value)
84
87
  end
85
88
 
86
89
  # Adds a new field (name-value pair) to the entry.
87
90
  # Returns the new value.
88
- def add(name,value)
89
- raise(ArgumentError, "BibTeX::Entry field name must be of type Symbol; was: #{name.class.name}.") unless name.kind_of?(Symbol)
90
- raise(ArgumentError, "BibTeX::Entry field value must be of type Array, Symbol, or String; was: #{value.class.name}.") unless [Array,::String,Symbol].map { |k| value.kind_of?(k) }.inject { |sum,n| sum || n }
91
- @fields[name] = value.kind_of?(Array) ? value : [value]
91
+ def add(name, value)
92
+ raise(ArgumentError, "BibTeX::Entry field name must be of type Symbol; was: #{name.class.name}.") unless name.is_a?(Symbol)
93
+ raise(ArgumentError, "BibTeX::Entry field value must be of type Array, Symbol, or String; was: #{value.class.name}.") unless [Array,::String,Symbol].map { |k| value.is_a?(k) }.inject { |sum,n| sum || n }
94
+ @fields[name] = Extensions.string_replacement(value.is_a?(Array) ? value : [value])
92
95
  end
93
96
 
94
97
  # Removes the field with a given name from the entry.
@@ -99,7 +102,7 @@ module BibTeX
99
102
 
100
103
  # Adds all the fields contained in a given hash to the entry.
101
104
  def <<(fields)
102
- raise(ArgumentError, "BibTeX::Entry fields must be of type Hash; was: #{fields.class.name}.") unless fields.kind_of?(Hash)
105
+ raise(ArgumentError, "BibTeX::Entry fields must be of type Hash; was: #{fields.class.name}.") unless fields.is_a?(Hash)
103
106
  fields.each { |n,v| add(n,v) }
104
107
  self
105
108
  end
@@ -113,7 +116,7 @@ module BibTeX
113
116
  # definitions of all the required fields for that type.
114
117
  def valid?
115
118
  !@@RequiredFields[@type].map { |f|
116
- f.kind_of?(Array) ? !(f & @fields.keys).empty? : !@fields[f].nil?
119
+ f.is_a?(Array) ? !(f & @fields.keys).empty? : !@fields[f].nil?
117
120
  }.include?(false)
118
121
  end
119
122
 
@@ -131,14 +134,18 @@ module BibTeX
131
134
  self
132
135
  end
133
136
 
134
- # Replaces all constants in this entry's field values which are defined in +hsh+.
135
- def replace!(hsh)
136
- @fields.keys.each { |k| @fields[k] = StringReplacement.replace(@fields[k],hsh) }
137
+ # Replaces all constants in this entry's field values which are defined in +hash+.
138
+ def replace!(hash)
139
+ @fields.keys.each { |k| @fields[k] = @fields[k].replace_strings(hash) }
137
140
  end
138
141
 
142
+ def join!
143
+ @fields.keys.each { |k| @fields[k] = @fields[k].join_strings }
144
+ end
145
+
139
146
  # Returns a string of all the entry's fields.
140
147
  def content
141
- @fields.keys.map { |k| "#{k} = #{StringReplacement.to_s(@fields[k], :delimiter => ['{','}'])}" }.join(",\n")
148
+ @fields.keys.map { |k| "#{k} = #{ @fields[k].to_s(:quotes => %w({ })) }" }.join(",\n")
142
149
  end
143
150
 
144
151
  # Returns a string representation of the entry.
@@ -146,8 +153,9 @@ module BibTeX
146
153
  ["@#{type}{#{key},",content.gsub(/^/,' '),"}\n"].join("\n")
147
154
  end
148
155
 
149
- def to_hash
150
- @fields.keys.map { |k| { k.to_s => StringReplacement.to_s(@fields[k], :delimiter => ['{','}']) } }.inject({ 'key' => @key, 'type' => @type.to_s }) { |sum,n| sum.merge(n) }
156
+ def to_hash(options={})
157
+ options[:quotes] ||= %w({ })
158
+ @fields.keys.map { |k| { k.to_s => @fields[k].to_s(options) } }.inject({ 'key' => @key, 'type' => @type.to_s }) { |sum,n| sum.merge(n) }
151
159
  end
152
160
 
153
161
  def to_xml
@@ -155,7 +163,7 @@ module BibTeX
155
163
  xml.attributes['key'] = @key
156
164
  @fields.each do |k,v|
157
165
  e = REXML::Element.new(k.to_s)
158
- e.text = StringReplacement.to_s(v, :delimiter => ['',''])
166
+ e.text = v.to_s
159
167
  xml.add_element(e)
160
168
  end
161
169
  xml