Reputation: 1193
How can I implement expand
in the script below (expanding commands and variables as normal in tcl), I want it to print out:
'
hello {
$b
}
{tcl world}
'
This is how I imagine the script will look:
proc clever_func {script} {
set script [uplevel 1 expand [list $script]]
puts "'$script'"
}
proc isolated_client_function {} {
set a hello
set b difficult
set c tcl
set d world
clever_func {
$a {
$b
}
[list $c $d]
}
}
isolated_client_function
Upvotes: 1
Views: 193
Reputation: 247210
The subst
command will take you most of the way there.
proc expand {script} {
uplevel 1 [list subst $script]
}
set a hello
set b difficult
set c tcl
set d world
expand {
$a {
$b
}
[list $c $d]
}
outputs
hello {
difficult
}
tcl world
I'm not sure off the top of my head how to prevent $b
from being substituted. You'll probably have to parse the script yourself.
If you want the last part to have the quoting you demonstrate, you need another level of list-ness
expand {
$a {
$b
}
[list [list $c $d]]
}
outputs
hello {
difficult
}
{tcl world}
Upvotes: 1
Reputation: 21517
An example isn't a sufficient replacement for a specification, but it seems that there are no built-in TCL facility doing what you want. It would be possible to perform a substitution on a single command tail (by prepending list
to a command and eval
ling it at any level you want), but not for a pseudo-script with two "commands". (It's also possible to do what string interpolation does, using subst
, but you probably already know why it's not what you want: it will also expand $b
).
I see two possibilities to get what you want:
Tokenize your input using sugar::scriptToList
, then perform substitution manually in the list of tokens, then convert the result back to textual form with sugar::listToScript
. These features of sugar
macroprocessor are designed to let you modify scripts semantically while preserving formatting, comments and layout.
Break down your input into separate "commands": first split at each newline and semicolon, then use info complete
to collect pieces corresponding to complete "commands" (IIRC there will be some corner cases with backslash-newline continuation: beware). On each complete "command" use the trick of prepending "list "
, evaluating the result in necessary context (uplevel
). Thus for each command you'll get a list where substitution has already been performed when appropiate. You will lose nuances of formatting inside each "command" (like the number of spaces separating words and the kind of space), and you will lose original command separators unless you take care to remember them yourself. It might not be bad for you if the goal is to get a kind of "pre-expanded script" to be eval
uated later in some other context.
Upvotes: 2