bibtex-ruby 1.3.5 → 1.3.6
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.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 }
|