bibtex-ruby 1.1.2 → 1.2.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/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