bibtex-ruby 2.0.12 → 2.1.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/Rakefile CHANGED
@@ -1,21 +1,24 @@
1
- # -*- ruby -*-
2
- lib = File.expand_path('../lib/', __FILE__)
3
- $:.unshift lib unless $:.include?(lib)
1
+ # encoding: utf-8
2
+
3
+ require 'bundler'
4
+ begin
5
+ Bundler.setup
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ $:.unshift(File.join(File.dirname(__FILE__), './lib'))
13
+
4
14
 
5
15
  require 'rake/clean'
6
16
  require 'rake/testtask'
7
17
 
8
- require 'rdoc/task'
9
-
10
18
  require 'bibtex/version'
11
19
 
12
- RDoc::Task.new(:rdoc => ['clean','racc']) do |rd|
13
- rd.main = 'README.md'
14
- rd.title = "BibTeX-Ruby Documentation"
15
- rd.rdoc_files.include('README.md',"lib/**/*.rb")
16
- rd.rdoc_dir = "doc/html"
17
- rd.options << '--webcvs=http://github.com/inukshuk/bibtex-ruby/tree/master/'
18
- end
20
+ require 'yard'
21
+ YARD::Rake::YardocTask.new
19
22
 
20
23
  Rake::TestTask.new(:test_task) do |t|
21
24
  t.libs << 'lib' << 'test'
@@ -31,12 +34,12 @@ begin
31
34
  rescue LoadError
32
35
  desc 'Cucumber rake task not available'
33
36
  task :features do
34
- abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
37
+ abort 'Cucumber rake task is not available. Please install cucumber as a gem or plugin'
35
38
  end
36
39
  end
37
40
 
38
41
 
39
- task :default => ['racc']
42
+ task :default => [:test, :features]
40
43
 
41
44
  desc 'Generates the BibTeX parser'
42
45
  task :racc => ['lib/bibtex/parser.rb','lib/bibtex/name_parser.rb']
@@ -54,6 +57,18 @@ file 'lib/bibtex/name_parser.rb' => ['lib/bibtex/names.y'] do
54
57
  sh 'bundle exec racc -o lib/bibtex/name_parser.rb lib/bibtex/names.y'
55
58
  end
56
59
 
60
+ desc 'Run an IRB session with BibTeX-Ruby loaded'
61
+ task :console, [:script] do |t,args|
62
+ ARGV.clear
63
+
64
+ require 'irb'
65
+ require 'bibtex'
66
+
67
+ IRB.conf[:SCRIPT] = args.script
68
+ IRB.start
69
+ end
70
+
71
+
57
72
  desc 'Runs the benchmarks (and plots the results)'
58
73
  task :benchmark => ['racc'] do
59
74
  require File.expand_path('../test/benchmark.rb', __FILE__)
@@ -69,7 +84,9 @@ end
69
84
  desc 'Updates the Manifest file'
70
85
  task :manifest => ['clean', 'racc'] do
71
86
  m = File.open('Manifest', 'w')
72
- m.print FileList['**/*'].reject{ |f| f.end_with?('rbc') }.join("\n")
87
+ m.print FileList['**/*'].reject{ |f|
88
+ f.start_with?('coverage') || f.end_with?('rbc')
89
+ }.join("\n")
73
90
  m.close
74
91
  end
75
92
 
@@ -89,7 +106,4 @@ CLEAN.include('lib/bibtex/parser.rb')
89
106
  CLEAN.include('lib/bibtex/parser.output')
90
107
  CLEAN.include('lib/bibtex/name_parser.rb')
91
108
  CLEAN.include('lib/bibtex/name_parser.output')
92
- CLEAN.include('doc/html')
93
109
  CLEAN.include('*.gem')
94
-
95
- # vim: syntax=ruby
data/bibtex-ruby.gemspec CHANGED
@@ -9,12 +9,12 @@ Gem::Specification.new do |s|
9
9
  s.version = BibTeX::Version::STRING.dup
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.authors = ['Sylvester Keil']
12
- s.email = ['http://sylvester.keil.or.at']
12
+ s.email = ['sylvester@keil.or.at']
13
13
  s.homepage = 'http://inukshuk.github.com/bibtex-ruby'
14
14
  s.license = 'GPL-3'
15
15
 
16
16
  s.summary = 'A BibTeX parser, converter and API for Ruby.'
17
- s.description = <<-END_DESCRIPTION
17
+ s.description = <<-END_DESCRIPTION.gsub(/^\s+/, '')
18
18
  BibTeX-Ruby is the Rubyist's swiss-army-knife for all things BibTeX. It
19
19
  includes a parser for all common BibTeX objects (@string, @preamble,
20
20
  @comment and regular entries) and a sophisticated name parser that
@@ -28,18 +28,12 @@ Gem::Specification.new do |s|
28
28
  s.add_runtime_dependency('latex-decode', ['>=0.0.6'])
29
29
  s.add_runtime_dependency('multi_json', ['~>1.3'])
30
30
 
31
- s.add_development_dependency('rake', ['~>0.9'])
32
- s.add_development_dependency('racc', ['~>1.4'])
33
- s.add_development_dependency('rdoc', ['~>3.9'])
34
-
35
31
  s.files = File.open('Manifest').readlines.map(&:chomp)
36
32
  s.test_files = Dir.glob('test/**/test*.rb')
37
33
  s.executables = []
38
34
  s.require_path = 'lib'
39
35
 
40
- s.rdoc_options = %w{--line-numbers --inline-source --title "BibTeX-Ruby\ Documentation" --main README.md --webcvs=http://github.com/inukshuk/bibtex-ruby/tree/master/}
41
- s.extra_rdoc_files = %w{README.md}
42
-
36
+ s.has_rdoc = 'yard'
43
37
  end
44
38
 
45
39
  # vim: syntax=ruby
@@ -59,4 +59,42 @@ Feature: Searching in BibTeX bibliographies
59
59
  Then there should be exactly 3 matches
60
60
  When I search for "@*[year=2007]"
61
61
  Then there should be exactly 1 match
62
-
62
+
63
+ @query
64
+ Scenario: Find entries using compound queries
65
+ Given the bibliography:
66
+ """
67
+ @book{pickaxe,
68
+ Address = {Raleigh, North Carolina},
69
+ Author = {Thomas, Dave, and Fowler, Chad, and Hunt, Andy},
70
+ Date-Added = {2010-08-05 09:54:07 +0200},
71
+ Date-Modified = {2010-08-05 10:07:01 +0200},
72
+ Keywords = {ruby},
73
+ Publisher = {The Pragmatic Bookshelf},
74
+ Series = {The Facets of Ruby},
75
+ Title = {Programming Ruby 1.9: The Pragmatic Programmer's Guide},
76
+ Year = {2009}
77
+ }
78
+ @article{a1,
79
+ Title = {An Article},
80
+ Keywords = {@book}
81
+ }
82
+ @book{dragon,
83
+ Address = {Boston},
84
+ Author = {Aho, Alfred V., and Lam, Monica S., and Ullman, Jeffrey D.},
85
+ Booktitle = {Compilers: Principles, Techniques, and Tools},
86
+ Date-Added = {2010-08-05 09:57:15 +0200},
87
+ Date-Modified = {2010-08-05 10:06:32 +0200},
88
+ Edition = {second},
89
+ Keywords = {compiler, lex, yacc},
90
+ Publisher = {Addison Wesley},
91
+ Title = {Compilers: Principles, Techniques, and Tools},
92
+ Year = {2007}
93
+ }
94
+ """
95
+ When I search for "@*[keywords = @book || edition = second]"
96
+ Then there should be exactly 2 matches
97
+ When I search for "@*[keywords = @book && edition = second]"
98
+ Then there should be exactly 0 matches
99
+ When I search for "@*[keywords = @book && title ~= Article]"
100
+ Then there should be exactly 1 match
@@ -1,6 +1,18 @@
1
+ begin
2
+ if RUBY_VERSION > '1.8'
3
+ require 'debugger'
4
+ require 'simplecov'
5
+ else
6
+ require 'ruby-debug'
7
+ Debugger.start
8
+ end
9
+ rescue LoadError
10
+ # ignore
11
+ end
12
+
1
13
  require 'bibtex'
2
14
  require 'minitest/unit'
3
15
 
4
16
  World do
5
17
  extend MiniTest::Assertions
6
- end
18
+ end
data/lib/bibtex.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #--
2
2
  # BibTeX-Ruby
3
- # Copyright (C) 2010-2011 Sylvester Keil <sylvester.keil.or.at>
3
+ # Copyright (C) 2010-2012 Sylvester Keil <sylvester.keil.or.at>
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -56,10 +56,13 @@ end
56
56
  # Debugger.start
57
57
 
58
58
  require 'bibtex/extensions'
59
- require 'bibtex/compatibility'
59
+
60
60
  require 'bibtex/value'
61
61
  require 'bibtex/filters'
62
62
  require 'bibtex/name_parser'
63
+
64
+ require 'bibtex/compatibility'
65
+
63
66
  require 'bibtex/names'
64
67
  require 'bibtex/replaceable'
65
68
  require 'bibtex/elements'
@@ -1,6 +1,6 @@
1
1
  #--
2
2
  # BibTeX-Ruby
3
- # Copyright (C) 2010-2011 Sylvester Keil <sylvester.keil.or.at>
3
+ # Copyright (C) 2010-2012 Sylvester Keil <sylvester.keil.or.at>
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -1,3 +1,4 @@
1
+ # coding: utf-8
1
2
 
2
3
  unless Symbol.include?(Comparable)
3
4
  class Symbol
@@ -7,4 +8,11 @@ unless Symbol.include?(Comparable)
7
8
  to_s <=> other.to_s
8
9
  end
9
10
  end
10
- end
11
+ end
12
+
13
+ if RUBY_VERSION < '1.9'
14
+ $KCODE = 'u'
15
+ require 'jcode'
16
+
17
+ BibTeX::NameParser.patterns[:upper] = /[[:upper:]ÄÖÜ][^\t\r\n\s\{\}\d\\,]*/o
18
+ end
@@ -1,17 +1,17 @@
1
1
  #--
2
2
  # BibTeX-Ruby
3
- # Copyright (C) 2010-2011 Sylvester Keil <sylvester.keil.or.at>
4
- #
3
+ # Copyright (C) 2010-2012 Sylvester Keil <sylvester.keil.or.at>
4
+ #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
7
7
  # the Free Software Foundation, either version 3 of the License, or
8
8
  # (at your option) any later version.
9
- #
9
+ #
10
10
  # This program is distributed in the hope that it will be useful,
11
11
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
13
  # GNU General Public License for more details.
14
- #
14
+ #
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  #++
@@ -23,10 +23,10 @@ module BibTeX
23
23
  #
24
24
  class Element
25
25
  include Comparable
26
-
26
+
27
27
  attr_writer :id
28
28
  attr_reader :bibliography
29
-
29
+
30
30
  # Returns an array of BibTeX elements.
31
31
  def self.parse(input, options = {})
32
32
  case input
@@ -45,7 +45,7 @@ module BibTeX
45
45
  raise ArgumentError, "failed to parse Element from #{input.inspect}"
46
46
  end
47
47
  end
48
-
48
+
49
49
  # Returns a string containing the object's content.
50
50
  def content(options = {}); ''; end
51
51
 
@@ -54,33 +54,33 @@ module BibTeX
54
54
 
55
55
  # Invokes BibTeX string joining on this element.
56
56
  def join; self; end
57
-
57
+
58
58
  # Returns the element's id.
59
59
  def id; @id ||= object_id.to_s; end
60
-
60
+
61
61
  # Returns the BibTeX type (if applicable) or the normalized class name.
62
62
  def type
63
63
  self.class.name.split(/::/).last.gsub(/([[:lower:]])([[:upper:]])/) { "#{$1}_#{$2}" }.downcase.intern
64
64
  end
65
-
65
+
66
66
  # Returns a list of names for that Element. All Elements except Entries return an empty list.
67
67
  def names
68
68
  []
69
69
  end
70
-
70
+
71
71
  def has_type?(type)
72
72
  self.type == type.intern || defined?(type) == 'constant' && is_a?(type)
73
73
  end
74
-
75
- [:entry, :book, :article, :collection, :string, :preamble, :comment]. each do |type|
74
+
75
+ [:entry, :book, :article, :collection, :string, :preamble, :comment].each do |type|
76
76
  method_id = "#{type}?"
77
77
  define_method(method_id) { has_type?(type) } unless method_defined?(method_id)
78
78
  end
79
-
79
+
80
80
  # Returns true if the element matches the given query.
81
81
  def matches?(query)
82
82
  return true if query.nil? || query.respond_to?(:empty?) && query.empty?
83
-
83
+
84
84
  case query
85
85
  when Symbol
86
86
  query.to_s == id.to_s
@@ -88,63 +88,61 @@ module BibTeX
88
88
  query == self
89
89
  when Regexp
90
90
  to_s.match(query)
91
+ when /^\/(.+)\/$/
92
+ to_s.match(Regexp.new($1))
91
93
  when /@(\*|\w+)(?:\[([^\]]*)\])?/
92
94
  query.scan(/@(\*|\w+)(?:\[([^\]]*)\])?/).any? do |type, condition|
93
- has_type?(type) && ( condition.nil? || meets?(condition.split(/,\s*/)) )
95
+ if has_type?(type)
96
+ if condition.nil? || condition.empty?
97
+ true
98
+ else
99
+ condition.to_s.split(/\s*\|\|\s*/).any? do |conditions|
100
+ meets_all? conditions.split(/\s*(?:,|&&)\s*/)
101
+ end
102
+ end
103
+ end
94
104
  end
95
- when /^\/(.+)\/$/
96
- to_s.match(Regexp.new($1))
97
105
  else
98
106
  id.to_s == query
99
- end
107
+ end
100
108
  end
101
-
109
+
102
110
  alias === matches?
103
111
  alias match? matches?
104
-
105
- # Returns true if the element meets all of the given conditions.
106
- def meets?(*conditions)
107
- conditions.flatten.all? do |condition|
108
- property, operator, value = condition.split(/\s*([!~\/\^<>]?=)\s*/)
109
-
110
- if property.nil?
111
- true
112
- else
113
- case operator
114
- when '!=', '/='
115
- !respond_to?(property) || send(property).to_s != value
116
- when '^='
117
- respond_to?(property) && send(property).to_s.match("^#{value}")
118
- when '~='
119
- respond_to?(property) && send(property).to_s.match(value)
120
- when '<='
121
- respond_to?(property) && send(property).to_i <= value.to_i
122
- when '>='
123
- respond_to?(property) && send(property).to_i >= value.to_i
124
- else
125
- respond_to?(property) && send(property).to_s == value
126
- end
127
- end
112
+
113
+ def meets_all?(*conditions)
114
+ meets? conditions.flatten, :all?
115
+ end
116
+ alias meet_all? meets_all?
117
+
118
+ def meets_any?(*conditions)
119
+ meets? conditions.flatten, :any?
120
+ end
121
+ alias meet_any? meets_any?
122
+
123
+ # Returns true if the element meets all or any of the given conditions.
124
+ def meets?(conditions, op = :all?)
125
+ conditions.send(op) do |condition|
126
+ meets_condition? condition
128
127
  end
129
128
  end
130
-
131
129
  alias meet? meets?
132
-
130
+
133
131
  alias to_s content
134
-
132
+
135
133
  def to_hash(options = {})
136
134
  { type => content }
137
135
  end
138
-
136
+
139
137
  def to_yaml(options = {})
140
138
  require 'yaml'
141
139
  to_hash.to_yaml
142
140
  end
143
-
141
+
144
142
  def to_json(options = {})
145
143
  MultiJson.dump(to_hash(options))
146
144
  end
147
-
145
+
148
146
  def to_xml(options = {})
149
147
  require 'rexml/document'
150
148
  xml = REXML::Element.new(type)
@@ -158,25 +156,52 @@ module BibTeX
158
156
  @bibliography = bibliography
159
157
  self
160
158
  end
161
-
159
+
162
160
  # Called when the element was removed from a bibliography.
163
161
  def removed_from_bibliography(bibliography)
164
162
  @bibliography = nil
165
163
  self
166
164
  end
167
-
165
+
168
166
  def <=>(other)
169
167
  return nil unless other.respond_to? :type and other.respond_to? :to_s
170
168
  [type, to_s] <=> [other.type, other.to_s]
171
169
  end
172
-
170
+
173
171
  # Returns the Element as a nicely formatted string.
174
172
  def inspect
175
173
  "#<#{self.class} #{content.gsub(/\n/, ' ')}>"
176
174
  end
175
+
176
+ private
177
+
178
+ def meets_condition?(condition)
179
+ property, operator, value = condition.split(/\s*([!~\/\^<>]?=)\s*/)
180
+
181
+ if property.nil?
182
+ true
183
+ else
184
+ actual = respond_to?(property) ? send(property) : nil
185
+
186
+ case operator
187
+ when '!=', '/='
188
+ actual.nil? || actual.to_s != value
189
+ when '^='
190
+ !actual.nil? && actual.to_s.match("^#{value}")
191
+ when '~='
192
+ !actual.nil? && actual.to_s.match(value)
193
+ when '<='
194
+ !actual.nil? && actual.to_i <= value.to_i
195
+ when '>='
196
+ !actual.nil? && actual.to_i >= value.to_i
197
+ else
198
+ !actual.nil? && actual.to_s == value
199
+ end
200
+ end
201
+ end
177
202
  end
178
203
 
179
-
204
+
180
205
  #
181
206
  # Represents a @string object.
182
207
  #
@@ -187,9 +212,9 @@ module BibTeX
187
212
  # @string and @preamble objects, as well as in field values
188
213
  # of regular entries.
189
214
  #
190
- class String < Element
215
+ class String < Element
191
216
  include Replaceable
192
-
217
+
193
218
  attr_reader :key
194
219
 
195
220
  # Creates a new instance.
@@ -201,7 +226,7 @@ module BibTeX
201
226
  # Sets the string's key (i.e., the symbol identifying the constant).
202
227
  def key=(key)
203
228
  raise(ArgumentError, "keys must be convertible to Symbol; was: #{type.class.name}.") unless type.respond_to?(:to_sym)
204
-
229
+
205
230
  unless bibliography.nil?
206
231
  bibliography.strings.delete(@key)
207
232
  bibliography.strings[key.to_sym] = self
@@ -214,7 +239,7 @@ module BibTeX
214
239
  def [](key)
215
240
  @key == key ? @value : nil
216
241
  end
217
-
242
+
218
243
 
219
244
  # Called when the element was added to a bibliography.
220
245
  def added_to_bibliography(bibliography)
@@ -222,7 +247,7 @@ module BibTeX
222
247
  bibliography.strings[@key] = self
223
248
  self
224
249
  end
225
-
250
+
226
251
  # Called when the element was removed from a bibliography.
227
252
  def removed_from_bibliography(bibliography)
228
253
  super
@@ -239,23 +264,23 @@ module BibTeX
239
264
  def to_s(options = {})
240
265
  "@string{ #{content} }"
241
266
  end
242
-
267
+
243
268
  def to_hash(options = {})
244
269
  { :string => { @key => @value.to_s(:quotes => '"') } }
245
270
  end
246
-
271
+
247
272
  def to_xml(options = {})
248
273
  require 'rexml/document'
249
-
274
+
250
275
  xml = REXML::Element.new(:string)
251
-
276
+
252
277
  k, v = REXML::Element.new(:key), REXML::Element.new(:value)
253
278
  k.text = key.to_s
254
279
  v.text = value.to_s(:quotes => '"')
255
-
280
+
256
281
  xml.add_elements(k)
257
282
  xml.add_elements(v)
258
-
283
+
259
284
  xml
260
285
  end
261
286
  end
@@ -273,7 +298,7 @@ module BibTeX
273
298
  def initialize(value = '')
274
299
  @value = Value.new(value)
275
300
  end
276
-
301
+
277
302
  # Returns a string representation of the @preamble's content.
278
303
  def content
279
304
  @value.to_s(:quotes => '"')
@@ -288,7 +313,7 @@ module BibTeX
288
313
  # Represents a @comment object.
289
314
  class Comment < Element
290
315
  attr_accessor :content
291
-
316
+
292
317
  def initialize(content = '')
293
318
  @content = content
294
319
  end
@@ -300,7 +325,7 @@ module BibTeX
300
325
 
301
326
  # Represents text in a `.bib' file, but outside of an
302
327
  # actual BibTeX object; typically, such text is treated
303
- # as a comment and is ignored by the parser.
328
+ # as a comment and is ignored by the parser.
304
329
  # BibTeX-Ruby offers this class to allows for
305
330
  # post-processing of this type of `meta' content. If you
306
331
  # want the parser to include +MetaComment+ objects, you
@@ -308,7 +333,7 @@ module BibTeX
308
333
  # option.
309
334
  class MetaContent < Element
310
335
  attr_accessor :content
311
-
336
+
312
337
  def initialize(content = '')
313
338
  @content = content
314
339
  end