bibsync 0.0.2 → 0.0.3
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.
- data/.travis.yml +2 -1
- data/lib/bibsync/actions/jabref.xml +19 -0
- data/lib/bibsync/actions/jabref_format.rb +1 -1
- data/lib/bibsync/actions/synchronize_files.rb +1 -1
- data/lib/bibsync/actions/synchronize_metadata.rb +2 -2
- data/lib/bibsync/bibliography.rb +2 -167
- data/lib/bibsync/entry.rb +164 -0
- data/lib/bibsync/literal.rb +3 -0
- data/lib/bibsync/transformer.rb +18 -1
- data/lib/bibsync/utils.rb +1 -1
- data/lib/bibsync/version.rb +1 -1
- data/lib/bibsync.rb +3 -1
- data/test/actions/test_fetch_from_arxiv.rb +18 -0
- data/test/actions/test_jabref_format.rb +21 -0
- data/test/actions/test_synchronize_files.rb +29 -0
- data/test/actions/test_validate.rb +11 -0
- data/test/helper.rb +5 -1
- data/test/test_bibliography.rb +6 -90
- data/test/test_entry.rb +84 -0
- metadata +25 -13
- checksums.yaml +0 -7
data/.travis.yml
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
2
|
+
<!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
|
3
|
+
<preferences EXTERNAL_XML_VERSION="1.0">
|
4
|
+
<root type="user">
|
5
|
+
<map/>
|
6
|
+
<node name="net">
|
7
|
+
<map/>
|
8
|
+
<node name="sf">
|
9
|
+
<map/>
|
10
|
+
<node name="jabref">
|
11
|
+
<map>
|
12
|
+
<entry key="exportInOriginalOrder" value="true"/>
|
13
|
+
<entry key="saveInOriginalOrder" value="true"/>
|
14
|
+
</map>
|
15
|
+
</node>
|
16
|
+
</node>
|
17
|
+
</node>
|
18
|
+
</root>
|
19
|
+
</preferences>
|
@@ -13,7 +13,7 @@ module BibSync
|
|
13
13
|
if File.read(@bib.file, 80) !~ /JabRef/
|
14
14
|
notice 'Transforming file with JabRef'
|
15
15
|
tmp_file = "#{@bib.file}.tmp.bib"
|
16
|
-
`jabref --nogui --import #{Shellwords.escape @bib.file} --output #{Shellwords.escape tmp_file} 2>&1 >/dev/null`
|
16
|
+
`jabref --primp #{Shellwords.escape File.join(File.dirname(__FILE__), 'jabref.xml')} --nogui --import #{Shellwords.escape @bib.file} --output #{Shellwords.escape tmp_file} 2>&1 >/dev/null`
|
17
17
|
File.rename(tmp_file, @bib.file) if File.exists?(tmp_file)
|
18
18
|
end
|
19
19
|
end
|
@@ -49,7 +49,7 @@ module BibSync
|
|
49
49
|
info('Downloading DOI metadata', key: entry)
|
50
50
|
text = fetch("http://dx.doi.org/#{entry[:doi]}", 'Accept' => 'text/bibliography; style=bibtex')
|
51
51
|
raise text if text == 'Unknown DOI'
|
52
|
-
|
52
|
+
Entry.parse(text).each {|k, v| entry[k] = v }
|
53
53
|
rescue => ex
|
54
54
|
entry.delete(:doi)
|
55
55
|
error('DOI download failed', key: entry, ex: ex)
|
@@ -112,7 +112,7 @@ module BibSync
|
|
112
112
|
date = xml.xpath('//arXiv/updated').map(&:content).first || xml.xpath('//arXiv/created').map(&:content).first
|
113
113
|
date = Date.parse(date)
|
114
114
|
entry[:year] = date.year
|
115
|
-
entry[:month] =
|
115
|
+
entry[:month] = Literal.new(%w(jan feb mar apr may jun jul aug sep oct nov dec)[date.month - 1])
|
116
116
|
doi = xml.xpath('//arXiv/doi').map(&:content).first
|
117
117
|
entry[:doi] = doi if doi
|
118
118
|
journal = xml.xpath('//arXiv/journal-ref').map(&:content).first
|
data/lib/bibsync/bibliography.rb
CHANGED
@@ -27,7 +27,7 @@ module BibSync
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def [](key)
|
30
|
-
@entries[key]
|
30
|
+
@entries[key.to_s]
|
31
31
|
end
|
32
32
|
|
33
33
|
def delete(entry)
|
@@ -102,7 +102,7 @@ module BibSync
|
|
102
102
|
else
|
103
103
|
entry = Entry.new
|
104
104
|
text = entry.parse(text)
|
105
|
-
entry.key ||= @entries.size
|
105
|
+
entry.key ||= "entry#{@entries.size}" # Number of entries for comment id
|
106
106
|
self << entry
|
107
107
|
end
|
108
108
|
end
|
@@ -112,170 +112,5 @@ module BibSync
|
|
112
112
|
"% #{DateTime.now}\n% Encoding: UTF8\n\n" <<
|
113
113
|
@entries.values.join("\n") << "\n"
|
114
114
|
end
|
115
|
-
|
116
|
-
class RawValue < String; end
|
117
|
-
|
118
|
-
class Entry
|
119
|
-
include Enumerable
|
120
|
-
|
121
|
-
attr_accessor :bibliography, :type
|
122
|
-
attr_reader :key
|
123
|
-
|
124
|
-
def self.parse(text)
|
125
|
-
Entry.new.tap {|e| e.parse(text) }
|
126
|
-
end
|
127
|
-
|
128
|
-
def initialize(fields = {})
|
129
|
-
self.key = fields.delete(:key) if fields.include?(:key)
|
130
|
-
self.type = fields.delete(:type) if fields.include?(:type)
|
131
|
-
@fields = fields
|
132
|
-
end
|
133
|
-
|
134
|
-
def key=(key)
|
135
|
-
key = key.to_s
|
136
|
-
raise 'Key cannot be empty' if key.empty?
|
137
|
-
if bib = bibliography
|
138
|
-
bib.delete(self)
|
139
|
-
@key = key
|
140
|
-
bib << self
|
141
|
-
else
|
142
|
-
@key = key
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def file=(file)
|
147
|
-
raise 'No bibliography set' unless bibliography
|
148
|
-
file =~ /\.(\w+)\Z/
|
149
|
-
self[:file] = ":#{bibliography.relative_path(file)}:#{$1.upcase}" # JabRef file format "description:path:type"
|
150
|
-
file
|
151
|
-
end
|
152
|
-
|
153
|
-
def file
|
154
|
-
if self[:file]
|
155
|
-
raise 'No bibliography set' unless bibliography
|
156
|
-
_, file, type = self[:file].split(':', 3)
|
157
|
-
path = File.join(File.absolute_path(File.dirname(bibliography.file)), file)
|
158
|
-
{ name: File.basename(path), type: type.upcase.to_sym, path: path }
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def [](key)
|
163
|
-
@fields[convert_key(key)]
|
164
|
-
end
|
165
|
-
|
166
|
-
def []=(key, value)
|
167
|
-
if value
|
168
|
-
key = convert_key(key)
|
169
|
-
value = RawValue === value ? RawValue.new(value.to_s.strip) : value.to_s.strip
|
170
|
-
if @fields[key] != value || @fields[key].class != value.class
|
171
|
-
@fields[key] = value
|
172
|
-
dirty!
|
173
|
-
end
|
174
|
-
else
|
175
|
-
delete(key)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
def delete(key)
|
180
|
-
key = convert_key(key)
|
181
|
-
if @fields.include?(key)
|
182
|
-
@fields.delete(key)
|
183
|
-
dirty!
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
def each(&block)
|
188
|
-
@fields.each(&block)
|
189
|
-
end
|
190
|
-
|
191
|
-
def comment?
|
192
|
-
type.to_s.downcase == 'comment'
|
193
|
-
end
|
194
|
-
|
195
|
-
def dirty!
|
196
|
-
bibliography.dirty! if bibliography
|
197
|
-
end
|
198
|
-
|
199
|
-
def to_s
|
200
|
-
s = "@#{type}{"
|
201
|
-
if comment?
|
202
|
-
s << self[:comment]
|
203
|
-
else
|
204
|
-
s << "#{key},\n" << to_a.map {|k,v| RawValue === v ? " #{k} = #{v}" : " #{k} = {#{v}}" }.join(",\n") << "\n"
|
205
|
-
end
|
206
|
-
s << "}\n"
|
207
|
-
end
|
208
|
-
|
209
|
-
def parse(text)
|
210
|
-
raise 'Unexpected token' if text !~ /\A\s*@(\w+)\s*\{/
|
211
|
-
self.type = $1
|
212
|
-
text = $'
|
213
|
-
|
214
|
-
if comment?
|
215
|
-
text, self[:comment] = parse_field(text)
|
216
|
-
else
|
217
|
-
raise 'Expected entry key' if text !~ /([^,]+),\s*/
|
218
|
-
self.key = $1.strip
|
219
|
-
text = $'
|
220
|
-
|
221
|
-
until text.empty?
|
222
|
-
case text
|
223
|
-
when /\A(\s+|%[^\n]+\n)/
|
224
|
-
text = $'
|
225
|
-
when /\A\s*(\w+)\s*=\s*/
|
226
|
-
text, key = $', $1
|
227
|
-
if text =~ /\A\{/
|
228
|
-
text, self[key] = parse_field(text)
|
229
|
-
else
|
230
|
-
text, value = parse_field(text)
|
231
|
-
self[key] = RawValue.new(value)
|
232
|
-
end
|
233
|
-
else
|
234
|
-
break
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
raise 'Expected closing }' unless text =~ /\A\s*\}/
|
240
|
-
$'
|
241
|
-
end
|
242
|
-
|
243
|
-
private
|
244
|
-
|
245
|
-
def parse_field(text)
|
246
|
-
value = ''
|
247
|
-
count = 0
|
248
|
-
until text.empty?
|
249
|
-
case text
|
250
|
-
when /\A\{/
|
251
|
-
text = $'
|
252
|
-
value << $& if count > 0
|
253
|
-
count += 1
|
254
|
-
when /\A\}/
|
255
|
-
break if count == 0
|
256
|
-
count -= 1
|
257
|
-
text = $'
|
258
|
-
value << $& if count > 0
|
259
|
-
when /\A,/
|
260
|
-
text = $'
|
261
|
-
break if count == 0
|
262
|
-
value << $&
|
263
|
-
when /\A[^\}\{,]+/
|
264
|
-
text = $'
|
265
|
-
value << $&
|
266
|
-
else
|
267
|
-
break
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
raise 'Expected closing }' if count != 0
|
272
|
-
|
273
|
-
return text, value
|
274
|
-
end
|
275
|
-
|
276
|
-
def convert_key(key)
|
277
|
-
key.to_s.downcase.to_sym
|
278
|
-
end
|
279
|
-
end
|
280
115
|
end
|
281
116
|
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
module BibSync
|
2
|
+
class Entry
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_accessor :bibliography, :type
|
6
|
+
attr_reader :key
|
7
|
+
|
8
|
+
def self.parse(text)
|
9
|
+
Entry.new.tap {|e| e.parse(text) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(fields = {})
|
13
|
+
self.key = fields.delete(:key) if fields.include?(:key)
|
14
|
+
self.type = fields.delete(:type) if fields.include?(:type)
|
15
|
+
@fields = fields
|
16
|
+
end
|
17
|
+
|
18
|
+
def key=(key)
|
19
|
+
key = key.to_s
|
20
|
+
raise 'Key cannot be empty' if key.empty?
|
21
|
+
if bib = bibliography
|
22
|
+
bib.delete(self)
|
23
|
+
@key = key
|
24
|
+
bib << self
|
25
|
+
else
|
26
|
+
@key = key
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def file=(file)
|
31
|
+
raise 'No bibliography set' unless bibliography
|
32
|
+
file =~ /\.(\w+)\Z/
|
33
|
+
self[:file] = ":#{bibliography.relative_path(file)}:#{$1.upcase}" # JabRef file format "description:path:type"
|
34
|
+
file
|
35
|
+
end
|
36
|
+
|
37
|
+
def file
|
38
|
+
if self[:file]
|
39
|
+
raise 'No bibliography set' unless bibliography
|
40
|
+
_, file, type = self[:file].split(':', 3)
|
41
|
+
path = File.join(File.absolute_path(File.dirname(bibliography.file)), file)
|
42
|
+
{ name: File.basename(path), type: type.upcase.to_sym, path: path }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def [](key)
|
47
|
+
@fields[convert_key(key)]
|
48
|
+
end
|
49
|
+
|
50
|
+
def []=(key, value)
|
51
|
+
if value
|
52
|
+
key = convert_key(key)
|
53
|
+
value = Literal === value ? Literal.new(value.to_s.strip) : value.to_s.strip
|
54
|
+
if @fields[key] != value || @fields[key].class != value.class
|
55
|
+
@fields[key] = value
|
56
|
+
dirty!
|
57
|
+
end
|
58
|
+
else
|
59
|
+
delete(key)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def delete(key)
|
64
|
+
key = convert_key(key)
|
65
|
+
if @fields.include?(key)
|
66
|
+
@fields.delete(key)
|
67
|
+
dirty!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def each(&block)
|
72
|
+
@fields.each(&block)
|
73
|
+
end
|
74
|
+
|
75
|
+
def comment?
|
76
|
+
type.to_s.downcase == 'comment'
|
77
|
+
end
|
78
|
+
|
79
|
+
def dirty!
|
80
|
+
bibliography.dirty! if bibliography
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_s
|
84
|
+
s = "@#{type}{"
|
85
|
+
if comment?
|
86
|
+
s << self[:comment]
|
87
|
+
else
|
88
|
+
s << "#{key},\n" << to_a.map {|k,v| Literal === v ? " #{k} = #{v}" : " #{k} = {#{v}}" }.join(",\n") << "\n"
|
89
|
+
end
|
90
|
+
s << "}\n"
|
91
|
+
end
|
92
|
+
|
93
|
+
def parse(text)
|
94
|
+
raise 'Unexpected token' if text !~ /\A\s*@(\w+)\s*\{/
|
95
|
+
self.type = $1
|
96
|
+
text = $'
|
97
|
+
|
98
|
+
if comment?
|
99
|
+
text, self[:comment] = parse_field(text)
|
100
|
+
else
|
101
|
+
raise 'Expected entry key' if text !~ /([^,]+),\s*/
|
102
|
+
self.key = $1.strip
|
103
|
+
text = $'
|
104
|
+
|
105
|
+
until text.empty?
|
106
|
+
case text
|
107
|
+
when /\A(\s+|%[^\n]+\n)/
|
108
|
+
text = $'
|
109
|
+
when /\A\s*(\w+)\s*=\s*/
|
110
|
+
text, key = $', $1
|
111
|
+
if text =~ /\A\{/
|
112
|
+
text, self[key] = parse_field(text)
|
113
|
+
else
|
114
|
+
text, value = parse_field(text)
|
115
|
+
self[key] = Literal.new(value)
|
116
|
+
end
|
117
|
+
else
|
118
|
+
break
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
raise 'Expected closing }' unless text =~ /\A\s*\}/
|
124
|
+
$'
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def parse_field(text)
|
130
|
+
value = ''
|
131
|
+
count = 0
|
132
|
+
until text.empty?
|
133
|
+
case text
|
134
|
+
when /\A\{/
|
135
|
+
text = $'
|
136
|
+
value << $& if count > 0
|
137
|
+
count += 1
|
138
|
+
when /\A\}/
|
139
|
+
break if count == 0
|
140
|
+
count -= 1
|
141
|
+
text = $'
|
142
|
+
value << $& if count > 0
|
143
|
+
when /\A,/
|
144
|
+
text = $'
|
145
|
+
break if count == 0
|
146
|
+
value << $&
|
147
|
+
when /\A[^\}\{,]+/
|
148
|
+
text = $'
|
149
|
+
value << $&
|
150
|
+
else
|
151
|
+
break
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
raise 'Expected closing }' if count != 0
|
156
|
+
|
157
|
+
return text, value
|
158
|
+
end
|
159
|
+
|
160
|
+
def convert_key(key)
|
161
|
+
key.to_s.downcase.to_sym
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
data/lib/bibsync/transformer.rb
CHANGED
@@ -6,6 +6,23 @@ module BibSync
|
|
6
6
|
bib.each do |entry|
|
7
7
|
next if entry.comment?
|
8
8
|
|
9
|
+
# Fix math mode of title and abstract
|
10
|
+
[:title, :abstract].each do |k|
|
11
|
+
next unless v = entry[k]
|
12
|
+
|
13
|
+
parts = v.split('$', -1)
|
14
|
+
parts.each_with_index do |part, i|
|
15
|
+
if i % 2 == 0 # Not in math mode
|
16
|
+
|
17
|
+
# Fix underscores which are not wrapped by $
|
18
|
+
parts[i].gsub!(/(\s|\A)([^\s]*?_[^\s]*?)([:\.,]|(\-\w+))?(\s|\Z)/) do
|
19
|
+
"#{$1}$#{$2}$#{$3}#{$5}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
entry[k] = parts.join('$')
|
24
|
+
end
|
25
|
+
|
9
26
|
if entry[:author]
|
10
27
|
entry[:author] = entry[:author].gsub(/\{(\w+)\}/, '\\1').gsub(/#/, ' and ')
|
11
28
|
end
|
@@ -20,7 +37,7 @@ module BibSync
|
|
20
37
|
end
|
21
38
|
|
22
39
|
if entry[:month]
|
23
|
-
entry[:month] =
|
40
|
+
entry[:month] = Literal.new(entry[:month].downcase)
|
24
41
|
end
|
25
42
|
|
26
43
|
if entry[:journal]
|
data/lib/bibsync/utils.rb
CHANGED
@@ -32,7 +32,7 @@ module BibSync
|
|
32
32
|
|
33
33
|
def arxiv_id(arxiv, opts = {})
|
34
34
|
raise unless opts.include?(:prefix) && opts.include?(:version)
|
35
|
-
arxiv = arxiv[:arxiv] if
|
35
|
+
arxiv = arxiv[:arxiv] if Entry === arxiv
|
36
36
|
if arxiv
|
37
37
|
arxiv = arxiv.sub(/\A.*\//, '') unless opts[:prefix]
|
38
38
|
arxiv = arxiv.sub(/v\d+\Z/, '') unless opts[:version]
|
data/lib/bibsync/version.rb
CHANGED
data/lib/bibsync.rb
CHANGED
@@ -4,7 +4,9 @@ require 'date'
|
|
4
4
|
require 'pathname'
|
5
5
|
require 'bibsync/version'
|
6
6
|
require 'bibsync/utils'
|
7
|
+
require 'bibsync/log'
|
7
8
|
require 'bibsync/transformer'
|
8
9
|
require 'bibsync/bibliography'
|
9
|
-
require 'bibsync/
|
10
|
+
require 'bibsync/entry'
|
11
|
+
require 'bibsync/literal'
|
10
12
|
require 'bibsync/actions'
|
@@ -1,4 +1,22 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe BibSync::Actions::FetchFromArXiv do
|
4
|
+
before do
|
5
|
+
@tmpdir = File.join(testdir, 'tmp')
|
6
|
+
FileUtils.mkdir(@tmpdir)
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
FileUtils.rm_rf(@tmpdir)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:action) do
|
14
|
+
BibSync::Actions::FetchFromArXiv.new(dir: @tmpdir, fetch: %w(0911.2512v1 http://arxiv.org/abs/0911.1461))
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should download files' do
|
18
|
+
action.run
|
19
|
+
File.exists?(File.join(@tmpdir, '0911.2512v3.pdf')).must_equal true
|
20
|
+
File.exists?(File.join(@tmpdir, '0911.1461v3.pdf')).must_equal true
|
21
|
+
end
|
4
22
|
end
|
@@ -1,4 +1,25 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe BibSync::Actions::JabRefFormat do
|
4
|
+
before do
|
5
|
+
@tmpfile = File.join(fixturedir, 'tmp.bib')
|
6
|
+
FileUtils.copy(File.join(fixturedir, 'test.bib'), @tmpfile)
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
File.unlink(@tmpfile) if File.exists?(@tmpfile)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:bib) do
|
14
|
+
BibSync::Bibliography.new(@tmpfile)
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:action) do
|
18
|
+
BibSync::Actions::JabRefFormat.new(bib: bib)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should format file' do
|
22
|
+
action.run
|
23
|
+
File.read(@tmpfile).must_match(/created\s+with\s+JabRef/)
|
24
|
+
end
|
4
25
|
end
|
@@ -1,4 +1,33 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe BibSync::Actions::SynchronizeFiles do
|
4
|
+
before do
|
5
|
+
@tmpdir = File.join(fixturedir, 'tmp')
|
6
|
+
FileUtils.mkdir(@tmpdir)
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
FileUtils.rm_rf(@tmpdir)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:bib) do
|
14
|
+
BibSync::Bibliography.new(File.join(@tmpdir, 'test.bib'))
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:action) do
|
18
|
+
BibSync::Actions::SynchronizeFiles.new(bib: bib, dir: @tmpdir)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should synchronize files' do
|
22
|
+
10.times do |i|
|
23
|
+
bib << BibSync::Entry.new(key: i) if i % 2 == 0
|
24
|
+
FileUtils.touch(File.join(@tmpdir, "#{i}.pdf"))
|
25
|
+
end
|
26
|
+
bib.size.must_equal 5
|
27
|
+
action.run
|
28
|
+
bib.size.must_equal 10
|
29
|
+
10.times do |i|
|
30
|
+
bib[i].file[:name].must_equal "#{i}.pdf"
|
31
|
+
end
|
32
|
+
end
|
4
33
|
end
|
@@ -1,4 +1,15 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe BibSync::Actions::Validate do
|
4
|
+
let(:bib) do
|
5
|
+
BibSync::Bibliography.new(File.join(fixturedir, 'test.bib'))
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:action) do
|
9
|
+
BibSync::Actions::Validate.new(bib: bib)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should not raise an exception' do
|
13
|
+
action.run
|
14
|
+
end
|
4
15
|
end
|
data/test/helper.rb
CHANGED
data/test/test_bibliography.rb
CHANGED
@@ -29,7 +29,7 @@ describe BibSync::Bibliography do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'must be true after adding an entry' do
|
32
|
-
bib << BibSync::
|
32
|
+
bib << BibSync::Entry.new(key: 'test')
|
33
33
|
bib.dirty?.must_equal true
|
34
34
|
end
|
35
35
|
|
@@ -54,7 +54,7 @@ describe BibSync::Bibliography do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'must be false after adding an entry' do
|
57
|
-
newbib << BibSync::
|
57
|
+
newbib << BibSync::Entry.new(key: 'test')
|
58
58
|
newbib.empty?.must_equal false
|
59
59
|
end
|
60
60
|
end
|
@@ -66,7 +66,7 @@ describe BibSync::Bibliography do
|
|
66
66
|
|
67
67
|
it 'must increment after adding an entry' do
|
68
68
|
size = bib.size
|
69
|
-
bib << BibSync::
|
69
|
+
bib << BibSync::Entry.new(key: 'test')
|
70
70
|
bib.size.must_equal size + 1
|
71
71
|
end
|
72
72
|
end
|
@@ -77,7 +77,7 @@ describe BibSync::Bibliography do
|
|
77
77
|
end
|
78
78
|
|
79
79
|
it 'must return entry' do
|
80
|
-
bib['TestBook'].must_be_instance_of BibSync::
|
80
|
+
bib['TestBook'].must_be_instance_of BibSync::Entry
|
81
81
|
bib['TestBook'].key.must_equal 'TestBook'
|
82
82
|
end
|
83
83
|
end
|
@@ -106,7 +106,7 @@ describe BibSync::Bibliography do
|
|
106
106
|
it 'must iterate over entries' do
|
107
107
|
found = false
|
108
108
|
bib.each do |entry|
|
109
|
-
entry.must_be_instance_of BibSync::
|
109
|
+
entry.must_be_instance_of BibSync::Entry
|
110
110
|
found = true
|
111
111
|
end
|
112
112
|
found.must_equal true
|
@@ -118,7 +118,7 @@ describe BibSync::Bibliography do
|
|
118
118
|
|
119
119
|
describe '#<<' do
|
120
120
|
it 'must support adding an entry' do
|
121
|
-
entry = BibSync::
|
121
|
+
entry = BibSync::Entry.new(key: 'test')
|
122
122
|
bib << entry
|
123
123
|
bib['test'].must_be_same_as entry
|
124
124
|
end
|
@@ -136,87 +136,3 @@ describe BibSync::Bibliography do
|
|
136
136
|
describe '#to_s' do
|
137
137
|
end
|
138
138
|
end
|
139
|
-
|
140
|
-
describe BibSync::Bibliography::Entry do
|
141
|
-
describe '#self.parse' do
|
142
|
-
it 'should parse entry' do
|
143
|
-
entry = BibSync::Bibliography::Entry.parse(File.read(File.join(fixturedir, 'entry.bib')))
|
144
|
-
entry.type.must_equal 'BOOK'
|
145
|
-
entry.key.must_equal 'TestBook'
|
146
|
-
entry[:title].must_equal 'BookTitle'
|
147
|
-
entry[:publisher].must_equal 'BookPublisher'
|
148
|
-
entry[:year].must_equal '2000'
|
149
|
-
entry[:month].must_equal 'jan'
|
150
|
-
entry[:month].must_be_instance_of BibSync::Bibliography::RawValue
|
151
|
-
entry[:author].must_equal 'BookAuthor'
|
152
|
-
entry[:volume].must_equal 'BookVolume'
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
describe '#initialize' do
|
157
|
-
it 'should not set type and key' do
|
158
|
-
entry = BibSync::Bibliography::Entry.new
|
159
|
-
entry.type.must_be_nil
|
160
|
-
entry.key.must_be_nil
|
161
|
-
entry[:author].must_be_nil
|
162
|
-
end
|
163
|
-
|
164
|
-
it 'should initialize fields' do
|
165
|
-
entry = BibSync::Bibliography::Entry.new(type: 'ARTICLE', key: 'key', author: 'Daniel')
|
166
|
-
entry.type.must_equal 'ARTICLE'
|
167
|
-
entry.key.must_equal 'key'
|
168
|
-
entry[:author].must_equal 'Daniel'
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
describe '#file=' do
|
173
|
-
end
|
174
|
-
|
175
|
-
describe '#file' do
|
176
|
-
end
|
177
|
-
|
178
|
-
describe '#[]' do
|
179
|
-
end
|
180
|
-
|
181
|
-
describe '#[]=' do
|
182
|
-
end
|
183
|
-
|
184
|
-
describe '#delete' do
|
185
|
-
end
|
186
|
-
|
187
|
-
describe '#each' do
|
188
|
-
end
|
189
|
-
|
190
|
-
describe '#comment?' do
|
191
|
-
it 'should return true for a comment entry' do
|
192
|
-
BibSync::Bibliography::Entry.new(type: 'coMMent').comment?.must_equal true
|
193
|
-
end
|
194
|
-
|
195
|
-
it 'should return false for a non-comment entry' do
|
196
|
-
BibSync::Bibliography::Entry.new.comment?.must_equal false
|
197
|
-
BibSync::Bibliography::Entry.new(type: 'article').comment?.must_equal false
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
describe '#dirty!' do
|
202
|
-
end
|
203
|
-
|
204
|
-
describe '#to_s' do
|
205
|
-
end
|
206
|
-
|
207
|
-
describe '#parse' do
|
208
|
-
it 'should parse entry' do
|
209
|
-
entry = BibSync::Bibliography::Entry.new
|
210
|
-
entry.parse(File.read(File.join(fixturedir, 'entry.bib')))
|
211
|
-
entry.type.must_equal 'BOOK'
|
212
|
-
entry.key.must_equal 'TestBook'
|
213
|
-
entry[:title].must_equal 'BookTitle'
|
214
|
-
entry[:publisher].must_equal 'BookPublisher'
|
215
|
-
entry[:year].must_equal '2000'
|
216
|
-
entry[:month].must_equal 'jan'
|
217
|
-
entry[:month].must_be_instance_of BibSync::Bibliography::RawValue
|
218
|
-
entry[:author].must_equal 'BookAuthor'
|
219
|
-
entry[:volume].must_equal 'BookVolume'
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
data/test/test_entry.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
|
2
|
+
describe BibSync::Entry do
|
3
|
+
describe '#self.parse' do
|
4
|
+
it 'should parse entry' do
|
5
|
+
entry = BibSync::Entry.parse(File.read(File.join(fixturedir, 'entry.bib')))
|
6
|
+
entry.type.must_equal 'BOOK'
|
7
|
+
entry.key.must_equal 'TestBook'
|
8
|
+
entry[:title].must_equal 'BookTitle'
|
9
|
+
entry[:publisher].must_equal 'BookPublisher'
|
10
|
+
entry[:year].must_equal '2000'
|
11
|
+
entry[:month].must_equal 'jan'
|
12
|
+
entry[:month].must_be_instance_of BibSync::Literal
|
13
|
+
entry[:author].must_equal 'BookAuthor'
|
14
|
+
entry[:volume].must_equal 'BookVolume'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#initialize' do
|
19
|
+
it 'should not set type and key' do
|
20
|
+
entry = BibSync::Entry.new
|
21
|
+
entry.type.must_be_nil
|
22
|
+
entry.key.must_be_nil
|
23
|
+
entry[:author].must_be_nil
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should initialize fields' do
|
27
|
+
entry = BibSync::Entry.new(type: 'ARTICLE', key: 'key', author: 'Daniel')
|
28
|
+
entry.type.must_equal 'ARTICLE'
|
29
|
+
entry.key.must_equal 'key'
|
30
|
+
entry[:author].must_equal 'Daniel'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#file=' do
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#file' do
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#[]' do
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#[]=' do
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#delete' do
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#each' do
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#comment?' do
|
53
|
+
it 'should return true for a comment entry' do
|
54
|
+
BibSync::Entry.new(type: 'coMMent').comment?.must_equal true
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should return false for a non-comment entry' do
|
58
|
+
BibSync::Entry.new.comment?.must_equal false
|
59
|
+
BibSync::Entry.new(type: 'article').comment?.must_equal false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#dirty!' do
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#to_s' do
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#parse' do
|
70
|
+
it 'should parse entry' do
|
71
|
+
entry = BibSync::Entry.new
|
72
|
+
entry.parse(File.read(File.join(fixturedir, 'entry.bib')))
|
73
|
+
entry.type.must_equal 'BOOK'
|
74
|
+
entry.key.must_equal 'TestBook'
|
75
|
+
entry[:title].must_equal 'BookTitle'
|
76
|
+
entry[:publisher].must_equal 'BookPublisher'
|
77
|
+
entry[:year].must_equal '2000'
|
78
|
+
entry[:month].must_equal 'jan'
|
79
|
+
entry[:month].must_be_instance_of BibSync::Literal
|
80
|
+
entry[:author].must_equal 'BookAuthor'
|
81
|
+
entry[:volume].must_equal 'BookVolume'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
metadata
CHANGED
@@ -1,55 +1,62 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bibsync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Daniel Mendler
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-04-
|
12
|
+
date: 2013-04-09 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: nokogiri
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
|
-
- - '>='
|
19
|
+
- - ! '>='
|
18
20
|
- !ruby/object:Gem::Version
|
19
21
|
version: '0'
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
|
-
- - '>='
|
27
|
+
- - ! '>='
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '0'
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: rake
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
|
-
- - '>='
|
35
|
+
- - ! '>='
|
32
36
|
- !ruby/object:Gem::Version
|
33
37
|
version: '0'
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
|
-
- - '>='
|
43
|
+
- - ! '>='
|
39
44
|
- !ruby/object:Gem::Version
|
40
45
|
version: '0'
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: minitest
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
|
-
- - '>='
|
51
|
+
- - ! '>='
|
46
52
|
- !ruby/object:Gem::Version
|
47
53
|
version: '0'
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
|
-
- - '>='
|
59
|
+
- - ! '>='
|
53
60
|
- !ruby/object:Gem::Version
|
54
61
|
version: '0'
|
55
62
|
description: BibSync is a tool to synchronize scientific papers and BibTeX bibliography
|
@@ -75,12 +82,15 @@ files:
|
|
75
82
|
- lib/bibsync/actions/determine_arxiv_doi.rb
|
76
83
|
- lib/bibsync/actions/fetch_from_arxiv.rb
|
77
84
|
- lib/bibsync/actions/find_my_citations.rb
|
85
|
+
- lib/bibsync/actions/jabref.xml
|
78
86
|
- lib/bibsync/actions/jabref_format.rb
|
79
87
|
- lib/bibsync/actions/synchronize_files.rb
|
80
88
|
- lib/bibsync/actions/synchronize_metadata.rb
|
81
89
|
- lib/bibsync/actions/validate.rb
|
82
90
|
- lib/bibsync/bibliography.rb
|
83
91
|
- lib/bibsync/command.rb
|
92
|
+
- lib/bibsync/entry.rb
|
93
|
+
- lib/bibsync/literal.rb
|
84
94
|
- lib/bibsync/log.rb
|
85
95
|
- lib/bibsync/transformer.rb
|
86
96
|
- lib/bibsync/utils.rb
|
@@ -101,29 +111,31 @@ files:
|
|
101
111
|
- test/fixture/test.bib
|
102
112
|
- test/helper.rb
|
103
113
|
- test/test_bibliography.rb
|
114
|
+
- test/test_entry.rb
|
104
115
|
- test/test_utils.rb
|
105
116
|
homepage: https://github.com/minad/bibsync
|
106
117
|
licenses: []
|
107
|
-
metadata: {}
|
108
118
|
post_install_message:
|
109
119
|
rdoc_options: []
|
110
120
|
require_paths:
|
111
121
|
- lib
|
112
122
|
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
113
124
|
requirements:
|
114
|
-
- - '>='
|
125
|
+
- - ! '>='
|
115
126
|
- !ruby/object:Gem::Version
|
116
127
|
version: '0'
|
117
128
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
118
130
|
requirements:
|
119
|
-
- - '>='
|
131
|
+
- - ! '>='
|
120
132
|
- !ruby/object:Gem::Version
|
121
133
|
version: '0'
|
122
134
|
requirements: []
|
123
135
|
rubyforge_project: bibsync
|
124
|
-
rubygems_version:
|
136
|
+
rubygems_version: 1.8.24
|
125
137
|
signing_key:
|
126
|
-
specification_version:
|
138
|
+
specification_version: 3
|
127
139
|
summary: BibSync is a tool to synchronize scientific papers and BibTeX bibliography
|
128
140
|
files
|
129
141
|
test_files: []
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 21c0564e45a66b0339bf5b7bafaef25633adcd8e
|
4
|
-
data.tar.gz: 34a9ae41d395ba912e95accbb0c2cb87c8de69c3
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 46e87958376899e94b3bec951241bb02e3085f2e5141146477d9f8bb0de533e27c0c8d07b4c4e5a314f2d734cd386ee092362d38307e18a4d49303a746ad42c0
|
7
|
-
data.tar.gz: 46b15a8cf96461ce3fa3e45aef1585e6806177be668a20410ca940687c5d1f5667d30b1e76701b37503984c0a5ca0aa23025728b0154ee306c868ba8bcdaf1db
|