This is not necessarily the current version of this TIP.
| TIP: | 339 |
| Title: | Case-Insensitive Package Names |
| Version: | $Revision: 1.3 $ |
| Author: | Andreas Kupries <andreask at activestate dot com> |
| State: | Draft |
| Type: | Project |
| Tcl-Version: | 8.6 |
| Vote: | Pending |
| Created: | Friday, 14 November 2008 |
This document proposes to change the package management facilities of the Tcl core to handle package names in a case-insensitive manner, switching back to case-sensitive operation if and only if explicitly requested by the user. The case of package names is preserved in the storage however.
The package management facilities of Tcl are an area where the user of packages is currently burdened with more ... than is convenient or easy. A big problem is that Tcl compares package names case-sensitively. This means that Expect and expect are two different things to Tcl. In the real world however having two packages using the same name but different capitalization is extremely rare.
Yet the user of Tcl package facilities has to remember whatever ecclectic capitalization the package creator has chosen.
Changing this, i.e. having Tcl's package management go to case-insensitive comparison, will lift this burden and make things easier, as it is not necessary anymore to get the capitalization right. Most people will likely simply start to write all package names lower-case after this change.
The only command affected by the proposed change is package. More specifically, its sub-commands ifneeded, present, require, and versions.
In detail
package require name ...
This sub-command is changed to accept an additional option -strict.
If this option is present the sub-command performs an old-style, i.e. case-sensitive search for the package name.
Otherwise the command is changed to disregard case during the search for name. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations. To resolve this conflict the command will load the package in the matching set which was added first to its memory database via package ifneeded.
If that resolves to the wrong package the user has to use -strict and specify the exact name of the package required, capitalization and all. Given our rationale for the TIP this should be required seldomly.
package present ?-exact? name ?version?
This sub-command is changed to accept an additional option -strict.
If this option is present the sub-command performs an old-style, i.e. case-sensitive search for the package name.
Otherwise the command is changed to disregard case during the search for name. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations. To resolve this conflict the command will return the version of the package in the matching set it found first among the loaded packages.
If that resolves to the wrong package the user has to use -strict and specify the exact name of the package to look for, capitalization and all. Given our rationale for the TIP this should be required seldomly.
package versions name
This sub-command is changed to accept an additional option -strict.
If this option is present the sub-command performs an old-style, i.e. case-sensitive search for the package name.
Otherwise the command is changed to disregard case during the search for name. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations. To resolve this conflict the command will return the version of the package in the matching set which was added first to its memory database via package ifneeded.
If that resolves to the wrong package the user has to use -strict and specify the exact name of the package to query, capitalization and all. Given our rationale for the TIP this should be required seldomly.
package forget name ...
This sub-command is changed to accept an additional option -strict.
If this option is present the sub-command performs an old-style, i.e. case-sensitive search for the package name to forget.
Otherwise the command is changed to disregard case during the search for name. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations. Instead of resolving the conflict by forgetting only the first package found among the loaded this command will forget all of the packages matching the name.
If that does more than intended the user has to use -strict and specify the exact name(s) of the package to forget, capitalization and all. Given our rationale for the TIP this should be required seldomly.
package provide name version
This form of the command is left unchanged.
package provide name
This form of the command is like package present, except for the different handling of a package not in memory. It is therefore changed in the same manner, i.e:
This form of the sub-command is changed to accept an additional option -strict.
If this option is present this form of the sub-command performs an old-style, i.e. case-sensitive search for the package name before returning its version, or the empty string if nothing was found.
Otherwise this form of the sub-command is changed to disregard case during the search for name. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations. To resolve this conflict the command will return the version of the package in the matching set it found first among the loaded packages.
If that resolves to the wrong package the user has to use -strict and specify the exact name of the package to look for, capitalization and all. Given our rationale for the TIP this should be required seldomly.
It is important to note that the sub-command ifneeded does not change with regard to its API.
package ifneeded keeps storing the package name as given, preserving capitalization, and package provide searches case-sensitively. This means that the name used by provide has to match the name used by the ifneeded, just like the version numbers have to match. While we are working on easing the load on the user of a package with regard to letter case we do assume that the developer of a package does know how it is spelled, capitalization and all, therefore a strict, case-sensitive search is best to detect such avoidable mismatches.
At the C-level the only functions to consider are
Tcl_PkgPresent /exact
Tcl_PkgPresentEx /exact
Tcl_PkgRequire /exact
Tcl_PkgRequireEx /exact
Tcl_PkgRequireProc
The first four of these currently have an integer (boolean) argument exact. This argument is changed to an integer (bitset) flags, with the original exact value residing in bit 0. The strictness of the package name comparison is encoded in bit 1. For easy access to the flags we define
#define TCL_PKG_EXACT 1 /* Exact version required */
#define TCL_PKG_STRICT 2 /* Use strict (case-sensitive) package name
* comparison */
This change relies on the assumption that all (most) existing users of these functions use the constants 0 and 1 for exact, making them fully backward compatible.
The last function, Tcl_PkgRequireProc, has no arguments we can modify in this manner. Its behaviour is changed to perform case-insensitive searches, as specified above for the associated subcommands of package, and a new function is added for access to the old behaviour, i.e. case-sensitive searches. This new function is
Tcl_PkgRequireProcEx
It has the same signature as its pre-TIP counterpart, except that a flags argument is added after the clientData. This argument recognizes TCL_PKG_STRICT as defined above and uses it to switch between case-insensitive and strict search. The old Tcl_PkgRequireProc is reimplemented in terms of Tcl_PkgRequireProcEx.
An implementation patch is soon to be available at SourceForge [1].
This document has been placed in the public domain.
Please note that any correspondence to the author concerning this TIP is considered in the public domain unless otherwise specifically requested by the individual(s) authoring said correspondence. This is to allow information about the TIP to be placed in a public forum for discussion.
This is not necessarily the current version of this TIP.