diff --git a/NEWS.rst b/NEWS.rst index ae6582beb..429bf56b8 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -18,6 +18,14 @@ Modules 5.8.0 (not yet released) * Add :mfcmd:`module-info modulename` and :mfcmd:`module-info moduleversion` modulefile commands to get the name part and the version part of currently evaluating modulefile. (fix issue #713) +* Improve readability of :subcmd:`whatis` and :subcmd:`search` output: name of + each matching modulefile is reported once, followed by its + :mfcmd:`module-whatis` lines wrapped to the terminal width. (fix issue + #720) +* Add support for the :option:`--terse` option on :subcmd:`whatis` and + :subcmd:`search` sub-commands to get one output line per + :mfcmd:`module-whatis` entry prefixed by module name, without wrapping or + padding, and modulepath reported as a header line. (fix issue #720) .. _5.7 release notes: diff --git a/doc/source/changes.rst b/doc/source/changes.rst index 21f1a90c7..d344c4b7b 100644 --- a/doc/source/changes.rst +++ b/doc/source/changes.rst @@ -914,6 +914,11 @@ The following command line switches appeared on Modules 5. Starting Modules 5.6, :subcmd:`spider` sub-command is supported. +:option:`--terse` + + Starting Modules 5.8, :subcmd:`search` and :subcmd:`whatis` sub-commands are + supported. + :option:`--default`, :option:`--latest`, :option:`--indepth`, :option:`--no-indepth` @@ -1062,6 +1067,14 @@ The following module sub-commands appeared on Modules 5. of :subcmd:`reload` sub-command. No more support from ``MODULESBEGINENV``, initial environment handling now covers this use case. +:subcmd:`search`, :subcmd:`whatis` + + Starting Modules 5.8, name of each matching modulefile is reported once, + followed by its :mfcmd:`module-whatis` lines wrapped to the terminal width. + The :option:`--terse` option reports each :mfcmd:`module-whatis` line on its + own output line prefixed by the module name, without wrapping or padding, + and the modulepath as a header line. + Environment """"""""""" diff --git a/doc/source/module.rst b/doc/source/module.rst index 9a957f7d0..7f133a1ab 100644 --- a/doc/source/module.rst +++ b/doc/source/module.rst @@ -645,8 +645,9 @@ switches are accepted: .. option:: --terse, -t - Display :subcmd:`avail`, :subcmd:`list`, :subcmd:`savelist`, :subcmd:`spider` - and :subcmd:`stashlist` output in short format. + Display :subcmd:`avail`, :subcmd:`list`, :subcmd:`savelist`, + :subcmd:`search`, :subcmd:`spider`, :subcmd:`stashlist` and :subcmd:`whatis` + output in short format. .. only:: html or latex @@ -659,6 +660,9 @@ switches are accepted: .. versionchanged:: 5.6 Support for :subcmd:`spider` sub-command added + .. versionchanged:: 5.8 + Support for :subcmd:`search` and :subcmd:`whatis` sub-commands added + .. option:: --timer Prints at the end of the output an evaluation of the total execution time of @@ -2670,13 +2674,20 @@ Module Sub-Commands ``__init__`` or when no collection name is specified and no *default* collection exists -.. subcmd:: search [-a] [-j] string +.. subcmd:: search [-a] [-t|-j] string Seeks through the :mfcmd:`module-whatis` information of all *modulefiles* for the specified *string*. All *module-whatis* information matching the *string* in a case insensitive manner will be displayed. *string* may contain wildcard characters. + Name of each matching *modulefile* is reported once, followed by its + *module-whatis* lines. This text is wrapped to the terminal width and its + continuation lines are aligned under the start of the first line text. With + the :option:`--terse` option, each *module-whatis* line is reported on its + own output line prefixed by the module name, without wrapping or padding, + and the modulepath is reported as a header line. + .. only:: html or latex .. versionadded:: 4.0 @@ -2689,6 +2700,12 @@ Module Sub-Commands .. versionchanged:: 4.6 Option :option:`--all`/:option:`-a` added + .. versionchanged:: 5.8 + Module name is reported once with its *module-whatis* lines grouped + below and wrapped to terminal width; option + :option:`--terse`/:option:`-t` added to get one output line per + *module-whatis* line + .. subcmd:: sh-to-mod shell script [arg...] Evaluate with *shell* the designated *script* with defined *arguments* to @@ -3166,12 +3183,19 @@ Module Sub-Commands :subcmd:`module use` is called from the command-line or within an initialization modulefile script -.. subcmd:: whatis [-a] [-j] [pattern...] +.. subcmd:: whatis [-a] [-t|-j] [pattern...] Display the information set up by the :mfcmd:`module-whatis` commands inside *modulefiles* matching *pattern*. *pattern* may contain wildcard characters. If no *pattern* is specified, all :mfcmd:`module-whatis` lines will be shown. + Name of each matching *modulefile* is reported once, followed by its + *module-whatis* lines. This text is wrapped to the terminal width and its + continuation lines are aligned under the start of the first line text. With + the :option:`--terse` option, each *module-whatis* line is reported on its + own output line prefixed by the module name, without wrapping or padding, + and the modulepath is reported as a header line. + The parameter *pattern* may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see `Advanced module version specifiers`_ section below). @@ -3198,6 +3222,12 @@ Module Sub-Commands Results from a multi *pattern* search are consolidated under a single output + .. versionchanged:: 5.8 + Module name is reported once with its *module-whatis* lines grouped + below and wrapped to terminal width; option + :option:`--terse`/:option:`-t` added to get one output line per + *module-whatis* line + Modulefiles ^^^^^^^^^^^ diff --git a/init/Makefile b/init/Makefile index 244a25fe5..65c41c5a0 100644 --- a/init/Makefile +++ b/init/Makefile @@ -137,8 +137,8 @@ comp_stashlist_opts := -j -l -t --json --long --terse comp_clear_opts := --force -f comp_avail_opts := -a -C -d -i -j -L -l -o -S -t --all --contains --default --icase --json --latest --long --output --output= --starts-with --terse --indepth --no-indepth comp_mfile_opts := -i --icase -comp_whatis_opts := -a -i -j --all --icase --json -comp_search_opts := -a -j --all --json +comp_whatis_opts := -a -i -j -t --all --icase --json --terse +comp_search_opts := -a -j -t --all --json --terse comp_aliases_opts := -a --all comp_use_opts := -a --append -p --prepend comp_isavail_opts := -i --icase diff --git a/init/zsh-functions/_module.in b/init/zsh-functions/_module.in index 661c6a94a..7ddbe4c09 100644 --- a/init/zsh-functions/_module.in +++ b/init/zsh-functions/_module.in @@ -381,12 +381,14 @@ _module() { (whatis) _arguments \ '(-i --icase)'{-i,--icase}'[Case insensitive match]' \ + '(-t --terse)'{-t,--terse}'[Display output in terse format]' \ '(-j --json)'{-j,--json}'[Display output in JSON format]' \ '(-a --all)'{-a,--all}'[Include hidden modules in search]' \ "*::modulefile:{_module_avail_mods $cur}" && ret=0 ;; (apropos|keyword|search) _arguments \ + '(-t --terse)'{-t,--terse}'[Display output in terse format]' \ '(-j --json)'{-j,--json}'[Display output in JSON format]' \ '(-a --all)'{-a,--all}'[Include hidden modules in search]' \ && ret=0 diff --git a/tcl/report.tcl.in b/tcl/report.tcl.in index d893b9bd4..a2091ba45 100644 --- a/tcl/report.tcl.in +++ b/tcl/report.tcl.in @@ -1645,6 +1645,56 @@ proc showModulePath {} { } } +# split text into lines whose visible length does not exceed max_len, cutting +# at whitespace position (SGR codes consume no length). A word longer than +# max_len is kept whole on its own line +proc wrapTextToWidth {text max_len} { + # empty text produces one empty line + if {$text eq {}} { + return [list {}] + } + set wrapped_list {} + foreach line [split $text \n] { + while {1} { + # walk through line until max_len visible characters are passed + set idx 0 + set vis_len 0 + set line_len [string length $line] + while {$idx < $line_len} { + if {[string range $line $idx $idx+1] eq "\033\[" && [set midx\ + [string first m $line $idx]] != -1} { + set idx [expr {$midx + 1}] + } elseif {$vis_len == $max_len} { + break + } else { + incr idx + incr vis_len + } + } + # whole remaining line fits + if {$idx >= $line_len} { + lappend wrapped_list $line + break + } + # cut after word if no whitespace found before it + if {[set cut_idx [string last { } $line $idx]] < 1} { + set cut_idx [string first { } $line $idx] + } + if {$cut_idx == -1} { + lappend wrapped_list $line + break + } + lappend wrapped_list [string range $line 0 $cut_idx-1] + set line [string trimleft [string range $line $cut_idx+1 end]] + # nothing left to report if only whitespace remains after cut + if {$line eq {}} { + break + } + } + } + return $wrapped_list +} + proc displayTableHeader {sgrkey args} { foreach {title col_len} $args { set col "- [sgr $sgrkey $title] " @@ -2051,9 +2101,9 @@ Listing / Searching commands: [-i] [--indepth|--no-indepth] [mod ...] List all or matching available modules aliases [-a] List all module aliases - whatis [-a] [-i] [-j] [modulefile ...] + whatis [-a] [-i] [-j|-t] [modulefile ...] Print whatis information of modulefile(s) - apropos | keyword | search [-a] [-j] str + apropos | keyword | search [-a] [-j|-t] str Search all name and whatis containing str spider [-a] [-t|-l|-j] [-S|-C] [-d|-L] [-o LIST] [-i] [--indepth|--no-indepth] [mod ...] diff --git a/tcl/subcmd.tcl.in b/tcl/subcmd.tcl.in index d53928dfe..14139d5b3 100644 --- a/tcl/subcmd.tcl.in +++ b/tcl/subcmd.tcl.in @@ -217,6 +217,7 @@ proc cmdModuleSearch {args} { set mod_pattern_list [lassign $args search] set json [isStateEqual report_format json] + set terse [isStateEqual report_format terse] set icase [isIcase] lappend searchmod rc_defs_included @@ -399,16 +400,41 @@ proc cmdModuleSearch {args} { whatis a $::g_whatis 1] } else { set eltsgr [string map $matchmodmap $elt] - foreach line $::g_whatis { - set linesgr [string map $matchsearchmap $line] - lappend display_list "[string repeat { } [expr {20 -\ - [string length $elt]}]]$eltsgr: $linesgr" + # one line per whatis entry, each prefixed by module name + if {$terse} { + foreach line $::g_whatis { + set linesgr [string map $matchsearchmap $line] + lappend display_list "$eltsgr: $linesgr" + } + # module name on first line only, whatis text of next lines + # aligned under first line text and wrapped to term width + } else { + set eltpad [string repeat { } [expr {20 - [string length\ + $elt]}]] + set text_col [expr {[tcl::mathfunc::max 20 [string\ + length $elt]] + 2}] + set text_pad [string repeat { } $text_col] + set text_len [tcl::mathfunc::max [expr {[getState\ + term_columns] - $text_col}] 1] + set first 1 + foreach entry $::g_whatis { + foreach line [wrapTextToWidth [string map\ + $matchsearchmap $entry] $text_len] { + if {$first} { + set first 0 + lappend display_list "$eltpad$eltsgr: $line" + } else { + lappend display_list $text_pad$line + } + } + } } } } } - displayElementList $dir mp sepline 1 0 0 $display_list + displayElementList $dir mp [expr {$terse ? {terse} : {sepline}}] 1\ + 0 0 $display_list } } lpopState mode diff --git a/testsuite/modules.20-locate/100-wspace.exp b/testsuite/modules.20-locate/100-wspace.exp index 96fb3774d..5b11456f8 100644 --- a/testsuite/modules.20-locate/100-wspace.exp +++ b/testsuite/modules.20-locate/100-wspace.exp @@ -667,6 +667,8 @@ testouterr_cmd sh "unuse $modpath\\ wspac\\ " $ans {} # module whose name and target finish with space character testouterr_cmd sh {avail -t space\ y\ /1\ } OK "$mp:\n'space y /1 '(n )" testouterr_cmd_re sh {whatis space\ y\ /1\ } OK "$modlin $mpre $modlin\n\\s+space y /1 : space y /1 " +# whatis text cut at terminal width right before its trailing space +testouterr_cmd_re sh {-w 32 whatis space\ y\ /1\ } OK "$modlin $mpre $modlin\n\\s+space y /1 : space y /1" set ans [list] lappend ans [list set __MODULES_LMALTNAME "space y /1 &space y /n &al|space y /a "] lappend ans [list set _LMFILES_ "$mp/space y /1 "] diff --git a/testsuite/modules.50-cmds/730-linked_envvars.exp b/testsuite/modules.50-cmds/730-linked_envvars.exp index 579e548c9..8fd5418c9 100644 --- a/testsuite/modules.50-cmds/730-linked_envvars.exp +++ b/testsuite/modules.50-cmds/730-linked_envvars.exp @@ -573,8 +573,8 @@ testouterr_cmd_re bash {display link/1} OK $tserr setenv_var TESTSUITE_LINKED_ENVVARS append1 set tserr "$modlin $mpre $modlin \\s*link/1: link/1 -\\s*link/1: BAR: val2 -\\s*link/1: QUX: value" +\\s*BAR: val2 +\\s*QUX: value" testouterr_cmd_re bash {whatis link/1} OK $tserr setenv_var TESTSUITE_LINKED_ENVVARS prepend1 diff --git a/testsuite/modules.70-maint/055-whatis.exp b/testsuite/modules.70-maint/055-whatis.exp index fd3012596..f8a07c9e5 100644 --- a/testsuite/modules.70-maint/055-whatis.exp +++ b/testsuite/modules.70-maint/055-whatis.exp @@ -54,7 +54,10 @@ set ts_csh_2 "$header\n$whatis_2: Testsuite-Modulefile" # module-whatis call produce a single module-whatis line, not one line per passed argument set ts_csh_3 "$header\n$whatis_3: Testsuite Whatis Modulefile" set ts_csh_4 "$header\n$whatis_4: Testsuite Whatis Modulefile" -set ts_csh_5 "$header\n$whatis_5: Testsuite Whatis Modulefile\n$whatis_5: Second line of whatis tokens" +# module name is reported once, next whatis lines are aligned under text of +# first line +set text_pad [string repeat { } 22] +set ts_csh_5 "$header\n$whatis_5: Testsuite Whatis Modulefile\n${text_pad}Second line of whatis tokens" set ts_csh_6 "$err_path'$module_6'" set ts_csh_7 "$header\n$whatis_7: erroneous module test" @@ -62,21 +65,50 @@ set ts_csh_7 "$header\n$whatis_7: erroneous module test" # The tests # -testouterr_cmd_re "csh" "--terse whatis $module_1" "OK" "$ts_csh_1" -testouterr_cmd_re "csh" "--terse whatis $module_2" "OK" "$ts_csh_2" -testouterr_cmd_re "csh" "--terse whatis $module_3" "OK" "$ts_csh_3" +testouterr_cmd_re "csh" "whatis $module_1" "OK" "$ts_csh_1" +testouterr_cmd_re "csh" "whatis $module_2" "OK" "$ts_csh_2" +testouterr_cmd_re "csh" "whatis $module_3" "OK" "$ts_csh_3" skip_if_quick_mode -testouterr_cmd_re "csh" "--terse whatis $module_4" "OK" "$ts_csh_4" -testouterr_cmd_re "csh" "--terse whatis $module_5" "OK" "$ts_csh_5" +testouterr_cmd_re "csh" "whatis $module_4" "OK" "$ts_csh_4" +testouterr_cmd_re "csh" "whatis $module_5" "OK" "$ts_csh_5" +testouterr_cmd_re "csh" "whatis $module_5 $module_2" "OK" "$ts_csh_5\n$whatis_2: Testsuite-Modulefile" # command nickname tests -testouterr_cmd_re "csh" "--terse wh $module_5" "OK" "$ts_csh_5" +testouterr_cmd_re "csh" "wh $module_5" "OK" "$ts_csh_5" + +set module_8 "verssort/1.8-2015-12-01" +set text_pad_8 [string repeat { } 25] + +# whatis text is wrapped to terminal width, module name longer than its column +# shifts text start column +testouterr_cmd_re "csh" "-w 40 whatis $module_5" "OK" "$header\n$whatis_5: Testsuite Whatis\n${text_pad}Modulefile\n${text_pad}Second line of\n${text_pad}whatis tokens" +testouterr_cmd_re "csh" "whatis $module_8" "OK" "$header\n$module_8: module version sort test" +testouterr_cmd_re "csh" "-w 40 whatis $module_8" "OK" "$header\n$module_8: module version\n${text_pad_8}sort test" +# word longer than remaining width is kept whole on its own line +testouterr_cmd_re "csh" "-w 30 whatis $module_8" "OK" "$header\n$module_8: module\n${text_pad_8}version\n${text_pad_8}sort\n${text_pad_8}test" +testouterr_cmd_re "csh" "-w 10 whatis $module_8" "OK" "$header\n$module_8: module\n${text_pad_8}version\n${text_pad_8}sort\n${text_pad_8}test" +testouterr_cmd_re "csh" "-w 1 whatis $module_8" "OK" "$header\n$module_8: module\n${text_pad_8}version\n${text_pad_8}sort\n${text_pad_8}test" + +# terse output mode: one line per whatis entry, each prefixed by module name +# without padding nor wrapping, modulepath reported as header line +set header_t "$modpathre:" +set ts_csh_5t "$header_t\n$module_5: Testsuite Whatis Modulefile\n$module_5: Second line of whatis tokens" +testouterr_cmd_re "csh" "--terse whatis $module_5" "OK" "$ts_csh_5t" +testouterr_cmd_re "csh" "-t whatis $module_5 $module_2" "OK" "$ts_csh_5t\n$module_2: Testsuite-Modulefile" +testouterr_cmd_re "csh" "whatis -t $module_8" "OK" "$header_t\n$module_8: module version sort test" +testouterr_cmd_re "csh" "-w 30 -t whatis $module_8" "OK" "$header_t\n$module_8: module version sort test" +testouterr_cmd_re "csh" "-t whatis $module_1" "OK" "$ts_csh_1" + +# json output is not affected by terse mode +set ts_json_5 "{\"$modpathre\": {\n\"$module_5\": { \"name\": \"$module_5\", \"whatis\": \\\[ \"Testsuite Whatis Modulefile\", \"Second line of whatis tokens\" \\\]}\n}}" +testouterr_cmd_re "csh" "-j whatis $module_5" "OK" "$ts_json_5" +testouterr_cmd_re "csh" "-t -j whatis $module_5" "OK" "$ts_json_5" # setup MODULEPATH with a trailing slash and an empty dir element setenv_path_var MODULEPATH {} "$modpath/" -testouterr_cmd_re "csh" "--terse whatis $module_1" "OK" "$ts_csh_1" +testouterr_cmd_re "csh" "whatis $module_1" "OK" "$ts_csh_1" # restore MODULEPATH setenv_path_var MODULEPATH $modpath @@ -115,7 +147,7 @@ setenv_loaded_module [list foo bar] "/path/to/foo" set ts_csh_8 "$err_loinconsist LOADEDMODULES=foo bar _LMFILES_=/path/to/foo" -testouterr_cmd_re "csh" "--terse whatis $module_5" ERR $ts_csh_8 +testouterr_cmd_re "csh" "whatis $module_5" ERR $ts_csh_8 # # Cleanup diff --git a/testsuite/modules.70-maint/060-apropos.exp b/testsuite/modules.70-maint/060-apropos.exp index 320529c25..ecf33a27f 100644 --- a/testsuite/modules.70-maint/060-apropos.exp +++ b/testsuite/modules.70-maint/060-apropos.exp @@ -35,7 +35,10 @@ set header "$modlin $modpathre $modlin" set warn_opt "$warn_msgs: Unsupported option " set ts_1 " whatis/lines: Testsuite Whatis Modulefile" -set ts_1a " whatis/lines: Second line of whatis tokens" +# module name is reported once, next whatis lines are aligned under text of +# first line +set text_pad [string repeat { } 22] +set ts_1a "${text_pad}Second line of whatis tokens" # different behavior than C-version: on Tcl-version multiple arguments provided on a single # module-whatis call produce a single module-whatis line, not one line per passed argument set ts_2 " whatis/multiple: Testsuite Whatis Modulefile" @@ -69,6 +72,29 @@ testouterr_cmd_re "csh" "apropos token" "ERR" "$header\n$ts_1\n$ts_1a" testouterr_cmd_re "csh" "keyword token" "ERR" "$header\n$ts_1\n$ts_1a" testouterr_cmd_re "csh" "search token" "ERR" "$header\n$ts_1\n$ts_1a" +# terse output mode: one line per whatis entry, each prefixed by module name +# without padding nor wrapping, modulepath reported as header line +set header_t "$modpathre:" +set ts_1t "whatis/lines: Testsuite Whatis Modulefile\nwhatis/lines: Second line of whatis tokens" +testouterr_cmd_re "csh" "-t search token" "ERR" "$header_t\n$ts_1t" +testouterr_cmd_re "csh" "search -t token" "ERR" "$header_t\n$ts_1t" +testouterr_cmd_re "csh" "-w 45 -t search Whatis" "ERR" "$header_t\n$ts_1t\nwhatis/multiple: Testsuite Whatis Modulefile\nwhatis/string: Testsuite Whatis Modulefile" + +# text is wrapped to terminal width +testouterr_cmd_re "csh" "-w 45 search Whatis" "ERR" "$header\n whatis/lines: Testsuite Whatis\n${text_pad}Modulefile\n${text_pad}Second line of whatis\n${text_pad}tokens\n whatis/multiple: Testsuite Whatis\n${text_pad}Modulefile\n whatis/string: Testsuite Whatis\n${text_pad}Modulefile" + +# highlighted search string does not count in wrapped line length +setenv_var MODULES_COLOR always +setenv_var MODULES_COLORS {hi=1:mp=1;94} +set hi [sgr 1] +set nohi [sgr 22] +set header_sgr "$modlin [sgr {1;94}]$modpathre[sgr 0] $modlin" +testouterr_cmd_re "csh" "-w 49 search token" "ERR" "$header_sgr\n whatis/lines: Testsuite Whatis Modulefile\n${text_pad}Second line of whatis\n${text_pad}${hi}token${nohi}s" +testouterr_cmd_re "csh" "-w 50 search token" "ERR" "$header_sgr\n whatis/lines: Testsuite Whatis Modulefile\n${text_pad}Second line of whatis ${hi}token${nohi}s" +testouterr_cmd_re "csh" "-w 49 -t search token" "ERR" "[sgr {1;94}]$modpathre[sgr 0]:\nwhatis/lines: Testsuite Whatis Modulefile\nwhatis/lines: Second line of whatis ${hi}token${nohi}s" +setenv_var MODULES_COLOR never +unsetenv_var MODULES_COLORS + # # test with erroneous modulefile # should not produce error message diff --git a/testsuite/modules.70-maint/240-icase.exp b/testsuite/modules.70-maint/240-icase.exp index 5b8b5fa27..203c63166 100644 --- a/testsuite/modules.70-maint/240-icase.exp +++ b/testsuite/modules.70-maint/240-icase.exp @@ -161,7 +161,7 @@ testouterr_cmd sh {avail -i -t nOcAsE/vi} OK "$mp:\nnocase/virt" testouterr_cmd sh {avail -i -t NOCASE/Dee} OK "$mp:\nnocase/deep/(dirsym)\nnocase/deep/2\nnocase/deep/3" testouterr_cmd sh {avail -i -t NOcaSe2} OK "$mp:\nnocase2" testouterr_cmd sh {avail -i -t NOcase3} OK "$mp:\nnocase3(@)" -testouterr_cmd_re sh {whatis -i -t noCASE/aL*} OK "$modlin $mpre $modlin\n\\s+nocase/1: nocase/1" +testouterr_cmd_re sh {whatis -i -t noCASE/aL*} OK "$mpre:\nnocase/1: nocase/1" testouterr_cmd sh {paths -i noCASE/VE*} [list [list text $mp/nocase/1]] {} testouterr_cmd sh {whatis -i -t noCASE/aL} ERR $err_path'noCASE/aL' testouterr_cmd sh {paths -i noCASE/VE} OK {} @@ -174,7 +174,7 @@ testouterr_cmd_re sh {whatis -i noCASE/.hiDden} OK "$modlin $mpre $modlin\n\\s+n # add a bit of wildcard characters in specification testouterr_cmd sh {avail -i -t nOcAsE/vi?} OK "$mp:\nnocase/virt" -testouterr_cmd_re sh {whatis -i -t noCASE/a*L*} OK "$modlin $mpre $modlin\n\\s+nocase/1: nocase/1" +testouterr_cmd_re sh {whatis -i -t noCASE/a*L*} OK "$mpre:\nnocase/1: nocase/1" testouterr_cmd sh {whatis -i -t noCASE/a*L} ERR $err_path'noCASE/a*L' testouterr_cmd sh {paths -i noCASE/V*E?} OK {} testouterr_cmd sh {paths -i noCASE/V*E*} [list [list text $mp/nocase/1]] {}