bibtex-ruby 1.3.5 → 1.3.6
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/Gemfile.lock +4 -2
- data/History.txt +5 -0
- data/Manifest +4 -0
- data/README.md +9 -12
- data/bibtex-ruby.gemspec +1 -0
- data/features/issues/braced_strings.feature +48 -0
- data/features/issues/trailing_comma.feature +21 -0
- data/features/step_definitions/bibtex_steps.rb +9 -1
- data/features/strings.feature +1 -0
- data/lib/bibtex/bibliography.rb +25 -22
- data/lib/bibtex/bibtex.y +11 -23
- data/lib/bibtex/elements.rb +11 -13
- data/lib/bibtex/entry.rb +4 -2
- data/lib/bibtex/lexer.rb +142 -163
- data/lib/bibtex/names.rb +10 -10
- data/lib/bibtex/parser.output +135 -132
- data/lib/bibtex/parser.rb +69 -81
- data/lib/bibtex/utilities.rb +1 -1
- data/lib/bibtex/version.rb +1 -1
- data/test/bibtex/test_lexer.rb +11 -0
- data/test/fixtures/benchmark.bib +1 -1
- data/test/profile.dot +129 -74
- data/test/profile.rb +4 -2
- metadata +18 -3
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bibtex-ruby (1.3.
|
4
|
+
bibtex-ruby (1.3.6)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
@@ -11,7 +11,7 @@ GEM
|
|
11
11
|
watchr
|
12
12
|
builder (3.0.0)
|
13
13
|
columnize (0.3.2)
|
14
|
-
cucumber (0.10.
|
14
|
+
cucumber (0.10.6)
|
15
15
|
builder (>= 2.1.2)
|
16
16
|
diff-lcs (>= 1.1.2)
|
17
17
|
gherkin (~> 2.4.0)
|
@@ -32,6 +32,7 @@ GEM
|
|
32
32
|
term-ansicolor (>= 1.0.4)
|
33
33
|
racc (1.4.6)
|
34
34
|
rake (0.9.2)
|
35
|
+
rdoc (3.6.1)
|
35
36
|
ruby-debug (0.10.4)
|
36
37
|
columnize (>= 0.1)
|
37
38
|
ruby-debug-base (~> 0.10.4.0)
|
@@ -64,6 +65,7 @@ DEPENDENCIES
|
|
64
65
|
mynyml-redgreen (>= 0.7)
|
65
66
|
racc (>= 1.4)
|
66
67
|
rake (>= 0.8)
|
68
|
+
rdoc (>= 3.6)
|
67
69
|
ruby-debug
|
68
70
|
ruby-debug19
|
69
71
|
ruby-prof (>= 0.10)
|
data/History.txt
CHANGED
data/Manifest
CHANGED
@@ -7,6 +7,7 @@ README.md
|
|
7
7
|
Rakefile
|
8
8
|
auto.watchr
|
9
9
|
bibtex-ruby.gemspec
|
10
|
+
doc
|
10
11
|
examples
|
11
12
|
examples/bib2html.rb
|
12
13
|
examples/bib2yaml.rb
|
@@ -15,9 +16,11 @@ features
|
|
15
16
|
features/bibtex.feature
|
16
17
|
features/entries.feature
|
17
18
|
features/issues
|
19
|
+
features/issues/braced_strings.feature
|
18
20
|
features/issues/number_keys.feature
|
19
21
|
features/issues/parse_months.feature
|
20
22
|
features/issues/slash_keys.feature
|
23
|
+
features/issues/trailing_comma.feature
|
21
24
|
features/names.feature
|
22
25
|
features/preambles.feature
|
23
26
|
features/query.feature
|
@@ -54,6 +57,7 @@ test/bibtex
|
|
54
57
|
test/bibtex/test_bibliography.rb
|
55
58
|
test/bibtex/test_elements.rb
|
56
59
|
test/bibtex/test_entry.rb
|
60
|
+
test/bibtex/test_lexer.rb
|
57
61
|
test/bibtex/test_names.rb
|
58
62
|
test/bibtex/test_parser.rb
|
59
63
|
test/bibtex/test_string.rb
|
data/README.md
CHANGED
@@ -43,18 +43,15 @@ many styles:
|
|
43
43
|
|
44
44
|
>> require 'citeproc' # requires the citeproc-ruby gem
|
45
45
|
=> true
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
=> "Thomas, Dave, Chad Fowler, and Andy Hunt. Programming Ruby 1.9:
|
56
|
-
The Pragmatic Programmer's Guide. Raleigh, North Carolina:
|
57
|
-
The Pragmatic Bookshelf, 2009."
|
46
|
+
>> CiteProc.process b[:pickaxe].to_citeproc, :style => :apa
|
47
|
+
=> "Thomas, D., Fowler, C., & Hunt, A. (2009). Programming Ruby 1.9: The Pragmatic Programmer's
|
48
|
+
Guide. The Facets of Ruby. Raleigh, North Carolina: The Pragmatic Bookshelf."
|
49
|
+
>> CiteProc.process b[:pickaxe].to_citeproc, :style => 'chicago-author-date'
|
50
|
+
=> "Thomas, Dave, Chad Fowler, and Andy Hunt. 2009. Programming Ruby 1.9: The Pragmatic
|
51
|
+
Programmer's Guide. The Facets of Ruby.Raleigh, North Carolina: The Pragmatic Bookshelf."
|
52
|
+
>> CiteProc.process b[:pickaxe].to_citeproc, :style => :mla
|
53
|
+
=> "Thomas, Dave, Chad Fowler, and Andy Hunt. Programming Ruby 1.9: The Pragmatic Programmer's
|
54
|
+
Guide. Raleigh, North Carolina: The Pragmatic Bookshelf, 2009."
|
58
55
|
|
59
56
|
|
60
57
|
Installation
|
data/bibtex-ruby.gemspec
CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency('json', ['>= 1.5'])
|
28
28
|
s.add_development_dependency('ruby-prof', ['>= 0.10'])
|
29
29
|
s.add_development_dependency('gnuplot', ['>= 2.3'])
|
30
|
+
s.add_development_dependency('rdoc', ['>= 3.6'])
|
30
31
|
|
31
32
|
s.files = File.open('Manifest').readlines.map(&:chomp)
|
32
33
|
s.test_files = Dir.glob('test/**/test*.rb')
|
@@ -0,0 +1,48 @@
|
|
1
|
+
Feature: BibTeX Braced Strings
|
2
|
+
As a hacker who works with bibliographies
|
3
|
+
I want to be able to parse BibTeX files containing string definitions using braced expressions
|
4
|
+
Because applications such as BibDesk produce that format
|
5
|
+
|
6
|
+
@string
|
7
|
+
Scenario: A simple string assignment
|
8
|
+
When I parse the following file:
|
9
|
+
"""
|
10
|
+
@string{ foo = {foo} }
|
11
|
+
"""
|
12
|
+
Then my bibliography should contain 1 string
|
13
|
+
|
14
|
+
@string @replacement
|
15
|
+
Scenario: A BibTeX file with string assignments
|
16
|
+
When I parse the following file:
|
17
|
+
"""
|
18
|
+
Simple strings:
|
19
|
+
@string{ foo1 = {foo} }
|
20
|
+
@string{ foo2 = {foo}}
|
21
|
+
@string{ foo3 ={foo}}
|
22
|
+
@string{foo4={foo}}
|
23
|
+
@string{ foo5 = {"foo" bar} }
|
24
|
+
@string{ foo6 = {"foo" bar{"}} }
|
25
|
+
|
26
|
+
Compound strings:
|
27
|
+
@string{ foo7 = foo1 }
|
28
|
+
@string{ foo8 = foo1 # {bar} }
|
29
|
+
@string{ foo9 = {foo } # {bar} }
|
30
|
+
|
31
|
+
"""
|
32
|
+
Then my bibliography should contain 9 strings
|
33
|
+
And my bibliography should contain these strings:
|
34
|
+
| value |
|
35
|
+
| foo |
|
36
|
+
| foo |
|
37
|
+
| foo |
|
38
|
+
| foo |
|
39
|
+
| "foo" bar |
|
40
|
+
| "foo" bar{"} |
|
41
|
+
| foo1 |
|
42
|
+
| foo1 # "bar" |
|
43
|
+
| "foo " # "bar" |
|
44
|
+
When I replace and join all strings in my bibliography
|
45
|
+
Then the string "foo7" should be "foo"
|
46
|
+
And the string "foo8" should be "foobar"
|
47
|
+
And the string "foo9" should be "foo bar"
|
48
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Feature: Parse BibTeX files with trailing commas
|
2
|
+
As a hacker who works with bibliographies
|
3
|
+
I want to be able to parse BibTeX files with a trailing comma
|
4
|
+
|
5
|
+
Scenario: A BibTeX file with lots of objects and comments
|
6
|
+
When I parse the following file:
|
7
|
+
"""
|
8
|
+
@article{rb2011,
|
9
|
+
author = {Keil, Sylvester},
|
10
|
+
title = "BibTeX-Ruby",
|
11
|
+
year = 2011,
|
12
|
+
},
|
13
|
+
|
14
|
+
@article{key03,
|
15
|
+
year = 2000,
|
16
|
+
title = "A {bunch {of} braces {in}} title",
|
17
|
+
},
|
18
|
+
"""
|
19
|
+
Then my bibliography should contain an entry with key "rb2011"
|
20
|
+
And my bibliography should contain 1 articles published in 2011
|
21
|
+
And my bibliography should contain an entry with key "key03"
|
@@ -71,10 +71,18 @@ Then /^there should be exactly (\d+) match(?:es)?$/ do |matches|
|
|
71
71
|
end
|
72
72
|
|
73
73
|
|
74
|
+
Then /^my bibliography should contain (\d+) (\w+)$/ do |count, type|
|
75
|
+
assert_equal count.to_i, @bibliography.q("@#{type.chomp('s')}").length
|
76
|
+
end
|
77
|
+
|
74
78
|
Then /^my bibliography should contain (\d+) (\w+) published in (\d+)$/ do |count, type, year|
|
75
|
-
assert_equal @bibliography.q("@#{type.chomp
|
79
|
+
assert_equal count.to_i, @bibliography.q("@#{type.chomp('s')}[year=#{year}]").length
|
76
80
|
end
|
77
81
|
|
78
82
|
Then /^my bibliography should contain an? (\w+) with id "([^"]*)"$/ do |type, id|
|
79
83
|
assert_equal @bibliography[id.to_sym].type, type.to_sym
|
80
84
|
end
|
85
|
+
|
86
|
+
Then /^the string "([^"]*)" should be "([^"]*)"$/ do |key, value|
|
87
|
+
assert_equal value, @bibliography.strings[key.to_sym].v.to_s
|
88
|
+
end
|
data/features/strings.feature
CHANGED
data/lib/bibtex/bibliography.rb
CHANGED
@@ -30,7 +30,9 @@ module BibTeX
|
|
30
30
|
|
31
31
|
include Enumerable
|
32
32
|
include Comparable
|
33
|
-
|
33
|
+
|
34
|
+
DEFAULTS = { :parse_names => true, :parse_months => true }.freeze
|
35
|
+
|
34
36
|
class << self
|
35
37
|
|
36
38
|
# Opens and parses the `.bib' file at the given +path+. Returns
|
@@ -40,7 +42,11 @@ module BibTeX
|
|
40
42
|
# to specify a save path other than the path from where the file is
|
41
43
|
# loaded).
|
42
44
|
#
|
43
|
-
# The options argument is passed on to BibTeX::Parser.new.
|
45
|
+
# The options argument is passed on to BibTeX::Parser.new. Additional
|
46
|
+
# option parameters are:
|
47
|
+
#
|
48
|
+
# -:parse_names: set to false to disable automatic name parsing
|
49
|
+
# -:parse_months: set to false to disable automatic month conversion
|
44
50
|
#
|
45
51
|
def open(path, options = {})
|
46
52
|
b = parse(Kernel.open(path).read, options)
|
@@ -55,10 +61,7 @@ module BibTeX
|
|
55
61
|
|
56
62
|
# Parses the given string and returns a corresponding Bibliography instance.
|
57
63
|
def parse(bibtex, options = {})
|
58
|
-
|
59
|
-
b.parse_names unless b.nil? || options[:parse_names] == false
|
60
|
-
b.parse_months unless b.nil? || options[:parse_months] == false
|
61
|
-
b
|
64
|
+
Parser.new(options).parse(bibtex)
|
62
65
|
end
|
63
66
|
|
64
67
|
#
|
@@ -73,7 +76,7 @@ module BibTeX
|
|
73
76
|
end
|
74
77
|
|
75
78
|
attr_accessor :path
|
76
|
-
attr_reader :data, :strings, :entries, :errors
|
79
|
+
attr_reader :data, :strings, :entries, :errors, :options
|
77
80
|
|
78
81
|
attr_by_type :article, :book, :journal, :collection, :preamble, :comment, :meta_content
|
79
82
|
|
@@ -81,13 +84,13 @@ module BibTeX
|
|
81
84
|
|
82
85
|
|
83
86
|
#
|
84
|
-
# Creates a new bibliography
|
87
|
+
# Creates a new bibliography.
|
85
88
|
#
|
86
|
-
def initialize(
|
87
|
-
@
|
88
|
-
@strings = {}
|
89
|
-
|
90
|
-
|
89
|
+
def initialize(options = {})
|
90
|
+
@options = DEFAULTS.merge(options)
|
91
|
+
@data, @strings, @entries = [], {}, {}
|
92
|
+
|
93
|
+
yield self if block_given?
|
91
94
|
end
|
92
95
|
|
93
96
|
# Adds a new element, or a list of new elements to the bibliography.
|
@@ -100,8 +103,8 @@ module BibTeX
|
|
100
103
|
self
|
101
104
|
end
|
102
105
|
|
103
|
-
alias
|
104
|
-
alias
|
106
|
+
alias << add
|
107
|
+
alias push add
|
105
108
|
|
106
109
|
# Saves the bibliography to the current path.
|
107
110
|
def save(options = {})
|
@@ -116,12 +119,12 @@ module BibTeX
|
|
116
119
|
end
|
117
120
|
|
118
121
|
def parse_names
|
119
|
-
|
122
|
+
@entries.values.each { |e| e.parse_names }
|
120
123
|
self
|
121
124
|
end
|
122
125
|
|
123
126
|
def parse_months
|
124
|
-
|
127
|
+
@entries.values.each { |e| e.parse_month }
|
125
128
|
self
|
126
129
|
end
|
127
130
|
|
@@ -139,8 +142,8 @@ module BibTeX
|
|
139
142
|
objects.length == 1 ? objects[0] : objects
|
140
143
|
end
|
141
144
|
|
142
|
-
alias
|
143
|
-
alias
|
145
|
+
alias remove delete
|
146
|
+
alias rm delete
|
144
147
|
|
145
148
|
#
|
146
149
|
# Returns an element or a list of elements according to the given index,
|
@@ -221,7 +224,7 @@ module BibTeX
|
|
221
224
|
self
|
222
225
|
end
|
223
226
|
|
224
|
-
alias
|
227
|
+
alias join_strings join
|
225
228
|
|
226
229
|
def rename(*arguments, &block)
|
227
230
|
q('@entry') { |e| e.rename(*arguments, &block) }
|
@@ -300,13 +303,13 @@ module BibTeX
|
|
300
303
|
send(query_handler(selector), &filter)
|
301
304
|
end
|
302
305
|
|
303
|
-
alias
|
306
|
+
alias q query
|
304
307
|
|
305
308
|
def find_by_type(*types, &block)
|
306
309
|
q(types.flatten.compact.map { |t| "@#{t}" }.join(', '), &block)
|
307
310
|
end
|
308
311
|
|
309
|
-
alias
|
312
|
+
alias find_by_types find_by_type
|
310
313
|
|
311
314
|
def <=>(other)
|
312
315
|
other.respond_to?(:to_a) ? to_a <=> other.to_a : nil
|
data/lib/bibtex/bibtex.y
CHANGED
@@ -30,7 +30,7 @@ expect 0
|
|
30
30
|
|
31
31
|
rule
|
32
32
|
|
33
|
-
bibliography : /* empty */ { result = BibTeX::Bibliography.new }
|
33
|
+
bibliography : /* empty */ { result = BibTeX::Bibliography.new(@options) }
|
34
34
|
| objects { result = val[0] }
|
35
35
|
|
36
36
|
objects : object { result = BibTeX::Bibliography.new << val[0] }
|
@@ -60,6 +60,7 @@ rule
|
|
60
60
|
| string_value SHARP string_literal { result << val[2] }
|
61
61
|
|
62
62
|
string_literal : NAME { result = val[0].downcase.to_sym }
|
63
|
+
| LBRACE content RBRACE { result = val[1] }
|
63
64
|
| STRING_LITERAL { result = val[0] }
|
64
65
|
|
65
66
|
entry : entry_head assignments RBRACE { result = val[0] << val[1] }
|
@@ -79,7 +80,6 @@ rule
|
|
79
80
|
|
80
81
|
value : string_value { result = val[0] }
|
81
82
|
| NUMBER { result = val[0] }
|
82
|
-
| LBRACE content RBRACE { result = val[1] }
|
83
83
|
|
84
84
|
end
|
85
85
|
|
@@ -88,43 +88,31 @@ require 'bibtex/lexer'
|
|
88
88
|
|
89
89
|
---- inner
|
90
90
|
|
91
|
-
attr_reader :lexer
|
91
|
+
attr_reader :lexer, :options
|
92
92
|
|
93
|
+
DEFAULTS = { :include => [:errors], :debug => ENV['DEBUG'] == true }.freeze
|
94
|
+
|
93
95
|
def initialize(options = {})
|
94
|
-
|
96
|
+
@options = DEFAULTS.merge(options)
|
95
97
|
@lexer = Lexer.new(@options)
|
96
98
|
end
|
97
99
|
|
98
|
-
def options
|
99
|
-
@options ||= { :include => [:errors], :debug => ENV['DEBUG'] == true }
|
100
|
-
end
|
101
|
-
|
102
100
|
def parse(input)
|
103
|
-
@yydebug = debug?
|
104
|
-
|
105
|
-
@lexer.data = input
|
106
|
-
@lexer.analyse
|
101
|
+
@yydebug = debug?
|
102
|
+
@lexer.analyse(input)
|
107
103
|
|
108
104
|
do_parse
|
105
|
+
#yyparse(@lexer,:each)
|
109
106
|
end
|
110
107
|
|
111
108
|
def next_token
|
112
|
-
|
113
|
-
if token[0] == :ERROR
|
114
|
-
include_errors? ? token : next_token
|
115
|
-
else
|
116
|
-
[token[0],token[1][0]]
|
117
|
-
end
|
109
|
+
@lexer.next_token
|
118
110
|
end
|
119
111
|
|
120
112
|
def debug?
|
121
113
|
@options[:debug] == true
|
122
114
|
end
|
123
|
-
|
124
|
-
def include_errors?
|
125
|
-
@options[:include].include?(:errors)
|
126
|
-
end
|
127
|
-
|
115
|
+
|
128
116
|
def on_error(tid, val, vstack)
|
129
117
|
Log.error("Failed to parse BibTeX on value %s (%s) %s" % [val.inspect, token_to_str(tid) || '?', vstack.inspect])
|
130
118
|
#raise(ParseError, "Failed to parse BibTeX on value %s (%s) %s" % [val.inspect, token_to_str(tid) || '?', vstack.inspect])
|
data/lib/bibtex/elements.rb
CHANGED
@@ -38,9 +38,7 @@ module BibTeX
|
|
38
38
|
end
|
39
39
|
|
40
40
|
# Returns a string containing the object's content.
|
41
|
-
def content(options = {})
|
42
|
-
''
|
43
|
-
end
|
41
|
+
def content(options = {}); ''; end
|
44
42
|
|
45
43
|
# Invokes BibTeX string replacement on this element.
|
46
44
|
def replace(*arguments); self; end
|
@@ -70,28 +68,28 @@ module BibTeX
|
|
70
68
|
|
71
69
|
# Returns true if the element matches the given query.
|
72
70
|
def matches?(query)
|
73
|
-
return true if query
|
71
|
+
return true if !query || query.respond_to?(:empty?) && query.empty?
|
74
72
|
|
75
73
|
case query
|
76
|
-
when Element
|
77
|
-
self == query
|
78
74
|
when Symbol
|
79
|
-
|
75
|
+
query == id
|
76
|
+
when Element
|
77
|
+
query == self
|
80
78
|
when Regexp
|
81
79
|
to_s.match(query)
|
82
|
-
when /^\/(.+)\/$/
|
83
|
-
to_s.match(Regexp.new($1))
|
84
80
|
when /@(\w+)(?:\[([^\]]*)\])?/
|
85
81
|
query.scan(/@(\w+)(?:\[([^\]]*)\])?/).any? do |type, condition|
|
86
82
|
has_type?(type) && ( condition.nil? || meets?(condition.split(/,\s*/)) )
|
87
83
|
end
|
84
|
+
when /^\/(.+)\/$/
|
85
|
+
to_s.match(Regexp.new($1))
|
88
86
|
else
|
89
87
|
id == query.to_sym
|
90
88
|
end
|
91
89
|
end
|
92
90
|
|
93
|
-
alias
|
94
|
-
alias
|
91
|
+
alias === matches?
|
92
|
+
alias match? matches?
|
95
93
|
|
96
94
|
# Returns true if the element meets all of the given conditions.
|
97
95
|
def meets?(*conditions)
|
@@ -101,9 +99,9 @@ module BibTeX
|
|
101
99
|
end
|
102
100
|
end
|
103
101
|
|
104
|
-
alias
|
102
|
+
alias meet? meets?
|
105
103
|
|
106
|
-
alias
|
104
|
+
alias to_s content
|
107
105
|
|
108
106
|
def to_hash(options = {})
|
109
107
|
{ type => content }
|