dyndoc-ruby-core 1.0.0

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 (138) hide show
  1. checksums.yaml +7 -0
  2. data/dyndoc/.DS_Store +0 -0
  3. data/dyndoc/Dyn/.postload +1 -0
  4. data/dyndoc/Dyn/.preload +1 -0
  5. data/dyndoc/Dyn/After.dyn +3 -0
  6. data/dyndoc/Dyn/Base.dyn +18 -0
  7. data/dyndoc/Dyn/Minimum.dyn +20 -0
  8. data/dyndoc/Model/Html/DefaultPost_html.dyn +5 -0
  9. data/dyndoc/Model/Html/DefaultPre_html.dyn +15 -0
  10. data/dyndoc/Model/Odt/DefaultPost_content.xml +3 -0
  11. data/dyndoc/Model/Odt/DefaultPost_tmpl_content.xml +3 -0
  12. data/dyndoc/Model/Odt/DefaultPre_content.xml +8 -0
  13. data/dyndoc/Model/Odt/DefaultPre_tmpl_content.xml +8 -0
  14. data/dyndoc/Model/Tex/ContentPost_tmpl.tex +1 -0
  15. data/dyndoc/Model/Tex/ContentPre_tmpl.tex +6 -0
  16. data/dyndoc/Model/Tex/DefaultPost_tmpl.tex +73 -0
  17. data/dyndoc/Model/Tex/DefaultPre_tmpl.tex +16 -0
  18. data/dyndoc/Model/Ttm/DefaultPost_tmpl.ttm +3 -0
  19. data/dyndoc/Model/Ttm/DefaultPre_tmpl.ttm +16 -0
  20. data/dyndoc/Std/Array.dyn +96 -0
  21. data/dyndoc/Std/Composer.dyn +38 -0
  22. data/dyndoc/Std/DevTag.dyn +101 -0
  23. data/dyndoc/Std/DynVar.dyn +23 -0
  24. data/dyndoc/Std/File.dyn +55 -0
  25. data/dyndoc/Std/Git.dyn +34 -0
  26. data/dyndoc/Std/List.dyn +46 -0
  27. data/dyndoc/Std/OOP.dyn +32 -0
  28. data/dyndoc/Std/Signal.dyn +18 -0
  29. data/dyndoc/Std/String.dyn +22 -0
  30. data/dyndoc/Std/Styles.dyn +1 -0
  31. data/dyndoc/Std/Test.dyn +282 -0
  32. data/dyndoc/Std/Utils.dyn +42 -0
  33. data/dyndoc/Std/Verb.dyn +5 -0
  34. data/dyndoc/Style/Notation/Math.dyn +7 -0
  35. data/dyndoc/Style/Notation/Stat/Classic.dyn +8 -0
  36. data/dyndoc/Style/Notation/Stat/Cqls.dyn +44 -0
  37. data/dyndoc/Style/Text/Std.dyn +5 -0
  38. data/dyndoc/Style/Text/StdAlias.dyn +3 -0
  39. data/dyndoc/Style/Text/StdTex.dyn +17 -0
  40. data/dyndoc/Style/Text/Txt.dyn +1 -0
  41. data/dyndoc/Tex/.postload +1 -0
  42. data/dyndoc/Tex/.preload +1 -0
  43. data/dyndoc/Tex/10pt_tmpl.tex +1 -0
  44. data/dyndoc/Tex/11pt_tmpl.tex +1 -0
  45. data/dyndoc/Tex/12pt_tmpl.tex +1 -0
  46. data/dyndoc/Tex/Article_tmpl.tex +1 -0
  47. data/dyndoc/Tex/Beamer.dyn_tex +35 -0
  48. data/dyndoc/Tex/BeamerHandout_tmpl.tex +2 -0
  49. data/dyndoc/Tex/Book_tmpl.tex +1 -0
  50. data/dyndoc/Tex/DefaultFirst_tmpl.tex +1 -0
  51. data/dyndoc/Tex/DefaultLast_tmpl.tex +8 -0
  52. data/dyndoc/Tex/Default_tmpl.tex +9 -0
  53. data/dyndoc/Tex/First_tmpl.tex +8 -0
  54. data/dyndoc/Tex/Fr_tmpl.tex +17 -0
  55. data/dyndoc/Tex/Header_tmpl.tex +3 -0
  56. data/dyndoc/Tex/InclGraph_tmpl.tex +19 -0
  57. data/dyndoc/Tex/InclSpatProc_tmpl.tex +70 -0
  58. data/dyndoc/Tex/InclSumMI_tmpl.tex +4 -0
  59. data/dyndoc/Tex/LargeA4_tmpl.tex +5 -0
  60. data/dyndoc/Tex/Last_tmpl.tex +1 -0
  61. data/dyndoc/Tex/Option_tmpl.tex +8 -0
  62. data/dyndoc/Tex/Png_tmpl.tex +1 -0
  63. data/dyndoc/Tex/RefCite2_tmpl.tex +16 -0
  64. data/dyndoc/Tex/RefCite_tmpl.tex +16 -0
  65. data/dyndoc/Tex/Report_tmpl.tex +1 -0
  66. data/dyndoc/Tex/Theorem_tmpl.tex +14 -0
  67. data/dyndoc/Tools/.DS_Store +0 -0
  68. data/dyndoc/Tools/Atom.dyn/index.dyn +42 -0
  69. data/dyndoc/Tools/AtomDyndocker.dyn/index.dyn +43 -0
  70. data/dyndoc/Tools/R/Fig.dyn +144 -0
  71. data/dyndoc/Tools/R/Tools.dyn +344 -0
  72. data/dyndoc/Tools/Tex/Beamer.dyn +204 -0
  73. data/dyndoc/Tools/Tex/BeamerSlide.dyn_tex +199 -0
  74. data/dyndoc/Tools/Tex/Pgf.dyn +115 -0
  75. data/dyndoc/Tools/Tex/Table.dyn +278 -0
  76. data/dyndoc/Tools/Tex/Tools.dyn +37 -0
  77. data/dyndoc/Tools/Tex/Verb.dyn +77 -0
  78. data/dyndoc/Tools/Web/.DS_Store +0 -0
  79. data/dyndoc/Tools/Web/Ace.dyn +54 -0
  80. data/dyndoc/Tools/Web/Code.dyn +129 -0
  81. data/dyndoc/Tools/Web/DHtmlX.dyn +39 -0
  82. data/dyndoc/Tools/Web/DataTable.dyn_html +354 -0
  83. data/dyndoc/Tools/Web/Html.dyn +286 -0
  84. data/dyndoc/Tools/Web/Html/JQuery.dyn +123 -0
  85. data/dyndoc/Tools/Web/Html/Styles.dyn +4 -0
  86. data/dyndoc/Tools/Web/JQueryTools.dyn +87 -0
  87. data/dyndoc/Tools/Web/Layout.dyn +86 -0
  88. data/dyndoc/Tools/Web/Layout/CQLS.dyn +6 -0
  89. data/dyndoc/Tools/Web/Layout/LJK.dyn +41 -0
  90. data/dyndoc/Tools/Web/TabBar.dyn +37 -0
  91. data/dyndoc/Tools/Web/Ttm.dyn +20 -0
  92. data/dyndoc/Tools/Web/Txtl.dyn +14 -0
  93. data/lib/dyndoc-core.rb +59 -0
  94. data/lib/dyndoc/base/envir.rb +541 -0
  95. data/lib/dyndoc/base/filter/call.rb +127 -0
  96. data/lib/dyndoc/base/filter/filter_mngr.rb +637 -0
  97. data/lib/dyndoc/base/filter/server.rb +882 -0
  98. data/lib/dyndoc/base/filters.rb +3 -0
  99. data/lib/dyndoc/base/helpers.rb +9 -0
  100. data/lib/dyndoc/base/helpers/core.rb +32 -0
  101. data/lib/dyndoc/base/helpers/parser.rb +188 -0
  102. data/lib/dyndoc/base/scanner.rb +886 -0
  103. data/lib/dyndoc/base/tags.rb +4 -0
  104. data/lib/dyndoc/base/tags/keys_mngr.rb +401 -0
  105. data/lib/dyndoc/base/tags/part_tag.rb +194 -0
  106. data/lib/dyndoc/base/tags/tag_mngr.rb +125 -0
  107. data/lib/dyndoc/base/tags/user_tag.rb +216 -0
  108. data/lib/dyndoc/base/tmpl.rb +6 -0
  109. data/lib/dyndoc/base/tmpl/eval.rb +581 -0
  110. data/lib/dyndoc/base/tmpl/extension.rb +337 -0
  111. data/lib/dyndoc/base/tmpl/manager.rb +450 -0
  112. data/lib/dyndoc/base/tmpl/oop.rb +57 -0
  113. data/lib/dyndoc/base/tmpl/parse_do.rb +2446 -0
  114. data/lib/dyndoc/base/tmpl/rbenvir.rb +54 -0
  115. data/lib/dyndoc/base/utils.rb +367 -0
  116. data/lib/dyndoc/common/dynArray.rb +234 -0
  117. data/lib/dyndoc/common/file.rb +52 -0
  118. data/lib/dyndoc/common/init.rb +2 -0
  119. data/lib/dyndoc/common/tilt.rb +149 -0
  120. data/lib/dyndoc/common/utils.rb +61 -0
  121. data/lib/dyndoc/common/uv.rb +163 -0
  122. data/lib/dyndoc/init/config.rb +296 -0
  123. data/lib/dyndoc/init/home.rb +9 -0
  124. data/lib/dyndoc/plugins/tex.rb +4 -0
  125. data/lib/dyndoc/plugins/tex/beamer.rb +208 -0
  126. data/lib/dyndoc/plugins/tex/tex_eval.rb +69 -0
  127. data/lib/dyndoc/plugins/tex/tex_parse_do.rb +25 -0
  128. data/lib/dyndoc/plugins/tex/tex_user_tag.rb +32 -0
  129. data/share/R/dyndocMsys2.R +5 -0
  130. data/share/R/dyndocTools.R +9 -0
  131. data/share/R/test.R +14 -0
  132. data/share/R/tools/dynArray.R +34 -0
  133. data/share/R/tools/dynCapture.R +84 -0
  134. data/share/R/tools/dynMsys2.R +54 -0
  135. data/share/julia/dynArray.jl +93 -0
  136. data/share/julia/dyndoc.jl +110 -0
  137. data/share/julia/ruby.jl +37 -0
  138. metadata +202 -0
@@ -0,0 +1,3 @@
1
+ require "dyndoc/base/filter/filter_mngr"
2
+ require "dyndoc/base/filter/call"
3
+ require "dyndoc/base/filter/server"
@@ -0,0 +1,9 @@
1
+ require 'dyndoc/base/helpers/core'
2
+
3
+ #Dyndoc.warn "path helpers",File.join(File.dirname(__FILE__),"helpers/**/*.rb").gsub('\\','/')
4
+ #Dyndoc.warn "helpers",Dir[File.join(File.dirname(__FILE__),"helpers/**/*.rb").gsub('\\','/')]
5
+
6
+ Dir[File.join(File.dirname(__FILE__),"helpers/**/*.rb").gsub('\\','/')].each{|lib|
7
+ require lib unless File.basename(lib,".rb")=="core"
8
+ }
9
+
@@ -0,0 +1,32 @@
1
+ #Inside a ruby block all the methods of the class TemplateManager are accessible
2
+ #because a new envir is created as in the body of such a method called new_envir
3
+
4
+ #The main difference between this kind of helpers and a simple file containing definition of functions
5
+ #is that these functions are executed in the Object module as a normal ruby function does.
6
+
7
+ module Dyndoc
8
+
9
+ module Ruby
10
+
11
+ module Helpers
12
+
13
+ # Helpers are functions (in fact methods) used inside a ruby block!
14
+ # Put here only system helpers!
15
+ # The user is pleased to create helpers in the dyndoc/helpers directory
16
+ # and require them by the [#helpers] tag. The following is just an example!
17
+
18
+ def hello!(who="everybody")
19
+ puts "Hello "+who+"!"
20
+ end
21
+
22
+ end
23
+
24
+ class TemplateManager
25
+
26
+ include Helpers
27
+
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,188 @@
1
+ module Dyndoc;module Ruby;module Helpers
2
+
3
+
4
+ # preprocessing for parsing a string
5
+ # convert name to #{name!} in order to be executed!
6
+ def process_bang(str)
7
+ str.gsub(/[#{FilterManager.letters}]*\:?[#{FilterManager.letters}]*\!/) {|e| "\#{" + e + "}"}
8
+ end
9
+
10
+ ## TODO: improve this by using lookbehind with Regepr
11
+ def detect_string_inside_string(str)
12
+ ary=str.split(/(\")/)
13
+ inside,res=false,[""]
14
+ ary.each_index do |cpt|
15
+ if ary[cpt]=="\"" and cpt>0 and ary[cpt-1][-1,1]!="\\" #lookbehind
16
+ if inside
17
+ res[-1] += "\"" #end of the previous string
18
+ res << "" unless cpt == ary.length-1 #new string
19
+ else
20
+ res << "\"" #beginning of a string
21
+ end
22
+ inside = !inside
23
+ else
24
+ res[-1]+=ary[cpt]
25
+ end
26
+ end
27
+ return res
28
+ end
29
+
30
+ def process_rb(str)
31
+
32
+ part=detect_string_inside_string(str)
33
+ #p part
34
+ part.each_index{|i|
35
+ delim=(i%2==0 ? "\"" : "\\\"" ) #depending on inside or outside string!!!!
36
+ part[i].gsub!(/<[\w\.\_\-]+\@>/) {|e|
37
+ "@vars.extract_raw(#{delim}"+e[1...-1]+"#{delim})[:rb]"
38
+ }
39
+ part[i].gsub!(/<([\w\.\_\-]+)((?:[\$\[][^>])+(?:(?!\$>).){0,500})?\$>/) {|e|
40
+ var=$1+"$"
41
+ #puts "process_rb:<var$>";p $1;p $2
42
+ if (arg=$2)
43
+ #@vars.extract_raw(var)[:r].arg=arg
44
+ #puts "arg";p arg;p @vars.extract_raw(var)[:r].value_with_arg
45
+ "@vars.extract_raw(#{delim}"+var+"#{delim})[:r].set_arg(#{delim}"+arg+"#{delim}).value_with_arg"
46
+ else
47
+ "@vars.extract_raw(#{delim}"+var+"#{delim})[:r].value"
48
+ end
49
+ }
50
+
51
+ part[i].gsub!(/<([\w\.\_\-]+)((?:[\&\[][^>])+(?:(?!\&>).){0,500})?\&>/) {|e|
52
+ var=$1+"&"
53
+ #puts "process_rb:<var$>";p $1;p $2
54
+ if (arg=$2)
55
+ #@vars.extract_raw(var)[:r].arg=arg
56
+ #puts "arg";p arg;p @vars.extract_raw(var)[:r].value_with_arg
57
+ "@vars.extract_raw(#{delim}"+var+"#{delim})[:jl].set_arg(#{delim}"+arg+"#{delim}).value_with_arg"
58
+ else
59
+ "@vars.extract_raw(#{delim}"+var+"#{delim})[:jl].value"
60
+ end
61
+ }
62
+ #=end
63
+ part[i].gsub!(/<[\w\.\_\-]+\:>/) {|e|
64
+ "@vars.extract_raw(#{delim}"+e[1...-2]+"#{delim})[:val][0]"
65
+ }
66
+ ## dynArray var
67
+ part[i].gsub!(/<[\w\.\_\-]+\%>/) {|e|
68
+ #p e[1...-1]
69
+ #p @vars.extract_raw(e[1...-1])
70
+ #@vars.extract_raw(e[1...-1])[:rb][0]-= 10
71
+ #(Dyndoc::Vector.get[@vars.extract_raw(e[1...-1])[:rb].ids(:rb)])[0]=10
72
+ @vars.extract_raw(e[1...-1])[:rb].wrapper(:rb)
73
+ }
74
+
75
+ }
76
+ #-| TO DEBUG: Dyndoc.warn part.join("") if part.join("")!=str
77
+ #p part.join("")
78
+ str.replace(part.join(""))
79
+
80
+ end
81
+
82
+ =begin
83
+ def process_rb(str)
84
+ #puts "str";p str
85
+ str.gsub!(/<[\w\.\_\-]+\@>/) {|e|
86
+ "@vars.extract_raw(\""+e[1...-1]+"\")[:rb]"
87
+ }
88
+ #puts "str(suite)";p str
89
+ #=begin
90
+ # str.gsub!(/<([\w\.\_\-]+)((?:[\@\[][^>])+(?:(?!\@>).)*)?\@>/) {|e|
91
+ #p $1;p $2
92
+ # arg = ( $2 ? ( $2[0,1]=="@" ? "."+$2[1..-1] : $2 ) : "" )
93
+ #p arg
94
+ # "@vars.extract_raw(\""+$1+"@\")[:rb]"+arg
95
+ # }
96
+ #=end
97
+ #=begin
98
+ # str.gsub!(/<[\w\.\_\-]+\$>/) {|e|
99
+ # "@vars.extract_raw(\""+e[1...-1]+"\")[:r].value"
100
+ # }
101
+ #=end
102
+ #=begin
103
+ str.gsub!(/<([\w\.\_\-]+)((?:[\$\[][^>])+(?:(?!\$>).){0,500})?\$>/) {|e|
104
+ var=$1+"$"
105
+ #puts "process_rb:<var$>";p $1;p $2
106
+ if (arg=$2)
107
+ #@vars.extract_raw(var)[:r].arg=arg
108
+ #puts "arg";p arg;p @vars.extract_raw(var)[:r].value_with_arg
109
+ "@vars.extract_raw(\""+var+"\")[:r].set_arg(\""+arg+"\").value_with_arg"
110
+ else
111
+ "@vars.extract_raw(\""+var+"\")[:r].value"
112
+ end
113
+ }
114
+ #=end
115
+ str.gsub!(/<[\w\.\_\-]+\:>/) {|e|
116
+ "@vars.extract_raw(\""+e[1...-2]+"\")[:val][0]"
117
+ }
118
+ #p str
119
+ end
120
+ =end
121
+
122
+ def process_r(str)
123
+ #str.gsub!(/<[\w\.\_\-]+\@>/) {|e|
124
+ # "dynVar[["+e[1...-2]+"]]"
125
+ #}
126
+ str2=str.dup
127
+ ## ruby var
128
+ str.gsub!(/<([\w\.\_\-]+)(\@)?((?:[\@\[][^>])+(?:(?!\@>).){0,500})?\@>/) {|e|
129
+ #puts "process_r: ("+$1+","+($2 ? $2 : "nil" )+","+($3 ? $3 : "nil")+")"
130
+ if $3
131
+ arg =( $3[0,1]=="@" ? "."+$3[1..-1] : $3 )
132
+ #p arg
133
+ #p "dynRbVar[\""+$1+"@\",\""+arg+"\"]"
134
+ "dynVarWithArg[[\""+$1+"\",\""+arg+"\",mode=\"@\"]]"
135
+ else
136
+ "dynVar[["+$1+",mode=\"@\","+($2 ? "FALSE" : "TRUE")+"]]"
137
+ end
138
+ }
139
+ ## Julia var
140
+ str.gsub!(/<([\w\.\_\-]+)(\&)?((?:[\&\[][^>])+(?:(?!\&>).){0,500})?\&>/) {|e|
141
+ #puts "process_r(jl): ("+$1+","+($2 ? $2 : "nil" )+","+($3 ? $3 : "nil")+")"
142
+ if $3
143
+ arg =( $3[0,1]=="&" ? "."+$3[1..-1] : $3 ) #TODO: try to apply
144
+ #p arg
145
+ #p "dynRbVar[\""+$1+"@\",\""+arg+"\"]"
146
+ "dynVarWithArg[[\""+$1+"\",\""+arg+"\",mode=\"&\"]]"
147
+ else
148
+ "dynVar[["+$1+",mode=\"&\","+($2 ? "FALSE" : "FALSE")+"]]"
149
+ end
150
+ }
151
+ ## R var
152
+ str.gsub!(/<[\w\.\_\-]+\$>/) {|e|
153
+ ".dynStack$rb"+@vars.extract_raw(e[1...-1]).object_id.abs.to_s
154
+ }
155
+ ## dynArray var
156
+ str.gsub!(/<[\w\.\_\-]+\%>/) {|e|
157
+ #p e[1...-1]
158
+ #p @vars.extract_raw(e[1...-1])
159
+ @vars.extract_raw(e[1...-1])[:rb].wrapper(:r)
160
+ }
161
+ ## Dyndoc var
162
+ str.gsub!(/<[\w\.\_\-]+\:>/) {|e|
163
+ "dynVar["+e[1...-2]+"]"
164
+ }
165
+ #-| TO DEBUG: Dyndoc.warn str if str!=str2
166
+ end
167
+
168
+ def process_jl(str)
169
+ str2=str.dup
170
+ ## dynArray var
171
+ str.gsub!(/<[\w\.\_\-]+\%>/) {|e|
172
+ #p e[1...-1]
173
+ #p @vars.extract_raw(e[1...-1])
174
+ @vars.extract_raw(e[1...-1])[:rb].wrapper(:jl)
175
+ }
176
+ #-| TO DEBUG: Dyndoc.warn str if str!=str2
177
+ end
178
+
179
+ def clean_block_without_bracket(code)
180
+ #puts "initial code";p code
181
+ if code[0][0]==:main and code[0][1] =~ /^\s*\[/ and code[-1][0]==:main and code[-1][1] =~ /\]\s*$/
182
+ code[0][1].sub!(/^(\s*)(\[)/) {|e| $1}
183
+ code[-1][1]=code[-1][1].reverse.sub(/^(\s*)(\])/) {|e| $1}.reverse
184
+ #puts "cleaned code";p code
185
+ end
186
+ end
187
+
188
+ end;end;end
@@ -0,0 +1,886 @@
1
+ # Objectif du Scanner:
2
+ # 1) Gestion du parsing en mode dtag
3
+ # .) Imbrication des blocs :dtag {%...%}
4
+ # .) Bloc texte est splitté en une alternance de blocs :main et de blocs :dtag {%...%}
5
+ # .) Sortie de process en une structure:
6
+ # ex: [[:main,"..."] [:if, [:args,"...",[...]"],[:main,"..."],:else,[:main,"..."]]
7
+ # .) NEW: un bloc peut être inséré dans un argument :args
8
+ # TODO: 1) desescaper le délimiteur dans :args
9
+ # 2) Gestion du parsing des appels fonctions @{...}@
10
+ # TODO
11
+ # 3) TODO: imbrication des modes #{} :{} et :R{} à gérer
12
+ # RMK: 1) a-t-on besoin d'autant de mode? A réfléchir mais c'est en fonction des priorités d'exécution.
13
+ # 2) Il y a 4 grands modes d'utilisation:
14
+ # a) Mode imbriqué blocks dtag : {% ...%}
15
+ # rmk: exécution d'un block intérieur après le bloc :main précédent du block principal!
16
+ # b) Mode séquentiel Part tags : %() utiles dans pour le multi-output
17
+ # c) Mode séquentiel Utilisateur : [#...]
18
+ # d) Mode imbriqué dans blocks texte : #[r,R,Rb]{}, :[R,r]{} , @{}@
19
+ # rmk: exécution des blocks intérieurs avant le block principal
20
+
21
+ require 'strscan'
22
+
23
+ if RUBY_VERSION < "1.9"
24
+
25
+ class String
26
+ alias :byteslice :"[]"
27
+ end
28
+
29
+ end
30
+
31
+ module Dyndoc
32
+ class Scanner
33
+
34
+ @@type={}
35
+
36
+ @@close={"("=>")","["=>"]","{"=>"}"}
37
+ @@open={"}"=>"{",")"=>"(","]"=>"["}
38
+
39
+ #IMPORTANT: start and close delimiters are unique and not useable inside text!
40
+ #RMK: this differs from the actual CallManager
41
+
42
+ attr_reader :scan
43
+
44
+ def initialize(type,start=nil,stop=nil,mode=nil,escape=nil)
45
+ @tag_type=type
46
+ @tag=@@type[type]
47
+ @start=@tag[:start] unless start
48
+ @start=/#{@start}/ if @start.is_a? String
49
+ @stop=@tag[:stop] unless stop
50
+ @stop=/#{@stop}/ if @stop.is_a? String
51
+ @mode=@tag[:mode] unless mode
52
+ @escape={:start=>@tag[:escape_start],:stop=>@tag[:escape_stop]} unless escape
53
+ #mode corresponds to @start[@mode[:start],@mode[:length]] and @stop[@mode[:stop],@mode[:length]]
54
+ init_strange
55
+ @scan=StringScanner.new("")
56
+ end
57
+
58
+ ######################################
59
+ # stack is a sequence of delimiters
60
+ # clean_stack selects only the associated open and closed delimiters!
61
+ #####################################
62
+ def clean_stack(stack)
63
+ open_stack,keep=[],{}
64
+ stack.each do |elt|
65
+ if elt[1]==1
66
+ open_stack << elt
67
+ else
68
+ if open_stack.empty?
69
+ ##too many closed delimiters
70
+ else
71
+ keep[elt]=true
72
+ keep[open_stack.pop]=true
73
+ end
74
+ end
75
+ end
76
+ =begin
77
+ if Dyndoc.cfg_dir[:debug]
78
+ tmp=stack.select{|elt| !keep[elt]}.select{|e| @tag_type==:call and e[2] and e[1]==1 and e[2]!='{'}
79
+ begin p @txt;p tmp end unless tmp.empty?
80
+ end
81
+ =end
82
+ stack.select{|elt| keep[elt]}
83
+ end
84
+
85
+ def token_stack
86
+ @scan.string=@txt
87
+ @scan.pos=0
88
+ stack,s=[],0
89
+ mode=-2 #stop
90
+ begin
91
+ if mode!=-1
92
+ p1=@scan.check_until(@start)
93
+ if p1
94
+ s1=@scan.pre_match.size
95
+ m1=@scan.matched
96
+ end
97
+ end
98
+ if mode!=1
99
+ p2=@scan.check_until(@stop)
100
+ if p2
101
+ s2=@scan.pre_match.size
102
+ m2=@scan.matched
103
+ end
104
+ end
105
+ if p1 and p2
106
+ mode=(s1<s2 ? 1 : -1)
107
+ elsif p2 and !p1
108
+ mode=-1
109
+ elsif !p2 and p1
110
+ mode=-3 #error
111
+ elsif !p2 and !p1
112
+ mode=-2 #stop
113
+ end
114
+ if mode==1
115
+ stack << [s1,mode,m1] unless @escape[:start] and @escape[:start].include? m1
116
+ @scan.scan_until(@start)
117
+ elsif mode==-1
118
+ s=s2
119
+ stack << [s2,mode,m2] unless @escape[:stop] and @escape[:stop].include? m2
120
+ @scan.scan_until(@stop)
121
+ end
122
+ s=@scan.pos
123
+ end while mode>-2
124
+ return clean_stack(stack)
125
+ end
126
+
127
+ def init_atom
128
+ if @tag[:atom]
129
+ @txt.gsub!(@tag[:atom][:match]){|w|
130
+ m=@tag[:atom][:match].match(w)
131
+ res=""
132
+ (1...m.size).each{|i|
133
+ res << (@tag[:atom][:replace][i] ? @tag[:atom][:replace][i] : m[i])
134
+ }
135
+ res
136
+ }
137
+ end
138
+ end
139
+
140
+ def tokenize(txt)
141
+ @txt=txt
142
+ init_atom
143
+ stack=token_stack
144
+ #p txt
145
+ #p stack
146
+ stack2=[]
147
+ root=block={:inside=>[]} #init bloc
148
+ while !stack.empty?
149
+ elt=stack.shift
150
+ #puts "stack2";p stack2
151
+ if elt[1]==1
152
+ #new bloc
153
+ parent=block
154
+ block={:type=>elt[2][0...-1],:start=>elt[0],:inside=>[]}
155
+ stack2 << [block,parent]
156
+ elsif elt[1]==-1
157
+ block,parent=stack2.pop
158
+ block[:stop]=elt[0]+elt[2].size-1
159
+ if parent[:start]
160
+ block[:start] -= parent[:start]
161
+ block[:stop] -= parent[:start]
162
+ end
163
+ parent[:inside] << block
164
+ block=parent
165
+ end
166
+ end
167
+ return (@token={:txt=> @txt,:inside=> (root[:inside])})
168
+ end
169
+
170
+ ## Extract a structure with a root block which is a text block and the child blocks which are dtag blocks.
171
+ @@strange="_[_?_]_"
172
+
173
+ def init_strange(strange=@@strange)
174
+ @strange=strange
175
+ @re_strange=/#{Regexp.escape(@strange)}/
176
+ @re_strange2=/(#{Regexp.escape(@strange)})/
177
+ end
178
+
179
+ def extract(res=nil,txt=nil,type=nil)
180
+ if res
181
+ start=0
182
+ txt2=""
183
+ ind=0
184
+ res2=res.map{|r|
185
+ txt2 << txt[start...(r[:start])]
186
+ txt2 << @@strange
187
+ ind += 1
188
+ r2={}
189
+ start=r[:stop]+1
190
+ if r[:inside].empty?
191
+ r2[:txt]=txt[(r[:start])..(r[:stop])]
192
+ r2[:type]=r[:type]
193
+ r2
194
+ else
195
+ tmp=extract(r[:inside],txt[(r[:start])..(r[:stop])],r[:type])
196
+ tmp
197
+ end
198
+ }
199
+ txt2 << txt[start..-1]
200
+ {:txt=>txt2,:type=>type,:inside=> res2}
201
+ else
202
+ res=@token[:inside].dup
203
+ return extract(res,@token[:txt])
204
+ end
205
+ end
206
+
207
+ def rebuild_after_filter(res,filter=nil)
208
+ txt=""
209
+ start=0
210
+ #p res
211
+ parts=res[:txt].split(@re_strange,-1)
212
+ ##puts "parts";p parts
213
+ ##puts "inside";p res[:inside]
214
+ res[:inside].map do |e|
215
+ txt << parts.shift
216
+
217
+ txt2= (e[:inside] ? rebuild_after_filter(e,filter) : e[:txt] )
218
+ #puts "txt2";p txt2; p [res[:type],e[:type]]
219
+ #IMPORTANT: process has to have as the second argument e[:type] corresponding to the inside_type and as the third argument res[:type] corresponding to the out_type
220
+ ##Dyndoc.warn "scan",txt2,e[:type],res[:type],(filter ? filter.process(txt2,e[:type],res[:type]) : txt2)
221
+ txt2=((filter and !(txt2=~/\[HTML\]/)) ? filter.process(txt2,e[:type],res[:type]) : txt2)
222
+ ##p txt2
223
+ txt << txt2
224
+ end
225
+ #puts "txt";p txt
226
+ txt << parts.shift unless parts.empty?
227
+ txt
228
+ end
229
+
230
+ end
231
+
232
+ class CallScanner < Scanner
233
+
234
+ @@type[:call]={
235
+ :start=>/\\?(?:\#|\#\#|@|#F|#R|#r|\:R|\:r|#Rb|#rb|\:|\:Rb|\:rb|\:jl|#jl)?\{/,
236
+ :stop=> /\\?\}/,
237
+ :mode=>{:start=>-1,:stop=>0,:length=>1},
238
+ :escape_start=>['\{'], #doivent être parsable dans start
239
+ :escape_stop=>['\}'], #doivent être parsable dans stop
240
+ }
241
+
242
+ def initialize(type=:call,start=nil,stop=nil,mode=nil,escape=nil)
243
+ super
244
+ @type_stop_filter="#!"
245
+ end
246
+ end
247
+
248
+ class DevTagScanner < Scanner
249
+
250
+ =begin TO_REMOVE
251
+ @@type[:dtag] = {
252
+ :start=>'\{%(\w*)',
253
+ :stop=> '%\}',
254
+ :keyword=>['%',''],
255
+ :block=> '[\]|]',
256
+ :mode=>{:start=>0,:stop=>-1,:length=>1}
257
+ }
258
+ =end
259
+ @@type[:dtag] = {
260
+ :start=>'\{[\#\@]([\w\:\|-]*[<>]?[=?!><]?(\.\w*)?)\]',
261
+ :stop=> '\[[\#\@]([\w\:\|-]*[<>]?[=?!><]?)\}',
262
+ :atom=>{:match=>/(\{[\#\@][\w\:\|]*)([\#\@]\})/,:replace=>{2=>"][#}"}},
263
+ :block=> '\]', #no longer |
264
+ :keyword=>['\[[\#\@]','\]'],
265
+ :mode=>{:start=>0,:stop=>-1,:length=>1}
266
+ }
267
+
268
+ def get_tag_blck
269
+ @@tagblck_set
270
+ end
271
+
272
+
273
+ def initialize(type=:dtag,start=nil,stop=nil,mode=nil,escape=nil)
274
+ super
275
+ init_tag(@tag_type) if [:dtag].include? @tag_type
276
+ end
277
+
278
+ @@tagblck_set=[:<<,:<,:do,:>>,:>,:">!",:out,:nl,:"\\n",:"r<",:"R<",:"rb<",:"m<",:"M<",:"jl<",:"r>>",:"R>>",:rverb,:"rb>>",:rbverb,:"jl>>",:jlverb,:rout,:"r>",:"R>",:"rb>",:"m>",:"M>",:"jl>",:"_<",:"_>",:"__>",:"html>",:"tex>",:"txtl>",:"ttm>",:"md>",:"adoc>",:tag,:"??",:"?",:yield,:"=",:"-",:+,:"%"]
279
+ #Rmk: when a symbol is included in another one, you have to place it before! Ex: :>> before :> and also :<< before :<
280
+
281
+ @@tagblck_dyndoc_set = [:main,:content,:before,:after,:require,:helpers,:preamble,:postamble,:style,:title,:path,:first,:last,:default,:cfg]
282
+ @@tagblck_tex_set=[:class,:optclass,:package,:texinputs]
283
+ @@tagblck_html_set=[:js,:css,:header,:footer]
284
+
285
+ TXT_DTAG=[:txt,:code,:>,:<,:<<]
286
+
287
+ @@dtag={
288
+ :dtag => {
289
+ :instr=>["newBlck","input","require","hide","format","txt",">","<","<<",">>","code","verb","if","unless","for","loop","case","var","set","def","func","meth","new","super","do","out","blck","blckAnyTag","saved","b>","call","R","r","m","M","jl","renv","rverb","rbverb","jlverb","rout","rb","eval","ifndef","tags","keys","opt","document","yield","get","part"],
290
+ :alias=>{
291
+ :vars=>:var,
292
+ :dyn=>:eval,
293
+ :rmk=>:hide,
294
+ :static => :saved,
295
+ :comment=>:hide,
296
+ :>> => [:blck,:>],
297
+ #:"b>" => [:blck, :>],
298
+ :"rb>" => [:blck, :"rb>"],
299
+ :"R>" => [:blck, :"R>"],
300
+ :"jl>" => [:blck, :"jl>"],
301
+ :"jl>>" => [:blck, :"jl>>"],
302
+ :"rb<" => [:blck, :"rb<"],
303
+ :"R<" => [:blck, :"R<"],
304
+ :"jl<" => [:blck, :"jl<"],
305
+ :"r>>" => [:blck, :"r>>"],
306
+ :"R>>" => [:blck, :"r>>"],
307
+ :"*<" => [:blck, :"*<"],
308
+ :"*>" => [:blck, :"*>"],
309
+ :"_>" => [:blck, :"_>"],
310
+ :"tex>" => [:blck, :"tex>"],
311
+ :"html>" => [:blck, :"html>"],
312
+ :"txtl>" => [:blck, :"txtl>"],
313
+ :"md>" => [:blck, :"md>"],
314
+ :"adoc>" => [:blck, :"adoc>"],
315
+ :"ttm>" => [:blck, :"ttm>"]
316
+ },
317
+ :empty_keyword=>["?","empty"],
318
+ :keyword=>{
319
+ :document => @@tagblck_dyndoc_set + @@tagblck_tex_set + @@tagblck_html_set,
320
+ :if=> [:else,:elsif,:if,:unless],
321
+ :unless=> [:else,:elsif,:if,:unless],
322
+ :for=>[],
323
+ :loop=>[:break],
324
+ :case=>[:when,:else],
325
+ :var=>[:","],
326
+ :set=>[],
327
+ :def=>[:",",:binding],
328
+ :meth=>[:","],
329
+ :new=>[:",",:of,:in,:blck],
330
+ :super=>[:",",:parent,:blck],
331
+ :do=>[],
332
+ :out=>[],
333
+ :blck=>[],
334
+ :saved=>[],
335
+ :call=> [:",",:blck,:"->"],
336
+ :style=> [:of,:",",:blck,:default],
337
+ :input=>[:","],
338
+ :r=>[:in],
339
+ :rverb=>[:in,:mode],
340
+ :rbverb=>[:mode],
341
+ :jlverb=>[:mode],
342
+ :rout=>[:in,:mode],
343
+ :eval=>[:to],
344
+ :ifndef=>[:<<],
345
+ :tags=>[:when],
346
+ :keys=> [],
347
+ :part=>[],
348
+ :get=>[:blck]
349
+ },
350
+ :keyword_reg=>{ #to overpass :keyword
351
+ :new=> '[%.\w,><?=+:-]+',
352
+ :call=> '[%.\w,><?=+:-]+(?:\@|\$)?',
353
+ :style=>'[%.\w,><?=+:-]+',
354
+ :newBlck=>'[%.\w,><?=+:-]+',
355
+ :blckAnyTag=>'[%.\w,><?=+:-]+',
356
+ },
357
+ :with_tagblck =>[:document,:if,:unless,:for,:loop,:case,:set,:def,:meth,:new,:super,:do,:out,:blck,:saved,:call,:style,:rverb,:rbverb,:jlverb,:rout,:tags,:keys,:part],
358
+ :named_tag=>{
359
+ #=begin
360
+ :> => {:tag=>'(_TAG_)(?:[^\]]+)?',:rest=>/^>([^\]]*)$/},
361
+ :>> => {:tag=>'(_TAG_)(?:[^\]]+)?',:rest=>/^>>([^\]]*)$/},
362
+ :"r>" => {:tag=>'(_TAG_)(?:[^\]]+)?',:rest=>/^r>([^\]]*)$/},
363
+ :"rb>" => {:tag=>'(_TAG_)(?:[^\]]+)?',:rest=>/^rb>([^\]]*)$/},
364
+ :"=" => {:tag=>'(_TAG_)(?:[^\]]+)?',:rest=>/^=([^\]]*)$/}
365
+ #=end
366
+ },
367
+ :mode_arg=>:next_block,
368
+ :tag_code=>[:code,:<,:>,:<<,:txt], #used for arg mode!
369
+ :arg=>[:if,:unless,:elsif,:for,:case,:def,:func,:meth,:new,:super,:call,:input,:when,:break,:set,:style,:keys,:"?",:"rb<",:"r<",:"R<",:"m<",:"M<",:"jl<"],
370
+ :blck=>{
371
+ :instr=>[:document,:if,:unless,:case,:loop,:set,:tag,:keys,:rverb,:rbverb,:jlverb,:for],
372
+ :keyword=>{
373
+ :document=>@@tagblck_dyndoc_set + @@tagblck_tex_set + @@tagblck_html_set,
374
+ :set=>[:set],
375
+ :if=>[:if,:unless,:elsif,:else],
376
+ :unless=>[:if,:unless,:elsif,:else],
377
+ :case=>[:when,:else],
378
+ :loop=>[:loop,:break],
379
+ :tags=>[:when],
380
+ :rverb=>[:rverb,:in,:mode],
381
+ :rbverb=>[:rbverb,:mode],
382
+ :jlverb=>[:jlverb,:mode],
383
+ :rout=>[:rout,:in,:mode]
384
+ }
385
+ },
386
+ :style=>"@" #specify that the scanner recognize a style instead a call when blck[:type].include? "@"
387
+ }
388
+ }
389
+
390
+ attr_accessor :dtag
391
+
392
+ def init_tag(type=:dtag)
393
+ @dtag=@@dtag[type]
394
+ @tag_instr=@dtag[:instr]+@dtag[:alias].keys.map{|e| e.to_s}
395
+ @tag_alias=@dtag[:alias]
396
+ @tag_keyword=@dtag[:keyword]
397
+ @tag_keyword_reg=@dtag[:keyword_reg]
398
+ @tag_arg=@dtag[:arg]
399
+ @tag_code=(@dtag[:tag_code] ? @dtag[:tag_code] : [] )
400
+ @tag_style=@dtag[:style]
401
+ @tag_blck=@dtag[:blck]
402
+ ## deal with fixed blck tags
403
+ @named_tags=[]
404
+ @@keystagblck=@@tagblck_set.map{|e| complete_tag(e)}.compact.join("|") #only once!
405
+ @@named_tags_blck=@named_tags
406
+ end
407
+
408
+ def merge_tag(dtag)
409
+ if dtag
410
+ @tag_instr += dtag[:instr] if dtag[:instr]
411
+ @tag_instr += dtag[:alias].keys.map{|e| e.to_s} if dtag[:alias]
412
+ @tag_alias.merge!(dtag[:alias]) if dtag[:alias]
413
+ @tag_keyword.merge!(dtag[:keyword]) if dtag[:keyword]
414
+ @tag_keyword_reg.merge!(dtag[:keyword_reg]) if dtag[:keyword_reg]
415
+ @tag_arg += dtag[:arg] if dtag[:arg]
416
+ if dtag[:blck]
417
+ @tag_blck[:instr] += dtag[:blck][:instr] if dtag[:blck][:instr]
418
+ @tag_blck[:keyword].merge!(dtag[:blck][:keyword]) if dtag[:blck][:keyword]
419
+ end
420
+ end
421
+ end
422
+
423
+ ## update an existing tag keywork (ex: document for html structure by adding #css #js #menu or anything needed in the model)
424
+ def update_tag_keyword(keyword,tags_set=[],args={})
425
+ @tag_keyword[keyword] += tags_set
426
+ @tag_blck[:keyword][keyword] += new_tags_set if args[:mode] && args[:mode] == :blck
427
+ end
428
+
429
+ ## Types of result block:
430
+ ## 1) :main
431
+ ## 2) :args
432
+ ## 3) :instr (:if, :case, ...)
433
+ ## Types of parsed block:
434
+ ## 1) :text -> main block alternating text and dtag blocks
435
+ ## 2) :dtag -> {% ...%}
436
+
437
+ def find_args(inside)
438
+ ## Instruction delimiter
439
+ delim=@block[@scan.pos,1]
440
+ #p delim
441
+ @scan.pos += delim.bytesize #.length
442
+ st=@scan.pos
443
+ delim=@@close[delim] if @@close[delim]
444
+ #p delim
445
+ ## Arguments
446
+ begin
447
+ @scan.scan_until(/#{Regexp.escape(delim)}/)
448
+ end while @block[@scan.pos-2,1]=='\\'
449
+ sp=@scan.pos - delim.bytesize - 1 #.length - 1
450
+ args=@block.byteslice(st..sp) #@block[st..sp]
451
+ inside2=[]
452
+ (1..(args.split(@re_strange,-1).length-1)).each{ inside2 << inside.shift }
453
+ return [:args,{:txt=>args,:inside=>inside2}]
454
+ end
455
+
456
+ def find_text(from,key,inside)
457
+ #p ["key=",key]
458
+ res,to=nil,nil
459
+ pre=(@next_pre ? @next_pre : nil )
460
+ @next_pre=nil
461
+ if @scan[1].nil? or @scan[1].empty? or @is_arg
462
+ #p ["key=",key,@tag_selected]
463
+ if @tag_selected
464
+ @next_pre=key[2...-1].scan(@dtag[:named_tag][@tag_selected.to_sym][:rest])[0][0]
465
+ @next_pre=nil if @next_pre.empty?
466
+ end
467
+ @scan.scan_until(/#{Regexp.escape(key)}/)
468
+ to=@scan.pre_match.bytesize #.length
469
+ ##Dyndoc.warn "TOOOOOOOOOOO",[@scan.pre_match,to]
470
+ res=@block.byteslice(from...to) #@block[from...to]
471
+ else
472
+ #p ["pre_match=",@scan.pre_match,"to=",@scan.pre_match.bytesize]
473
+ to=@scan.pre_match.bytesize #.length
474
+ ##Dyndoc.warn "TOOOOOOOOOOO2222",[@scan.pre_match,to]
475
+ delim2=@scan[1]
476
+ delim2=@@open[delim2] if @@open[delim2]
477
+ #p ["delim2=",delim2,/#{Regexp.escape(delim2)}/]
478
+ #p @block[from...-1]
479
+ @scan.exist?(/#{Regexp.escape(delim2)}/)
480
+ to_tmp=@scan.pre_match.bytesize #.length
481
+ #p ["to_tmp=",to_tmp]
482
+ ## pre=@block[from...to_tmp].strip unless pre
483
+ #p [:pre,pre]
484
+ pre=@block.byteslice(from...to_tmp).strip unless pre
485
+ #p ["pre=",pre]
486
+ from=to_tmp+1
487
+ #p ["key:",key,@scan.matched,from,@block[from-1,1]]
488
+ @scan.scan_until(/#{@tag[:block]}\s*#{Regexp.escape(key)}/)
489
+ =begin
490
+ @scan.scan_until(/[\]|]\s*#{key}/)
491
+ =end
492
+ #p ["matched=",@scan.matched]
493
+ #p @scan.pre_match
494
+ #to=@scan.pre_match.length
495
+ res=@block.byteslice(from...to) #does not work for ruby2 => @block[from...to]
496
+ pre=nil if pre.empty?
497
+ #p ["res=",from,to,res,@block.byteslice(from...to)]
498
+ end
499
+ inside2=[]
500
+ (1..(res.split(@re_strange,-1).length-1)).each{ inside2 << inside.shift }
501
+ return [:text,{:name=>pre,:txt=>res,:inside=>inside2}] if pre
502
+ return [(@is_arg ? :args : :text),{:txt=>res,:inside=>inside2}]
503
+ end
504
+
505
+
506
+ def complete_tag(key,add=true)
507
+ #Regexp.escape(key.to_s)+((@dtag[:named_tag][key]) ? @dtag[:named_tag][key] : "")
508
+ if @dtag[:named_tag][key]
509
+ if add
510
+ @named_tags << key
511
+ return nil
512
+ else
513
+ @dtag[:named_tag][key][:tag].sub("_TAG_",Regexp.escape( key.to_s ))
514
+ end
515
+ else
516
+ return Regexp.escape(key.to_s)
517
+ end
518
+ end
519
+
520
+ def check_until_for_named_tags
521
+ #if res
522
+ @named_tags.each_index{|i|
523
+ if @scan[3+i]
524
+ @tag_selected=@scan[3+i].to_sym
525
+ #puts "here we go: #{@tag_selected}"
526
+ break
527
+ end
528
+ }
529
+ #end
530
+ #return res
531
+ end
532
+
533
+ ## ATTENTION: Ne pas faire de recurrence dans convert_block à cause de @scan! qui est en unique exemplaire!
534
+ def convert_block(blck)
535
+ #puts "split_block";p blck
536
+ @block= blck[:txt]
537
+ inside=blck[:inside]
538
+ style=blck[:type].include? @tag_style
539
+ pre_res=[]
540
+ res=[]
541
+ =begin
542
+ ## Mode -> unused now!
543
+ mode=@block[0,@mode[:length]]
544
+ mode2=(@@close[mode] ? @@close[mode] : mode)
545
+ =end
546
+ @scan.string=@block
547
+ @scan.pos=0
548
+ ## Instruction
549
+ #@scan.scan_until(/(?:#{@tag_instr.join("|")})/)
550
+ @scan.scan_until(@start)
551
+ instr=@scan[1] #@scan.matched
552
+ #p [:instr,instr]
553
+ # next block is a arg block?
554
+ @is_arg=false
555
+ if @tag_instr.include? instr
556
+ instr=instr.to_sym
557
+ instr=@tag_alias[instr] if @tag_alias.include? instr
558
+ if instr.is_a? Array
559
+ res += instr
560
+ instr=instr[0]
561
+ else
562
+ res << instr
563
+ end
564
+ if (@tag_arg+@tag_code).include? instr
565
+ case @dtag[:mode_arg]
566
+ when :find
567
+ res << find_args(inside)
568
+ when :next_block
569
+ @is_arg=true
570
+ end
571
+ end
572
+ else
573
+ instr2=(style ? :style : :call)
574
+ #pour un éventuel ajout de > ou < à la fin
575
+ if [">","<"].include? instr[-1,1]
576
+ instr2,instr=(instr2.to_s+instr[-1,1]).to_sym,instr[0...-1]
577
+ end
578
+ res << instr2 << [:args, {:txt=>instr,:inside=>[]}]
579
+ instr=instr2
580
+ end
581
+ ## Text block
582
+ ## find keywords
583
+ from=true
584
+ #p "todoooo"
585
+ while from
586
+ from=@scan.pos
587
+ #p @tag_keyword[instr]
588
+ #p /(#{@tag[:block]}?)\s*(#{@tag[:keyword][0]}(?:#{keytags=(@tag_keyword[instr] ? @tag_keyword[instr] : [] ).map{|e| Regexp.escape(e.to_s)}.join("|")})#{@dtag[:empty_keyword][0]}#{@tag[:keyword][1]})/
589
+ tag_keyword=nil
590
+ if @dtag[:empty_keyword][0].empty?
591
+ #no empty tag!
592
+ tag_keyword=@tag_keyword[instr] if @tag_keyword[instr]
593
+ else
594
+ tag_keyword=(@tag_keyword[instr] ? @tag_keyword[instr] : [] )
595
+ end
596
+ keytags=nil
597
+ @named_tags,@tag_selected=[],nil
598
+ if tag_keyword
599
+ #p tag_keyword
600
+ if @tag_keyword_reg and @tag_keyword_reg[instr]
601
+ tag_keyword=@tag_keyword_reg[instr]
602
+ blocktag_reg=/(#{@tag[:block]}?)\s*(#{@tag[:keyword][0]}#{tag_keyword}#{@dtag[:empty_keyword][0]}#{@tag[:keyword][1]})/
603
+ tag_reg=/#{tag_keyword}/
604
+ else
605
+ keytags=tag_keyword.map{|e| complete_tag(e)}.compact.join("|")
606
+ #puts "keytags(1)";p keytags
607
+ #puts "INSTR="; p instr
608
+ if @dtag[:with_tagblck].include? instr
609
+ keytags += "|" unless keytags.empty?
610
+ keytags += @@keystagblck
611
+ @named_tags += @@named_tags_blck
612
+ end
613
+ ##puts "keytags(2)";p keytags
614
+ tag_reg=/(?:#{keytags})/
615
+ unless @named_tags.empty?
616
+ keytags += "|"+(@named_tags.map{|tag| complete_tag(tag,nil)}.join("|"))
617
+ end
618
+ ##Dyndoc.warn "keytags",keytags
619
+ blocktag_reg=/(#{@tag[:block]}?)\s*(#{@tag[:keyword][0]}(?:#{keytags})#{@dtag[:empty_keyword][0]}#{@tag[:keyword][1]})/
620
+ end
621
+ ##Dyndoc.warn "to scan", @scan.string[@scan.pos..-1]
622
+ ##Dyndoc.warn "tag_reg",[blocktag_reg,tag_reg]
623
+ end
624
+ if (tag_keyword and (@scan.check_until(blocktag_reg))) #or (!@named_tags.empty? and check_until_for_named_tags)
625
+ check_until_for_named_tags unless @named_tags.empty?
626
+ key=@scan[2]
627
+ ##Dyndoc.warn "keyword",[key,@scan[0],@scan[1],@scan[2]]
628
+ ##Dyndoc.warn "pre_math,tag_selected",[@scan.pre_match,@tag_selected] if key=="[#tag]"
629
+ res << find_text(from,key,inside)
630
+ @is_arg=false if @is_arg
631
+ ##Dyndoc.warn "key(AV)",[key,tag_reg] if key=="[#tag]"
632
+ if @tag_selected
633
+ #puts "tag_selected";p @tag_selected
634
+ res << (key=@tag_selected)
635
+ else
636
+ #key=tag_reg.match(key)[0]
637
+ key= key.scan(tag_reg)[0]
638
+ ##Dyndoc.warn "key(AP)",key if key=="tag"
639
+ res << (key=key.to_sym) if key and !key.empty?
640
+ end
641
+ #res << (key=key[1..-1].to_sym)
642
+ #p @tag_arg
643
+ if @tag_arg.include? key #without @tag_code inside a block
644
+ case @dtag[:mode_arg]
645
+ when :find
646
+ res << find_args(inside)
647
+ from=@scan.pos
648
+ when :next_block
649
+ @is_arg=true
650
+ end
651
+ end
652
+ else
653
+ #Last text block!
654
+ #p /(#{@tag[:block]}?)\s*(#{@tag[:stop]})/
655
+ @scan.check_until(/(#{@tag[:block]}?)\s*(#{@tag[:stop]})/)
656
+ #puts "last"; p @scan[2];p @scan[0]; p @scan[1]
657
+ #p @scan.pre_match
658
+ res << find_text(from,@scan[2],inside)
659
+ #p res
660
+ from=false
661
+ end
662
+ #puts "from2";p from
663
+ end
664
+ #puts "res";p res
665
+ return res
666
+ end
667
+
668
+ def parse_block(blck)
669
+ res=convert_block(blck)
670
+ #puts "res";p res
671
+ ##Stop scan when :txt instruction to avoid parsing!
672
+ if TXT_DTAG.include? res[0]
673
+ res2=[res[0],rebuild_after_filter(res[1][1])]
674
+ # NO MORE POSSIBLE! res2 << res[1][1][:name] if res[1][1][:name]
675
+ #p res2
676
+ return res2
677
+ end
678
+ res2=[]
679
+ res.each{|e|
680
+ #p e
681
+ if e.is_a? Array
682
+ case e[0]
683
+ when :args
684
+ res2 << parse_args(e[1])
685
+ when :text
686
+ res2 += parse_text(e[1])
687
+ end
688
+ else
689
+ res2 << e
690
+ end
691
+ }
692
+ #p res2
693
+ #make :blck block if necessary
694
+ res2=ajust_with_blck(res2)
695
+ #puts "res2";p res2
696
+ return res2
697
+ end
698
+
699
+ def ajust_with_blck(res)
700
+ return res unless @tag_blck[:keyword].include? res[0]
701
+ instr=@tag_blck[:keyword][res[0]]
702
+ res_blck,blck=[],nil
703
+ begin
704
+ b=res.shift
705
+ if instr.include? b
706
+ #create the :blck block
707
+ res_blck << b
708
+ #is there an :args block?
709
+ res_blck << res.shift if @tag_arg.include? b
710
+ #if no first tag_blck then put the default :out tag
711
+ blck=[:blck]
712
+ blck << :out unless @@tagblck_set.include? res[0]
713
+ else
714
+ if blck
715
+ blck << b
716
+ else
717
+ #needed for example :case block
718
+ res_blck << b
719
+ end
720
+ #is the end of blck?
721
+ if res.empty? or (instr.include? res[0])
722
+ res_blck << blck if blck
723
+ blck=nil
724
+ end
725
+ end
726
+ end until res.empty?
727
+ res_blck
728
+ end
729
+
730
+ def parse_args(blck)
731
+ res=[:args]
732
+ #puts ":args";p blck[:txt]
733
+ parts=blck[:txt].split(@re_strange,-1)
734
+ #p parts
735
+ #p blck[:inside]
736
+ blck[:inside].map do |e|
737
+ res << [:main,parts.shift]
738
+ res << parse_block(e)
739
+ end
740
+ res << [:main,parts.shift]
741
+ res
742
+ end
743
+
744
+ def parsed_block_with_modifier(res_block)
745
+ res=nil
746
+ instr=res_block[0,1].to_s
747
+ if !["<","<<",">"].include? instr and [">","<"].include?(modif=instr[-1,1])
748
+ res=modif.to_sym
749
+ res_block[0,1]=instr[0...-1].to_sym
750
+ end
751
+ res
752
+ end
753
+
754
+ def parse_text(blck)
755
+ #puts "blck";p blck
756
+ res=[]
757
+ blck[:txt].split(@re_strange2,-1).each{|e|
758
+ if e==@strange
759
+
760
+ b=blck[:inside].shift
761
+ res_b=parse_block(b)
762
+ if (res_modif=parsed_block_with_modifier(res_b))
763
+ res << res_modif
764
+ end
765
+ #puts "parse_text: res_b";p res_b
766
+ res << res_b
767
+ else
768
+ res << [:main,e]
769
+ end
770
+ }
771
+ res=[[:named,blck[:name]]+res] if blck[:name]
772
+ res
773
+ end
774
+
775
+ def rebuild_after_parse(res)
776
+ txt=""
777
+ start=0
778
+ parts=res[:txt].split(@re_strange,-1)
779
+ res[:inside].map do |e|
780
+ txt << parts.shift
781
+ txt << (e[:inside] ? rebuild_after_parse(e) : e[:txt])
782
+ end
783
+ txt << parts.shift
784
+ txt
785
+ end
786
+
787
+ def process(txt)
788
+ tokenize(txt)
789
+ parse_text(extract)
790
+ end
791
+
792
+ def pretty_print(res,tab=0)
793
+ res.each{|b|
794
+ if b.is_a? Array
795
+ pretty_print(b,tab+1)
796
+ else
797
+ puts " "*tab+b.inspect+"\n"
798
+ end
799
+ }
800
+ end
801
+
802
+ end
803
+
804
+ class VarsScanner < Scanner
805
+
806
+ @@type[:vars]={
807
+ :start=>'<<([\w\@]*)\s*\[',
808
+ :stop=> '\]',
809
+ :mode=>{:start=>-1,:stop=>0,:length=>1}
810
+ }
811
+
812
+ def initialize(type=:vars,start=nil,stop=nil,mode=nil,escape=nil)
813
+ super
814
+ end
815
+
816
+ def make_vars(res)
817
+ vars=[]
818
+ start=0
819
+ parts=res[:txt].split(@re_strange,-1).join("").strip
820
+ #puts "parts";p parts
821
+ #p res
822
+ #puts "inside";p res[:inside]
823
+ res[:inside].map do |e|
824
+ vars2= [e[:type][2..-1].strip,(e[:inside] ? make_vars(e) : e[:txt][(e[:type].bytesize+1)...-1] )] #instead of length
825
+ vars << vars2
826
+ end
827
+ #puts "vars";p vars
828
+ vars
829
+ end
830
+
831
+ def build_dyn_vars(res)
832
+ #puts "res";p res
833
+ is_arr=res.map{|k,v| k}.join("").empty?
834
+ cpt=-1
835
+ res2=[]
836
+ res.each{|k,v|
837
+ #p k;p v
838
+ key2=(k.empty? ? (is_arr ? "" : "key")+(cpt+=1).to_s : k)
839
+ res0=((v.is_a? Array) ? build_dyn_vars(v) : [["",v]])
840
+ #puts "res0";p res0
841
+ res2+=res0.map{|k0,v0| [key2+(k0.empty? ? "" : "." )+k0,v0]}
842
+ #puts "res2";p res2
843
+ }
844
+ #puts "res2";p res2
845
+ res2
846
+ end
847
+
848
+ def build_rb_vars(res)
849
+ #puts "res";p res
850
+ is_arr=res.map{|k,v| k}.join("").empty?
851
+ cpt=0
852
+ res2=(is_arr ? [] : {})
853
+ res.each{|k,v|
854
+ #p k;p v
855
+ v2=((v.is_a? Array) ? build_rb_vars(v) : v)
856
+ if is_arr
857
+ res2 << v2
858
+ else
859
+ key2=(is_arr ? (cpt+=1) : (k.empty? ? "key"+(cpt+=1).to_s : k).to_sym)
860
+ res2[key2]=v2
861
+ end
862
+ }
863
+ #puts "res2";p res2
864
+ res2
865
+ end
866
+
867
+
868
+ def build_vars(txt,type=:dyn)
869
+ #puts "txt";p txt
870
+ return nil unless txt[0,2]=="<<"
871
+ res=tokenize(txt)
872
+ return nil if res[:inside].empty?
873
+ res=make_vars(extract)
874
+ case type
875
+ when :dyn
876
+ #puts "res in build_vars";p res
877
+ build_dyn_vars(res)
878
+ when :rb
879
+ build_rb_vars(res)
880
+ when :r
881
+ end
882
+ end
883
+
884
+
885
+ end
886
+ end