#!/usr/bin/env zsh ################################################################################ # # This file is autoloaded by .zshrc, and actually loaded when executed # ################################################################################ # # Filename: cd # Description: cd with magic # If trying to cd to a file, cd to files directory instead # # Authors: Dennis Eriksen <d@ennis.no> # Bug-Reports: Email <idgatt@dnns.no> # License: This file is licensed under the BSD-3-Clause license. # emulate -L zsh # Idea from from https://github.com/mika/zsh-pony#smart-cd # But this is smarter, since it works more like the builtin. # cd has three "modes" # # cd [-qsLP] [arg] # Change the current directory to arg, or to the value of $HOME if arg is # not specified. If arg is ‘-’, change to the previous directory. # # cd [ -qsLP ] old new # Substitutes the string new for the string old in the name of the current # directory ($PWD), and tries to change to this new directory # # cd [ -qsLP ] {+|-}n # Extracts an entry from the directory stack, and changes to that directory # # This function aims to only work in the first mode. # Regex to check for flags local regex='^-[qsLP]*$' # If at least one argument, and # last argument (${argv[-1]}) is not a flag if (( ARGC )) && [[ ! ${argv[-1]} =~ $regex ]]; then # Count arguments. Start at one because we just checked if the last argument # was a flag. local -i arguments=1 # Check all the other arguments if they're flags. if (( ARGC > 1 )); then for i in {$(( ARGC - 1 ))..1}; do # If argument is not empty, and does not match regex if [[ -n ${argv[-$i]} && ! ${argv[-$i]} =~ $regex ]]; then # Count as argument let arguments+=1 fi done fi # If only one actual argument, and # last argument is not a directory, and # it contains a slash, and # it either exists (as a file) or its base directory is a directory if (( arguments == 1 )) && [[ ! -d ${argv[-1]} ]] && [[ ${argv[-1]} == */* ]] && [[ -e ${argv[-1]} || -d ${argv[-1]:h} ]]; then # If the q-flag was not used [[ ${argv:1:-1} != *q* ]] && print -- "Correcting ${argv[-1]} to ${argv[-1]:h}" # Remove trailing pathname (everything after last /), so we can cd to the # directory of the specified file argv[-1]=${argv[-1]:h} fi fi # Run builtin cd builtin cd $@ # END OF FILE #################################################################