Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | TIP 712 - Add "positive" options to the subst command |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk | main |
Files: | files | file ages | folders |
SHA3-256: |
f41248f05784051abfdeb81f88cfc3d9 |
User & Date: | max 2025-06-17 12:27:48.701 |
Context
2025-06-17
| ||
13:35 | Update macOS info in README.md and macosx/README check-in: 4361a247f8 user: culler tags: trunk, main | |
12:27 | TIP 712 - Add "positive" options to the subst command check-in: f41248f057 user: max tags: trunk, main | |
2025-06-15
| ||
03:03 | Merge 9.0 - tests for handle leaks for exec check-in: 166bfb6375 user: apnadkarni tags: trunk, main | |
2025-05-21
| ||
10:09 | Rebase to latest trunk Closed-Leaf check-in: d265be08af user: jan.nijtmans tags: tip-712 | |
Changes
Changes to doc/subst.n.
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | .TH subst n 7.4 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME subst \- Perform backslash, command, and variable substitutions .SH SYNOPSIS \fBsubst \fR?\fB\-nobackslashes\fR? ?\fB\-nocommands\fR? ?\fB\-novariables\fR? \fIstring\fR .BE .SH DESCRIPTION .PP This command performs variable substitutions, command substitutions, and backslash substitutions on its \fIstring\fR argument and returns the fully-substituted result. The substitutions are performed in exactly the same way as for Tcl commands. As a result, the \fIstring\fR argument is actually substituted twice, once by the Tcl parser in the usual fashion for Tcl commands, and again by the \fIsubst\fR command. .PP If any of the \fB\-nobackslashes\fR, \fB\-nocommands\fR, or \fB\-novariables\fR are specified, then the corresponding substitutions are not performed. For example, if \fB\-nocommands\fR is specified, command substitution is not performed: open and close brackets are treated as ordinary characters with no special interpretation. .PP Note that the substitution of one kind can include substitution of other kinds. For example, even when the \fB\-novariables\fR option is specified, command substitution is performed without restriction. This means that any variable substitution necessary to complete the command substitution will still take place. Likewise, any command substitution necessary to complete a variable substitution will take place, even when \fB\-nocommands\fR is specified. See the | > > > > > > > > > > > > > > > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | .TH subst n 7.4 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME subst \- Perform backslash, command, and variable substitutions .SH SYNOPSIS .nf \fBsubst \fR?\fB\-nobackslashes\fR? ?\fB\-nocommands\fR? ?\fB\-novariables\fR? \fIstring\fR \fBsubst \fR?\fB\-backslashes\fR? ?\fB\-commands\fR? ?\fB\-variables\fR? \fIstring\fR .fi .BE .SH DESCRIPTION .PP This command performs variable substitutions, command substitutions, and backslash substitutions on its \fIstring\fR argument and returns the fully-substituted result. The substitutions are performed in exactly the same way as for Tcl commands. As a result, the \fIstring\fR argument is actually substituted twice, once by the Tcl parser in the usual fashion for Tcl commands, and again by the \fIsubst\fR command. .PP If any of the \fB\-nobackslashes\fR, \fB\-nocommands\fR, or \fB\-novariables\fR are specified, then the corresponding substitutions are not performed. For example, if \fB\-nocommands\fR is specified, command substitution is not performed: open and close brackets are treated as ordinary characters with no special interpretation. .PP If any of the \fB\-backslashes\fR, \fB\-commands\fR, or \fB\-variables\fR are specified, then only the corresponding substitutions are performed. This means that the following lines are equivalent: .PP .CS \fBsubst\fR -nobackslashes -nocommands $string \fBsubst\fR -variables $string .CE .PP It is not allowed to combine positive and negated options. .PP Note that the substitution of one kind can include substitution of other kinds. For example, even when the \fB\-novariables\fR option is specified, command substitution is performed without restriction. This means that any variable substitution necessary to complete the command substitution will still take place. Likewise, any command substitution necessary to complete a variable substitution will take place, even when \fB\-nocommands\fR is specified. See the |
︙ | ︙ |
Changes to generic/tclCmdMZ.c.
︙ | ︙ | |||
3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 | TclSubstOptions( Tcl_Interp *interp, Tcl_Size numOpts, Tcl_Obj *const opts[], int *flagPtr) { static const char *const substOptions[] = { "-nobackslashes", "-nocommands", "-novariables", NULL }; static const int optionFlags[] = { | > | > > > > > | | > > > > > > > > > > > | 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 | TclSubstOptions( Tcl_Interp *interp, Tcl_Size numOpts, Tcl_Obj *const opts[], int *flagPtr) { static const char *const substOptions[] = { "-backslashes", "-commands", "-variables", "-nobackslashes", "-nocommands", "-novariables", NULL }; static const int optionFlags[] = { TCL_SUBST_BACKSLASHES, /* -backslashes */ TCL_SUBST_COMMANDS, /* -commands */ TCL_SUBST_VARIABLES, /* -variables */ TCL_SUBST_BACKSLASHES << 16, /* -nobackslashes */ TCL_SUBST_COMMANDS << 16, /* -nocommands */ TCL_SUBST_VARIABLES << 16 /* -novariables */ }; int flags = numOpts ? 0 : TCL_SUBST_ALL; for (Tcl_Size i = 0; i < numOpts; i++) { int optionIndex; if (Tcl_GetIndexFromObj(interp, opts[i], substOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } flags |= optionFlags[optionIndex]; } if (flags >> 16) { /* negative options specified */ if (flags & 0xFFFF) { /* positive options specified too */ if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot combine positive and negative options", -1)); } return TCL_ERROR; } /* mask default flags using negative options */ flags = TCL_SUBST_ALL & ~(flags >> 16); } *flagPtr = flags; return TCL_OK; } int Tcl_SubstObjCmd( |
︙ | ︙ | |||
3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 | int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int flags; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "?-nobackslashes? ?-nocommands? ?-novariables? string"); return TCL_ERROR; } if (TclSubstOptions(interp, objc-2, objv+1, &flags) != TCL_OK) { return TCL_ERROR; } | > | 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 | int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int flags; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "?-backslashes? ?-commands? ?-variables? " "?-nobackslashes? ?-nocommands? ?-novariables? string"); return TCL_ERROR; } if (TclSubstOptions(interp, objc-2, objv+1, &flags) != TCL_OK) { return TCL_ERROR; } |
︙ | ︙ |
Changes to tests/subst.test.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ::tcltest::loadTestedCommands catch [list package require -exact tcl::test [info patchlevel]] testConstraint testbytestring [llength [info commands testbytestring]] test subst-1.1 {basics} -returnCodes error -body { subst | | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ::tcltest::loadTestedCommands catch [list package require -exact tcl::test [info patchlevel]] testConstraint testbytestring [llength [info commands testbytestring]] test subst-1.1 {basics} -returnCodes error -body { subst } -result {wrong # args: should be "subst ?-backslashes? ?-commands? ?-variables? ?-nobackslashes? ?-nocommands? ?-novariables? string"} test subst-1.2 {basics} -returnCodes error -body { subst a b c } -result {bad option "a": must be -backslashes, -commands, -variables, -nobackslashes, -nocommands, or -novariables} test subst-2.1 {simple strings} { subst {} } {} test subst-2.2 {simple strings} { subst a } a |
︙ | ︙ | |||
119 120 121 122 123 124 125 | test subst-6.1 {clear the result after command substitution} -body { catch {unset a} subst {[concat foo] $a} } -returnCodes error -result {can't read "a": no such variable} test subst-7.1 {switches} -returnCodes error -body { subst foo bar | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | test subst-6.1 {clear the result after command substitution} -body { catch {unset a} subst {[concat foo] $a} } -returnCodes error -result {can't read "a": no such variable} test subst-7.1 {switches} -returnCodes error -body { subst foo bar } -result {bad option "foo": must be -backslashes, -commands, -variables, -nobackslashes, -nocommands, or -novariables} test subst-7.2 {switches} -returnCodes error -body { subst -no bar } -result {ambiguous option "-no": must be -backslashes, -commands, -variables, -nobackslashes, -nocommands, or -novariables} test subst-7.3 {switches} -returnCodes error -body { subst -bogus bar } -result {bad option "-bogus": must be -backslashes, -commands, -variables, -nobackslashes, -nocommands, or -novariables} test subst-7.4 {switches} { set x 123 subst -nobackslashes {abc $x [expr {1 + 2}] \\\x41} } {abc 123 3 \\\x41} test subst-7.5 {switches} { set x 123 subst -nocommands {abc $x [expr {1 + 2}] \\\x41} } {abc 123 [expr {1 + 2}] \A} test subst-7.6 {switches} { set x 123 subst -novariables {abc $x [expr {1 + 2}] \\\x41} } {abc $x 3 \A} test subst-7.7 {switches} { set x 123 subst -nov -nob -noc {abc $x [expr {1 + 2}] \\\x41} } {abc $x [expr {1 + 2}] \\\x41} test subst-7.8 {positive switches} { set x 123 subst -backslashes {abc $x [expr {1 + 2}] \\\x41} } {abc $x [expr {1 + 2}] \A} test subst-7.9 {positive switches} { set x 123 subst -commands {abc $x [expr {1 + 2}] \\\x41} } {abc $x 3 \\\x41} test subst-7.10 {positive switches} { set x 123 subst -variables {abc $x [expr {1 + 2}] \\\x41} } {abc 123 [expr {1 + 2}] \\\x41} test subst-7.4.11 {positive switches} { set x 123 subst -commands -variables {abc $x [expr {1 + 2}] \\\x41} } {abc 123 3 \\\x41} test subst-7.12 {positive switches} { set x 123 subst -backslashes -variables {abc $x [expr {1 + 2}] \\\x41} } {abc 123 [expr {1 + 2}] \A} test subst-7.13 {positive switches} { set x 123 subst -backslashes -commands {abc $x [expr {1 + 2}] \\\x41} } {abc $x 3 \A} test subst-7.14 {positive switches} { set x 123 subst -ba -co -va {abc $x [expr {1 + 2}] \\\x41} } {abc 123 3 \A} test subst-7.15 {mixed switches} -returnCodes error -body { set x 123 subst -backslashes -novariables {abc $x [expr {1 + 2}] \\\x41} } -result {cannot combine positive and negative options} test subst-8.1 {return in a subst} { subst {foo [return {x}; bogus code] bar} } {foo x bar} test subst-8.2 {return in a subst} { subst {foo [return x ; bogus code] bar} } {foo x bar} test subst-8.3 {return in a subst} { |
︙ | ︙ |