w2tags 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. data/COPYING +340 -0
  2. data/LICENSE +6 -0
  3. data/MIT-LICENSE +18 -0
  4. data/Manifest.txt +95 -0
  5. data/README.rdoc +264 -0
  6. data/Rakefile +23 -0
  7. data/VERSION +1 -0
  8. data/bin/w2tags +143 -0
  9. data/doc/ERB.HOT.rdoc +82 -0
  10. data/doc/FAQ.rdoc +81 -0
  11. data/doc/HAML.rdoc +310 -0
  12. data/doc/HOT.rdoc +137 -0
  13. data/doc/History.rdoc +757 -0
  14. data/doc/W2TAGS.rdoc +150 -0
  15. data/example/common.hot +11 -0
  16. data/example/from_readme.erb +78 -0
  17. data/example/from_readme.w2erb +64 -0
  18. data/example/from_w2tags.erb +32 -0
  19. data/example/from_w2tags.w2erb +32 -0
  20. data/example/rails_basic.hot +10 -0
  21. data/hot/erb.hot +156 -0
  22. data/hot/erb_form.hot +42 -0
  23. data/hot/erb_head.hot +15 -0
  24. data/hot/erb_jquery.hot +8 -0
  25. data/hot/erb_merb.hot +12 -0
  26. data/hot/erb_table.hot +43 -0
  27. data/hot/html.hot +31 -0
  28. data/hot/jquery.hot +88 -0
  29. data/hot/nvelocity.hot +23 -0
  30. data/hot/rails/sc_zebra.hot +10 -0
  31. data/hot/rails/scaffold.hot +15 -0
  32. data/hot/vm.hot +9 -0
  33. data/hot/vm2.hot +34 -0
  34. data/hot/vm_crud.hot +34 -0
  35. data/hot/vm_popup.hot +74 -0
  36. data/hot/xul.hot +114 -0
  37. data/lib/w2tags/block/plain_text.rb +57 -0
  38. data/lib/w2tags/block/remark.rb +37 -0
  39. data/lib/w2tags/block/sass.rb +66 -0
  40. data/lib/w2tags/merb_hook.rb +15 -0
  41. data/lib/w2tags/parser.rb +975 -0
  42. data/lib/w2tags/rails_hook.rb +15 -0
  43. data/lib/w2tags/sinatra_hook.rb +50 -0
  44. data/lib/w2tags.rb +100 -0
  45. data/plugins//w2tags//README +2 -0
  46. data/plugins//w2tags//generators//w2scaffold//USAGE +29 -0
  47. data/plugins//w2tags//generators//w2scaffold//templates//controller.rb +85 -0
  48. data/plugins//w2tags//generators//w2scaffold//templates//functional_test.rb +45 -0
  49. data/plugins//w2tags//generators//w2scaffold//templates//helper.rb +2 -0
  50. data/plugins//w2tags//generators//w2scaffold//templates//helper_test.rb +4 -0
  51. data/plugins//w2tags//generators//w2scaffold//templates//layout.html.erb +17 -0
  52. data/plugins//w2tags//generators//w2scaffold//templates//style.css +54 -0
  53. data/plugins//w2tags//generators//w2scaffold//templates//view_edit.html.erb +18 -0
  54. data/plugins//w2tags//generators//w2scaffold//templates//view_edit.html.w2erb +17 -0
  55. data/plugins//w2tags//generators//w2scaffold//templates//view_index.html.erb +24 -0
  56. data/plugins//w2tags//generators//w2scaffold//templates//view_index.html.w2erb +14 -0
  57. data/plugins//w2tags//generators//w2scaffold//templates//view_new.html.erb +17 -0
  58. data/plugins//w2tags//generators//w2scaffold//templates//view_new.html.w2erb +16 -0
  59. data/plugins//w2tags//generators//w2scaffold//templates//view_show.html.erb +10 -0
  60. data/plugins//w2tags//generators//w2scaffold//templates//view_show.html.w2erb +9 -0
  61. data/plugins//w2tags//generators//w2scaffold//w2scaffold_generator.rb +106 -0
  62. data/plugins//w2tags//install.rb +1 -0
  63. data/spec/spec_helper.rb +17 -0
  64. data/spec/w2tags_spec.rb +8 -0
  65. data/tasks/ann.rake +81 -0
  66. data/tasks/bones.rake +21 -0
  67. data/tasks/gem.rake +126 -0
  68. data/tasks/git.rake +41 -0
  69. data/tasks/manifest.rake +49 -0
  70. data/tasks/notes.rake +28 -0
  71. data/tasks/post_load.rake +39 -0
  72. data/tasks/rdoc.rake +51 -0
  73. data/tasks/rubyforge.rake +57 -0
  74. data/tasks/setup.rb +268 -0
  75. data/tasks/spec.rake +55 -0
  76. data/tasks/svn.rake +48 -0
  77. data/tasks/test.rake +38 -0
  78. data/test/enlightning.hot +3 -0
  79. data/test/feature.hot +28 -0
  80. data/test/parser_test.rb +203 -0
  81. data/test/tricky.hot +8 -0
  82. data/test/vars.hot +30 -0
  83. data/test/w2tags_basic_usability.rb +187 -0
  84. data/test/w2tags_enlightning.rb +42 -0
  85. data/test/w2tags_form.rb +32 -0
  86. data/test/w2tags_hot.rb +85 -0
  87. data/test/w2tags_hot_var.rb +115 -0
  88. data/test/w2tags_no_parsing.rb +37 -0
  89. metadata +163 -0
@@ -0,0 +1,975 @@
1
+ module W2Tags
2
+ # Copyright (c) 2008 - 2009 Widi Harsojo
3
+ class Parser
4
+ attr_accessor :silent
5
+ #change debuging ex: obj.dbg[:parse] = true
6
+ attr_accessor :dbg
7
+ #set extention for ext auto loading HOT files
8
+ attr_accessor :ext
9
+ attr_reader :spc
10
+
11
+ block= ::W2Tags::Block.constants
12
+ include *(block.collect{|m|eval("::W2Tags::Block::#{m.to_s}")})
13
+ #initiall create instance object, default if no arguments will be
14
+ #target for html
15
+ def initialize(ext = 'html')
16
+ @dbg={
17
+ :hot =>nil,
18
+ :stack =>nil,
19
+ :parse =>nil,
20
+ :constanta=>nil
21
+ }
22
+
23
+ #regex for w2tags
24
+ @rg_tag = [
25
+ /^[ \t]*(%)([!]?[\w\-&\/:#.]+\{.*\}[=]*)!([^\n]*)\n/,
26
+ /^[ \t]*(%)([!]?[\w\-&\/:#.=]+)!([^\n]*)([\n])/]
27
+
28
+ #regex for function tags
29
+ @rg_hot = [
30
+ /(%)([!]?[ \t\$\w\-&\/:#.%=]+\{.*\}[=]*)~([^\n]*)\n/,
31
+ /(%)([!]?[ \t\$\w\-&\/:#.%=]+)~([^\n]*)\n/ ]
32
+ @rgx = nil #current regular expression
33
+ @ext = ext #target extension
34
+ @hot = 'hot' #source of file hot
35
+ @w2x = 'w2x' #source file to include
36
+ @src_path= '' #path for source file
37
+ @silent = false #for test
38
+
39
+ @spc = '' #current begining space of current source line
40
+ @ind = ' ' #indentation size
41
+ @row = 'row' #current source line
42
+ @key = 'key' #key extracted from regex function
43
+
44
+ @mem_hot= nil #@tg_nex will be use (for "%") if this var == nil
45
+ @mem_tag= {'^'=>"%div$*!"} #get memorize of w2tag
46
+ @mem_var= {'$me'=>"wharsojo"}
47
+ @mem_var['$basepath'] = File.basename(File.expand_path('.'))
48
+
49
+ @tg_hot = {} #{'div'=>[proc{|this|"%div$*!"},nil]} #collection of tag_hot after reading from source hot
50
+ @tg_nex = {} #tag next activate on shortcut tag "%"
51
+ @tg_end = [] #momorize tag end from regex function
52
+ @doc_src= []
53
+ @doc_out= []
54
+
55
+ @tg_nex['html' ]= [0,proc { @mem_tag["^"] = "%head $*\n"}]
56
+ @tg_nex['head' ]= [0,proc { @mem_tag["^"] = "%body $*\n"}]
57
+ @tg_nex['ol' ]= [0,proc { @mem_tag["^"] = "%li $0\n" }]
58
+ @tg_nex['ul' ]= [0,proc { @mem_tag["^"] = "%li $0\n" }]
59
+ @tg_nex['dl' ]= [0,proc { @mem_tag["^"] = "%dt $0\n" }]
60
+ @tg_nex['dd' ]= [0,proc { @mem_tag["^"] = "%dt $0\n" }]
61
+ @tg_nex['form' ]= [0,proc { @mem_tag["^"] = "%input $0\n"}]
62
+ @tg_nex['select']= [0,proc { @mem_tag["^"] = "%option $0\n"}]
63
+ @tg_nex['table' ]= [0,proc { @tg_nex['tr'][0]= 0 }]
64
+ @tg_nex['tr' ]= [0,proc {
65
+ @tg_nex['tr' ][0]+= 1
66
+ if @tg_nex['tr'][0]== 1
67
+ @mem_tag["^"] = "%th $0\n"
68
+ else
69
+ @mem_tag["^"] = "%td $0\n"
70
+ end
71
+ }]
72
+
73
+ @tagr = proc do |this|
74
+ @key.strip!
75
+ tags_created = "<#{@key}"
76
+ tags_created << " #{@mem_var["*all*"].strip}" if @mem_var["*all*"]!=''
77
+ #tags_created << " #{@att}" if @att!=''
78
+ if @txt=='/'
79
+ tags_created << "/>\n"
80
+ else
81
+ tags_created << '>'
82
+ @ln_end = " "
83
+ if @txt==''
84
+ @tg_end.push "#{@spc}</#{@key}>#{@ln_end}"
85
+ p "Stack: #{@tg_end}" if @dbg[:stack]
86
+ else
87
+ if @txt.gsub!(/\<$/,'')
88
+ @tg_end.push "#{@spc}</#{@key}>#{@ln_end}"
89
+ else
90
+ @ln_end = "</#{@key}>#{@ln_end}"
91
+ end
92
+ if @mem_var["*code*"] && @mem_var["*code*"]!=''
93
+ tags_created << @mem_var["*code*"].gsub('$*',@txt)
94
+ else
95
+ tags_created << @txt.gsub(/^ +/,'') #remove gsub if don't want auto trim left
96
+ end
97
+ end
98
+ end
99
+ tags_created
100
+ end
101
+ @skiper= []
102
+ public_methods.each do |f|
103
+ send(f) if /_initialize$/ =~ (meth= f.to_s)
104
+ @skiper << [$1,'_skip'].join.to_sym if /(.*)_skip$/ =~ meth
105
+ end
106
+ end
107
+
108
+ #parsing from fullpath source to the fullpath target/result
109
+ #with the option of auto add 'initialize' and 'finalize'
110
+ #for source file in w2tags only fill with LF it will not
111
+ #translate, since behaviour for "\n\n\n".split("\n")
112
+ #will result in empty array
113
+ #if hot available it will add w2tags in:
114
+ #firstline with @initialize()
115
+ #lastline with @finalize()
116
+ #to not add, supply this function with init_start=false
117
+ #ex: parsing("t.w2tst","t.tst",false)
118
+ def parsing(src,tgt,init_start=true)
119
+ puts ">>#{src}"
120
+ puts ">>#{tgt}"
121
+ parse_init
122
+ @src_path= File.dirname(src)
123
+ @doc_src = IO.read(src).delete("\r").split("\n")
124
+ @doc_src<< "%finallize" if @tg_hot['finallize' ]
125
+
126
+ while (@row = @doc_src.shift) do #;p "row:#{@row}"
127
+ if init_start && !(/!hot!/ =~ @row)
128
+ @doc_src,@row = [[@row]+@doc_src,"%initialize"] if @tg_hot['initialize']
129
+ p "HEAD:#{init_start}"
130
+ init_start = false
131
+ end
132
+ parse_row
133
+ end
134
+ if @dbg[:constanta]
135
+ p "const_ "
136
+ @mem_var.keys.sort.each {|k|p "#{k.ljust 10} : #{@mem_var[k]}"}
137
+ end
138
+
139
+ if @dbg[:hot]
140
+ @tg_hot.keys.sort.each_with_index do |v,i|
141
+ puts "hot keys: #{i}. #{v}"
142
+ end
143
+ end
144
+
145
+ open(tgt,'w') do |f|
146
+ @doc_out.each do |row|
147
+ f << row
148
+ end
149
+ end
150
+
151
+ end
152
+
153
+ #it use to clean all the definition and reloading the hot file
154
+ def parse_init
155
+ @tg_end = [] #momorize tag end from regex function
156
+ @doc_src = []
157
+ @doc_out = []
158
+ @tg_hot = {}
159
+ merge_tags
160
+ end
161
+
162
+ #to test parsing on source line and return will be the result,
163
+ #everytime it execude, it clean up and reloading the HOT files.
164
+ def parse_line row,init=true
165
+ parse_init if init
166
+ dbg[:parse]= false
167
+ @doc_src = row.delete("\r").split("\n") << ",/"
168
+ while (@row= @doc_src.shift) do #;p "row:#{@row}"
169
+ parse_row
170
+ end
171
+ @doc_out
172
+ end
173
+
174
+ #the actual parsing on row, but it use for parsing the files not to
175
+ #test the source line, since some of the row have a command that
176
+ #has effect on source, result and the row will be empty, please use
177
+ #parse_line if you want to test interactively on IRB.
178
+ def parse_row row=nil
179
+ @row = row if row
180
+ @row<<"\n" #;p "row:#{@row}"
181
+ p "_____> #{@row}" if @dbg[:parse] && @plt == 99 && @rmk == 99
182
+
183
+ parse_spc
184
+
185
+ @ln_end = "" #imediate ends tag
186
+ @row.gsub!(/\\\\/,'') #esc char \\
187
+ @row.gsub!('\}','') #esc char \)
188
+ @row.gsub!('\;','') #esc char \;
189
+ while (parse_all) do; end
190
+ @row.gsub!('','\\')
191
+ @row.gsub!('','}')
192
+ @row.gsub!('',';')
193
+ if @ln_end!=""
194
+ @row.gsub!(/([\n\t ]*$)/,'')
195
+ @row << "#{@ln_end.strip}\n"
196
+ end
197
+ if @row.strip!=""
198
+ p "#####> #{@row}" if @dbg[:parse]
199
+ @doc_out << @row.rstrip+"\n"
200
+ end
201
+ @row
202
+ end
203
+
204
+ #parse one w2tags, result will be name of the target file created
205
+ def parse_file(src,init_start=true,chk_date=false)
206
+ tgt,@ext = [src[/(.+\.)w2(\w+)$/,1]<<$2,$2]
207
+
208
+ return nil if !File.exist?(src) #p "src: #{src} not found..."
209
+ if chk_date && File.exist?(tgt)
210
+ return nil if File.mtime(src) <= File.mtime(tgt)
211
+ end
212
+
213
+ puts "\nParsing W2Tags File:#{src}"
214
+ parsing(src,tgt,init_start)
215
+ tgt
216
+ end
217
+
218
+ #parse multiple w2tags files, result will be array of target file created
219
+ def parse_files(srcs,init_start=true)
220
+ srcs.collect do |src|
221
+ src.gsub!(/\n/,'')
222
+ parse_file(src,init_start)
223
+ end.compact
224
+ end
225
+
226
+ def end_tags(arr)
227
+ @tg_end = @tg_end + arr
228
+ end
229
+
230
+ #call from proc hot before it render hots line
231
+ #see in source code "w2tags.rb::read_filehot"
232
+ #default behaviour for tag_nex will not execute
233
+ #since @mem_hot will assigned w/o nil
234
+ #assigned nil using "%!" in w2tags
235
+ def chg_mem_hot(nxt)
236
+ @mem_hot = nxt
237
+ @mem_tag["^"] = nxt if nxt
238
+ end
239
+
240
+ #pop up end tags from the stack
241
+ #result will be string contains end tags from stack
242
+ #who's space inside each end tags > current space
243
+ def multi_end(ttls)
244
+ rpls = ''
245
+ ttl = @tg_end.size-1
246
+ ttl = ttls-1 if ttls
247
+ ttl.downto(0) do |i|
248
+ sz = @tg_end[i][/^ +/].to_s.size
249
+ if ttls || @spc.size <= sz
250
+ send = @tg_end.pop.to_s
251
+ if send.strip[0,5]=="!run!"
252
+ scrpt = send.gsub("\n","\n#{@spc}").split("\n")
253
+ @doc_src = scrpt[1,99]+@doc_src
254
+ else
255
+ spc = send[/(^[ \t]*)/,1].to_s
256
+ rpls << send.gsub(/\n/,"\n#{spc}") + "\n"
257
+ end
258
+ end
259
+ end
260
+ p "End..: #{rpls.strip}" if @dbg[:parse] && rpls!= ''
261
+ rpls
262
+ end
263
+
264
+ private
265
+
266
+ # try to shift empty line create document and add current
267
+ # row to source. but it means re parsing current row.
268
+ def swap_last_empt_src_with_end_tg(end_tg)
269
+ last = []
270
+ while @doc_out[-1] && @doc_out[-1].to_s.strip == ''
271
+ last << @doc_out.pop
272
+ end
273
+ end_tg.shift if end_tg[0].strip==''
274
+ @doc_src = end_tg + @doc_src
275
+ #p "Swp..: #{@doc_src[-1]}" if @dbg[:parse]
276
+ end
277
+
278
+ #merging file hot based on the target extension, and target
279
+ #extension it self based on source extension, example:
280
+ #suppose you have source of w2tags 'index.html.w2erb'
281
+ #it just like autoloading:
282
+ # !hot!erb
283
+ #it will search HOT files in current folder, if it not found
284
+ #it will search in gem/hot and merging the HOT
285
+ def merge_tags
286
+ hot1 = "#{@src_path}/#{@ext}.#{@hot}"
287
+ hot2 = "#{W2Tags::Dir}/../hot/#{@ext}.#{@hot}"
288
+ filehot = hot1 if File.exist?(hot1)
289
+ filehot = hot2 if File.exist?(hot2)
290
+ if filehot
291
+ puts '=>'+File.expand_path(filehot) if !@silent
292
+ @tg_hot.merge!(W2Tags.read_filehot(filehot))
293
+ end
294
+ @tg_hot
295
+ end
296
+
297
+ #define variable ( &var! or @var! )tobe use by parser in hot for
298
+ #the next line parsing, example on w2tags:
299
+ # &myvar=hello\n
300
+ # ^{.myclass &myvar!}
301
+ #
302
+ #it will translate on the fly to:
303
+ # ^{.myclass hello}
304
+ #
305
+ #for @var! is uniq value split by ";", example on w2tags:
306
+ # @myvar=hello;world\n
307
+ # @myvar=world;tags\n
308
+ # ^{.myclass @myvar!}
309
+ #
310
+ #it will translate on the fly to:
311
+ # ^{.myclass hello;world;tags}
312
+ def parse_set_var
313
+ if @row.gsub!( /^[ \t]*(&[\w]+)=([^\n]+)([\n])/,'')
314
+ @mem_var[$1+"!"] = $2.strip
315
+ elsif @row.gsub!(/^[ \t]*(@[\w]+)=([^\n]+)([\n])/,'')
316
+ k,v = [$1+"!",$2.strip] #;p v
317
+ #v << ';'+@mem_var[k].to_s if v[0,1]!=';' && @mem_var[k]
318
+ v = (@mem_var[k].to_s + ';' + v) if v[0,1]!=';' && @mem_var[k]
319
+ @mem_var[k] = v.split(';').uniq.select{|x|x!=''}.join(';')
320
+ p "uniq var> #{v}" if @dbg[:parse] #&& @plt == 99 && @rmk == 99
321
+ end
322
+ end
323
+
324
+ #when parsing and found tag
325
+ # !hot!filehot1;filehotN
326
+ #it will search HOT files in current folder, if it not found it will search
327
+ #in gem/hot and merging the HOT, this command can have multiple
328
+ #file HOT separate with ";"
329
+ def merge_hot
330
+ if(/!hot!([\w;]+)([`\n])/ =~ @row;@rgx = $~)
331
+ hots= @rgx[1].split(';').collect {|x|x+'.'+@hot}
332
+ rpl = ['']
333
+ hots.each do |hot|
334
+ fls = File.exist?(hot) ? hot :
335
+ File.exist?(@src_path+'/'+hot) ? @src_path+'/'+hot :
336
+ File.exist?(W2Tags::Dir+'/../hot/'+hot) ? W2Tags::Dir+'/../hot/'+hot : ''
337
+ if fls==''
338
+ rpl << "<!--"+hot+", Not Found-->\n"
339
+ else
340
+ puts '=>'+File.expand_path(fls) if !@silent
341
+ @tg_hot.merge!(W2Tags.read_filehot(fls))
342
+ end
343
+ end
344
+ @row.gsub!(@rgx.to_s,rpl.join)
345
+ end
346
+ end
347
+
348
+ #when parsing and found tag
349
+ # !inc!fileinc
350
+ #it will include / replace current row from file inside .w2x, and after
351
+ #parser will try to get current row after merging to be evaluate
352
+ def merge_w2x
353
+ if(/!inc![ ]?([\/\w._]+)([`\n])/ =~ @row;@rgx = $~)
354
+ mac = @src_path+'/'+$1+'.'+@w2x
355
+ src = $~.to_s #;p mac
356
+ if File.exist?(mac)
357
+ pop = $~.captures.pop
358
+ new = IO.read(mac).delete("\r").gsub("\n","\n"+@spc) + ( pop=='`' ? "\n"+@spc : '' )
359
+ @doc_src= @row.gsub(src,new).split("\n")+@doc_src
360
+ @row= @doc_src.shift+"\n"
361
+ parse_spc
362
+ else
363
+ @row.gsub!(src,"<!--"+mac+", Not Found-->\n")
364
+ nil
365
+ end
366
+ end
367
+ end
368
+
369
+ #get space (tab and spaces) on the left of the code and save it to instance
370
+ #it will be use if row replace with more than one row and replacement row
371
+ #must continue with current column (indent).
372
+ def parse_spc
373
+ @spc = @row[/(^[ \t]+)/,1].to_s #sometime result is nil
374
+ end
375
+
376
+ #do the translation from the params inside function like:
377
+ # %a par1;par2;par3
378
+ #it do following job:
379
+ # * replace constanta (&var!) inside params of the function
380
+ # * replace constanta (&var!) inside new line of source code
381
+ # (inside instance var @new)
382
+ # * replace var $0 - $9 inside var @new from params if function have
383
+ # 3 params so 3 var $ will be replace from the params and if var @new
384
+ # have var # more than what function params suply, it will replace with
385
+ # an empty string
386
+ # * if in var @new define only 1 var $ and function params got more than
387
+ # 1, it will multiply the @new line with total number of lparams
388
+ # to get the illustrate I'll show you with an example:
389
+ # inside hot file :
390
+ # >>td
391
+ # <td>$0</td>
392
+ # --------------------
393
+ # function call: @td(col1;col2) # will result in
394
+ # --------------------
395
+ # <td>col1</td>
396
+ # <td>col2</td>
397
+ # * some of the replacement behaviour for var $ are :
398
+ # 1. optional meaning that var $ inside [ xxx $ xxxx ] sequare bracket are
399
+ # optional if not suply from params it will an emppty replacement
400
+ # 2. default value meaning that var $ inside [ xxx $ left sequare bracket
401
+ # are a default if not suply from params but if it suply from params it
402
+ # will empty the default and relace var $ from the params
403
+ # 3. execute String.method if var $ in the left got ":", example
404
+ # inside hot file:
405
+ # >>td
406
+ # <td>:capitalize$0</td>
407
+ # --------------------
408
+ # function call: @td(col1;col2) # will result in
409
+ # --------------------
410
+ # <td>Col1</td>
411
+ # <td>Col2</td>
412
+ def get_dollar(prms,ends=nil) #prms='@0;@1;@2' from hot
413
+ @mem_var.each do |k,v| #;p "#{k}, #{v}"
414
+ prms.gsub!(k,v)
415
+ if k[0,1]=='*' and Regexp.new("~([^~]+)~#{k}".gsub('*','\\*')) =~ @new
416
+ @new.gsub!($~.to_s,(v!='' ? v : $1))
417
+ else
418
+ @new.gsub!(k,v)
419
+ end
420
+ end
421
+ prms = prms.split(';') #W2Tags::splitter(prms)
422
+ new_prms = @new.scan(/\$[0-9]/).uniq
423
+ new_alls = @new.scan(/\$\*/) #;p 'rpl:',new_alls,new_prms,prms
424
+ @new.gsub!($1,"<%= \"#{$2}\" %>") if /(==(\$[0-9]))/ =~ @new
425
+ @new.gsub!($1,"<%= #{$2} %>") if /(=(\$[0-9]))/ =~ @new
426
+ if /^@[0-9]$/ =~ prms[0]
427
+ rpl = prms.shift.gsub('@','$')
428
+ repeat = @new
429
+ repeat.gsub!('$0',prms.shift) #repeat.gsub!('$*',rpl)
430
+ @new = ''
431
+ prms.each_with_index do |x,i| #;p "$0 #{x} => #{repeat}"
432
+ @new += repeat.gsub(rpl,x)
433
+ if i+1<prms.size
434
+ @new += "\n"+@spc+ends.join("\n") if ends
435
+ @new += "\n"+@spc
436
+ end
437
+ end
438
+ elsif new_alls==[] && new_prms.size==1 && prms.size>1
439
+ tmp = ""
440
+ rpt = @rgx.to_s.gsub(@rgx[3]+"\n","")
441
+ prms.each_with_index do |x,i|
442
+ tmp<< rpt+x #tmp<< @new.gsub(new_prms[0],x)
443
+ tmp<< "\n#{@spc}" if i+1<prms.size
444
+ end
445
+ @new = tmp
446
+ else
447
+ i = new_prms.size - 1
448
+ new_prms.sort.reverse.each do |x|
449
+ opt_v = Regexp.new('~([^$|\n]*)\\'+x+'([^\|\n]*)~')
450
+ def_v = Regexp.new('~([^~]+)~\\'+x)
451
+ eva_v = Regexp.new('\\'+x+'.([^~$]+)~') #$1.upcase~
452
+ if opt_v =~ @new #;p $1
453
+ rpl = ''
454
+ rpl = "#{$1.to_s}#{prms[i]}#{$2.to_s}" if prms[i] && prms[i].strip!=""
455
+ @new.gsub!(opt_v,rpl)
456
+ #p "options: #{rpl} >> #{@new}"
457
+ elsif def_v =~ @new #;p $1
458
+ src = $~.to_s
459
+ rpl = (prms[i] && prms[i].strip!="" ? prms[i] : $1)
460
+ @new.gsub!(src,rpl)
461
+ #p "default: #{@new}"
462
+ end
463
+ while eva_v=~ "\n#{@new}" do
464
+ src = "#{x}.#{$1}~" ; #p "\n#{@new} => #{src}"
465
+ evl = "\"#{prms[i]}\".#{$1}"; #p "====> #{evl} <=="
466
+ rpl = prms[i] ? eval(evl).to_s : ""
467
+ @new.gsub!(src,rpl)
468
+ end
469
+ #p "rest: #{x} => #{prms[i].to_s}"
470
+ @new.gsub!(x,prms[i].to_s)
471
+ i = i -1
472
+ end
473
+ @new.gsub!(/\$\*/,prms[new_prms.size,99].to_a.join(';') )
474
+ @new.gsub!(/\n\t+$/,'') #remove line if only tabs
475
+ end
476
+ end
477
+
478
+ #pop up end tags from the stack
479
+ def multi_end2(ttls)
480
+ rpls = ''
481
+ ttl = @tg_end.size-1
482
+ ttl = ttls-1 if ttls
483
+ ttl.downto(0) do |i|
484
+ sz = @tg_end[i][/^ +/].to_s.size
485
+ if ttls || @spc.size <= sz
486
+ send = @tg_end.pop
487
+ if send.strip[0,5]=="!run!"
488
+ scrpt = send.gsub("\n","\n#{@spc}").split("\n")
489
+ @doc_src = scrpt[1,99]+@doc_src
490
+ else
491
+ spc = send[/(^[ \t]*)/,1].to_s
492
+ rpls << send.gsub(/\n/,"\n#{spc}") + "\n"
493
+ end
494
+ end
495
+ end
496
+ p "End2 : #{rpls.strip}" if @dbg[:parse] && rpls!= ''
497
+ rpls
498
+ end
499
+
500
+ #command execution "-key", internally parsed to "%_key~", so both command
501
+ #are the same except that command "-key" need to translate to "%_key~" and
502
+ #it goes to Hot files key definition to lookup to. some of these definition
503
+ # built in (for erb: %_if , %_elsif , %_else , %_end , ... etc)
504
+ # -if => %_if
505
+ # -li => %_li
506
+ def shortcut_exec(regex)
507
+ if(regex =~ @row;@rgx = $~)
508
+ srcs = @rgx.to_s
509
+ rplc = "#{@rgx[1]}%!_#{@rgx[2]}~ #{@rgx[3]}\n"
510
+ @row.gsub!(srcs,rplc)
511
+ p "reExe_ #{@row}" if @dbg[:parse]
512
+ end
513
+ end
514
+
515
+ #command execution "=", internally parsed to "%=~", so both command
516
+ #are the same except that command "=" need to translate to "%=~" and
517
+ #it goes to Hot files key definition to lookup to. you can redefine it.
518
+ def shortcut_equal(regex)
519
+ if(regex =~ @row;@rgx = $~)
520
+ srcs = @rgx.to_s
521
+ rplc = "#{@rgx[1]}%!=~#{@rgx[3]}\n"
522
+ @row.gsub!(srcs,rplc)
523
+ p "reEqu_ #{rplc}" if @dbg[:parse]
524
+ end
525
+ end
526
+
527
+ #this command is the selector from command
528
+ # %..key.. params1;paramsN \n
529
+ #ex:
530
+ # %div<space>params\n or %div<\n>.
531
+ #if key div fine in hot, it will translate to HOT tags, but if not
532
+ #it become w2tags
533
+ def get_hot_simple(regex)
534
+ if regex =~ @row ;@rgx = $~
535
+ chk1= @rgx[2][-1,1] + @rgx[3][0,2].to_s
536
+ chk2= @rgx[2][/"\}!/]
537
+ chk3= @rgx[2][/"\}~/]
538
+ # already become w2tags, ignore!!!
539
+ if (/[=\}][!~][ ]?/ !~ chk1 && chk2 == nil && chk3 == nil)
540
+ keys = @rgx[2].strip
541
+ opts = @rgx[3]
542
+ #p chk1
543
+ # FIX for:
544
+ # %form#dodol{action="<%= #{aaa} %>"} <%= #{bbb} %>
545
+ # <form id="dodol" action="<%= #{aaa} %>"><%= #{bbb}%></form>
546
+ # when wrong splitting, fix the splitting...
547
+ # assume last attribute don't have spaceses!!! ==>{opt="blah"}<==
548
+ fixd = keys.split('"} ')
549
+ if fixd.length>1
550
+ keys = fixd[0]+'"}'
551
+ opts = fixd[1]+opts
552
+ end
553
+
554
+ srcs = @rgx.captures.join
555
+ opts = $1 << opts if keys.gsub!(/(\/)$/,'')
556
+ hots = keys.gsub(/\{.*\}$/,'').gsub(/[:#.][\w\-#.=]*$/,'')
557
+ rplc = @tg_hot[hots]!=nil ?
558
+ "%!#{keys}~ #{opts}" :
559
+ "%!#{keys}! #{opts}"
560
+ @row.gsub!(srcs,rplc)
561
+ p "reHot> #{@row} << -H-O-T-" if @dbg[:parse]
562
+ end
563
+ end
564
+ end
565
+
566
+ #translation for tags with shortcut of name, id, or class and put in constants
567
+ # ex: %div:name#id.class{attribute}=
568
+ #will result in some of this var:
569
+ # @mem_var['$$' ] => :name#id.class{attribute}==
570
+ # @mem_var['$:' ] => :name
571
+ # @mem_var['$#' ] => #id
572
+ # @mem_var['$.' ] => .class
573
+ # @mem_var['$@' ] => {attribute}
574
+ # @mem_var['*:' ] => name
575
+ # @mem_var['*#' ] => id
576
+ # @mem_var['*.' ] => class
577
+ # @mem_var['*@' ] => attribute
578
+ # @mem_var['*all*' ] => name="name" id="id" class="class"
579
+ # @mem_var['*name*' ] => name="name"
580
+ # @mem_var['*id*' ] => id="id"
581
+ # @mem_var['*class*'] => class="class"
582
+ # this var will be use in parsing w2tags/hot command
583
+ def nameidclass_var()
584
+ #@key = keys = @rgx[2].strip.gsub(/(\{(.*)\})/,'') #greedy :)
585
+ @key = keys = @key.strip.gsub(/(\{(.*)\})/,'') #greedy :)
586
+ @att = $2.to_s.strip
587
+ @mem_var['$$' ]= ''
588
+ @mem_var['$&' ]= ''
589
+ @mem_var['$:' ]= ''
590
+ @mem_var['$#' ]= ''
591
+ @mem_var['$.' ]= ''
592
+ @mem_var['$@' ]= $1.to_s
593
+ @mem_var['*&' ]= ''
594
+ @mem_var['*:' ]= ''
595
+ @mem_var['*#' ]= ''
596
+ @mem_var['*.' ]= ''
597
+ @mem_var['*@' ]= @att=='' ? '' : @att+' '
598
+ @mem_var['*all*' ]= ''
599
+ @mem_var['*name*' ]= ''
600
+ @mem_var['*id*' ]= ''
601
+ @mem_var['*class*']= ''
602
+ @mem_var['*code*' ]= ''
603
+ #p keys
604
+ if @key.gsub!(/([&:#.=])([\/\t\w\-#.= ]*$)/,'')
605
+ keys = $1+$2
606
+ if keys.gsub!(/^&([\/\w\-.]*)/,'')
607
+ if $1!=''
608
+ @mem_var['$&' ] = "&#{$1}"
609
+ @mem_var['*&' ] = $1
610
+ @mem_var['$$' ]<< "&#{$1}"
611
+ end
612
+ end
613
+ if keys.gsub!(/^:([\w\-.]*)/,'')
614
+ if $1!=''
615
+ @mem_var['$:' ] = ":#{$1}"
616
+ @mem_var['*:' ] = $1
617
+ @mem_var['*name*' ] = "name=\"#{$1}\" "
618
+ @mem_var['*all*' ]<< "name=\"#{$1}\" "
619
+ @mem_var['$$' ]<< ":#{$1}"
620
+ end
621
+ end
622
+ if keys.gsub!(/^#([\w\-]*)/,'')
623
+ if $1!=''
624
+ @mem_var['$#' ] = "##{$1}"
625
+ @mem_var['*#' ] = $1
626
+ @mem_var['*id*' ] = "id=\"#{$1}\" "
627
+ @mem_var['*all*' ]<< "id=\"#{$1}\" "
628
+ @mem_var['$$' ]<< "##{$1}"
629
+ end
630
+ end
631
+ if keys.gsub!(/^\.([\w\-\.]*)/,'')
632
+ if $1!=''
633
+ cl = $1
634
+ cx = cl.split('.').collect {|x|x.strip}.join(' ')
635
+ @mem_var['$.' ] = ".#{cl}"
636
+ @mem_var['*.' ] = cl
637
+ @mem_var['*class*'] = "class=\"#{cx}\" "
638
+ @mem_var['*all*' ]<< "class=\"#{cx}\" "
639
+ @mem_var['$$' ]<< ".#{cl}"
640
+ end
641
+ end
642
+ @key << keys
643
+ end
644
+ @mem_var['$$' ] << @mem_var['$@']
645
+ @mem_var['*all*'] << @mem_var['*@']
646
+ @mem_var['*att*'] = @mem_var['*@']
647
+ if @key[0,1]!='='
648
+ if @key.gsub!(/==$/,'')
649
+ @mem_var['*code*'] = '<%= "$*" %>'
650
+ @mem_var['$$' ]<< "=="
651
+ elsif @key.gsub!(/=$/,'')
652
+ @mem_var['*code*'] = "<%= $* %>"
653
+ @mem_var['$$' ]<< "="
654
+ end
655
+ end
656
+ end
657
+
658
+ #these not really visible for end user, since user usualy see the command as
659
+ #a HAML like command and translate to this HOT files. the translation usually
660
+ #came from method in:
661
+ # shortcut_exec
662
+ # get_hot_simple
663
+ #format for this command is
664
+ # %...key...~..params1;paramsN..\n
665
+ def parse_hot
666
+ eva = ''
667
+ col = @row.split('%')
668
+ return false if col.size==1
669
+ (col.size-1).downto(0) do |c|
670
+ eva = "%#{col[c]}" << eva
671
+ @rg_hot.each do |ht|
672
+ if(ht =~ eva;@rgx = $~)
673
+ @key = @rgx[2]
674
+ prms = @rgx[3].to_s.strip
675
+ if /^\!/ =~ @key
676
+ @new = (multi_end2(nil)+@spc+@rgx.to_s.gsub('%!','%')).split("\n")
677
+ swap_last_empt_src_with_end_tg(@new)
678
+ @row = ''
679
+ else
680
+ nameidclass_var()
681
+ # Auto closing, see in "erb.hot": _elsif _else:
682
+ # when last doc out is <% end %> and hot command is %_elsif or %_else
683
+ # then remove the last doc out <% end %>
684
+ if @doc_out[-1] and @doc_out[-1].strip=='<% end %>'
685
+ @doc_out.pop if %w[else elsif].include? prms.split(' ')[0]
686
+ end
687
+ while prms[-1,1]=='\\' do #concenation line if params end with \
688
+ prms.gsub!(/\\$/,'') << @doc_src.shift.strip
689
+ end
690
+ @mem_var["$tag"] = @key
691
+ if @tg_hot[@key]
692
+ hots = @tg_hot[@key]
693
+ hots[1]='' if !hots[1] #remark if not error!
694
+ @new = hots[0].call(self).clone
695
+ if @new.strip=="" #&& @tg_end[-1]
696
+ @tg_end << "#{@spc}#{hots[1][0]}"
697
+ empt = @row.gsub!(@rgx.to_s,"").strip
698
+ @row = empt if empt == "" #remove if empty (only \t,\n)
699
+ else
700
+ @tg_end << "#{@spc}#{hots[1][0]}" if hots[1]
701
+ @new.gsub!(/( *~\^.*[^\n]+)/,"^~^~^")
702
+ setvar = $1 # don't parse SetMem ~^
703
+ @new.gsub!(/\n/,"\n#{@spc}")
704
+ get_dollar(prms,hots[1])
705
+ @new.gsub!(/\^~\^~\^/,setvar) if setvar #restore SetMem
706
+ srcs = @rgx.to_s
707
+ @doc_src = @row.gsub(srcs,@new).split("\n")+@doc_src
708
+ @row = @doc_src.shift+"\n"
709
+ parse_spc
710
+ end
711
+ p "Func>> #{@new}" if @dbg[:parse]
712
+ else
713
+ @row.gsub!(@rgx.to_s,"<!-- no hot for:#{@key} -->")
714
+ end
715
+ end
716
+ break
717
+ end
718
+ end
719
+ break if @rgx
720
+ end
721
+ @rgx!=nil
722
+ end
723
+
724
+ #internal use call from
725
+ # get_div
726
+ # get_input
727
+ def get_shortcut(regex,tag)
728
+ if(regex =~ @row;@rgx = $~)
729
+ src = @rgx.captures.join
730
+ keys= @rgx[1,2].join.strip
731
+ opts= @rgx[3].to_s
732
+ opts= $1 << opts if keys.gsub!(/(\/)$/,'')
733
+ #tgt = "%!#{tag}#{keys}!#{opts}"
734
+ tgt = "%#{tag}#{keys} #{opts}"
735
+ @row.gsub!(src,tgt)
736
+ p "to#{tag.capitalize[0,3]}: #{tgt}" if @dbg[:parse]
737
+ end
738
+ @rgx!=nil
739
+ end
740
+
741
+ #shortcut for
742
+ # "%...div...!params",
743
+ #and user no need to write
744
+ # "%div"
745
+ #if user supply the command with ID or CLASS.
746
+ # %div#key my key features
747
+ #same as:
748
+ # #key my key features
749
+ #
750
+ # %div.okey my key features
751
+ #same as:
752
+ # .okey my key features
753
+ def get_div( regex)
754
+ get_shortcut(regex,'div')
755
+ end
756
+
757
+ #shortcut for
758
+ # "%...input...!params",
759
+ #and user no need to write
760
+ # "%input"
761
+ #if user supply the command with NAME
762
+ # %input:wharsojo my key features
763
+ #same as:
764
+ # :wharsojo my key features
765
+ def get_input(regex)
766
+ get_shortcut(regex,'input')
767
+ end
768
+
769
+ #popup the closing tags when indentation are less than the previous.
770
+ def auto_close
771
+ if @tg_end.size>1
772
+ sz = @tg_end[-1][/^ +/].to_s.size
773
+ if @spc.size <= sz
774
+ ed = multi_end(nil).rstrip
775
+ p "AutE:#{ed}#{@row}" if @dbg[:parse]
776
+ @doc_out += [ed,@row]
777
+ @row = ''
778
+ true
779
+ end
780
+ end
781
+ end
782
+
783
+ #all regex for line will be parse in this methods return value of not nill
784
+ #will try to parse the line (@row) again, if finish parsing (return nil)
785
+ #it try to check the indentation to auto_close the line.
786
+ def parse_all
787
+ #check for skipping the block using add on module...
788
+ if @skiper.select{|f|send(f)}.length>0
789
+ p "skip > #{@row}" if @dbg[:parse]
790
+ else
791
+ @plt_opt= ''
792
+ #rtn= true if @selector.select{|f|send(f)}.length>0
793
+ rtn = true if shortcut_exec( /(^[\t ]*)\-([\w\-&\/:#.%]*\{.*\}[=]?) *([^\n]*)\n/)
794
+ rtn = true if shortcut_exec( /(^[\t ]*)\-([\w\-&\/:#.%=]*) *([^\n]*)\n/)
795
+ rtn = true if shortcut_equal( /(^[\t ]*)=([\w\-&\/:#.%=]*) *([^\n]*)\n/)
796
+
797
+ rtn = true if get_hot_simple(/^[\t ]*(%)([\$\w\-&\/:#.]+\{.*\}[= ]*)([^\n]*)\n/)
798
+ rtn = true if get_hot_simple(/^[\t ]*(%)([\$\w\-&\/:#.]+\{.*\}[= ]*)()\n/)
799
+ rtn = true if get_hot_simple(/^[\t ]*(%)([\$\w\-&\/:#.%=]+ )([^\n]*)\n/)
800
+ rtn = true if get_hot_simple(/^[\t ]*(%)([\$\w\-&\/:#.%=]+)()\n/)
801
+
802
+ rtn = true if get_div(/^[\t ]*([#.])([\w\-&\/.]*\{.*\}[= ]*)([^\n]*)\n/)
803
+ rtn = true if get_div(/^[\t ]*([#.])([\w\-&\/.]*\{.*\}[= ]*)()\n/)
804
+ rtn = true if get_div(/^[\t ]*([#.])([\w\-&\/.=]* )([^\n]*)\n/)
805
+ rtn = true if get_div(/^[\t ]*([#.])([\w\-&\/.=]*)()\n/)
806
+ rtn = true if get_input( /^[\t ]*(:)([\w\-&\/#.]*\{.*\}[= ]*)([^\n]*)\n/)
807
+ rtn = true if get_input( /^[\t ]*(:)([\w\-&\/#.]*\{.*\}[= ]*)()\n/)
808
+ rtn = true if get_input( /^[\t ]*(:)([\w\-&\/#.=]* )([^\n]*)\n/)
809
+ rtn = true if get_input( /^[\t ]*(:)([\w\-&\/#.=]*)()\n/)
810
+ rtn = true if parse_hot
811
+ rtn = true if merge_hot
812
+ rtn = true if merge_w2x
813
+ rtn = true if parse_set_var
814
+ rtn = true if parse_set_mem
815
+ rtn = true if parse_get_mem
816
+ rtn = true if inline_tag
817
+ rtn = true if parse_end
818
+ if parse_tags
819
+ rtn = nil
820
+ elsif !rtn
821
+ auto_close
822
+ end
823
+ end
824
+ rtn
825
+ end
826
+
827
+ #remember command "^", not really use but if you want less typing you can
828
+ #define this command inside HOT file for the next command to be execute like:
829
+ # HOT file:
830
+ # >>_tr
831
+ # ~^%td
832
+ #
833
+ # Source file:
834
+ # -tr
835
+ # ^ inside td
836
+ #I think its Ok.
837
+ def parse_set_mem
838
+ if @row.gsub!(/([ \t]*~\^)([^\n]+)(\n)/,'')
839
+ p "setMem ^ => #{$2+"\n"}" if @dbg[:parse]
840
+ @mem_tag["^"]= $2+"\n"
841
+ end
842
+ end
843
+
844
+ #call from parse_get_mem
845
+ def get_mem(regex)
846
+ if(regex =~ @row;@rgx = $~)
847
+ keys,tmp,prms,opt,ends= @rgx.captures
848
+ if opt=='!'
849
+ opt=''
850
+ @mem_hot=nil
851
+ end
852
+
853
+ @new = @mem_tag[keys].split(' ')
854
+ @new[0] << tmp
855
+ @new = @new.join(" ") << "\n"
856
+ get_dollar(prms)
857
+ rpl = @new #+opt.to_s+ends.to_s
858
+ p "stMem> #{rpl}" if @dbg[:parse]
859
+ @row.gsub!(@rgx.to_s,rpl)
860
+ rows = @row.split("\n")
861
+ if rows.size>1
862
+ @doc_src = rows+@doc_src
863
+ @row = @doc_src.shift+"\n"
864
+ end
865
+ end
866
+ @rgx!=nil
867
+ end
868
+
869
+ #remember command "^", not really use but if you want less typing you can
870
+ #define this command inside HOT file for the next command to be execute like:
871
+ # HOT file:
872
+ # >>_tr
873
+ # ~^%td
874
+ #
875
+ # Source file:
876
+ # -tr
877
+ # ^ inside td
878
+ #I think its Ok.
879
+ def parse_get_mem
880
+ get_mem(/([\^])([^ ]*) ([^\n]*)(\n)/)
881
+ end
882
+
883
+ #it call from parse_end
884
+ def get_end(regex)
885
+ if(regex =~ @row;@rgx = $~)
886
+ if @rgx[1]=='~'
887
+ @new = ''
888
+ @new = multi_end(1) if @tg_end.size>0
889
+ else
890
+ case @rgx[1]
891
+ when '!';@new = multi_end(nil)
892
+ when ',';@new = multi_end(@tg_end.size)
893
+ else ;@new = multi_end(@rgx[1].size)
894
+ end
895
+ end
896
+ @doc_src = @row.gsub(@rgx.to_s,@new).split("\n")+@doc_src
897
+ @row = ''
898
+ end
899
+ end
900
+
901
+ #user can popup the end tags using these folowing command:
902
+ # ,/ all end tags will be popup
903
+ # ~/ one or multi end tags will be popup (depend on how many ~ you write)
904
+ # !/ popup until the same indentation of "!/"
905
+ def parse_end
906
+ (get_end(/^(,)\/(\n)/) ? true : \
907
+ (get_end(/^[ \t]*(~+)\/(\n)/) ? true : \
908
+ get_end(/^[ \t]*(!)\/(\n)/)))
909
+ end
910
+
911
+ #parsing w2tags commands
912
+ def parse_tags
913
+ @rgx = nil
914
+ par = []
915
+ rgs = @rg_tag.collect {|r|par << (r =~ @row);$~}
916
+ if(max = par.compact.sort.pop) #have any to parse?
917
+ @rgx = rgs[par.index(max)]
918
+ @key = @rgx[2]
919
+ @txt = @rgx[3].strip
920
+
921
+ # when wrong splitting, fix the splitting...
922
+ # assume last attribute don't have spaceses!!! ==>{opt="blah"}<==
923
+ fixd = @key.split('"} ')
924
+ if fixd.length>1
925
+ @key = fixd[0]+'"}'
926
+ @txt = fixd[1]+@txt
927
+ end
928
+
929
+ if /^\!/ =~ @key
930
+ @new = (multi_end(nil)+@rgx.to_s.gsub('%!','%')).split("\n")
931
+ swap_last_empt_src_with_end_tg(@new)
932
+ @row = ''
933
+ p "W2Tag: try closing tag by indentation..." if @dbg[:parse]
934
+ return true
935
+ else
936
+ @mem_var["$tag"] = @key
937
+ nameidclass_var()
938
+ srcs = @rgx.to_s.gsub!(/^[ \t]*/,'')
939
+ tag_next = @tg_nex[@key] #;p "%mem_hot:#{@mem_hot}:#{@key}"
940
+ tag_next[1].call if tag_next && @mem_hot==nil
941
+ rplc = @tagr.call(self);
942
+ @mem_var.each do |k,v|
943
+ rplc.gsub!(k,v)
944
+ end
945
+ @row.gsub!(srcs,rplc)
946
+ end
947
+ p "W2Tag: #{@row}" if @dbg[:parse]
948
+ end
949
+ @rgx!=nil
950
+ end
951
+
952
+ #inline parsing
953
+ #I Like (%strong.bold{banana="boys"} (%i.italic cake%)%)!
954
+ #I Like <strong class="bold" banana="boys"><i class="italic">cake</i></strong>!
955
+ def inline_tag()
956
+ if(/\(%(.*?)%\)/ =~ @row;@rgx = $~)
957
+ src = $1.split(/\(%/)
958
+ txt = src.length>1 ? src.pop : src[0]
959
+ tmp = txt.lstrip.split(' ')
960
+ @key= tmp.shift
961
+ @txt= tmp.join(" ")
962
+ nameidclass_var()
963
+ @key.strip!
964
+ html= @mem_var["*code*"]
965
+ html= html=='' ? @txt : html.gsub("$*",@txt)
966
+ tags_created = "<#{@key}"
967
+ tags_created << " #{@mem_var["*all*"].strip}" if @mem_var["*all*"]!=''
968
+ tags_created << ">#{html}</#{@key}>"
969
+ @row.gsub!("(%#{txt}%)",tags_created)
970
+ p "InLin: #{@row}" if @dbg[:parse]
971
+ end
972
+ @rgx
973
+ end
974
+ end
975
+ end