--- init.tcl.orig 2018-02-06 21:19:00.604612300 -0600 +++ init.tcl 2018-02-06 21:20:29.211680400 -0600 @@ -817,3 +817,50 @@ } return } + + +# +# Front-end 'package' and add "search" subcommand +# +if { [info command ::tcl::package] ne "::tcl::package" } { + + rename ::package ::tcl::package + + + # package search string + # Search all package names for a case-insensitive match + # The argument "string" is used to contruct a glob pattern *${string}* + # + proc ::package {args} { + + if { [llength $args] > 0 } { + + set subCommand [lindex $args 0] + set subCommandLength [string length $subCommand] + + # Issue error message if the subcommand is not one supported by the 'package' + # command + if { [lsearch -glob {forget ifneeded names prefer present provide require search unknown vcompare versions vsatisfies} $subCommand*] == -1 } { + return -code error "bad option \"$subCommand\": must be forget, ifneeded, names, prefer, present, provide, require, search, unknown, vcompare, versions, or vsatisfies" + } + + if { [string match ${subCommand}* search] } { + + if { [llength $args] != 2 } { + return -code error "wrong # args: should be \"package search string\"" + } + + set allPackageNames [lsort [::tcl::package names]] + + set result [list ] + foreach match [lsearch -glob -all -nocase $allPackageNames *[lindex $args 1]*] { + lappend result [lindex $allPackageNames $match] + } + + return $result + } + } + + return [uplevel ::tcl::package $args] + } +}