texzip 0.1.6 → 0.1.7
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/History.txt +3 -0
- data/lib/texzip/Project.rb +518 -512
- data/version.txt +1 -1
- metadata +1 -1
data/History.txt
CHANGED
data/lib/texzip/Project.rb
CHANGED
@@ -8,516 +8,522 @@ class TeXzip::Error < Exception; end
|
|
8
8
|
|
9
9
|
class TeXzip::Project < HighLine
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
11
|
+
PACKAGE_EXTENSIONS = %w(.sty .cls)
|
12
|
+
IMAGE_EXTENSIONS = %w(.png .jpg .pdf .eps .pstex)
|
13
|
+
TEXIMAGE_EXTENSIONS = %w(.pspdftex .pdf_t .pstex_t)
|
14
|
+
|
15
|
+
class Quit < Exception; end
|
16
|
+
|
17
|
+
attr_accessor :overwrite_all
|
18
|
+
|
19
|
+
class FilePath
|
20
|
+
def initialize(root_dir, file)
|
21
|
+
@root_dir = Pathname.new(root_dir).expand_path
|
22
|
+
@file = Pathname.new(file)
|
23
|
+
@file = @root_dir.join(file).expand_path.relative_path_from(@root_dir)
|
24
|
+
@out_file = @file
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_output_directory dir
|
28
|
+
@out_dir = Pathname.new(dir).expand_path
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_plain_output_directory dir
|
32
|
+
set_output_directory dir
|
33
|
+
@out_file = @file.basename
|
34
|
+
end
|
35
|
+
|
36
|
+
def file
|
37
|
+
@file
|
38
|
+
end
|
39
|
+
|
40
|
+
def out_file= file
|
41
|
+
@out_file = Pathname.new(file)
|
42
|
+
end
|
43
|
+
|
44
|
+
def output_path
|
45
|
+
@out_dir.join(@out_file).expand_path
|
46
|
+
end
|
47
|
+
|
48
|
+
def path
|
49
|
+
@root_dir.join(@file).expand_path
|
50
|
+
end
|
51
|
+
|
52
|
+
def extname
|
53
|
+
@file.extname
|
54
|
+
end
|
55
|
+
|
56
|
+
def hash
|
57
|
+
path.to_s.hash
|
58
|
+
end
|
59
|
+
|
60
|
+
def eql?(file_path)
|
61
|
+
path.to_s.eql? file_path.path.to_s
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def initialize( master_file )
|
66
|
+
super()
|
67
|
+
@tex_master_file = Pathname.new(master_file).expand_path
|
68
|
+
|
69
|
+
# All possible include-paths for TeX
|
70
|
+
@tex_dirs = [@tex_master_file.dirname]
|
71
|
+
@tex_dirs.concat((ENV["TEXINPUTS"] || "").split(':').map{|d| Pathname.new(d)})
|
72
|
+
@tex_dirs.map! &:expand_path
|
73
|
+
@tex_dirs.uniq!
|
74
|
+
|
75
|
+
@overwrite_all = false
|
76
|
+
|
77
|
+
parse_files
|
78
|
+
end
|
79
|
+
|
80
|
+
def parse_files
|
81
|
+
# The hash of all files, including the whole text.
|
82
|
+
@tex_files = {}
|
83
|
+
@image_files = Set.new
|
84
|
+
@bib_files = Set.new
|
85
|
+
@cites = Set.new
|
86
|
+
|
87
|
+
# Read all files recursively
|
88
|
+
unparsed_files = [@tex_master_file]
|
89
|
+
until unparsed_files.empty?
|
90
|
+
fname = unparsed_files.pop
|
91
|
+
file = find_file( fname )
|
92
|
+
if file.nil? then
|
93
|
+
if PACKAGE_EXTENSIONS.include? File.extname(fname)
|
94
|
+
next
|
95
|
+
else
|
96
|
+
raise TeXzip::Error, "Can't find file: #{fname}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
unless @tex_files.has_key? file
|
101
|
+
included_files = parse_file file
|
102
|
+
unparsed_files.concat included_files
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
unless @bib_files.empty?
|
107
|
+
@bib = BibTeX::Bibliography.new
|
108
|
+
@bib_files.each do |bib_file|
|
109
|
+
bib = BibTeX.open(bib_file.path)
|
110
|
+
bib.replace_strings
|
111
|
+
@bib.add(bib.data)
|
112
|
+
end
|
113
|
+
else
|
114
|
+
@bib = nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns the master-file's path.
|
119
|
+
def master_file
|
120
|
+
@tex_master_file
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns a list of included tex and sty files.
|
124
|
+
# @return [Array<Pathname>] Included tex files.
|
125
|
+
def tex_files
|
126
|
+
@tex_files.keys
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns a list of included image-files.
|
130
|
+
# @return [Array<Pathname>] Included image files.
|
131
|
+
def image_files
|
132
|
+
@image_files.to_a
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns a list of included BibTeX-files.
|
136
|
+
# @return [Array<Pathname>] Included BibTeX files.
|
137
|
+
def bib_files
|
138
|
+
@bib_files.to_a
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns a list of citations.
|
142
|
+
# @return [Array<String>] Citations.
|
143
|
+
def cites
|
144
|
+
@cites.to_a
|
145
|
+
end
|
146
|
+
|
147
|
+
# Returns the full path for a certain file.
|
148
|
+
#
|
149
|
+
# The file is searched in the current directory as well as all
|
150
|
+
# directories given by the environment variable +TEXINPUTS+
|
151
|
+
#
|
152
|
+
# @param [String] file The (relative) path of the file.
|
153
|
+
# @param [Array<String>] extensions The (possible) file extensions.
|
154
|
+
# @return [Pathname,nil] The path to the file if exist.
|
155
|
+
def find_file( file, extensions = [] )
|
156
|
+
extensions.unshift "" # the empty extension
|
157
|
+
extensions.uniq!
|
158
|
+
|
159
|
+
@tex_dirs.each do |d|
|
160
|
+
extensions.each do |ext|
|
161
|
+
file_path = d.join(file + ext).expand_path
|
162
|
+
if File.file? file_path
|
163
|
+
return FilePath.new(d, file + ext)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
return nil
|
168
|
+
end
|
169
|
+
|
170
|
+
# Returns the full paths for all variants of a certain file.
|
171
|
+
#
|
172
|
+
# The files are searched in the current directory as well as all
|
173
|
+
# directories given by the environment variable +TEXINPUTS+
|
174
|
+
#
|
175
|
+
# @param [String] file The base file-name.
|
176
|
+
# @param [Array<String>] extensions The possible file-extensions.
|
177
|
+
# @return [Array<Pathname>] All found files.
|
178
|
+
def find_files( file, extensions )
|
179
|
+
extensions.uniq!
|
180
|
+
|
181
|
+
files = []
|
182
|
+
|
183
|
+
extensions.each do |ext|
|
184
|
+
@tex_dirs.each do |d|
|
185
|
+
file_path = d.join(file + ext).expand_path
|
186
|
+
if file_path.file?
|
187
|
+
files << FilePath.new(d, file + ext)
|
188
|
+
break
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
files
|
194
|
+
end
|
195
|
+
|
196
|
+
# Load and parse a single tex-file.
|
197
|
+
#
|
198
|
+
# The file is parsed for commands including images, BibTeX-files
|
199
|
+
# and citations. The command along with the command's argument is
|
200
|
+
# passed to the block. The block is assumed to return a list of
|
201
|
+
# further tex-files to be parsed.
|
202
|
+
#
|
203
|
+
# @param [Pathname,String] file_name The name of the TeX-file to parse
|
204
|
+
# @return [Array<String>] A list of included TeX-files.
|
205
|
+
def parse_file file_name, &block
|
206
|
+
text = nil
|
207
|
+
File.open(file_name.path, "rb") do |f|
|
208
|
+
text = f.read
|
209
|
+
end
|
210
|
+
@tex_files[file_name] = text
|
211
|
+
|
212
|
+
block = method(:handle_command) unless block
|
213
|
+
|
214
|
+
included_files = []
|
215
|
+
text_without_comments = ""
|
216
|
+
text.each_line do |line|
|
217
|
+
comment_match = line.match /(?:\\)*%/
|
218
|
+
if comment_match and (comment_match.end(0) - comment_match.begin(0)).odd?
|
219
|
+
line = line[0...comment_match.end(0)]
|
220
|
+
end
|
221
|
+
text_without_comments.concat line
|
222
|
+
end
|
223
|
+
|
224
|
+
text_without_comments.scan(/\\(documentclass|usepackage|include|input|includegraphics|bibliography|cite)(?:\[[^\]]+\])?\{([^}]+)\}/) do |cmd, arg|
|
225
|
+
new_files = block.call cmd, arg
|
226
|
+
included_files.concat new_files if new_files
|
227
|
+
end
|
228
|
+
included_files
|
229
|
+
end
|
230
|
+
|
231
|
+
# Handles parsed commands.
|
232
|
+
def handle_command command, argument
|
233
|
+
case command
|
234
|
+
when "includegraphics"
|
235
|
+
add_image argument
|
236
|
+
when "bibliography"
|
237
|
+
argument.split(',').uniq.each{|f| add_bib f.strip}
|
238
|
+
when "usepackage"
|
239
|
+
return [argument + ".sty"]
|
240
|
+
when "documentclass"
|
241
|
+
return [argument + ".cls"]
|
242
|
+
when "cite"
|
243
|
+
@cites.merge argument.split(',').map(&:strip)
|
244
|
+
else
|
245
|
+
ext = File.extname(argument)
|
246
|
+
if TEXIMAGE_EXTENSIONS.include?(ext)
|
247
|
+
file = find_file(argument)
|
248
|
+
unless file
|
249
|
+
puts "WARNING: Can't find tex-image file #{argument}"
|
250
|
+
return nil
|
251
|
+
end
|
252
|
+
dir = File.dirname(argument)
|
253
|
+
parse_file file do |command, arg|
|
254
|
+
if command == "includegraphics"
|
255
|
+
add_image File.join(dir, arg)
|
256
|
+
else
|
257
|
+
raise TeXzip::Error, "Unexpected command '\\#{command}' in tex-image file: \\#{argument}"
|
258
|
+
end
|
259
|
+
nil
|
260
|
+
end
|
261
|
+
elsif ext != ".tex"
|
262
|
+
argument += ".tex"
|
263
|
+
end
|
264
|
+
return [argument]
|
265
|
+
end
|
266
|
+
return nil
|
267
|
+
end
|
268
|
+
|
269
|
+
# Adds an image to the list of included images.
|
270
|
+
# @param [String] image_file_name The path of the image-file
|
271
|
+
def add_image image_file_name
|
272
|
+
ext = File.extname(image_file_name)
|
273
|
+
if ext == ""
|
274
|
+
image_files = find_files( image_file_name, IMAGE_EXTENSIONS )
|
275
|
+
else
|
276
|
+
image_files = [find_file( image_file_name )].compact
|
277
|
+
end
|
278
|
+
|
279
|
+
if image_files.empty?
|
280
|
+
puts "WARNING: Can't find included image #{image_file_name}"
|
281
|
+
else
|
282
|
+
@image_files.merge image_files
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# Adds a BibTeX-file to the list of included BibTeX-files.
|
287
|
+
# @param [String] image_file_name The path of the BibTeX-file.
|
288
|
+
def add_bib bib_file_name
|
289
|
+
bib_file = find_file( bib_file_name, [".bib"] )
|
290
|
+
|
291
|
+
if bib_file.nil?
|
292
|
+
puts "WARNING: Can't find included BibTeX file #{bib_file_name}"
|
293
|
+
else
|
294
|
+
@bib_files.add bib_file
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def modify_files outdir, image_dir, plain_img, bibtex_file
|
299
|
+
@output_directory = Pathname.new(outdir).expand_path
|
300
|
+
@output_image_directory = @output_directory.join(Pathname.new(image_dir)).expand_path
|
301
|
+
@output_bibtex = @output_directory.join(Pathname.new(bibtex_file)).expand_path
|
302
|
+
@modified_files = {}
|
303
|
+
|
304
|
+
plain_img_files = Hash.new{|h,k| h[k] = []}
|
305
|
+
|
306
|
+
@tex_files.each_key do |file|
|
307
|
+
if TEXIMAGE_EXTENSIONS.include? file.extname
|
308
|
+
if plain_img
|
309
|
+
file.set_plain_output_directory @output_image_directory
|
310
|
+
plain_img_files[file.file.to_s] << file
|
311
|
+
else
|
312
|
+
file.set_output_directory @output_image_directory
|
313
|
+
end
|
314
|
+
else
|
315
|
+
file.set_output_directory @output_directory
|
316
|
+
end
|
317
|
+
end
|
318
|
+
@tex_files.each_pair do |file, text|
|
319
|
+
@modified_files[file] = update_file file, text, plain_img
|
320
|
+
end
|
321
|
+
|
322
|
+
@image_files.each do |file|
|
323
|
+
if plain_img
|
324
|
+
file.set_plain_output_directory @output_image_directory
|
325
|
+
plain_img_files[file.file.to_s] << file
|
326
|
+
else
|
327
|
+
file.set_output_directory @output_image_directory
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
# maybe rename some files
|
332
|
+
plain_img_files.each_pair do |fname, files|
|
333
|
+
ext = File.extname(fname)
|
334
|
+
next if files.size <= 1
|
335
|
+
# TODO: not supported when updating references
|
336
|
+
raise "Multiple images with the same name but different directories"
|
337
|
+
cnt = 2
|
338
|
+
files.each do |file|
|
339
|
+
loop do
|
340
|
+
new_fname = fname.basename.sub_ext("#{cnt}#{ext}")
|
341
|
+
if plain_img_files.include?(new_fname.to_s)
|
342
|
+
cnt += 1
|
343
|
+
else
|
344
|
+
file.out_file = new_fname
|
345
|
+
break
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
filter_bibtex
|
352
|
+
end
|
353
|
+
|
354
|
+
def update_file tex_file, text, plain
|
355
|
+
ext = tex_file.path.extname
|
356
|
+
|
357
|
+
new_text = ""
|
358
|
+
text.each_line do |line|
|
359
|
+
comment_match = line.match /(?:\\)*%/
|
360
|
+
if comment_match and (comment_match.end(0) - comment_match.begin(0)).odd?
|
361
|
+
comment = line[comment_match.end(0) .. -1]
|
362
|
+
line = line[0...comment_match.end(0)]
|
363
|
+
else
|
364
|
+
comment = ""
|
365
|
+
end
|
366
|
+
new_line = line.gsub(/(\\(include|input|includegraphics|bibliography)(?:\[[^\]]+\])?)\{([^}]+)\}/) { |m|
|
367
|
+
start = $1
|
368
|
+
cmd = $2
|
369
|
+
file = $3
|
370
|
+
if cmd == "includegraphics"
|
371
|
+
if TEXIMAGE_EXTENSIONS.include? ext
|
372
|
+
file = File.join(tex_file.file.dirname, file)
|
373
|
+
end
|
374
|
+
new_file = @output_image_directory.join(Pathname.new(file)).relative_path_from(@output_directory)
|
375
|
+
# TODO: this does not support multiple files with same name
|
376
|
+
new_file = @output_image_directory.join(new_file.basename).relative_path_from(@output_directory) if plain
|
377
|
+
elsif cmd == "bibliography"
|
378
|
+
new_file = @output_bibtex.basename.to_s.gsub(/\.bib$/, '')
|
379
|
+
else
|
380
|
+
if TEXIMAGE_EXTENSIONS.include? File.extname(file)
|
381
|
+
new_file = @output_image_directory.join(Pathname.new(file)).relative_path_from(@output_directory)
|
382
|
+
# TODO: this does not support multiple files with same name
|
383
|
+
new_file = @output_image_directory.join(new_file.basename).relative_path_from(@output_directory) if plain
|
384
|
+
else
|
385
|
+
new_file = @output_directory.join(Pathname.new(file)).relative_path_from(@output_directory)
|
386
|
+
end
|
387
|
+
end
|
388
|
+
"#{start}{#{new_file}}"
|
389
|
+
}
|
390
|
+
new_text.concat new_line
|
391
|
+
new_text.concat comment
|
392
|
+
end
|
393
|
+
|
394
|
+
return new_text
|
395
|
+
end
|
396
|
+
|
397
|
+
def filter_bibtex
|
398
|
+
if @bib
|
399
|
+
cites = @cites.to_a.map{|c| c.to_s}
|
400
|
+
seen_cites = cites.to_set
|
401
|
+
until cites.empty?
|
402
|
+
cite = cites.pop
|
403
|
+
entries = @bib[cite]
|
404
|
+
if entries.nil?
|
405
|
+
puts "WARNING: Can't find BibTeX-entry #{cite}"
|
406
|
+
else
|
407
|
+
entries = [entries] unless entries.kind_of? Array
|
408
|
+
entries.each do |entry|
|
409
|
+
crossref = entry["crossref"]
|
410
|
+
if crossref
|
411
|
+
crossref.split(',').map(&:strip).each do |ref|
|
412
|
+
ref = ref.to_s
|
413
|
+
cites << ref if seen_cites.add? ref
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
@bib = BibTeX::Bibliography.new.add(@bib.data.select{|entry| seen_cites.include? entry.key.to_s})
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
def write_files( force = false )
|
425
|
+
cwd = Pathname.getwd.expand_path
|
426
|
+
write_data do |path, data|
|
427
|
+
puts "Write file #{path.relative_path_from(cwd)}"
|
428
|
+
FileUtils.mkdir_p path.dirname unless path.dirname.exist?
|
429
|
+
if data.kind_of? Pathname
|
430
|
+
FileUtils.copy data, path
|
431
|
+
else
|
432
|
+
File.open(path, "wb") do |f|
|
433
|
+
f.write data
|
434
|
+
end
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
def write_archive( archive_file, force = false )
|
440
|
+
require 'ffi-libarchive'
|
441
|
+
|
442
|
+
archive_file = Pathname.new(archive_file).expand_path
|
443
|
+
return unless ask_overwrite(archive_file)
|
444
|
+
|
445
|
+
compression = case File.basename(archive_file.to_s)
|
446
|
+
when /\.tgz$/, /\.tar\.gz$/
|
447
|
+
:gzip
|
448
|
+
when /\.tbz2$/, /\.tar\.bz2$/
|
449
|
+
:bzip2
|
450
|
+
when /\.txz$/, /\.tar\.xz$/
|
451
|
+
:xz
|
452
|
+
when /\.tlzma$/, /\.tar\.lzma$/
|
453
|
+
:lzma
|
454
|
+
when /\.tZ$/, /\.tar\.Z$/
|
455
|
+
:Z
|
456
|
+
when /\.tar$/
|
457
|
+
:none
|
458
|
+
else
|
459
|
+
raise TeXzip::Error, "Can't derive archive-type from file name #{archive_file}"
|
460
|
+
end
|
461
|
+
|
462
|
+
puts "Write archive #{archive_file.relative_path_from(Pathname.getwd)}"
|
463
|
+
Archive.write_open_filename archive_file.to_s, compression, :tar do |ar|
|
464
|
+
write_data true do |path, data|
|
465
|
+
ar.add_entry do |e|
|
466
|
+
e.pathname = path.relative_path_from(@output_directory).to_s
|
467
|
+
if data.kind_of? Pathname
|
468
|
+
e.copy_stat(data.to_s)
|
469
|
+
File.open(data, "rb", &:read)
|
470
|
+
else
|
471
|
+
e.mode = 0644
|
472
|
+
e.atime = Time.now
|
473
|
+
e.mtime = Time.now
|
474
|
+
e.filetype = :file
|
475
|
+
data
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
def write_data( force = false, &block )
|
483
|
+
raise ArgumentError, "Block required" unless block
|
484
|
+
|
485
|
+
overwrite_all = force
|
486
|
+
commands = []
|
487
|
+
|
488
|
+
@modified_files.each_pair do |file, text|
|
489
|
+
if force or ask_overwrite(file.output_path)
|
490
|
+
commands << [file.output_path, text]
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
@image_files.each do |file|
|
495
|
+
if force or ask_overwrite(file.output_path)
|
496
|
+
commands << [file.output_path, file.path]
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
if @bib and (force or ask_overwrite(@output_bibtex))
|
501
|
+
commands << [@output_bibtex, @bib.to_s]
|
502
|
+
end
|
503
|
+
|
504
|
+
commands.each do |path, data|
|
505
|
+
block.call path, data
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
def ask_overwrite file
|
510
|
+
if !@overwrite_all and File.exist?(file)
|
511
|
+
ask("File #{file.relative_path_from(Pathname.getwd)} exists. Overwrite? [Ynaq]") do |q|
|
512
|
+
q.character = true
|
513
|
+
q.validate = /[ynaq\r ]/
|
514
|
+
q.case = :down
|
515
|
+
q.overwrite = false
|
516
|
+
q.answer_type = lambda{ |c|
|
517
|
+
case c
|
518
|
+
when "q"; raise Quit
|
519
|
+
when "y"; true
|
520
|
+
when "n"; false
|
521
|
+
when "a"; @overwrite_all = true; true
|
522
|
+
end
|
523
|
+
}
|
524
|
+
end
|
525
|
+
else
|
526
|
+
true
|
527
|
+
end
|
528
|
+
end
|
523
529
|
end
|
data/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.7
|