deplate 0.7.3 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. data/AUTHORS.TXT +3 -0
  2. data/CHANGES.TXT +248 -175
  3. data/LICENSE.TXT +0 -0
  4. data/NEWS.TXT +28 -24
  5. data/README.TXT +0 -0
  6. data/TODO.TXT +174 -88
  7. data/VERSION.TXT +1 -1
  8. data/bin/deplate +0 -0
  9. data/bin/deplate.bat +0 -0
  10. data/etc/deplate.ini +91 -3
  11. data/lib/action_view/helpers/deplate.rb +45 -0
  12. data/lib/deplate.rb +6 -1
  13. data/lib/deplate/abstract-class.rb +0 -0
  14. data/lib/deplate/bib.rb +576 -0
  15. data/lib/deplate/builtin.rb +0 -0
  16. data/lib/deplate/cache.rb +55 -5
  17. data/lib/deplate/commands.rb +346 -183
  18. data/lib/deplate/common.rb +209 -48
  19. data/lib/deplate/converter.rb +12 -6
  20. data/lib/deplate/core.rb +777 -378
  21. data/lib/deplate/counters.rb +254 -0
  22. data/lib/deplate/css/article.css +4 -3
  23. data/lib/deplate/css/deplate.css +121 -5
  24. data/lib/deplate/css/heading-navbar.css +0 -0
  25. data/lib/deplate/css/layout-deplate-print.css +0 -0
  26. data/lib/deplate/css/layout-deplate.css +0 -0
  27. data/lib/deplate/css/sans-serif.css +0 -0
  28. data/lib/deplate/css/serif-e.css +0 -0
  29. data/lib/deplate/css/serif-rel.css +0 -0
  30. data/lib/deplate/css/serif.css +9 -3
  31. data/lib/deplate/css/slides.css +0 -0
  32. data/lib/deplate/css/tabbar-left.css +0 -0
  33. data/lib/deplate/css/tabbar-right-ie.css +3 -9
  34. data/lib/deplate/css/tabbar-right.css +51 -18
  35. data/lib/deplate/css/tabbar-top.css +7 -1
  36. data/lib/deplate/css/tabbar.css +0 -0
  37. data/lib/deplate/css/text-sans-serif.css +0 -0
  38. data/lib/deplate/css/text-serif.css +0 -0
  39. data/lib/deplate/define.rb +183 -177
  40. data/lib/deplate/deplate-string.rb +82 -0
  41. data/lib/deplate/docbook.rb +236 -128
  42. data/lib/deplate/elements.rb +584 -417
  43. data/lib/deplate/etc.rb +163 -101
  44. data/lib/deplate/external.rb +42 -11
  45. data/lib/deplate/fmt/dbk-article-4.1.2.rb +0 -0
  46. data/lib/deplate/fmt/dbk-article.rb +0 -0
  47. data/lib/deplate/fmt/dbk-book.rb +0 -0
  48. data/lib/deplate/fmt/dbk-ref.rb +3 -3
  49. data/lib/deplate/fmt/dbk-slides.rb +0 -0
  50. data/lib/deplate/fmt/dbk-snippet.rb +0 -0
  51. data/lib/deplate/fmt/html-snippet.rb +0 -0
  52. data/lib/deplate/fmt/html.rb +783 -550
  53. data/lib/deplate/fmt/htmlsite.rb +192 -199
  54. data/lib/deplate/fmt/htmlslides.rb +0 -0
  55. data/lib/deplate/fmt/htmlwebsite.rb +3 -3
  56. data/lib/deplate/fmt/latex-snippet.rb +0 -0
  57. data/lib/deplate/fmt/latex.rb +242 -83
  58. data/lib/deplate/fmt/null.rb +32 -0
  59. data/lib/deplate/fmt/php.rb +4 -4
  60. data/lib/deplate/fmt/phpsite.rb +6 -5
  61. data/lib/deplate/fmt/plain.rb +160 -106
  62. data/lib/deplate/fmt/template.rb +0 -0
  63. data/lib/deplate/fmt/xhtml10t.rb +0 -0
  64. data/lib/deplate/formatter-snippet.rb +0 -0
  65. data/lib/deplate/formatter.rb +613 -301
  66. data/lib/deplate/input.rb +202 -142
  67. data/lib/deplate/input/deplate-headings.rb +4 -6
  68. data/lib/deplate/input/deplate-restricted.rb +15 -9
  69. data/lib/deplate/input/deplate.rb +2 -4
  70. data/lib/deplate/input/rdoc.rb +39 -38
  71. data/lib/deplate/input/template.rb +0 -0
  72. data/lib/deplate/lib/Makefile.config +29 -0
  73. data/lib/deplate/lib/latex/deplate.sty +54 -0
  74. data/lib/deplate/lib/latex/highlight-extra.sty +0 -0
  75. data/lib/deplate/lib/latex/highlight-typical.sty +0 -0
  76. data/lib/deplate/lib/php/page-comment.inc.php +216 -0
  77. data/lib/deplate/lib/tabmenu.js +0 -0
  78. data/lib/deplate/locale/de.latin1 +155 -17
  79. data/lib/deplate/locale/ru.koi8-r +0 -0
  80. data/lib/deplate/locale/zh_cn.gb2312 +0 -0
  81. data/lib/deplate/macros.rb +133 -82
  82. data/lib/deplate/messages.rb +6 -4
  83. data/lib/deplate/metadata.rb +0 -0
  84. data/lib/deplate/metadata/marshal.rb +0 -0
  85. data/lib/deplate/metadata/xml.rb +0 -0
  86. data/lib/deplate/metadata/yaml.rb +0 -0
  87. data/lib/deplate/mod/anyword.rb +3 -3
  88. data/lib/deplate/mod/babelfish.rb +4 -4
  89. data/lib/deplate/mod/code-gvim.rb +8 -4
  90. data/lib/deplate/mod/code-highlight.rb +3 -3
  91. data/lib/deplate/mod/colored-log.rb +0 -0
  92. data/lib/deplate/mod/de.rb +2 -2
  93. data/lib/deplate/mod/en.rb +0 -0
  94. data/lib/deplate/mod/endnotes.rb +0 -0
  95. data/lib/deplate/mod/fr.rb +0 -0
  96. data/lib/deplate/mod/html-asciimath.rb +0 -0
  97. data/lib/deplate/mod/html-deplate-button.rb +0 -0
  98. data/lib/deplate/mod/html-headings-navbar.rb +5 -13
  99. data/lib/deplate/mod/html-jsmath.rb +39 -0
  100. data/lib/deplate/mod/html-obfuscate-email.rb +3 -3
  101. data/lib/deplate/mod/html-sidebar.rb +0 -0
  102. data/lib/deplate/mod/htmlslides-navbar-fh.rb +3 -3
  103. data/lib/deplate/mod/iconv.rb +0 -0
  104. data/lib/deplate/mod/imgurl.rb +4 -4
  105. data/lib/deplate/mod/inlatex-compound.rb +7 -10
  106. data/lib/deplate/mod/koma.rb +0 -0
  107. data/lib/deplate/mod/latex-emph-table-head.rb +0 -0
  108. data/lib/deplate/mod/latex-styles.rb +7 -4
  109. data/lib/deplate/mod/latex-verbatim-small.rb +0 -0
  110. data/lib/deplate/mod/makefile.rb +23 -7
  111. data/lib/deplate/mod/mark-external-urls.rb +3 -3
  112. data/lib/deplate/mod/markup-1-warn.rb +10 -10
  113. data/lib/deplate/mod/markup-1.rb +0 -0
  114. data/lib/deplate/mod/navbar-png.rb +24 -8
  115. data/lib/deplate/mod/noindent.rb +0 -0
  116. data/lib/deplate/mod/numpara.rb +0 -0
  117. data/lib/deplate/mod/particle-math.rb +4 -4
  118. data/lib/deplate/mod/php-extra.rb +46 -6
  119. data/lib/deplate/mod/pstoedit.rb +0 -0
  120. data/lib/deplate/mod/recode.rb +0 -0
  121. data/lib/deplate/mod/ru_koi8-r.rb +0 -0
  122. data/lib/deplate/mod/smart-dash.rb +26 -0
  123. data/lib/deplate/mod/smiley.rb +69 -7
  124. data/lib/deplate/mod/soffice.rb +0 -0
  125. data/lib/deplate/mod/symbols-latin1.rb +14 -23
  126. data/lib/deplate/mod/symbols-od-utf-8.rb +5 -3
  127. data/lib/deplate/mod/symbols-plain.rb +5 -35
  128. data/lib/deplate/mod/symbols-sgml.rb +8 -9
  129. data/lib/deplate/mod/symbols-utf-8.rb +8 -9
  130. data/lib/deplate/mod/symbols-xml.rb +5 -9
  131. data/lib/deplate/mod/syntax-region-alt.rb +5 -5
  132. data/lib/deplate/mod/utf8.rb +0 -0
  133. data/lib/deplate/mod/validate-html.rb +0 -0
  134. data/lib/deplate/mod/xmlrpc.rb +0 -0
  135. data/lib/deplate/mod/zh-cn-autospace.rb +18 -20
  136. data/lib/deplate/mod/zh-cn.rb +4 -6
  137. data/lib/deplate/nukumi2.rb +71 -0
  138. data/lib/deplate/once-method.rb +0 -0
  139. data/lib/deplate/output.rb +19 -21
  140. data/lib/deplate/particles.rb +178 -116
  141. data/lib/deplate/regions.rb +99 -58
  142. data/lib/deplate/skeletons.rb +122 -0
  143. data/lib/deplate/structured.rb +164 -106
  144. data/lib/deplate/template.rb +67 -43
  145. data/lib/deplate/templates/html-doc.html +0 -0
  146. data/lib/deplate/templates/html-left-tabbar-js.html +0 -0
  147. data/lib/deplate/templates/html-left-tabbar.html +0 -0
  148. data/lib/deplate/templates/html-tabbar-right-pcomments.php +22 -0
  149. data/lib/deplate/templates/html-tabbar-right-step.html +24 -0
  150. data/lib/deplate/templates/html-tabbar-right-table.html +0 -0
  151. data/lib/deplate/templates/html-tabbar-right.html +2 -4
  152. data/lib/deplate/templates/html-tabbar-top.html +0 -9
  153. data/lib/deplate/templates/html-tabbar.html +0 -0
  154. data/lib/deplate/variables.rb +127 -0
  155. data/lib/deplate/wiki-markup.rb +99 -33
  156. data/lib/deplate/xml.rb +18 -18
  157. data/lib/deplate/zh-cn.rb +0 -0
  158. data/lib/ps2ppm.rb +0 -0
  159. data/man/man1/deplate.1 +564 -474
  160. metadata +201 -186
@@ -3,7 +3,7 @@
3
3
  # @Website: http://deplate.sf.net/
4
4
  # @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
5
5
  # @Created: 24-Feb-2004.
6
- # @Last Change: 02-Nov-2005.
6
+ # @Last Change: 07-Jun-2006.
7
7
 
8
8
  require 'uri'
9
9
  require 'optparse'
@@ -26,8 +26,11 @@ module Deplate; end
26
26
  class Deplate::Core
27
27
  extend Forwardable
28
28
 
29
- Version = '0.7.3'
30
- MicroRev = '2132'
29
+ Version = '0.8'
30
+ # VersionSfx = 'a'
31
+ VersionSfx = 'final'
32
+ MicroRev = '2711'
33
+
31
34
  if ENV['HOME']
32
35
  CfgDir = File.join(ENV['HOME'].gsub(/\\/, '/'), '.deplate')
33
36
  elsif ENV['USERPROFILE']
@@ -50,10 +53,6 @@ MESSAGE
50
53
  # FileCache = File.join(CfgDir, 'file_list.dat')
51
54
  FileCache = nil
52
55
 
53
- # The structure containing index definitions
54
- IndexEntry = Struct.new('DeplateIndexEntry', :name, :synonymes,
55
- :label, :file, :level_as_string)
56
-
57
56
  # If true, don't load user configuration files.
58
57
  @vanilla = false
59
58
 
@@ -123,6 +122,7 @@ MESSAGE
123
122
  :htmlslides_next => 57,
124
123
  :html_relations => 58,
125
124
  :css => 60,
125
+ :styles => 65,
126
126
  :javascript => 70,
127
127
  :head_end => 80,
128
128
  :body_beg => 90,
@@ -131,14 +131,14 @@ MESSAGE
131
131
  :body_pre => 105,
132
132
 
133
133
  #body
134
- :body_begin => 0,
134
+ :inner_body_begin => 0,
135
135
  :navbar_js => 4,
136
136
  :navbar_top => 5,
137
137
  :body_title => 20,
138
138
  :body => 50,
139
139
  :footnotes => 75,
140
140
  :navbar_bottom => 95,
141
- :body_end => 100,
141
+ :inner_body_end => 100,
142
142
 
143
143
  #post matter
144
144
  :body_post => 0,
@@ -156,6 +156,8 @@ MESSAGE
156
156
  # A hash of formatter names and corresponding classes
157
157
  @@formatter_classes = {}
158
158
 
159
+ @@bib_style = {}
160
+
159
161
  # A hash of names of input formats and corresponding classes
160
162
  @@input_classes = {}
161
163
 
@@ -195,15 +197,16 @@ MESSAGE
195
197
  options.ask_user = bool
196
198
  end
197
199
 
198
- opts.on('-A', '--allow ALLOW', 'Allow certain things: x, X, $') do |string|
199
- options.allow += string.strip.split(/[,; ]+/)
200
+ opts.on('-A', '--allow ALLOW',
201
+ 'Allow certain things: l, r, t, w, W, x, X, $') do |string|
202
+ allow(options.allow, string)
200
203
  log("options.allow = #{string}")
201
204
  end
202
205
 
203
206
  opts.on('-c', '--config FILE', String,
204
207
  'Alternative user cfg file') do |file|
205
208
  log("options.cfg = #{file}")
206
- options.cfg = file
209
+ options.cfg = [file]
207
210
  end
208
211
 
209
212
  opts.on('--[no-]clean', 'Clean up temporary files') do |b|
@@ -230,11 +233,13 @@ MESSAGE
230
233
 
231
234
  opts.on('-d', '--dir DIR', String, 'Output directory') do |dir|
232
235
  log("options.dir = #{dir}")
233
- if dir.kind_of?(String) and File.directory?(dir)
234
- options.dir = dir
235
- else
236
- log(["Directory doesn't exist", dir], :error)
237
- end
236
+ ensure_dir_exists(dir, options)
237
+ options.dir = dir
238
+ # if dir.kind_of?(String) and File.directory?(dir)
239
+ # options.dir = dir
240
+ # else
241
+ # log(["Directory doesn't exist", dir], :error)
242
+ # end
238
243
  end
239
244
 
240
245
  opts.on('-D', '--define NAME=VALUE', String,
@@ -243,13 +248,8 @@ MESSAGE
243
248
  if m
244
249
  k = m[1]
245
250
  v = m[3]
246
- if v
247
- v = remove_backslashes(v.gsub(/(^|[^\\])~/, '\\1 '))
248
- else
249
- v ='1'
250
- end
251
251
  log(%{options.variables[#{k}] = "#{v}"})
252
- options.variables[k] = v
252
+ canonic_args(options.variables, k, v)
253
253
  else
254
254
  log(["Malformed variable definition on command line", text], :error)
255
255
  end
@@ -323,7 +323,11 @@ MESSAGE
323
323
 
324
324
  opts.on('-o', '--out FILE', String, "Output to file or stdout ('-')") do |file|
325
325
  log("options.out = #{file}")
326
- options.out = file
326
+ d, f = File.split(file)
327
+ if d != '.'
328
+ options.dir = d
329
+ end
330
+ options.out = f
327
331
  options.explicitOut = true
328
332
  end
329
333
 
@@ -358,12 +362,22 @@ MESSAGE
358
362
  options.recurse_hierarchy = bool
359
363
  end
360
364
 
365
+ opts.on('-s', '--skeleton NAME', String, 'Make skeleton available') do |str|
366
+ log("options.skeletons << #{str}")
367
+ options.skeletons << str
368
+ end
369
+
361
370
  opts.on('--[no-]simple-names', 'Disable simple wiki names') do |bool|
362
371
  unless bool
363
372
  options.disabled_particles << Deplate::HyperLink::Simple
364
373
  end
365
374
  end
366
375
 
376
+ opts.on('--split-level LEVEL', Integer, 'Heading level for splitting') do |i|
377
+ log("options.split_level = #{i}")
378
+ options.split_level = i
379
+ end
380
+
367
381
  opts.on('--suffix SUFFIX', String, 'Suffix for output files') do |str|
368
382
  log("options.suffix = #{str}")
369
383
  options.suffix = str
@@ -374,7 +388,7 @@ MESSAGE
374
388
  log("options.template = #{@@templates[str]}")
375
389
  options.template = str
376
390
  else
377
- log(["Template not found", str], :error)
391
+ log(['Template not found', str], :error)
378
392
  exit 5
379
393
  end
380
394
  end
@@ -388,10 +402,10 @@ MESSAGE
388
402
  'Allow the execution of ruby code') do |level|
389
403
  if level
390
404
  options.allow_ruby = level
391
- options.allow << level
405
+ allow(options.allow, level)
392
406
  else
393
407
  options.allow_ruby = true
394
- options.allow << 'x'
408
+ allow(options.allow, 'x')
395
409
  end
396
410
  log("options.allow_ruby = #{options.allow_ruby}")
397
411
  end
@@ -399,7 +413,7 @@ MESSAGE
399
413
  opts.on('-X', '--[no-]allow-exec', '--[no-]external',
400
414
  'Allow the execution of helper applications') do |bool|
401
415
  options.allow_external = bool
402
- options.allow << 'X'
416
+ allow(options.allow, 'X')
403
417
  log("options.allow_external = #{bool}")
404
418
  end
405
419
 
@@ -467,6 +481,20 @@ MESSAGE
467
481
  exit 1
468
482
  end
469
483
 
484
+ opts.on_tail('--list-modules [REGEXP]', Regexp,
485
+ 'List modules matching a pattern') do |rx|
486
+ m = rx.nil? ? modules : modules.find_all {|n| n =~ rx}
487
+ puts m.join("\n")
488
+ exit 1
489
+ end
490
+
491
+ opts.on_tail('--list-css [REGEXP]', Regexp,
492
+ 'List css files matching a pattern') do |rx|
493
+ m = rx.nil? ? csss : csss.find_all {|n| n =~ rx}
494
+ puts m.join("\n")
495
+ exit 1
496
+ end
497
+
470
498
  opts.on_tail('--version', 'Show version') do
471
499
  puts version
472
500
  exit 0
@@ -479,6 +507,9 @@ MESSAGE
479
507
  end
480
508
 
481
509
  @@command_line_args = args.dup
510
+ if options.ini_command_line_arguments
511
+ args += options.ini_command_line_arguments
512
+ end
482
513
  options.files = opts.parse!(args)
483
514
 
484
515
  if options.list
@@ -508,7 +539,6 @@ MESSAGE
508
539
 
509
540
  if formatter_class
510
541
  f = options.files[0]
511
- options.dir ||= '.'
512
542
  case f
513
543
  when '-'
514
544
  options.ext = ''
@@ -519,7 +549,10 @@ MESSAGE
519
549
  options.srcdir ||= File.dirname(f)
520
550
  options.suffix ||= formatter_class.suffix
521
551
  if options.out
522
- options.out = options.dir ? File.join(options.dir, options.out) : options.out
552
+ options.out = Deplate::Core.file_join(options.dir, options.out)
553
+ # if options.out != '-'
554
+ # options.out = options.dir ? Deplate::Core.file_join(options.dir, options.out) : options.out
555
+ # end
523
556
  else
524
557
  options.out = get_out_fullname(f, options.suffix, options)
525
558
  end
@@ -549,13 +582,57 @@ MESSAGE
549
582
  require 'deplate/mod/en' unless @@messages_last
550
583
 
551
584
  # load general user config
552
- options.cfg ||= File.join(CfgDir, 'config.rb')
585
+ options.cfg ||= ['config.rb', CfgDir]
553
586
  unless options.vanilla
554
- user_config(options, options.cfg)
587
+ user_config(options, *options.cfg)
555
588
  user_setup(options) if defined?(user_setup)
556
589
  end
557
590
  end
558
591
 
592
+ # Set certain allow flags in array.
593
+ def allow(arr, ids)
594
+ case ids
595
+ when String
596
+ ids = ids.split(/[,; ]+/)
597
+ # ids = ids.scan(/[a-zA-Z.:]/)
598
+ when Array
599
+ else
600
+ log(['Internal error', 'allow', ids], :error)
601
+ end
602
+ ids.each do |i|
603
+ m = i[0..0]
604
+ case m
605
+ when '-'
606
+ arr.delete(i[1..-1])
607
+ when '+'
608
+ arr << i[1..-1]
609
+ else
610
+ arr << i
611
+ end
612
+ end
613
+ arr
614
+ end
615
+
616
+ # Check whether a certain action is allowed
617
+ def is_allowed?(options, ids, args={})
618
+ arr = options.allow
619
+ case ids
620
+ when String
621
+ ids = ids.split(/[,; ]/)
622
+ when Array
623
+ else
624
+ log(['Internal error', 'allow', ids], :error)
625
+ end
626
+ for i in ids
627
+ if arr.include?(i)
628
+ return true
629
+ end
630
+ end
631
+ logger = args[:logger]
632
+ logger.log(['No permission', ids.join(', ')], :anyway) if logger
633
+ return false
634
+ end
635
+
559
636
  # Read CfgDir/deplate.ini
560
637
  #
561
638
  # This file knows the following commands/entries
@@ -570,85 +647,91 @@ MESSAGE
570
647
  #
571
648
  # Lines beginning with one of ';#%' are considered comments.
572
649
  def read_ini(options)
573
- for inifile in [
574
- File.join(Dir.pwd, "deplate.rc", 'deplate.ini'),
575
- File.join(CfgDir, 'deplate.ini'),
576
- ]
577
- if File.exist?(inifile)
578
- ini = File.open(inifile) {|io| io.read}
579
- mode = :normal
580
- acc = []
581
- endm = nil
582
- setter = nil
583
- for line in ini
584
- line.chomp!
585
- case mode
586
- when :normal
587
- if line =~ /^\s*[;#%*]/
588
- # comment
589
- next
590
- elsif line =~ /^\s*mod\s+(\S+)/
591
- options.modules << $1
592
- elsif line =~ /^\s*fmt\s+(\S+)/
593
- options.fmt = $1
594
- elsif line =~ /^\s*clip\s+([^\s=]+)\s*=\s*(.+)/
595
- options.clips[$1] = $2
596
- elsif line =~ /^\s*wiki ([A-Z]+)(\.\w+)?\s*=\s*(.+)/
597
- Deplate::InterWiki.add($1, $3, $2)
598
- elsif line =~ /^\s*wikichars\s*(\S+)\s*(\S+)/
599
- Deplate::HyperLink.setup($1, $2)
600
- elsif line =~ /^\s*app\s*([_\w]+)\s*=\s*(.+)/
601
- Deplate::External.def_app $1, $2
602
- elsif line =~ /^\s*(option\s+|:)([_\w]+)([!~]|\s*([?%])?=\s*(.+))/
603
- case $3
604
- when '!'
605
- val = true
606
- when '~'
607
- val = false
608
- else
609
- case $4
610
- when '?'
611
- case $5
612
- when 'true', 'yes', 'on'
613
- val = true
614
- when 'false', 'no', 'off'
615
- val = false
616
- else
617
- Deplate::Core.log(['Malformed configuration line', line], :error)
618
- next
619
- end
620
- when '%'
621
- val = $5.to_i
650
+ read_ini_file(options, File.join(CfgDir, 'deplate.ini'))
651
+ read_ini_file(options, File.join(Dir.pwd, "deplate.rc", 'deplate.ini')) if is_allowed?(options, 'r')
652
+ end
653
+
654
+ def read_ini_file(options, inifile)
655
+ if File.exist?(inifile)
656
+ ini = File.open(inifile) {|io| io.read}
657
+ mode = :normal
658
+ acc = []
659
+ endm = nil
660
+ setter = nil
661
+ for line in ini
662
+ line.chomp!
663
+ case mode
664
+ when :normal
665
+ if line =~ /^\s*[;#%*]/
666
+ # comment
667
+ next
668
+ elsif line =~ /^(-\S+)(\s+(.*?)\s*)?$/
669
+ options.ini_command_line_arguments ||= []
670
+ options.ini_command_line_arguments << $1
671
+ options.ini_command_line_arguments << $3 if $3
672
+ elsif line =~ /^\s*allow\s+(.+?)\s*$/
673
+ allow(options.allow, $1)
674
+ elsif line =~ /^\s*mod\s+(\S+)/
675
+ options.modules << $1
676
+ elsif line =~ /^\s*fmt\s+(\S+)/
677
+ options.fmt = $1
678
+ elsif line =~ /^\s*clip\s+([^\s=]+)\s*=\s*(.+)/
679
+ options.clips[$1] = $2
680
+ elsif line =~ /^\s*wiki ([A-Z]+)(\.\w+)?\s*=\s*(.+)/
681
+ Deplate::InterWiki.add($1, $3, $2)
682
+ elsif line =~ /^\s*wikichars\s*(\S+)\s*(\S+)/
683
+ Deplate::HyperLink.setup($1, $2)
684
+ elsif line =~ /^\s*app\s*([_\w]+)\s*=\s*(.+)/
685
+ Deplate::External.def_app $1, $2
686
+ elsif line =~ /^\s*(option\s+|:)([_\w]+)([!~]|\s*([?%])?=\s*(.+))/
687
+ case $3
688
+ when '!'
689
+ val = true
690
+ when '~'
691
+ val = false
692
+ else
693
+ case $4
694
+ when '?'
695
+ case $5
696
+ when 'true', 'yes', 'on'
697
+ val = true
698
+ when 'false', 'no', 'off'
699
+ val = false
622
700
  else
623
- val = $5
701
+ Deplate::Core.log(['Malformed configuration line', line], :error)
702
+ next
624
703
  end
704
+ when '%'
705
+ val = $5.to_i
706
+ else
707
+ val = $5
625
708
  end
626
- options.send("#$2=", val)
627
- elsif line =~ /^\s*\$(\S+)\s*=\s*(.+)/
628
- ENV[$1] = $2
629
- elsif line =~ /^\s*(\S+)\s*=<<(.+)/
630
- mode = :multiline
631
- endm = $2
632
- setter = lambda {|val| options.variables[$1] = val}
633
- elsif line =~ /^\s*(\S+)\s*=\s*(.+)/
634
- options.variables[$1] = $2
635
- end
636
- when :multiline
637
- if line == endm
638
- setter.call(acc)
639
- acc = []
640
- mode = :normal
641
- else
642
- acc << line
643
709
  end
710
+ options.send("#$2=", val)
711
+ elsif line =~ /^\s*\$(\S+)\s*=\s*(.+)/
712
+ ENV[$1] = $2
713
+ elsif line =~ /^\s*(\S+)\s*=<<(.+)/
714
+ mode = :multiline
715
+ endm = $2
716
+ setter = lambda {|val| canonic_args(options.variables, $1, val)}
717
+ elsif line =~ /^\s*(\S+)\s*=\s*(.+)/
718
+ canonic_args(options.variables, $1, $2)
719
+ end
720
+ when :multiline
721
+ if line == endm
722
+ setter.call(acc)
723
+ acc = []
724
+ mode = :normal
644
725
  else
645
- raise "Invalid mode"
726
+ acc << line
646
727
  end
728
+ else
729
+ raise "Invalid mode"
647
730
  end
648
731
  end
649
732
  end
650
- end
651
-
733
+ end
734
+
652
735
  # Load the input definition if any.
653
736
  # options:: A OpenStruct as returned by Deplate::Core.deplate_options
654
737
  def require_input(options, input_name=nil)
@@ -661,8 +744,8 @@ MESSAGE
661
744
 
662
745
  # Load the formatter named in options.fmt.
663
746
  # options:: A OpenStruct as returned by Deplate::Core.deplate_options
664
- def require_formatter(options)
665
- fmt = options.fmt
747
+ def require_formatter(options, fmt=nil)
748
+ fmt ||= options.fmt
666
749
  if @@formatter_classes[fmt]
667
750
  Deplate::Core.log(['Formatter already loaded', fmt])
668
751
  else
@@ -670,8 +753,8 @@ MESSAGE
670
753
  fmtf = @@formatters[fmt]
671
754
  require fmtf
672
755
  end
673
- user_config(options, File.join(CfgDir, 'after', 'fmt', '%s.rb' % fmt))
674
- user_config(options, File.join(CfgDir, 'after', 'fmt', fmt))
756
+ user_config(options, File.join('after', 'fmt', '%s.rb' % fmt), CfgDir)
757
+ user_config(options, File.join('after', 'fmt', fmt), CfgDir)
675
758
  end
676
759
 
677
760
  # Load a module.
@@ -683,10 +766,12 @@ MESSAGE
683
766
  vsave, $VERBOSE = $VERBOSE, false
684
767
  begin
685
768
  require mf
686
- user_config(options, File.join(CfgDir, 'after', 'mod', '%s.rb' % module_name))
687
- user_config(options, File.join(CfgDir, 'after', 'mod', module_name))
769
+ user_config(options, File.join('after', 'mod', '%s.rb' % module_name), CfgDir)
770
+ user_config(options, File.join('after', 'mod', module_name), CfgDir)
771
+ return true
688
772
  rescue Exception => e
689
773
  Deplate::Core.log(["Loading module failed", module_name, e], :error)
774
+ return false
690
775
  ensure
691
776
  $VERBOSE = vsave
692
777
  end
@@ -710,17 +795,29 @@ MESSAGE
710
795
  # options:: A OpenStruct as returned by Deplate::Core.deplate_options
711
796
  # file:: Either a file name or a directory; if it is a
712
797
  # directory, all ruby files in that directory will be loaded
713
- def user_config(options, file)
798
+ def user_config(options, file, dir=nil)
714
799
  unless options.vanilla
715
- if File.exist?(file)
716
- if File.stat(file).directory?
717
- for f in Dir[File.join(file, '*.rb')]
718
- user_config(options, f)
719
- end
720
- else
721
- Deplate::Core.log(["Loading", file])
722
- load(file)
800
+ if dir
801
+ dirs = [dir]
802
+ dirs << File.join(current_pwd, 'deplate.rc') if is_allowed?(options, 'r')
803
+ for f in dirs
804
+ load_user_config(options, File.join(f, file))
723
805
  end
806
+ else
807
+ load_user_config(options, file)
808
+ end
809
+ end
810
+ end
811
+
812
+ def load_user_config(options, file)
813
+ if File.exist?(file)
814
+ if File.stat(file).directory?
815
+ for f in Dir[File.join(file, '*.rb')]
816
+ user_config(options, f)
817
+ end
818
+ else
819
+ Deplate::Core.log(["Loading", file])
820
+ load(file)
724
821
  end
725
822
  end
726
823
  end
@@ -736,13 +833,43 @@ MESSAGE
736
833
  options.variables ||= Deplate::Variables.new
737
834
  options.clips ||= {}
738
835
  options.ext ||= ''
739
- options.dir ||= '.'
836
+ # options.dir ||= '.'
740
837
  options.allow ||= []
838
+ options.skeletons ||= []
839
+ options.split_level ||= 1
741
840
  options.disabled_particles ||= []
841
+ options.autoindexed ||= []
842
+ reset_listings_and_counters(options, true)
742
843
  read_ini(options) unless inherit
743
844
  return options
744
845
  end
745
846
 
847
+ def reset_listings_and_counters(options, conditionally=false)
848
+ unless conditionally and options.counters
849
+ c = options.counters = Deplate::Counters.new(self)
850
+ c.def_counter('toc')
851
+ c.def_counter('lot', :parent => 'toc:1')
852
+ c.def_counter('lof', :parent => 'toc:1')
853
+ end
854
+ unless conditionally and options.listings
855
+ l = options.listings = Deplate::Listings.new(self)
856
+ l.def_listing('toc', nil,
857
+ 'prefix' => 'hd',
858
+ 'entity' => 'heading'
859
+ )
860
+ l.def_listing('lot', nil,
861
+ 'prefix' => 'tab',
862
+ # 'counter' => :tables,
863
+ 'entity' => 'table'
864
+ )
865
+ l.def_listing('lof', nil,
866
+ 'prefix' => 'fig',
867
+ # 'counter' => :figures,
868
+ 'entity' => 'figure'
869
+ )
870
+ end
871
+ end
872
+
746
873
  # Return the current version number as string.
747
874
  def version
748
875
  Deplate::Core::Version
@@ -750,7 +877,12 @@ MESSAGE
750
877
 
751
878
  # Return the current micorversion number as string.
752
879
  def microversion
753
- [Deplate::Core::Version, Deplate::Core::MicroRev].join('-')
880
+ [
881
+ Deplate::Core::Version,
882
+ Deplate::Core::VersionSfx,
883
+ '-',
884
+ Deplate::Core::MicroRev,
885
+ ].join
754
886
  end
755
887
 
756
888
  # Enable colored log output
@@ -759,7 +891,7 @@ MESSAGE
759
891
  unless @@colored_output
760
892
  unstopable_require('term/ansicolor') do
761
893
  eval <<-EOR
762
- class Color
894
+ class Deplate::Color
763
895
  class << self
764
896
  include Term::ANSIColor
765
897
  end
@@ -791,10 +923,15 @@ MESSAGE
791
923
  end
792
924
  modules, @@modules = collect_deplate_options('modules', 'mod')
793
925
  formatters, @@formatters = collect_deplate_options('formatters','fmt')
794
- csss, @@css = collect_deplate_options('css', 'css', '.css')
795
- templates, @@templates = collect_deplate_options('templates', 'templates', '')
796
926
  input_defs, @@input_defs = collect_deplate_options('input', 'input')
797
927
  meta_fmts, @@metadata_formats = collect_deplate_options('metadata', 'metadata')
928
+ csss, @@css = collect_deplate_options('css', 'css',
929
+ :suffix => '.css',
930
+ :rc => true)
931
+ templates, @@templates = collect_deplate_options('templates', 'templates',
932
+ :suffix => '',
933
+ :rc => true)
934
+
798
935
  if FileCache
799
936
  File.open(FileCache, 'w+') do |f|
800
937
  data = {
@@ -828,9 +965,83 @@ MESSAGE
828
965
  end
829
966
  end
830
967
 
968
+ def canonic_args(hash, key, val)
969
+ if key[-1..-1] == '!'
970
+ key = key[0..-2]
971
+ type = :bool
972
+ end
973
+ if key =~ /^no[A-Z]/
974
+ key = key[2..2].downcase + key[3..-1]
975
+ val = false
976
+ type = :bool
977
+ elsif val.nil?
978
+ type = :bool
979
+ val = true
980
+ else
981
+ case val
982
+ when nil, 'true'
983
+ type = :bool
984
+ val = true
985
+ when 'false'
986
+ type = :bool
987
+ val = false
988
+ else
989
+ type = :string
990
+ if val =~ /^"(.*?)"$/
991
+ val = val[1..-2]
992
+ else
993
+ val = val.strip
994
+ end
995
+ val = Deplate::Core.remove_backslashes(val)
996
+ end
997
+ end
998
+ case type
999
+ when :bool
1000
+ hash["no#{key[0..0].upcase}#{key[1..-1]}"] = !val
1001
+ end
1002
+ hash[key] = val
1003
+ hash
1004
+ end
1005
+
1006
+ def query_user(options, msg, results, rv=true)
1007
+ ok = if options and options.ask
1008
+ puts msg
1009
+ results.include?(gets.chomp)
1010
+ else
1011
+ true
1012
+ end
1013
+ ok ? rv : !rv
1014
+ end
1015
+
831
1016
  # Remove all backslashes from +text+
832
1017
  def remove_backslashes(text)
833
- return text.gsub(/\\(.)/, '\\1')
1018
+ return text.gsub(/\\(.)/, '\\1') if text
1019
+ end
1020
+
1021
+ def escape_characters(text, args)
1022
+ esc = args[:esc] || args[:escape] || args['esc'] || args['escape'] || ''
1023
+ ebs = args[:escapebackslash] || args['escapebackslash'] || 0
1024
+ case ebs
1025
+ when true
1026
+ ebs = 1
1027
+ else
1028
+ ebs = ebs.to_i
1029
+ end
1030
+ if esc.include?('\\')
1031
+ esc = esc.delete('\\')
1032
+ ebs ||= 1
1033
+ end
1034
+ if ebs > 0
1035
+ text = text.gsub(/\\/, '\\\\' * ebs)
1036
+ end
1037
+ unless esc.empty?
1038
+ text = text.gsub(/([#{esc}])/, '\\\\\\1')
1039
+ end
1040
+ text
1041
+ end
1042
+
1043
+ def authors_split(text)
1044
+ text.split(/\s+and\s+/) if text
834
1045
  end
835
1046
 
836
1047
  # Clean +idx+'s (a instance of Deplate::IndexEntry) name from backslashes
@@ -861,7 +1072,7 @@ MESSAGE
861
1072
  # Return the canonic file name for +name+. +maj+ and +min+
862
1073
  # correspond to section numbers.
863
1074
  def canonic_file_name(name, sfx, maj=nil, min=nil, dir=nil)
864
- name = File.basename(name, File.extname(name))
1075
+ name = File.basename(name, '.*')
865
1076
  name = clean_file_name(name)
866
1077
  if !name or (maj and maj != 0)
867
1078
  canonic_numbered_file_name(name, sfx, maj, min, dir)
@@ -876,18 +1087,28 @@ MESSAGE
876
1087
 
877
1088
  # Return a valid file name based on +text+
878
1089
  def clean_file_name(text, replacement='_')
879
- text.gsub(/[[:cntrl:].+*:"?<>|&\\\/]/, replacement) if text
1090
+ rx = /[[:cntrl:].+*:"?<>|&\\\/]/
1091
+ text.gsub(rx, replacement) if text
880
1092
  end
881
1093
 
882
1094
  # Make sure +dir+ exists
883
- def ensure_dir_exists(dir)
1095
+ def ensure_dir_exists(dir, options=nil)
884
1096
  unless File.exist?(dir) or dir.empty? or dir == '.'
885
- parent = File.dirname(dir)
886
- unless File.exist?(parent)
887
- ensure_dir_exists(parent)
1097
+ if !options or
1098
+ options.force or
1099
+ Deplate::Core.query_user(options,
1100
+ "Create directory '#{dir}' (y/N)? ",
1101
+ 'y')
1102
+ parent = File.dirname(dir)
1103
+ unless File.exist?(parent)
1104
+ ensure_dir_exists(parent, options)
1105
+ end
1106
+ Deplate::Core.log(["Creating directory", dir])
1107
+ Dir.mkdir(dir)
1108
+ else
1109
+ log(["Directory doesn't exist", dir, Dir.pwd], :error)
1110
+ exit 5
888
1111
  end
889
- Deplate::Core.log(["Creating directory", dir])
890
- Dir.mkdir(dir)
891
1112
  end
892
1113
  end
893
1114
 
@@ -904,7 +1125,7 @@ MESSAGE
904
1125
  end
905
1126
 
906
1127
  # Purge *path and return it as sting
907
- def get_path(*path)
1128
+ def file_join(*path)
908
1129
  path.compact!
909
1130
  path.delete(".")
910
1131
  path.delete("")
@@ -918,75 +1139,110 @@ MESSAGE
918
1139
  # maj:: The major section/page number
919
1140
  # maj:: The minor section/page number
920
1141
  def get_out_fullname(fname, suffix, options, *args)
921
- File.join(options.dir, get_out_name(fname, suffix, options, *args))
1142
+ # File.join(options.dir, get_out_name(fname, suffix, options, *args))
1143
+ file_join(options.dir, get_out_name(fname, suffix, options, *args))
922
1144
  end
923
1145
 
924
1146
  def get_out_name(fname, suffix, options, maj=nil, min=nil)
925
1147
  path = []
926
1148
  path << get_out_name_dir(fname, options)
927
1149
  if suffix
928
- fn = File.basename(fname, options.ext)
1150
+ fn = File.basename(fname, '.*')
929
1151
  path << canonic_file_name(fn, suffix, maj, min)
930
1152
  else
931
1153
  path << fname
932
1154
  end
933
- get_path(*path)
1155
+ file_join(*path)
934
1156
  end
935
1157
 
1158
+ def declare_symbols(name, klass)
1159
+ @@symbols[name] = klass
1160
+ end
1161
+
936
1162
  def declare_input_format(input_class, name=nil)
937
1163
  @@input_classes[name || input_class.myname] = input_class
938
1164
  end
939
1165
 
1166
+ def declare_bibstyle(bib_class, style)
1167
+ @@bib_style[style] = bib_class
1168
+ end
1169
+
940
1170
  # Make a formatter class publically known.
941
1171
  def declare_formatter(formatter_class, name=nil)
942
1172
  @@formatter_classes[formatter_class.myname] = formatter_class
943
- name = (name || formatter_class.myname).gsub(/\W/, '_')
944
- self.class_eval %{
945
- def to_#{name}(text, sourcename=nil)
946
- format_with_formatter(#{formatter_class}, text, sourcename)
947
- end
948
- }
949
- # class << self
950
- # define_method("to_#{name}") do |text, *args|
951
- # sourcename, _ = args
952
- # format_with_formatter(formatter_class, text, sourcename)
953
- # end
954
- # end
1173
+ name = (name || formatter_class.myname).gsub(/[^[:alnum:]_]/, '_')
1174
+ self.class_eval do
1175
+ define_method("to_#{name}") do |text, *args|
1176
+ sourcename, _ = args
1177
+ reset(true)
1178
+ format_with_formatter(formatter_class, text, sourcename)
1179
+ end
1180
+ end
955
1181
  end
956
1182
 
957
1183
  # Collect all available modules/parts/libraries etc. Check the
958
1184
  # file system and the "builtin" modules (e.g., when using the
959
1185
  # win32 exerb distribution).
960
- def collect_deplate_options(id=nil, subdir='', suffix='.rb')
961
- hash = {}
962
- for d in library_directories(subdir)
1186
+ def collect_deplate_options(id=nil, subdir='', args={})
1187
+ suffix = args[:suffix] || '.rb'
1188
+ use_rc = args[:rc] || false
1189
+ hash = {}
1190
+ for d in library_directories(use_rc, subdir)
963
1191
  collect_deplate_options_in_hash(hash, suffix, Dir[File.join(d, '*%s' % suffix)])
964
1192
  end
965
1193
 
966
1194
  builtin = "builtin_#{id}"
967
1195
  if id and respond_to?(builtin)
968
- collect_deplate_options_in_hash(hash, suffix, send(builtin), File.join('deplate', subdir))
1196
+ files = send(builtin)
1197
+ # files.collect! {|f| "#{f}.rb"}
1198
+ collect_deplate_options_in_hash(hash, suffix, files, File.join('deplate', subdir))
969
1199
  end
970
-
1200
+
971
1201
  return hash.keys.sort, hash
972
1202
  end
973
1203
 
974
1204
  # Return an array of directorys that could contain deplate
975
1205
  # files.
976
- def library_directories(*subdirs)
1206
+ def library_directories(use_rc, *subdirs)
977
1207
  @library_directories ||= {}
978
- id = File.join(*subdirs)
979
- unless @library_directories[id]
980
- dirs = []
981
- dirs << File.join(CfgDir, *subdirs) unless @vanilla
982
- dirs << File.join(DataDir, *subdirs)
983
- dirs << File.join(LibDir, *subdirs)
984
- dirs.delete_if {|d| !File.exist?(d)}
985
- @library_directories[id] = dirs
1208
+ acc = []
1209
+ dirs = [DataDir, LibDir]
1210
+ dirs.unshift(CfgDir) unless @vanilla
1211
+ dirs.unshift(File.join(current_pwd, 'deplate.rc')) if use_rc
1212
+ for subdir in subdirs
1213
+ unless @library_directories[subdir]
1214
+ ad = []
1215
+ for dir in dirs
1216
+ if dir
1217
+ fd = File.join(dir, subdir)
1218
+ if File.exist?(fd)
1219
+ ad << fd
1220
+ end
1221
+ end
1222
+ end
1223
+ @library_directories[subdir] = ad
1224
+ end
1225
+ acc += @library_directories[subdir]
986
1226
  end
987
- @library_directories[id]
1227
+ acc
988
1228
  end
989
1229
 
1230
+ def is_file?(fname)
1231
+ return !fname.empty? && File.exists?(fname) && !File.directory?(fname)
1232
+ end
1233
+
1234
+ def current_pwd(deplate=nil)
1235
+ if deplate and deplate.current_source
1236
+ File.dirname(deplate.current_source)
1237
+ else
1238
+ Dir.pwd
1239
+ end
1240
+ end
1241
+
1242
+ def quiet?
1243
+ @@quiet
1244
+ end
1245
+
990
1246
  private
991
1247
  # Return the localized text.
992
1248
  def msg(text)
@@ -998,8 +1254,8 @@ MESSAGE
998
1254
  end
999
1255
 
1000
1256
  # Return the proper numbered output filename for name.
1001
- def canonic_numbered_file_name(name, sfx, maj, min, dir=nil)
1002
- name = File.basename(name, File.extname(name))
1257
+ def canonic_numbered_file_name(name, sfx, maj=0, min=0, dir=nil)
1258
+ name = File.basename(name, '.*')
1003
1259
  if min == 0
1004
1260
  idx = '%05d' % maj
1005
1261
  else
@@ -1012,9 +1268,11 @@ MESSAGE
1012
1268
  # Collect files in +array+ in +hash+.
1013
1269
  def collect_deplate_options_in_hash(hash, suffix, array, subdir=nil)
1014
1270
  for m in array
1015
- key = File.basename(m, suffix) || m
1016
- hash[key] ||= subdir ? File.join(subdir, m) : m
1017
- hash[key] ||= subdir ? File.join(subdir, m) : m
1271
+ unless !subdir and File.directory?(m)
1272
+ key = File.basename(m, suffix) || m
1273
+ hash[key] ||= subdir ? File.join(subdir, m) : m
1274
+ hash[key] ||= subdir ? File.join(subdir, m) : m
1275
+ end
1018
1276
  end
1019
1277
  end
1020
1278
 
@@ -1119,32 +1377,32 @@ MESSAGE
1119
1377
  def log_build_colored_message(text, condition, file=nil, line_begin=nil, line_end=nil)
1120
1378
  msg = []
1121
1379
  if file
1122
- msg << Color.green << Color.bold(file)
1123
- msg << Color.yellow << ':'
1380
+ msg << Deplate::Color.green << Deplate::Color.bold(file)
1381
+ msg << Deplate::Color.yellow << ':'
1124
1382
  if line_begin
1125
- msg << Color.cyan
1383
+ msg << Deplate::Color.cyan
1126
1384
  msg << line_begin
1127
1385
  msg << '-' << line_end if line_end and line_end != line_begin
1128
- msg << Color.yellow
1386
+ msg << Deplate::Color.yellow
1129
1387
  msg << ':'
1130
1388
  end
1131
1389
  case condition
1132
1390
  when :error, :unknown_macro
1133
- msg << Color.red
1391
+ msg << Deplate::Color.red
1134
1392
  else
1135
- msg << Color.blue
1393
+ msg << Deplate::Color.blue
1136
1394
  end
1137
1395
  msg << text
1138
1396
  else
1139
1397
  case condition
1140
1398
  when :error, :unknown_macro
1141
- msg << Color.red
1399
+ msg << Deplate::Color.red
1142
1400
  else
1143
- msg << Color.magenta
1401
+ msg << Deplate::Color.magenta
1144
1402
  end
1145
1403
  msg << text
1146
1404
  end
1147
- msg << Color.clear
1405
+ msg << Deplate::Color.clear
1148
1406
  return msg.join
1149
1407
  end
1150
1408
 
@@ -1184,9 +1442,6 @@ MESSAGE
1184
1442
  # A hash that holds the current document's variables.
1185
1443
  attr_accessor :variables
1186
1444
 
1187
- # A hash holding all known document services (names => method).
1188
- attr_accessor :doc_services
1189
-
1190
1445
  # Other document specific variables.
1191
1446
  # A hash containing the footnotes (id => object)
1192
1447
  attr_accessor :footnotes
@@ -1208,8 +1463,6 @@ MESSAGE
1208
1463
  # A hash (label => level_string). Use of this hash should be
1209
1464
  # replaced with uses of @label_aliases<+TBD+>
1210
1465
  attr_accessor :labels
1211
- # An array (unused!!!???<+TBD+>)
1212
- attr_accessor :labels_named
1213
1466
  # An array used to postpone labels until there is some regular
1214
1467
  # output.
1215
1468
  attr_accessor :labels_floating
@@ -1241,13 +1494,12 @@ MESSAGE
1241
1494
  # other elements.
1242
1495
  attr_accessor :postponed_print
1243
1496
 
1244
- attr_accessor :current_source, :current_heading, :current_table, :current_figure
1245
- attr_accessor :current_source_stats, :current_top
1246
- attr_accessor :table_of_contents, :table_of_tables, :table_of_figures
1497
+ attr_accessor :current_source, :current_source_stats
1247
1498
 
1248
1499
  # a stack with if/elseif status; skip input if the top-switch is true
1249
1500
  attr_accessor :switches
1250
1501
 
1502
+
1251
1503
  # formatter_name:: A formatter name
1252
1504
  # args:: A hash
1253
1505
  def initialize(formatter_name='html', args={})
@@ -1256,7 +1508,6 @@ MESSAGE
1256
1508
  @options = Deplate::Core.deplate_options(args[:options])
1257
1509
  @sources = args[:sources] || @options.files
1258
1510
  @dest = args[:dest] || @options.out || ''
1259
- @doc_services = args[:doc_services] || initialize_services
1260
1511
  @vanilla = args[:vanilla] || false
1261
1512
 
1262
1513
  # set_safe
@@ -1270,33 +1521,33 @@ MESSAGE
1270
1521
 
1271
1522
  formatter_class = args[:formatter] || @@formatter_classes[formatter_name]
1272
1523
  if formatter_class
1273
- Deplate::Core.log('Initializing formatter')
1524
+ log('Initializing formatter')
1274
1525
  @formatter = formatter_class.new(self, args)
1275
1526
  call_methods_matching(self, /^formatter_initialize_/)
1276
1527
  call_methods_matching(@formatter, /^formatter_initialize_/)
1277
1528
 
1278
- Deplate::Core.log('Initializing modules')
1529
+ log('Initializing modules')
1279
1530
  call_methods_matching(self, /^module_initialize_/)
1280
1531
 
1281
- Deplate::Core.log('Setting up text scanner')
1532
+ log('Setting up text scanner')
1282
1533
  call_methods_matching(self, /^input_initialize_/)
1283
1534
  call_methods_matching(self, /^hook_pre_input_initialize_/)
1284
1535
  initialize_input(args)
1285
1536
  call_methods_matching(self, /^hook_post_input_initialize_/)
1286
1537
 
1287
- Deplate::Core.log('Setting up formatter')
1538
+ log('Setting up formatter')
1288
1539
  call_methods_matching(@formatter, /^hook_pre_setup_/)
1289
1540
  @formatter.setup
1290
1541
  call_methods_matching(@formatter, /^hook_post_setup_/)
1291
1542
 
1292
- Deplate::Core.log('User initialization')
1543
+ log('User initialization')
1293
1544
  user_initialize if defined?(user_initialize)
1294
1545
 
1295
1546
  reset_output
1296
1547
  set_standard_clips
1297
1548
 
1298
1549
  if args[:now]
1299
- Deplate::Core.log('Here we go ...')
1550
+ log('Here we go ...')
1300
1551
  call_methods_matching(self, /^hook_pre_go_/)
1301
1552
  call_methods_matching(@formatter, /^hook_pre_go_/)
1302
1553
  go_now
@@ -1332,6 +1583,8 @@ MESSAGE
1332
1583
  end
1333
1584
  end
1334
1585
 
1586
+ # Change the input format to +name+.
1587
+ # name:: The name of an input format.
1335
1588
  def push_input_format(name)
1336
1589
  unless name
1337
1590
  return false
@@ -1351,6 +1604,9 @@ MESSAGE
1351
1604
  end
1352
1605
  end
1353
1606
 
1607
+ # Restore the previously used input format. If a +name+ is given and
1608
+ # the name matches the previous input format, do nothing.
1609
+ # name:: The name of an input format.
1354
1610
  def pop_input_format(name=nil)
1355
1611
  if @input_formats.empty?
1356
1612
  return false
@@ -1389,9 +1645,9 @@ MESSAGE
1389
1645
  end
1390
1646
  val = slot_names[slot]
1391
1647
  if val
1392
- val * modi
1648
+ return val * modi
1393
1649
  else
1394
- nil
1650
+ return nil
1395
1651
  end
1396
1652
  elsif slot.is_a?(String)
1397
1653
  pos = 0
@@ -1412,27 +1668,25 @@ MESSAGE
1412
1668
  end
1413
1669
  end
1414
1670
 
1415
- # Initialize symbol related modules.
1416
- def initialize_symbols
1417
- Deplate::Core.log("Initializing symbols")
1418
- call_methods_matching(self, /^initialize_symbols_/)
1419
- end
1420
-
1421
1671
  # Call all of obj's methods matching rx
1422
1672
  def call_methods_matching(obj, rx, *args)
1423
1673
  unless @vanilla
1424
- for m in obj.methods.find_all {|m| m =~ rx }
1674
+ for m in matching_methods(obj, rx)
1425
1675
  obj.send(m, *args)
1426
1676
  end
1427
1677
  end
1428
1678
  end
1429
-
1679
+
1680
+ def matching_methods(obj, rx)
1681
+ obj.methods.find_all {|m| m =~ rx }
1682
+ end
1683
+
1430
1684
  # Reset instance variables.
1431
1685
  # all:: reset really all variables (bool)
1432
1686
  def reset(all=false)
1433
1687
  @current_source = nil
1434
1688
  @current_source_stats = nil
1435
- @auto_filenames = {}
1689
+ @auto_numbered = {}
1436
1690
 
1437
1691
  @variables = @options.variables.dup
1438
1692
  @variables.deplate = self
@@ -1442,7 +1696,6 @@ MESSAGE
1442
1696
  @index_last_idx = 0
1443
1697
  @labels = {}
1444
1698
  @label_aliases = {}
1445
- @labels_named = []
1446
1699
  @labels_floating = []
1447
1700
  @ids = {}
1448
1701
  @preprocess = []
@@ -1454,22 +1707,15 @@ MESSAGE
1454
1707
 
1455
1708
  @headings = {}
1456
1709
 
1457
- @table_of_contents = []
1458
- @table_of_tables = []
1459
- @table_of_figures = []
1460
-
1461
- @current_heading = []
1462
1710
  @accum_elements = []
1463
1711
  @switches = []
1464
1712
  @metadata = {}
1465
1713
 
1466
- @current_figure = 0
1467
- @current_table = 0
1468
-
1469
1714
  set_lang(@@messages_last)
1470
1715
  set_standard_clips
1471
1716
 
1472
1717
  if all
1718
+ @endmessages = {}
1473
1719
  @allsources = {}
1474
1720
  @input_formats = []
1475
1721
  @options.citations = []
@@ -1477,6 +1723,7 @@ MESSAGE
1477
1723
  @options.dont_index = []
1478
1724
  @options.author = []
1479
1725
  @options.heading_names = []
1726
+ Deplate::Core.reset_listings_and_counters(@options)
1480
1727
  end
1481
1728
  end
1482
1729
 
@@ -1484,14 +1731,14 @@ MESSAGE
1484
1731
  # inherit_null_output:: The new output obj inherits the settings from the
1485
1732
  # initial/anonymous output class (bool)
1486
1733
  def reset_output(inherit_null_output=true)
1487
- log("Reset output", :debug)
1734
+ log('Reset output', :debug)
1488
1735
  @collected_output = []
1489
1736
  @output_filename = []
1490
1737
  @output_headings = []
1491
1738
  @output_maj_min = [0, 0]
1492
1739
  @null_output = @output.dup
1493
1740
  if @options.multi_file_output
1494
- dest = @variables["docBasename"] || @dest
1741
+ dest = @variables['docBasename'] || @dest
1495
1742
  dest &&= File.basename(dest)
1496
1743
  # Deplate::Core.canonic_file_name(dest, @options.suffix, 0, 0)
1497
1744
  else
@@ -1521,8 +1768,11 @@ MESSAGE
1521
1768
  if msg_class
1522
1769
  @options.messages = msg_class.new(self)
1523
1770
  @@message_object ||= @options.messages
1771
+ elsif is_allowed?('l') and require_module(lang)
1772
+ set_lang(lang)
1524
1773
  else
1525
- log(["Bad language definition", lang, "(#{@@messages.keys.join(', ')})"], :error)
1774
+ log(["Bad language definition", lang, "(#{@@messages.keys.join(', ')})"],
1775
+ :error)
1526
1776
  end
1527
1777
  end
1528
1778
 
@@ -1531,6 +1781,20 @@ MESSAGE
1531
1781
  self.class.log(*args)
1532
1782
  end
1533
1783
 
1784
+ # Register a new message to be displayed after processing the
1785
+ # current document.
1786
+ def endmessage(id, message)
1787
+ @endmessages[id] = message
1788
+ end
1789
+
1790
+ # Print messages after having printed the current document.
1791
+ def print_endmessages
1792
+ @endmessages.each do |id, message|
1793
+ log([message], :anyway)
1794
+ end
1795
+ @endmessages = {}
1796
+ end
1797
+
1534
1798
  # See Deplate::Core.require_module.
1535
1799
  def require_module(m)
1536
1800
  Deplate::Core.require_module(@options, m)
@@ -1587,17 +1851,9 @@ MESSAGE
1587
1851
  read_file
1588
1852
  process_document
1589
1853
  body_write if writeFile
1854
+ print_endmessages
1590
1855
  end
1591
1856
 
1592
- # Return the index for a top heading.
1593
- def output_index(top=nil)
1594
- if top
1595
- top_heading_idx(top)
1596
- else
1597
- @collected_output.size - 1
1598
- end
1599
- end
1600
-
1601
1857
  # Should the file be included or not, e.g., because of a -P
1602
1858
  # command line option
1603
1859
  def to_be_included?(file)
@@ -1627,9 +1883,18 @@ MESSAGE
1627
1883
  # Get the name for automatically generated auxiliary files (e.g.,
1628
1884
  # when no ID was provided)
1629
1885
  def auxiliary_auto_filename(type, idx, body=nil, suffix=nil)
1630
- fn = ["_#{type}_#{idx}"]
1631
- fn << '.' << suffix if suffix
1632
- return fn.join
1886
+ if @variables['mandatoryID']
1887
+ raise msg('No ID given')
1888
+ else
1889
+ prefix = @variables['prefixID']
1890
+ if prefix.nil?
1891
+ prefix = Deplate::Core.clean_file_name(File.basename(@dest, '.*'))
1892
+ end
1893
+ fn = [prefix]
1894
+ fn << ["_#{type}_#{idx}"]
1895
+ fn << '.' << suffix if suffix
1896
+ return fn.join
1897
+ end
1633
1898
  end
1634
1899
 
1635
1900
  # Get the proper filename for an auxiliary file, respecting
@@ -1637,7 +1902,7 @@ MESSAGE
1637
1902
  def auxiliary_filename(filename, full_name=false)
1638
1903
  sd = auxiliary_dirname(full_name)
1639
1904
  if sd
1640
- return Deplate::Core.get_path(sd, filename)
1905
+ return Deplate::Core.file_join(sd, filename)
1641
1906
  else
1642
1907
  return filename
1643
1908
  end
@@ -1648,11 +1913,16 @@ MESSAGE
1648
1913
  # - If auxiliaryDirSuffix isn't defined, return default if non-nil.
1649
1914
  # - Create dir if ensure_dir_exists is true.
1650
1915
  def auxiliary_dirname(full_name=false, ensure_dir_exists=false)
1651
- sdsfx = @variables['auxiliaryDirSuffix']
1652
1916
  path = []
1653
1917
  path << File.dirname(@dest) if full_name
1654
- path << File.basename(@dest, '.*') + sdsfx if sdsfx
1655
- rv = Deplate::Core.get_path(*path)
1918
+ aux = @variables['auxiliaryDir']
1919
+ if aux
1920
+ path << aux
1921
+ else
1922
+ sdsfx = @variables['auxiliaryDirSuffix']
1923
+ path << File.basename(@dest, '.*') + sdsfx if sdsfx
1924
+ end
1925
+ rv = Deplate::Core.file_join(*path)
1656
1926
  ensure_dir_exists(rv) if ensure_dir_exists
1657
1927
  rv
1658
1928
  end
@@ -1681,6 +1951,47 @@ MESSAGE
1681
1951
  return files
1682
1952
  end
1683
1953
 
1954
+ def find_in_lib(fname, args={})
1955
+ if args[:pwd]
1956
+ fn = File.join(Deplate::Core.current_pwd(self), fname)
1957
+ if Deplate::Core.is_file?(fn)
1958
+ return fn
1959
+ end
1960
+ end
1961
+ files = []
1962
+ if @formatter
1963
+ formatter_family_members do |myname|
1964
+ dd = File.join('lib', myname, fname)
1965
+ files << dd unless files.include?(dd)
1966
+ end
1967
+ end
1968
+ files << File.join('lib', fname)
1969
+ files = Deplate::Core.library_directories(true, *files)
1970
+ for fn in files
1971
+ if Deplate::Core.is_file?(fn)
1972
+ return fn
1973
+ end
1974
+ end
1975
+ return nil
1976
+ end
1977
+
1978
+ def formatter_family_members(formatter_class=nil)
1979
+ acc = []
1980
+ fmt = formatter_class ||= @formatter.class
1981
+ myname = fmt.myname
1982
+ while myname
1983
+ acc << myname
1984
+ yield(myname) if block_given?
1985
+ fmt = fmt.superclass
1986
+ myname = fmt.myname
1987
+ end
1988
+ formatter_class.related.each do |myname|
1989
+ acc << myname
1990
+ yield(myname) if block_given?
1991
+ end
1992
+ acc
1993
+ end
1994
+
1684
1995
  # Format either text or, if text is nil, the file "sourcename".
1685
1996
  # This is the method called by the Deplate::Formatter's
1686
1997
  # to_whatsoever methods.
@@ -1722,79 +2033,108 @@ MESSAGE
1722
2033
  # pair of #BEGIN, #END pseudo commands
1723
2034
  def include_stdin(array)
1724
2035
  if $stdin.eof?
1725
- log("No more input on STDIN", :anyway)
2036
+ log('No more input on STDIN', :anyway)
1726
2037
  exit 1
1727
2038
  end
1728
- maintain_current_source("") do
1729
- log("Including from STDIN")
2039
+ maintain_current_source('') do
2040
+ log('Including from STDIN')
1730
2041
  acc = []
1731
2042
  end_tag = nil
1732
2043
  $stdin.each_with_index do |l, i|
1733
2044
  if i == 0 and l =~ /^#BEGIN:/
1734
- end_tag = "#END:" + l[7..-1]
2045
+ end_tag = '#END:' + l[7..-1]
1735
2046
  elsif end_tag and l == end_tag
1736
2047
  break
1737
2048
  else
1738
2049
  acc << l
1739
2050
  end
1740
2051
  end
1741
- include_each(acc, array, "STDIN")
2052
+ include_each(acc, array, 'STDIN')
1742
2053
  end
1743
2054
  end
1744
2055
 
1745
2056
  # Read a file and add the parsed elements to array
1746
2057
  def include_file(array, filename)
1747
2058
  maintain_current_source(filename) do
1748
- log(["Including", filename])
2059
+ log(['Including', filename])
1749
2060
  filename_abs = File.expand_path(filename)
1750
2061
  unless @options.included
1751
2062
  filename_label = file_label(filename_abs)
1752
2063
  @labels_floating << filename_label
1753
2064
  end
1754
- File.open(filename, "r") do |io|
1755
- include_each(io, array, filename)
2065
+ File.open(filename, 'r') do |io|
2066
+ text = io.read
2067
+ include_each(text, array, filename)
1756
2068
  end
1757
2069
  end
1758
2070
  end
1759
2071
 
1760
- # Execute &block while maintaining @current_top
1761
- def maintain_current_top(top, &block)
1762
- begin
1763
- current_top = @current_top
1764
- @current_top = top
1765
- block.call
1766
- ensure
1767
- @current_top = current_top
1768
- end
1769
- end
1770
-
1771
2072
  # Include each line in enum and accumulate parsed elements in array
1772
2073
  def include_each(enum, array, sourcename=nil)
1773
- @input.include_enum(enum, array, 0)
2074
+ case enum
2075
+ when Array
2076
+ enum = enum.join("\n")
2077
+ end
2078
+ @input.include_string(enum, array, 0)
1774
2079
  end
1775
2080
 
1776
2081
  # Include strings as if read from a file and return the resulting array of parsed elements
1777
- def parsed_array_from_strings(strings, linenumber=nil, src="[array]")
2082
+ def parsed_array_from_strings(strings, linenumber=nil, src='[array]')
1778
2083
  array = []
1779
- include_stringarray(strings, array, linenumber, src)
2084
+ erx = @variables['embeddedTextRx']
2085
+ begin
2086
+ include_stringarray(strings, array, linenumber, src)
2087
+ ensure
2088
+ @variables['embeddedTextRx'] = erx if erx
2089
+ end
1780
2090
  return array
1781
2091
  end
1782
2092
 
1783
2093
  # Include strings as if read from a file and push parsed elements onto array
1784
- def include_stringarray(strings, array, linenumber=nil, src="[array]")
2094
+ def include_stringarray(strings, array, linenumber=nil, src='[array]')
1785
2095
  maintain_current_source(src) do
1786
- @input.include_enum(strings, array, linenumber || 0)
2096
+ include_each(strings, array, linenumber || 0)
1787
2097
  end
1788
2098
  end
1789
2099
 
2100
+ def auto_numbered(base, args=nil)
2101
+ if args
2102
+ n = if (s = args[:set])
2103
+ @auto_numbered[base] = s
2104
+ elsif (s = args[:inc])
2105
+ if @auto_numbered[base]
2106
+ @auto_numbered[base] += s
2107
+ else
2108
+ @auto_numbered[base] = 0
2109
+ end
2110
+ else
2111
+ log(['Internal error', 'auto_numbered', base, args], :error)
2112
+ nil
2113
+ end
2114
+ if (t = args[:fmt])
2115
+ t % n
2116
+ elsif (t = args[:fmt0])
2117
+ if n > 0
2118
+ t % n
2119
+ else
2120
+ t % nil
2121
+ end
2122
+ else
2123
+ n
2124
+ end
2125
+ else
2126
+ return @auto_numbered[base]
2127
+ end
2128
+ end
2129
+
1790
2130
  # Set the current top heading.
1791
2131
  # heading:: Heading object
1792
2132
  # text:: The output filename base
1793
2133
  def set_top_heading(heading, text)
1794
- if heading.level == 1
2134
+ if heading.level <= @options.split_level
1795
2135
  fname = nil
1796
2136
  sfx = @options.suffix
1797
- dir = @options.dir
2137
+ # dir = @options.dir
1798
2138
  if @output_headings.include?(heading)
1799
2139
  maj = top_heading_idx(heading)
1800
2140
  else
@@ -1802,19 +2142,41 @@ MESSAGE
1802
2142
  push_top_heading(heading)
1803
2143
  maj = @output_headings.size - 1
1804
2144
  unless text or !@options.multi_file_output
1805
- if @variables["autoFileNames"]
2145
+ afn = @variables['autoFileNames']
2146
+ if afn
1806
2147
  fname = Deplate::Core.clean_file_name(heading.get_text)[0..20]
1807
- c = @auto_filenames[fname]
2148
+ c = auto_numbered(fname)
1808
2149
  if c
1809
2150
  fname = Deplate::Core.canonic_file_name(fname, sfx, c, 0)
1810
- @auto_filenames[fname] += 1
2151
+ auto_numbered(fname, :inc => 1)
1811
2152
  else
1812
2153
  fname = Deplate::Core.canonic_file_name(fname, sfx)
1813
- @auto_filenames[fname] = 0
2154
+ auto_numbered(fname, :set => 0)
1814
2155
  end
1815
2156
  else
1816
- fname = File.basename(@dest, File.extname(@dest))
1817
- fname = Deplate::Core.canonic_file_name(fname, sfx, maj, 0)
2157
+ # if @variables['autoBaseName']
2158
+ # fname = File.basename(@current_source, '.*')
2159
+ # fmaj = if auto_numbered(fname)
2160
+ # auto_numbered(fname, :inc => 1)
2161
+ # else
2162
+ # auto_numbered(fname, :set => 0)
2163
+ # end
2164
+ # else
2165
+ # fname = File.basename(@dest, '.*')
2166
+ # fmaj = maj
2167
+ # end
2168
+ fname = @variables['autoBaseName'] ? @current_source : @dest
2169
+ fname = File.basename(fname, '.*')
2170
+ fmaj = if auto_numbered(fname)
2171
+ auto_numbered(fname, :inc => 1)
2172
+ # <+TBD+>
2173
+ elsif @accum_elements.size == 1 and
2174
+ @accum_elements[0].kind_of?(Deplate::Element::PotentialPageBreak)
2175
+ auto_numbered(fname, :set => 0)
2176
+ else
2177
+ auto_numbered(fname, :set => 1)
2178
+ end
2179
+ fname = Deplate::Core.canonic_file_name(fname, sfx, fmaj, 0)
1818
2180
  end
1819
2181
  end
1820
2182
  end
@@ -1858,6 +2220,15 @@ MESSAGE
1858
2220
  @output_headings.size
1859
2221
  end
1860
2222
 
2223
+ # Return the index for a top heading.
2224
+ def output_index(top=nil)
2225
+ if top
2226
+ top_heading_idx(top)
2227
+ else
2228
+ @collected_output.size - 1
2229
+ end
2230
+ end
2231
+
1861
2232
  # Return the nth output filename.
1862
2233
  # idx:: Top heading index (integer)
1863
2234
  def output_filename_by_idx(idx)
@@ -1869,6 +2240,7 @@ MESSAGE
1869
2240
 
1870
2241
  # accum format elts in pre/body|matter/post
1871
2242
  def printable_strings(strings, linenumber=nil, src="[array]")
2243
+ @formatter.pre_process
1872
2244
  output = []
1873
2245
  accum_elements = []
1874
2246
  include_stringarray(strings, accum_elements, linenumber, src)
@@ -1885,28 +2257,23 @@ MESSAGE
1885
2257
  end
1886
2258
  return output
1887
2259
  end
1888
-
1889
- # Run a "service", i.e., a small, mostly autonomous function/method that
1890
- # usually yields some formatted output.
1891
- def invoke_service(name, args={}, text="")
1892
- method = @doc_services[name]
1893
- if method
1894
- begin
1895
- return send(method, args || {}, text || "")
1896
- rescue Exception => e
1897
- puts e.backtrace[0..10].join("\n")
1898
- Deplate::Core.log(["Calling service failed", name, e], :error)
1899
- end
1900
- else
1901
- Deplate::Core.log(["Unknown service", name], :error)
1902
- end
2260
+
2261
+ def is_allowed?(ids, args={})
2262
+ args = args.dup
2263
+ args[:logger] ||= self
2264
+ Deplate::Core.is_allowed?(@options, ids, args)
1903
2265
  end
1904
-
2266
+
1905
2267
  # Return whether ruby code may be evaluated.
1906
2268
  def allow_ruby
1907
- return @options.allow_ruby
2269
+ @options.allow_ruby || is_allowed?('x')
1908
2270
  end
1909
2271
 
2272
+ # Return whether external applications may be run
2273
+ def allow_external
2274
+ @options.allow_external || is_allowed?('X')
2275
+ end
2276
+
1910
2277
  # Caller requests calling ruby code with some args
1911
2278
  def eval_ruby(invoker, args, code)
1912
2279
  ar = allow_ruby
@@ -1996,10 +2363,14 @@ MESSAGE
1996
2363
  end
1997
2364
 
1998
2365
  def relative_path_by_file(file, base_file)
1999
- if base_file
2000
- relative_path(file, File.dirname(base_file))
2366
+ if file
2367
+ if base_file
2368
+ relative_path(file, File.dirname(base_file))
2369
+ else
2370
+ File.basename(file)
2371
+ end
2001
2372
  else
2002
- File.basename(file)
2373
+ ''
2003
2374
  end
2004
2375
  end
2005
2376
 
@@ -2022,8 +2393,7 @@ MESSAGE
2022
2393
  # Amend +file+'s suffix.
2023
2394
  def file_with_suffix(file, sfx=nil, filename_only=false)
2024
2395
  sfx = sfx || ""
2025
- sfx0 = File.extname(file)
2026
- fn = File.basename(file, sfx0)
2396
+ fn = File.basename(file, '.*')
2027
2397
  if filename_only
2028
2398
  return fn + sfx
2029
2399
  else
@@ -2045,7 +2415,8 @@ MESSAGE
2045
2415
  else
2046
2416
  las = level_as_string.to_s
2047
2417
  end
2048
- if las == ""
2418
+ case las
2419
+ when '', '0'
2049
2420
  top = top_heading_by_idx(0)
2050
2421
  else
2051
2422
  top = nil
@@ -2057,6 +2428,8 @@ MESSAGE
2057
2428
  end
2058
2429
  end
2059
2430
  raise "Internal error: unknown level: #{level_as_string}"
2431
+ log(['Internal error: Unknown level', level_as_string], :error)
2432
+ return nil
2060
2433
  end
2061
2434
  end
2062
2435
  return top.destination
@@ -2077,7 +2450,7 @@ MESSAGE
2077
2450
  return "%s00%s" % [prefix, text.gsub(/\W/, "00")]
2078
2451
  end
2079
2452
  else
2080
- raise msg("No label")
2453
+ # raise msg("No label")
2081
2454
  log(["No label", prefix], :error)
2082
2455
  return nil
2083
2456
  end
@@ -2112,7 +2485,7 @@ MESSAGE
2112
2485
  for output in @collected_output
2113
2486
  rv = send(method, @dest, output)
2114
2487
  end
2115
- elsif @dest == "-"
2488
+ elsif @dest == '-'
2116
2489
  sep = @variables["stdoutSeparator"]
2117
2490
  for output in @collected_output
2118
2491
  puts(output.join("\n"))
@@ -2132,7 +2505,7 @@ MESSAGE
2132
2505
  call_methods_matching(@formatter, /^hook_post_write_file_/)
2133
2506
  output.merge_metadata(@metadata)
2134
2507
  if @options.metadata_model and output.metadata_available?
2135
- md_dest = File.join(@options.dir, output.metadata_destination)
2508
+ md_dest = Deplate::Core.file_join(@options.dir, output.metadata_destination)
2136
2509
  log(["Saving metadata", md_dest])
2137
2510
  write_metadata(md_dest, output)
2138
2511
  end
@@ -2173,31 +2546,34 @@ MESSAGE
2173
2546
 
2174
2547
  # Make sure +dir+ exists (create it if it doesn't).
2175
2548
  def ensure_dir_exists(dir)
2176
- unless File.exist?(dir)
2177
- if @options.force
2178
- Deplate::Core.ensure_dir_exists(dir)
2179
- else
2180
- log(["Destination directory doesn't exist", dir, Dir.pwd], :error)
2181
- exit 5
2182
- end
2183
- end
2549
+ Deplate::Core.ensure_dir_exists(dir, @options)
2550
+ # unless File.exist?(dir)
2551
+ # if @options.force
2552
+ # Deplate::Core.ensure_dir_exists(dir, @options)
2553
+ # else
2554
+ # log(["Destination directory doesn't exist", dir, Dir.pwd], :error)
2555
+ # exit 5
2556
+ # end
2557
+ # end
2184
2558
  end
2185
2559
 
2186
2560
  # Actually write something to some file.
2187
- def write_file(file, &block)
2561
+ def write_file(file, mode='w', &block)
2188
2562
  if file
2189
2563
  # pwd = Dir.pwd
2190
2564
  begin
2191
2565
  # Dir.chdir(@options.dir)
2192
2566
  ensure_dir_exists(File.dirname(file))
2193
- ok = if File.exist?(file) and @options.ask
2194
- print "File '#{file}' already exists. Overwrite (y/N)? "
2195
- gets.chomp == 'y'
2567
+ ok = if File.exist?(file)
2568
+ Deplate::Core.query_user(@options,
2569
+ "File '#{file}' already exists. Overwrite (y/N)? ",
2570
+ 'y')
2196
2571
  else
2197
2572
  true
2198
2573
  end
2199
2574
  if ok
2200
- File.open(file, 'w') do |io|
2575
+ log(['Writing file', file], :debug)
2576
+ File.open(file, mode) do |io|
2201
2577
  block.call(io)
2202
2578
  end
2203
2579
  end
@@ -2212,23 +2588,43 @@ MESSAGE
2212
2588
  end
2213
2589
  end
2214
2590
 
2215
- # Increase the heading level.
2216
- def increase_current_heading(level)
2217
- if @current_heading.size < level
2218
- while @current_heading.size < level
2219
- @current_heading << 1
2220
- end
2591
+ # Copy a file.
2592
+ def copy_file(from, to)
2593
+ if File.directory?(to)
2594
+ to = File.join(to, File.basename(from))
2595
+ dir = to
2596
+ else
2597
+ dir = File.dirname(to)
2598
+ end
2599
+ if File.exist?(to)
2600
+ log(['File already exists', to])
2221
2601
  else
2222
- while @current_heading.size > level
2223
- @current_heading.pop
2602
+ ok = if @options.ask
2603
+ puts "File '#{file}' already exists. Overwrite (y/N)? "
2604
+ gets.chomp == 'y'
2605
+ else
2606
+ true
2607
+ end
2608
+ if ok
2609
+ ensure_dir_exists(dir)
2610
+ File.copy(from, to)
2611
+ log(['Copy file', to])
2224
2612
  end
2225
- @current_heading << (@current_heading.pop + 1)
2226
2613
  end
2227
2614
  end
2228
-
2615
+
2616
+ def current_heading
2617
+ @options.counters.get('toc')
2618
+ end
2619
+
2229
2620
  # Get the current section's level as string.
2230
2621
  def get_current_heading
2231
- return @current_heading.join(".")
2622
+ @options.counters.get_s('toc')
2623
+ end
2624
+
2625
+ # Increase the heading level.
2626
+ def increase_current_heading(level)
2627
+ @options.counters.increase('toc', :level => level)
2232
2628
  end
2233
2629
 
2234
2630
  # Get the current top heading object.
@@ -2236,21 +2632,33 @@ MESSAGE
2236
2632
  top_heading_by_idx(top_heading_idx)
2237
2633
  end
2238
2634
 
2635
+ def get_numbering_mode(entity, default=1)
2636
+ (@variables["#{entity}Numbering"] || default).to_i
2637
+ end
2638
+
2239
2639
  # Register a new label.
2240
2640
  # invoker:: The labelled object
2241
2641
  # label:: The label name
2242
2642
  # level_as_string:: The section heading's level as string (redundant???)
2243
2643
  def add_label(invoker, label, level_as_string, opts={})
2244
2644
  if !opts[:anyway] and (@labels[label] or @label_aliases[label])
2245
- invoker.log(["Label already defined", label, level_as_string], :error)
2645
+ invoker.log(['Label already defined', label, level_as_string], :error)
2246
2646
  else
2247
2647
  @labels[label] = level_as_string
2248
2648
  @label_aliases[label] = opts[:container] || invoker
2249
2649
  end
2250
2650
  end
2251
2651
 
2252
- # <+TBD+>This doesn't work as intended. Elements still have to be labelled in order to
2253
- # be referred to by their ID
2652
+ def set_label_object(invoker, label, level_as_string, opts={})
2653
+ if @label_aliases[label]
2654
+ @label_aliases[label] = opts[:container] || invoker
2655
+ else
2656
+ # add_label(invoker, label, level_as_string, opts
2657
+ end
2658
+ end
2659
+
2660
+ # <+TBD+>This doesn't work as intended. Elements still have to be
2661
+ # labelled in order to be referred to by their ID
2254
2662
  def get_label_by_id(invoker, id)
2255
2663
  o = @ids[id]
2256
2664
  if o
@@ -2263,7 +2671,7 @@ MESSAGE
2263
2671
  # invoker.log(["Object has no label", id], :error)
2264
2672
  end
2265
2673
  else
2266
- invoker.log(["No object with that id", id], :error)
2674
+ invoker.log(['No object with that ID', id], :error)
2267
2675
  end
2268
2676
  end
2269
2677
 
@@ -2274,13 +2682,13 @@ MESSAGE
2274
2682
  f = f.top_heading.destination
2275
2683
  d = invoker.top_heading.destination
2276
2684
  if f == d
2277
- return ""
2685
+ return ''
2278
2686
  else
2279
2687
  return relative_path(f, File.dirname(d))
2280
2688
  end
2281
2689
  else
2282
2690
  # puts caller
2283
- invoker.log(["Reference to unknown label", label], :error)
2691
+ invoker.log(['Reference to unknown label', label], :error)
2284
2692
  end
2285
2693
  end
2286
2694
 
@@ -2353,18 +2761,18 @@ MESSAGE
2353
2761
  if @ids[id]
2354
2762
  # obj.log(["ID with the same name already exists", id, @ids[id].level_as_string], :error)
2355
2763
  else
2356
- obj.log(["Register id", id, obj.class], :debug)
2764
+ obj.log(["Register ID", id, obj.class], :debug)
2357
2765
  @ids[id] = obj
2358
2766
  end
2359
2767
  end
2360
2768
  end
2361
2769
 
2362
2770
  # Register a new index entry.
2363
- def add_index(container, names, level_as_string="")
2771
+ def add_index(container, names, level_as_string='')
2364
2772
  @index_last_idx += 1
2365
- id = "idx00#{@index_last_idx}"
2366
- words = names.split(/\s*\|\s*/)
2367
- lname = Deplate::Core.remove_backslashes(words[0])
2773
+ id = "idx00#{@index_last_idx}"
2774
+ words = names.split(/\s*\|\s*/)
2775
+ lname = Deplate::Core.remove_backslashes(words[0])
2368
2776
  level_as_string = container ? container.level_as_string : level_as_string
2369
2777
  if @options.dont_index.delete(lname)
2370
2778
  return nil
@@ -2388,7 +2796,13 @@ MESSAGE
2388
2796
  else
2389
2797
  f = @dest
2390
2798
  end
2391
- d = IndexEntry.new(lname, words, id, f, level_as_string)
2799
+ d = Deplate::IndexEntry.new(container) do |idx|
2800
+ idx.name = lname
2801
+ idx.synonymes = words
2802
+ idx.label = id
2803
+ idx.file = f
2804
+ idx.level_as_string = level_as_string
2805
+ end
2392
2806
  if i
2393
2807
  i << d
2394
2808
  else
@@ -2442,6 +2856,7 @@ MESSAGE
2442
2856
  def parse_and_format_without_wikinames(container, text, alt=true)
2443
2857
  excluded = [
2444
2858
  Deplate::HyperLink::Simple,
2859
+ Deplate::HyperLink::Extended,
2445
2860
  ]
2446
2861
  return parse_and_format(container, text, alt, excluded)
2447
2862
  end
@@ -2453,15 +2868,16 @@ MESSAGE
2453
2868
  arr = @output_headings
2454
2869
  depth = false
2455
2870
  else
2456
- arr = @table_of_contents
2871
+ arr = @options.listings.get('toc')
2457
2872
  end
2458
2873
  for section in arr
2459
2874
  if !depth or (section and section.level <= depth)
2460
2875
  unless section and section.args["noList"]
2461
2876
  if section.kind_of?(Deplate::NullTop)
2462
- v = section.caption
2877
+ v = section.caption.elt
2463
2878
  else
2464
- v = section.description.gsub(/<\/?[^>]*>/, "")
2879
+ v = section.description
2880
+ v = v.gsub(/<\/?[^>]*>/, "")
2465
2881
  v = [section.level_as_string, v].join(" ") unless section.plain_caption?
2466
2882
  end
2467
2883
  block.call(section, v)
@@ -2469,51 +2885,37 @@ MESSAGE
2469
2885
  end
2470
2886
  end
2471
2887
  end
2472
-
2473
- # <+TBD+>
2474
- def serve_object_by_id(args, text)
2475
- if args["id"]
2476
- o = @ids[args["id"]]
2477
- if o
2478
- return o
2479
- else
2480
- log(["Serving object failed because of unknown object", id], :error)
2481
- end
2482
- elsif args["array"]
2483
- text = args["array"]
2484
- sep = args["sep"]
2485
- if sep
2486
- sep = sep ? Regexp.escape(sep) : "\\s+"
2487
- else
2488
- sep = args["rx"]
2489
- end
2490
- if sep
2491
- return text.split(Regexp.new(sep))
2492
- else
2493
- log("Serving array failed because no separator was defined", :error)
2888
+
2889
+ def bib_styler(style)
2890
+ styler = @@bib_style[style] || @@bib_style['default']
2891
+ styler.new(self)
2892
+ end
2893
+
2894
+ def home_index
2895
+ hidx = @variables['homeIndex']
2896
+ if hidx
2897
+ return hidx
2898
+ else
2899
+ @collected_output.each_with_index do |o, i|
2900
+ unless o.body_empty?
2901
+ return i
2902
+ end
2494
2903
  end
2904
+ return 0
2495
2905
  end
2496
2906
  end
2497
2907
 
2498
- # <+TBD+>
2499
- def serve_formatted_object(args, text)
2500
- id = args["id"] || text
2501
- o = @variables[id]
2908
+ def object_by_id(id)
2909
+ o = @ids[id]
2502
2910
  if o
2503
- return o.format_as_string
2911
+ return o
2504
2912
  else
2505
- log(["Formatting object failed because of unknown variable", id], :error)
2913
+ log(['Unknown ID', id], :error)
2506
2914
  end
2507
2915
  end
2508
2916
 
2509
- private
2510
- def initialize_services
2511
- services = {}
2512
- services['object'] = :serve_object_by_id
2513
- services['format'] = :serve_formatted_object
2514
- return services
2515
- end
2516
2917
 
2918
+ private
2517
2919
  def set_safe
2518
2920
  if @options.allow_ruby and @options.allow_ruby.kind_of?(Integer)
2519
2921
  $SAFE = @options.allow_ruby
@@ -2532,7 +2934,7 @@ MESSAGE
2532
2934
  @clips = @options.clips.dup if options.clips_initialized
2533
2935
  end
2534
2936
 
2535
- def reset_footones
2937
+ def reset_footnotes
2536
2938
  @footnote_last_idx = 0
2537
2939
  @footnotes_used = []
2538
2940
  end
@@ -2558,16 +2960,17 @@ MESSAGE
2558
2960
  # Set @formatter to an instance of formatter_class, call block, and
2559
2961
  # restore the old @formatter
2560
2962
  def with_formatter(formatter_class, &block)
2561
- if @formatter.instance_of?(formatter_class)
2562
- block.call
2563
- else
2564
- formatter_orig = @formatter
2565
- begin
2566
- @formatter = formatter_class.new(self)
2567
- block.call
2568
- ensure
2569
- @formatter = formatter_orig
2963
+ formatter_orig = @formatter
2964
+ begin
2965
+ if @formatter.instance_of?(formatter_class)
2966
+ @formatter = @formatter.dup
2967
+ @formatter.reset!
2968
+ else
2969
+ @formatter = formatter_class.new(self, @args)
2570
2970
  end
2971
+ block.call
2972
+ ensure
2973
+ @formatter = formatter_orig
2571
2974
  end
2572
2975
  end
2573
2976
 
@@ -2617,13 +3020,11 @@ MESSAGE
2617
3020
 
2618
3021
  for fn in @footnotes.keys
2619
3022
  e = @footnotes[fn]
2620
- @current_top = e.top_heading
2621
3023
  @footnotes[fn] = e.process
2622
3024
  end
2623
3025
 
2624
3026
  for clp in @clips.keys
2625
3027
  e = @clips[clp]
2626
- @current_top = e.top_heading
2627
3028
  @clips[clp] = e.process
2628
3029
  end
2629
3030
  end
@@ -2633,7 +3034,6 @@ MESSAGE
2633
3034
  log("Processing elements")
2634
3035
  call_methods_matching(@formatter, /^hook_pre_process_/)
2635
3036
  @accum_elements.collect! do |e|
2636
- @current_top = e.top_heading
2637
3037
  e.process
2638
3038
  end
2639
3039
  @accum_elements.flatten!
@@ -2649,13 +3049,12 @@ MESSAGE
2649
3049
  end
2650
3050
 
2651
3051
  def print_etc
2652
- reset_footones
3052
+ reset_footnotes
2653
3053
  end
2654
3054
 
2655
3055
  def print
2656
3056
  log("Formatting elements")
2657
3057
  for e in @accum_elements
2658
- @current_top = e.top_heading
2659
3058
  e.print
2660
3059
  end
2661
3060
  for p in @postponed_print
@@ -2686,7 +3085,6 @@ MESSAGE
2686
3085
  # Set heading as the current top heading.
2687
3086
  def push_top_heading(heading)
2688
3087
  @output_headings << heading
2689
- @current_top = heading
2690
3088
  end
2691
3089
 
2692
3090
  def increase_maj_min(minor=false)
@@ -2699,6 +3097,7 @@ MESSAGE
2699
3097
 
2700
3098
  end
2701
3099
 
3100
+
2702
3101
  # vim: ff=unix
2703
3102
  # Local Variables:
2704
3103
  # revisionRx: MicroRev\s\+=\s\+\'