deplate 0.7.3 → 0.8

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.
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\+\'