diff --git a/NEWS b/NEWS index c957b824c..b4d6868c8 100644 --- a/NEWS +++ b/NEWS @@ -8,7 +8,13 @@ Any uppercase BUG_* names are modernish shell bug IDs. - Add new 'man' function in src/cmd/ksh93/fun/man. This integrates the --man self-documentation of ksh built-in and external AST commands with your system's 'man' command so you can conveniently use 'man' for all commands, - whether built-in or external. See the file for details. + whether built-in or external. To use this, put the file in a directory in + your $FPATH and then issue 'autoload man' in your .kshrc to override the + system's man(1) command. See the file for details. + +- Add new 'autocd' function in src/cmd/ksh93/fun/autocd. This activates a + feature like 'shopt -s autocd' in bash: type only a directory name to change. + See the file for details. Add this file to a directory in your $FPATH to use. - New feature to make 'set -b'/'set -o notify' more usable. When that option is on (and either the vi or emacs/gmacs line editor is in use), 'Done' and diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile index a4b048985..43b01abff 100644 --- a/src/cmd/ksh93/Mamfile +++ b/src/cmd/ksh93/Mamfile @@ -1441,6 +1441,12 @@ make install exec - then mkdir -p ${INSTALLROOT}/fun exec - fi done ${INSTALLROOT}/fun generated + make ${INSTALLROOT}/fun/autocd + prev ${INSTALLROOT}/fun + make fun/autocd + done fun/autocd + exec - ${STDCMP} 2>/dev/null -s fun/autocd ${INSTALLROOT}/fun/autocd || { ${STDMV} ${INSTALLROOT}/fun/autocd ${INSTALLROOT}/fun/autocd.old 2>/dev/null || true; ${STDCP} fun/autocd ${INSTALLROOT}/fun/autocd && chmod ugo+x ${INSTALLROOT}/fun/autocd ;} + done ${INSTALLROOT}/fun/autocd generated make ${INSTALLROOT}/fun/dirs prev ${INSTALLROOT}/fun make fun/dirs diff --git a/src/cmd/ksh93/fun/autocd b/src/cmd/ksh93/fun/autocd new file mode 100755 index 000000000..219ce99fe --- /dev/null +++ b/src/cmd/ksh93/fun/autocd @@ -0,0 +1,65 @@ +######################################################################## +# # +# This file is part of the ksh 93u+m package # +# Copyright (c) 2021-2022 Contributors to ksh 93u+m # +# # +# and is licensed under the # +# Eclipse Public License, Version 1.0 # +# # +# A copy of the License is available at # +# http://www.eclipse.org/org/documents/epl-v10.html # +# (with md5 checksum b35adb5213ca9657e911e9befb180842) # +# # +# Martijn Dekker # +# # +######################################################################## + +# This is a ksh implementation of an autocd feature like 'shopt -s autocd' +# in bash. Drop this file in a directory in your $FPATH, and type 'autocd' +# to activate. After that, you only need to type the name of an existing +# directory to change to it, without needing to type 'cd' first. +# +# This is implemented using the DEBUG trap. The exit status of an autocd +# is always 2 because this is necessary to stop the directory name from +# being executed as a command (see ksh(1) under Built-in Commands, 'trap'). + +_do_autocd() +{ + # do nothing if called from another function, or shell not interactive, or the + # command is ((arithmetic)), or the command contains blanks but is not quoted + if [[ .sh.level -ne 1 || ! -o interactive || $1 == \(* \ + || ($1 == *[[:blank:]]* && $1 != \'*\' && $1 != \$\'*\') ]] + then return + fi + # if command name is quoted (e.g. directory name containing spaces), unquote it + if [[ $1 == \'*\' || $1 == \$\'*\' ]] + then eval "set -- $1" + fi + # if the result is one word and it's not a command, then autocd + if (($#==1)) && ! command -v "$1" >/dev/null && [[ -d $1 ]] + then printf 'cd -- %q\n' "$1" >&2 + CDPATH= command cd -- "$1" + return 2 # status 2 == do not execute original command + fi +} + +autocd() +{ + if [[ ${1-} == '-d' ]] + then trap - DEBUG + print "autocd deactivated" + else trap '_do_autocd "${.sh.command}"' DEBUG + print "autocd activated -- type a directory path to cd, ~- to cd back" + print "type 'autocd -d' to deactivate" + fi +} + + +# Do a check at autoload time. This depends on a non-buggy DEBUG trap. +# It is horribly broken in every latter-years AT&T version of ksh93. + +if ((.sh.version < 20210220)); then + print "WARNING: this may crash or break ksh ${.sh.version};" >&2 + print " autocd requires ksh 93u+m 2021-02-20 or later" >&2 + sleep 1 +fi