@@ -1182,98 +1182,117 @@ _zsh_highlight_main_highlighter_highlight_path_separators()
11821182# $2 should be non-zero iff we're in command position.
11831183_zsh_highlight_main_highlighter_check_path ()
11841184{
1185- _zsh_highlight_main_highlighter_expand_path " $1 "
1186- local expanded_path=" $REPLY " tmp_path
1187- integer in_command_position=$2
1188-
1189- if [[ $zsyh_user_options [autocd] == on ]]; then
1190- integer autocd=1
1191- else
1192- integer autocd=0
1185+ if (( $+ _zsh_highlight_main__path_cache )) ; then
1186+ local cache_key=$1 $' \0' $2
1187+ if (( has_end && len == end_pos && ! in_alias )) && [[ $WIDGET != zle-line-finish ]]; then
1188+ cache_key+=$' \0'
1189+ fi
1190+ local cache_val=$_zsh_highlight_main__path_cache [$cache_key ]
1191+ if [[ -n $cache_val ]]; then
1192+ REPLY=${cache_val: 1}
1193+ return $cache_val [1]
1194+ fi
11931195 fi
11941196
1195- if (( in_command_position )) ; then
1196- # ### Currently, this value is never returned: either it's overwritten
1197- # ### below, or the return code is non-zero
1198- REPLY=arg0
1199- else
1200- REPLY=path
1201- fi
1197+ {
1198+ _zsh_highlight_main_highlighter_expand_path " $1 "
1199+ local expanded_path=" $REPLY " tmp_path
1200+ integer in_command_position=$2
12021201
1203- if [[ ${1[1]} == ' =' && $1 == ??* && ${1[2]} != $' \x28 ' && $zsyh_user_options [equals] == ' on' && $expanded_path [1] != ' /' ]]; then
1204- REPLY=unknown-token # will error out if executed
1205- return 0
1206- fi
1202+ if [[ $zsyh_user_options [autocd] == on ]]; then
1203+ integer autocd=1
1204+ else
1205+ integer autocd=0
1206+ fi
12071207
1208- [[ -z $expanded_path ]] && return 1
1208+ if (( in_command_position )) ; then
1209+ # ### Currently, this value is never returned: either it's overwritten
1210+ # ### below, or the return code is non-zero
1211+ REPLY=arg0
1212+ else
1213+ REPLY=path
1214+ fi
12091215
1210- # Check if this is a blacklisted path
1211- if [[ $expanded_path [1] == / ]]; then
1212- tmp_path=$expanded_path
1213- else
1214- tmp_path=$PWD /$expanded_path
1215- fi
1216- tmp_path=$tmp_path :a
1216+ if [[ ${1[1]} == ' =' && $1 == ??* && ${1[2]} != $' \x28 ' && $zsyh_user_options [equals] == ' on' && $expanded_path [1] != ' /' ]]; then
1217+ REPLY=unknown-token # will error out if executed
1218+ return 0
1219+ fi
12171220
1218- while [[ $tmp_path != / ]]; do
1219- [[ -n ${(M)ZSH_HIGHLIGHT_DIRS_BLACKLIST:# $tmp_path } ]] && return 1
1220- tmp_path=$tmp_path :h
1221- done
1221+ [[ -z $expanded_path ]] && return 1
12221222
1223- if (( in_command_position )) ; then
1224- if [[ -x $expanded_path ]]; then
1225- if (( autocd )) ; then
1226- if [[ -d $expanded_path ]]; then
1227- REPLY=autodirectory
1228- fi
1229- return 0
1230- elif [[ ! -d $expanded_path ]]; then
1231- # ### This seems unreachable for the current callers
1232- return 0
1233- fi
1234- fi
1235- else
1236- if [[ -L $expanded_path || -e $expanded_path ]]; then
1237- return 0
1223+ # Check if this is a blacklisted path
1224+ if [[ $expanded_path [1] == / ]]; then
1225+ tmp_path=$expanded_path
1226+ else
1227+ tmp_path=$PWD /$expanded_path
12381228 fi
1239- fi
1229+ tmp_path=$tmp_path :a
1230+
1231+ while [[ $tmp_path != / ]]; do
1232+ [[ -n ${(M)ZSH_HIGHLIGHT_DIRS_BLACKLIST:# $tmp_path } ]] && return 1
1233+ tmp_path=$tmp_path :h
1234+ done
12401235
1241- # Search the path in CDPATH
1242- if [[ $expanded_path != /* ]] && (( autocd || ! in_command_position )) ; then
1243- # TODO: When we've dropped support for pre-5.0.6 zsh, use the *(Y1) glob qualifier here.
1244- local cdpath_dir
1245- for cdpath_dir in $cdpath ; do
1246- if [[ -d " $cdpath_dir /$expanded_path " && -x " $cdpath_dir /$expanded_path " ]]; then
1247- if (( in_command_position && autocd )) ; then
1248- REPLY=autodirectory
1236+ if (( in_command_position )) ; then
1237+ if [[ -x $expanded_path ]]; then
1238+ if (( autocd )) ; then
1239+ if [[ -d $expanded_path ]]; then
1240+ REPLY=autodirectory
1241+ fi
1242+ return 0
1243+ elif [[ ! -d $expanded_path ]]; then
1244+ # ### This seems unreachable for the current callers
1245+ return 0
12491246 fi
1247+ fi
1248+ else
1249+ if [[ -L $expanded_path || -e $expanded_path ]]; then
12501250 return 0
12511251 fi
1252- done
1253- fi
1252+ fi
12541253
1255- # If dirname($1) doesn't exist, neither does $1.
1256- [[ ! -d ${expanded_path: h} ]] && return 1
1254+ # Search the path in CDPATH
1255+ if [[ $expanded_path != /* ]] && (( autocd || ! in_command_position )) ; then
1256+ # TODO: When we've dropped support for pre-5.0.6 zsh, use the *(Y1) glob qualifier here.
1257+ local cdpath_dir
1258+ for cdpath_dir in $cdpath ; do
1259+ if [[ -d " $cdpath_dir /$expanded_path " && -x " $cdpath_dir /$expanded_path " ]]; then
1260+ if (( in_command_position && autocd )) ; then
1261+ REPLY=autodirectory
1262+ fi
1263+ return 0
1264+ fi
1265+ done
1266+ fi
12571267
1258- # If this word ends the buffer, check if it's the prefix of a valid path.
1259- if (( has_end && (len == end_pos) )) &&
1260- (( ! in_alias )) &&
1261- [[ $WIDGET != zle-line-finish ]]; then
1262- # TODO: When we've dropped support for pre-5.0.6 zsh, use the *(Y1) glob qualifier here.
1263- local -a tmp
1264- if (( in_command_position )) ; then
1265- # We include directories even when autocd is enabled, because those
1266- # directories might contain executable files: e.g., BUFFER="/bi" en route
1267- # to typing "/bin/sh".
1268- tmp=( ${expanded_path} * (N-* ,N-/) )
1269- else
1270- tmp=( ${expanded_path} * (N) )
1268+ # If dirname($1) doesn't exist, neither does $1.
1269+ [[ ! -d ${expanded_path: h} ]] && return 1
1270+
1271+ # If this word ends the buffer, check if it's the prefix of a valid path.
1272+ if (( has_end && (len == end_pos) )) &&
1273+ (( ! in_alias )) &&
1274+ [[ $WIDGET != zle-line-finish ]]; then
1275+ # TODO: When we've dropped support for pre-5.0.6 zsh, use the *(Y1) glob qualifier here.
1276+ local -a tmp
1277+ if (( in_command_position )) ; then
1278+ # We include directories even when autocd is enabled, because those
1279+ # directories might contain executable files: e.g., BUFFER="/bi" en route
1280+ # to typing "/bin/sh".
1281+ tmp=( ${expanded_path} * (N-* ,N-/) )
1282+ else
1283+ tmp=( ${expanded_path} * (N) )
1284+ fi
1285+ (( ${+tmp[1]} )) && REPLY=path_prefix && return 0
12711286 fi
1272- (( ${+tmp[1]} )) && REPLY=path_prefix && return 0
1273- fi
12741287
1275- # It's not a path.
1276- return 1
1288+ # It's not a path.
1289+ return 1
1290+ } always {
1291+ local -i ret=$(( !! $? ))
1292+ if (( $+ _zsh_highlight_main__path_cache )) ; then
1293+ _zsh_highlight_main__path_cache[$cache_key ]=$ret$REPLY
1294+ fi
1295+ }
12771296}
12781297
12791298# Highlight an argument and possibly special chars in quotes starting at $1 in $arg
@@ -1809,15 +1828,16 @@ _zsh_highlight_main__precmd_hook() {
18091828 fi
18101829
18111830 _zsh_highlight_main__command_type_cache=()
1831+ _zsh_highlight_main__path_cache=()
18121832}
18131833
18141834autoload -Uz add-zsh-hook
18151835if add-zsh-hook precmd _zsh_highlight_main__precmd_hook 2> /dev/null; then
1816- # Initialize command type cache
1817- typeset -gA _zsh_highlight_main__command_type_cache
1836+ # Initialize caches
1837+ typeset -gA _zsh_highlight_main__command_type_cache _zsh_highlight_main__path_cache
18181838else
18191839 print -r -- >&2 ' zsh-syntax-highlighting: Failed to load add-zsh-hook. Some speed optimizations will not be used.'
1820- # Make sure the cache is unset
1821- unset _zsh_highlight_main__command_type_cache
1840+ # Make sure the caches are unset
1841+ unset _zsh_highlight_main__command_type_cache _zsh_highlight_main__path_cache
18221842fi
18231843typeset -g a ZSH_HIGHLIGHT_DIRS_BLACKLIST
0 commit comments