Initial reference implementation of TIP 712 (Add "positive" options to the subst command) with code, documentation and tests.

This commit is contained in:
max
2025-01-31 14:47:13 +00:00
parent 27f2debf9a
commit 6dd788dfc6
3 changed files with 81 additions and 11 deletions
+15
View File
@@ -13,7 +13,10 @@
.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
@@ -33,6 +36,18 @@ 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.
+30 -3
View File
@@ -3337,12 +3337,15 @@ TclSubstOptions(
int *flagPtr)
{
static const char *const substOptions[] = {
"-nobackslashes", "-nocommands", "-novariables", NULL
"-nobackslashes", "-nocommands", "-novariables",
"-backslashes", "-commands", "-variables", NULL
};
enum {
SUBST_NOBACKSLASHES, SUBST_NOCOMMANDS, SUBST_NOVARS
SUBST_NOBACKSLASHES, SUBST_NOCOMMANDS, SUBST_NOVARS,
SUBST_BACKSLASHES, SUBST_COMMANDS, SUBST_VARS
};
int i, flags = TCL_SUBST_ALL;
int positive = 0, negative = 0;
for (i = 0; i < numOpts; i++) {
int optionIndex;
@@ -3351,6 +3354,20 @@ TclSubstOptions(
&optionIndex) != TCL_OK) {
return TCL_ERROR;
}
if (optionIndex >= SUBST_NOBACKSLASHES &&
optionIndex <= SUBST_NOVARS) {
negative = 1;
} else if (optionIndex >= SUBST_BACKSLASHES &&
optionIndex <= SUBST_VARS && positive == 0) {
positive = 1;
/* Swap the default at the first positive switch */
flags = 0;
}
if (positive && negative) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"positive and negative switches cannot be combined", -1));
return TCL_ERROR;
}
switch (optionIndex) {
case SUBST_NOBACKSLASHES:
flags &= ~TCL_SUBST_BACKSLASHES;
@@ -3361,6 +3378,15 @@ TclSubstOptions(
case SUBST_NOVARS:
flags &= ~TCL_SUBST_VARIABLES;
break;
case SUBST_BACKSLASHES:
flags |= TCL_SUBST_BACKSLASHES;
break;
case SUBST_COMMANDS:
flags |= TCL_SUBST_COMMANDS;
break;
case SUBST_VARS:
flags |= TCL_SUBST_VARIABLES;
break;
default:
Tcl_Panic("Tcl_SubstObjCmd: bad option index to SubstOptions");
}
@@ -3390,7 +3416,8 @@ TclNRSubstObjCmd(
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv,
"?-nobackslashes? ?-nocommands? ?-novariables? string");
"?-nobackslashes? ?-nocommands? ?-novariables? "
"?-backslashes? ?-commands? ?-variables? string");
return TCL_ERROR;
}
+36 -8
View File
@@ -22,10 +22,10 @@ testConstraint testbytestring [llength [info commands testbytestring]]
test subst-1.1 {basics} -returnCodes error -body {
subst
} -result {wrong # args: should be "subst ?-nobackslashes? ?-nocommands? ?-novariables? string"}
} -result {wrong # args: should be "subst ?-nobackslashes? ?-nocommands? ?-novariables? ?-backslashes? ?-commands? ?-variables? string"}
test subst-1.2 {basics} -returnCodes error -body {
subst a b c
} -result {bad option "a": must be -nobackslashes, -nocommands, or -novariables}
} -result {bad option "a": must be -nobackslashes, -nocommands, -novariables, -backslashes, -commands, or -variables}
test subst-2.1 {simple strings} {
subst {}
@@ -123,29 +123,57 @@ test subst-6.1 {clear the result after command substitution} -body {
test subst-7.1 {switches} -returnCodes error -body {
subst foo bar
} -result {bad option "foo": must be -nobackslashes, -nocommands, or -novariables}
} -result {bad option "foo": must be -nobackslashes, -nocommands, -novariables, -backslashes, -commands, or -variables}
test subst-7.2 {switches} -returnCodes error -body {
subst -no bar
} -result {ambiguous option "-no": must be -nobackslashes, -nocommands, or -novariables}
} -result {ambiguous option "-no": must be -nobackslashes, -nocommands, -novariables, -backslashes, -commands, or -variables}
test subst-7.3 {switches} -returnCodes error -body {
subst -bogus bar
} -result {bad option "-bogus": must be -nobackslashes, -nocommands, or -novariables}
test subst-7.4 {switches} {
} -result {bad option "-bogus": must be -nobackslashes, -nocommands, -novariables, -backslashes, -commands, or -variables}
test subst-7.4.1 {switches} {
set x 123
subst -nobackslashes {abc $x [expr {1 + 2}] \\\x41}
} {abc 123 3 \\\x41}
test subst-7.5 {switches} {
test subst-7.4.2 {switches} {
set x 123
subst -commands -variables {abc $x [expr {1 + 2}] \\\x41}
} {abc 123 3 \\\x41}
test subst-7.5.1 {switches} {
set x 123
subst -nocommands {abc $x [expr {1 + 2}] \\\x41}
} {abc 123 [expr {1 + 2}] \A}
test subst-7.6 {switches} {
test subst-7.5.2 {switches} {
set x 123
subst -backslashes -variables {abc $x [expr {1 + 2}] \\\x41}
} {abc 123 [expr {1 + 2}] \A}
test subst-7.6.1 {switches} {
set x 123
subst -novariables {abc $x [expr {1 + 2}] \\\x41}
} {abc $x 3 \A}
test subst-7.6.2 {switches} {
set x 123
subst -backslashes -commands {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 {switches} {
set x 123
subst -backslashes {abc $x [expr {1 + 2}] \\\x41}
} {abc $x [expr {1 + 2}] \A}
test subst-7.9 {switches} {
set x 123
subst -commands {abc $x [expr {1 + 2}] \\\x41}
} {abc $x 3 \\\x41}
test subst-7.10 {switches} {
set x 123
subst -variables {abc $x [expr {1 + 2}] \\\x41}
} {abc 123 [expr {1 + 2}] \\\x41}
test subst-7.11 {switches} {
set x 123
subst -ba -co -va {abc $x [expr {1 + 2}] \\\x41}
} {abc 123 3 \A}
test subst-8.1 {return in a subst} {
subst {foo [return {x}; bogus code] bar}