REBOL [
Title: "RSP Preprocessor"
Date: 25-Jul-2010
Author: "Christopher Ross-Gill"
Notes: "Extracted from QM"
Type: 'module
File: %rsp.r
Exports: [load-rsp render render-each]
]
load-rsp: use [prototype to-set-block][
prototype: context [
out*: "" prin: func [val][repend out* val]
print: func [val][prin val prin newline]
]
to-set-block: func [block [block! object!] /local word][
either object? block [block: third block][
parse copy block [
(block: copy [])
any [set word word! (repend block [to-set-word word get/any word])]
]
]
block
]
func [[catch] body [string!] /local code mk][
code: make string! length? body
append code "^/out*: make string! {}^/"
parse/all body [
any [
end (append code "out*") break
| "<%" [
"=" copy mk to "%>" (repend code ["prin (" mk "^/)^/"])
| [#":" | #"!"] copy mk to "%>" (repend code ["prin build-tag [" mk "^/]^/"])
| copy mk to "%>" (repend code [mk newline])
| (throw make error! "Expected '%>'")
] 2 skip
| copy mk [to "<%" | to end] (repend code ["prin " mold mk "^/"])
]
]
func [args [block! object!]] compose/only [
args: make prototype to-set-block args
do bind/copy (throw-on-error [load code]) args
]
]
]
render: use [depth*][
depth*: 0 ;-- to break recursion
func [
[catch] rsp [file! url! string!]
/with locals [block! object!]
][
if depth* > 20 [return ""]
depth*: depth* + 1
rsp: case/all [
file? rsp [rsp: read rsp]
url? rsp [rsp: read rsp]
string? rsp [
throw-on-error [rsp: load-rsp rsp]
throw-on-error [rsp any [locals []]]
]
]
depth*: depth* - 1
rsp
]
]
render-each: func [
'items [word! block!]
source [series!]
body [file! url! string!]
/with locals /local out
][
out: copy ""
locals: append any [locals []] items: compose [(items)]
foreach :items source compose/only [
append out render/with body (locals)
]
return out
]