mirror of
https://github.com/zsh-users/zsh
synced 2024-10-04 15:09:11 +00:00
28065 plus unposted zsh.mdd:
add cdr and related functions and docs
This commit is contained in:
parent
924f40b772
commit
5da6530d83
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,12 @@
|
|||
2010-07-09 Peter Stephenson <pws@csr.com>
|
||||
|
||||
* 28065: Doc/Zsh/contrib.yo, Functions/Chpwd/.distfiles,
|
||||
Functions/Chpwd/cdr, Functions/Chpwd/_cdr,
|
||||
Functions/Chpwd/chpwd_recent_add,
|
||||
Functions/Chpwd/chpwd_recent_dirs,
|
||||
Functions/Chpwd/chpwd_recent_filehandler, plus Src/zsh.mdd
|
||||
(not posted): add cdr function, tools, and documentation.
|
||||
|
||||
2010-06-30 Clint Adams <clint@zsh.org>
|
||||
|
||||
* 27998, 28061, 28062: Functions/Newuser/zsh-newuser-install:
|
||||
|
@ -13343,5 +13352,5 @@
|
|||
|
||||
*****************************************************
|
||||
* This is used by the shell to define $ZSH_PATCHLEVEL
|
||||
* $Revision: 1.5019 $
|
||||
* $Revision: 1.5020 $
|
||||
*****************************************************
|
||||
|
|
|
@ -11,6 +11,7 @@ such as shell functions, look for comments in the function source files.
|
|||
|
||||
startmenu()
|
||||
menu(Utilities)
|
||||
menu(Recent Directories)
|
||||
menu(Version Control Information)
|
||||
menu(Prompt Themes)
|
||||
menu(ZLE Functions)
|
||||
|
@ -21,7 +22,7 @@ menu(User Configuration Functions)
|
|||
menu(Other Functions)
|
||||
endmenu()
|
||||
|
||||
texinode(Utilities)(Version Control Information)()(User Contributions)
|
||||
texinode(Utilities)(Recent Directories)()(User Contributions)
|
||||
sect(Utilities)
|
||||
|
||||
subsect(Accessing On-Line Help)
|
||||
|
@ -317,7 +318,270 @@ functions to be executed.
|
|||
)
|
||||
enditem()
|
||||
|
||||
texinode(Version Control Information)(Prompt Themes)(Utilities)(User Contributions)
|
||||
texinode(Recent Directories)(Version Control Information)(Utilities)(User
|
||||
Contributions)
|
||||
cindex(recent directories, maintaining list of)
|
||||
cindex(directories, maintaining list of recent)
|
||||
findex(cdr)
|
||||
findex(_cdr)
|
||||
findex(chpwd_recent_add)
|
||||
findex(chpwd_recent_dirs)
|
||||
findex(chpwd_recent_filehandler)
|
||||
sect(Remembering Recent Directories)
|
||||
|
||||
The function tt(cdr) allows you to change the working directory to a
|
||||
previous working directory from a list maintained automatically. It is
|
||||
similar in concept to the directory stack controlled by the tt(pushd),
|
||||
tt(popd) and tt(dirs) builtins, but is more configurable, and as it stores
|
||||
all entries in files it is maintained across sessions and (by default)
|
||||
between terminal emulators in the current session. (The tt(pushd)
|
||||
directory stack is not actually modified or used by tt(cdr) unless you
|
||||
configure it to do so as described in the configuration section below.)
|
||||
|
||||
subsect(Installation)
|
||||
|
||||
The system works by means of a hook function that is called every time the
|
||||
directory changes. To install the system, autoload the required functions
|
||||
and use the tt(add-zsh-hook) function described above:
|
||||
|
||||
example(autoload -Uz chpwd_recent_dirs cdr add-zsh-hook
|
||||
add-zsh-hook chpwd chpwd_recent_dirs)
|
||||
|
||||
Now every time you change directly interactively, no matter which
|
||||
command you use, the directory to which you change will be remembered
|
||||
in most-recent-first order.
|
||||
|
||||
subsect(Use)
|
||||
|
||||
All direct user interaction is via the tt(cdr) function.
|
||||
|
||||
The argument to cdr is a number var(N) corresponding to the var(N)th most
|
||||
recently changed-to directory. 1 is the immediately preceeding directory;
|
||||
the current directory is remembered but is not offered as a destination.
|
||||
Note that if you have multiple windows open 1 may refer to a directory
|
||||
changed to in another window; you can avoid this by having per-terminal
|
||||
files for storing directory as described for the
|
||||
tt(recent-dirs-file) style below.
|
||||
|
||||
If you set the tt(recent-dirs-default) style described below tt(cdr)
|
||||
will behave the same as tt(cd) if given a non-numeric argument, or more
|
||||
than one argument. The recent directory list is updated just the same
|
||||
however you change directory.
|
||||
|
||||
If the argument is omitted, 1 is assumed. This is similar to tt(pushd)'s
|
||||
behaviour of swapping the two most recent directories on the stack.
|
||||
|
||||
Completion for the argument to tt(cdr) is available if compinit has been
|
||||
run; menu selection is recommended, using:
|
||||
|
||||
example(zstyle ':completion:*:*:cdr:*:*' menu selection)
|
||||
|
||||
to allow you to cycle through recent directories; the order is preserved,
|
||||
so the first choice is the most recent directory before the current one.
|
||||
The verbose style is also recommended to ensure the directory is shown; this
|
||||
style is on by default so no action is required unless you have changed it.
|
||||
|
||||
subsect(Options)
|
||||
|
||||
The behaviour of tt(cdr) may be modified by the following options.
|
||||
|
||||
startitem()
|
||||
item(tt(-l))(
|
||||
lists the numbers and the corresponding directories in
|
||||
abbreviated form (i.e. with tt(~) substitution reapplied), one per line.
|
||||
The directories here are not quoted (this would only be an issue if a
|
||||
directory name contained a newline). This is used by the completion
|
||||
system.
|
||||
)
|
||||
item(tt(-r))(
|
||||
sets the variable tt(reply) to the current set of directories. Nothing
|
||||
is printed and the directory is not changed.
|
||||
)
|
||||
item(tt(-e))(
|
||||
allows you to edit the list of directories, one per line. The
|
||||
list can be edited to any extent you like; no sanity checking is
|
||||
performed. Completion is available. No quoting is necessary (except for
|
||||
newlines, where I have in any case no sympathy); directories are in
|
||||
unabbreviated from and contain an absolute path, i.e. they start with tt(/).
|
||||
Usually the first entry should be left as the current directory.
|
||||
)
|
||||
enditem()
|
||||
|
||||
subsect(Configuration)
|
||||
|
||||
Configuration is by mean of the styles mechanism that should be familiar
|
||||
from completion; if not, see the description of the tt(zstyle) command in
|
||||
ifzman(see zmanref(zshmodules))\
|
||||
ifnzman(noderef(The zsh/zutil Module)). The context for setting styles
|
||||
should be tt(':chpwd:*') in case the meaning of the context is extended in
|
||||
future, for example:
|
||||
|
||||
example(zstyle ':chpwd:*' recent-dirs-max 0)
|
||||
|
||||
sets the value of the tt(recent-dirs-max) style to 0. In practice the
|
||||
style name is specific enough that a context of '*' should be fine.
|
||||
|
||||
An exception is tt(recent-dirs-insert), which is used exclusively by the
|
||||
completion system and so has the usual completion system context
|
||||
(tt(':completion:*') if nothing more specific is needed), though again
|
||||
tt('*') should be fine in practice.
|
||||
|
||||
startitem()
|
||||
item(tt(recent-dirs-default))(
|
||||
If true, and the command is expecting a recent directory index, and
|
||||
either there is more than one argument or the argument is not an
|
||||
integer, then fall through to "cd". This allows the lazy to use only
|
||||
one command for directory changing. Completion recognises this, too;
|
||||
see recent-dirs-insert for how to control completion when this option
|
||||
is in use.
|
||||
)
|
||||
item(tt(recent-dirs-file))(
|
||||
The file where the list of directories is saved. The default
|
||||
is tt(${ZDOTDIR:-$HOME}/.chpwd-recent-dirs), i.e. this is in your
|
||||
home directory unless you have set the variable tt(ZDOTDIR) to point
|
||||
somewhere else. Directory names are saved in tt($')var(...)tt(') quoted
|
||||
form, so each line in the file can be supplied directly to the shell as an
|
||||
argument.
|
||||
|
||||
The value of this style may be an array. In this case, the first
|
||||
file in the list will always be used for saving directories while any
|
||||
other files are left untouched. When reading the recent directory
|
||||
list, if there are fewer than the maximum number of entries in the
|
||||
first file, the contents of later files in the array will be appended
|
||||
with duplicates removed from the list shown. The contents of the two
|
||||
files are not sorted together, i.e. all the entries in the first file
|
||||
are shown first. The special value tt(+) can appear in the list to
|
||||
indicate the default file should be read at that point. This allows
|
||||
effects like the following:
|
||||
|
||||
example(zstyle recent-dirs-file ':chpwd:*' \
|
||||
~/.chpwd-recent-dirs-${TTY##*/} +)
|
||||
|
||||
Recent directories are read from a file numbered according to
|
||||
the terminal. If there are insufficient entries the list
|
||||
is supplemented from the default file.
|
||||
)
|
||||
item(tt(recent-dirs-insert))(
|
||||
Used by completion. If tt(recent-dirs-default) is true, then setting
|
||||
this to tt(true) causes the actual directory, rather than its index, to
|
||||
be inserted on the command line; this has the same effect as using
|
||||
the corresponding index, but makes the history clearer and the line
|
||||
easier to edit. With this setting, if part of an argument was
|
||||
already typed, normal directory completion rather than recent
|
||||
directory completion is done; this is because recent directory
|
||||
completion is expected to be done by cycling through entries menu
|
||||
fashion.
|
||||
|
||||
If the value of the style is tt(always), then only recent directories will
|
||||
be completed; in that case, use the tt(cd) command when you want to
|
||||
complete other directories.
|
||||
|
||||
If the value is tt(fallback), recent directories will be tried first, then
|
||||
normal directory completion is performed if recent directory completion
|
||||
failed to find a match.
|
||||
|
||||
Finally, if the value is tt(both) then both sets of completions are
|
||||
presented; the usual tag mechanism can be used to distinguish results, with
|
||||
recent directories tagged as tt(recent-dirs). Note that the recent
|
||||
directories inserted are abbreviated with directory names where appropriate.
|
||||
)
|
||||
item(tt(recent-dirs-max))(
|
||||
The maximum number of directories to save to the file. If
|
||||
this is zero or negative there is no maximum. The default is 20.
|
||||
Note this includes the current directory, which isn't offered,
|
||||
so the highest number of directories you will be offered
|
||||
is one less than the maximum.
|
||||
)
|
||||
item(tt(recent-dirs-prune))(
|
||||
This style is an array determining what directories should (or should
|
||||
not) be added to the recent list. Elements of the array can include:
|
||||
|
||||
startitem()
|
||||
item(tt(parent))(
|
||||
Prune parents (more accurately, ancestors) from the recent list.
|
||||
If present, changing directly down by any number of directories
|
||||
causes the current directory to be overwritten. For example,
|
||||
changing from ~pws to ~pws/some/other/dir causes ~pws not to be
|
||||
left on the recent directory stack. This only applies to direct
|
||||
changes to descendant diretories; earlier directories on the
|
||||
list are not pruned. For example, changing from ~pws/yet/another
|
||||
to ~pws/some/other/dir does not cause ~pws to be pruned.
|
||||
)
|
||||
item(tt(pattern:var(pattern)))(
|
||||
Gives a zsh pattern for directories that should not be
|
||||
added to the recent list (if not already there). This element
|
||||
can be repeated to add different patterns. For example,
|
||||
tt('pattern:/tmp(|/*)') stops tt(/tmp) or its descendants from being
|
||||
added. The tt(EXTENDED_GLOB) option is always turned on for
|
||||
these patterns.
|
||||
)
|
||||
enditem()
|
||||
)
|
||||
item(tt(recent-dirs-pushd))(
|
||||
If set to true, tt(cdr) will use tt(pushd) instead of tt(cd) to change the
|
||||
directory, so the directory is saved on the directory stack. As the
|
||||
directory stack is completely separate from the list of files saved
|
||||
by the mechanism used in this file there is no obvious reason to do
|
||||
this.
|
||||
)
|
||||
enditem()
|
||||
|
||||
subsect(Use with dynamic directory naming)
|
||||
|
||||
It is possible to refer to recent directories using the dynamic directory
|
||||
name syntax that appeared in zsh version 4.3.7. If you create and
|
||||
autoload a function tt(zsh_directory_name) containing the following code,
|
||||
tt(~[1]) will refer to the most recent directory other than $PWD, and so on.
|
||||
This also includes completion.
|
||||
|
||||
example(if [[ $1 = n ]]; then
|
||||
if [[ $2 = <-> ]]; then
|
||||
# Recent directory
|
||||
typeset -ga reply
|
||||
autoload -Uz cdr
|
||||
cdr -r
|
||||
if [[ -n ${reply[$2]} ]]; then
|
||||
reply=LPAR()${reply[$2]}RPAR()
|
||||
return 0
|
||||
else
|
||||
reply=LPAR()RPAR()
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
elif [[ $1 = c ]]; then
|
||||
if [[ $PREFIX = <-> || -z $PREFIX ]]; then
|
||||
typeset -a keys values
|
||||
values=LPAR()${${(f)"$+LPAR()cdr -l+RPAR()"}/ ##/:}RPAR()
|
||||
keys=LPAR()${values%%:*}RPAR()
|
||||
_describe -t dir-index 'recent directory index' \
|
||||
values keys -V unsorted -S']'
|
||||
return
|
||||
fi
|
||||
fi
|
||||
return 1)
|
||||
|
||||
subsect(Details of directory handling)
|
||||
|
||||
This section is for the curious or confused; most users will not
|
||||
need to know this information.
|
||||
|
||||
Recent directories are saved to a file immediately and hence are
|
||||
preserved across sessions. Note currently no file locking is applied:
|
||||
the list is updated immediately on interactive commands and nowhere else
|
||||
(unlike history), and it is assumed you are only going to change
|
||||
directory in one window at once. This is not safe on shared accounts,
|
||||
but in any case the system has limited utility when someone else is
|
||||
changing to a different set of directories behind your back.
|
||||
|
||||
To make this a little safer, only directory changes instituted from the
|
||||
command line, either directly or indirectly through shell function calls
|
||||
(but not through subshells, evals, traps, completion functions and the
|
||||
like) are saved. Shell functions should use tt(cd -q) or tt(pushd -q) to
|
||||
avoid side effects if the change to the directory is to be invisible at the
|
||||
command line. See the contents of the function tt(chpwd_recent_dirs) for
|
||||
more details.
|
||||
|
||||
texinode(Version Control Information)(Prompt Themes)(Recent Directories)(User Contributions)
|
||||
sect(Gathering information from version control systems)
|
||||
cindex(version control utility)
|
||||
|
||||
|
|
8
Functions/Chpwd/.distfiles
Normal file
8
Functions/Chpwd/.distfiles
Normal file
|
@ -0,0 +1,8 @@
|
|||
DISTFILES_SRC='
|
||||
.distfiles
|
||||
cdr
|
||||
_cdr
|
||||
chpwd_recent_add
|
||||
chpwd_recent_dirs
|
||||
chpwd_recent_filehandler
|
||||
'
|
57
Functions/Chpwd/_cdr
Normal file
57
Functions/Chpwd/_cdr
Normal file
|
@ -0,0 +1,57 @@
|
|||
#compdef cdr
|
||||
|
||||
local expl insert_string
|
||||
integer default insert
|
||||
|
||||
zstyle -t ':chpwd:' recent-dirs-default && default=1
|
||||
if (( default )); then
|
||||
zstyle -s ':completion:${curcontext}' recent-dirs-insert insert_string
|
||||
case $insert_string in
|
||||
(both)
|
||||
insert=4
|
||||
;;
|
||||
|
||||
(fallback)
|
||||
insert=3
|
||||
;;
|
||||
|
||||
(always)
|
||||
insert=2
|
||||
;;
|
||||
|
||||
([tT]*|1|[yY]*)
|
||||
insert=1
|
||||
;;
|
||||
|
||||
(*)
|
||||
insert=0
|
||||
esac
|
||||
fi
|
||||
|
||||
# See if we should fall back to cd completion.
|
||||
if [[ default -ne 0 && insert -lt 2 && \
|
||||
( CURRENT -ne 2 || (-n $words[2] && $words[2] != <->) ) ]]; then
|
||||
$_comps[cd] "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
local -a values keys
|
||||
|
||||
if (( insert )); then
|
||||
# insert the actual directory, not the number
|
||||
values=(${${(f)"$(cdr -l)"}##<-> ##})
|
||||
# Suppress the usual space suffix, since there's no further argument
|
||||
# and it's useful to be able to edit the directory e.g. add /more/stuff.
|
||||
if _wanted -V recent-dirs expl 'recent directory' compadd -S '' -Q -a values
|
||||
then
|
||||
(( insert == 4 )) || return 0
|
||||
fi
|
||||
|
||||
(( insert >= 3 )) || return
|
||||
$_comps[cd] "$@"
|
||||
else
|
||||
values=(${${(f)"$(cdr -l)"}/ ##/:})
|
||||
keys=(${values%%:*})
|
||||
|
||||
_describe -t dir-index 'recent directory index' values keys -V unsorted
|
||||
fi
|
311
Functions/Chpwd/cdr
Normal file
311
Functions/Chpwd/cdr
Normal file
|
@ -0,0 +1,311 @@
|
|||
# Description
|
||||
# ===========
|
||||
#
|
||||
# Change to a recently used directory recorded in a file so that the
|
||||
# recent file list persists across sessions.
|
||||
#
|
||||
# To use this system,
|
||||
#
|
||||
# autoload -Uz chpwd_recent_dirs cdr add-zsh-hook
|
||||
# add-zsh-hook chpwd chpwd_recent_dirs
|
||||
#
|
||||
# (add-zsh-hook appeared in zsh version 4.3.4.) This ensures that all
|
||||
# directories you change to interactively are registered. The
|
||||
# chpwd_recent_dirs function does some guesswork to see if you are "really"
|
||||
# changing directory permanently, see below.
|
||||
#
|
||||
# The argument to cdr is a number corresponding to the Nth most recently
|
||||
# changed-to directory starting at 1 for the immediately preceeding
|
||||
# directory (the current directory is remembered but is not offered as a
|
||||
# destination). You can use directory arguments if you set the
|
||||
# recent-dirs-default style, see below; however, it should be noted
|
||||
# that if you do you gain nothing over using cd directly (the recent
|
||||
# directory list is updated in either case).
|
||||
#
|
||||
# If the argument is omitted, 1 is assumed.
|
||||
#
|
||||
# Completion is available if compinit has been run; menu selection is
|
||||
# recommended, using
|
||||
#
|
||||
# zstyle ':completion:*:*:cdr:*:*' menu selection
|
||||
#
|
||||
# and also the verbose style to ensure the directory is shown (this
|
||||
# is on by default).
|
||||
#
|
||||
# Options
|
||||
# =======
|
||||
#
|
||||
# "cdr -l" lists the numbers and the corresponding directories in
|
||||
# abbreviated form (i.e. with "~" substitution reapplied), one per line.
|
||||
# The directories here are not quoted (this would only be an issue if a
|
||||
# directory name contained a newline). This is used by the completion
|
||||
# system.
|
||||
#
|
||||
# "cdr -r" sets the parameter "reply" to the current set of directories.
|
||||
#
|
||||
# "cdr -e" allows you to edit the list of directories, one per line. The
|
||||
# list can be edited to any extent you like; no sanity checking is
|
||||
# performed. Completion is available. No quoting is necessary (except for
|
||||
# newlines, where I have in any case no sympathy); directories are in
|
||||
# unabbreviated from and contain an absolute path, i.e. they start with /
|
||||
# (and only /). Usually the first entry should be left as the current
|
||||
# directory.
|
||||
#
|
||||
# Details of directory handling
|
||||
# =============================
|
||||
#
|
||||
# Recent directories are saved to a file immediately and hence are
|
||||
# preserved across sessions. Note currently no file locking is applied:
|
||||
# the list is updated immediately on interactive commands and nowhere else
|
||||
# (unlike history), and it is assumed you are only going to change
|
||||
# directory in one window at once. This is not safe on shared accounts,
|
||||
# but in any case the system has limited utility when someone else is
|
||||
# changing to a different set of directories behind your back.
|
||||
#
|
||||
# To make this a little safer, only directory changes instituted from the
|
||||
# command line, either directly or indirectly through shell function calls
|
||||
# (but not through subshells, evals, traps, completion functions and the
|
||||
# like) are saved. This works best in versions of the shell from 4.3.11
|
||||
# which has facilities to check the evaluation context. Shell functions
|
||||
# should use cd -q or pushd -q to avoid side effects if the change to the
|
||||
# directory is to be invisible at the command line. See the function
|
||||
# chpwd_recent_dirs for more details.
|
||||
#
|
||||
# Styles
|
||||
# ======
|
||||
#
|
||||
# Various styles are available. The context for setting styles should be
|
||||
# ':chpwd:*' in case the meaning of the context is extended in future, for
|
||||
# example:
|
||||
#
|
||||
# zstyle ':chpwd:*' recent-dirs-max 0
|
||||
#
|
||||
# although the style name is specific enough that a context of '*' should
|
||||
# be fine in practice. The only exception is recent-dirs-insert, which is
|
||||
# used exclusively by the completion system and so has the usual completion
|
||||
# system context (':completion:*' if nothing more specific is needed,
|
||||
# though again '*' should be fine in practice).
|
||||
#
|
||||
# recent-dirs-default
|
||||
# If true, and the command is expecting a recent directory index, and
|
||||
# either there is more than one argument or the argument is not an
|
||||
# integer, then fall through to "cd". This allows the lazy to use only
|
||||
# one command for directory changing. Completion recognises this, too;
|
||||
# see recent-dirs-insert for how to control completion when this option
|
||||
# is in use.
|
||||
#
|
||||
# recent-dirs-file
|
||||
# The file where the list of directories is saved. The default
|
||||
# is ${ZDOTDIR:-$HOME}/.chpwd-recent-dirs, i.e. this is in your
|
||||
# home directory unless you have set ZDOTDIR to point somewhere else.
|
||||
# Directory names are saved in $'...' quoted form, so each line
|
||||
# in the file can be supplied directly to the shell as an argument.
|
||||
#
|
||||
# The value of this style may be an array. In this case, the first
|
||||
# file in the list will always be used for saving directories while any
|
||||
# other files are left untouched. When reading the recent directory
|
||||
# list, if there are fewer than the maximum number of entries in the
|
||||
# first file, the contents of later files in the array will be appended
|
||||
# with duplicates removed from the list shown. The contents of the two
|
||||
# files are not sorted together, i.e. all the entries in the first file
|
||||
# are shown first. The special value "+" can appear in the list to
|
||||
# indicate the default file should be read at that point. This allows
|
||||
# effects like the following:
|
||||
#
|
||||
# zstyle recent-dirs-file ':chpwd:*' ~/.chpwd-recent-dirs-${TTY##*/} +
|
||||
#
|
||||
# Recent directories are read from a file numbered according to
|
||||
# the terminal. If there are insufficient entries the list
|
||||
# is supplemented from the default file.
|
||||
#
|
||||
# recent-dirs-insert
|
||||
# Used by completion. If recent-dirs-default is true, then setting
|
||||
# this to true causes the actual directory, rather than its index, to
|
||||
# be inserted on the command line; this has the same effect as using
|
||||
# the corresponding index, but makes the history clearer and the line
|
||||
# easier to edit. With this setting, if part of an argument was
|
||||
# already typed, normal directory completion rather than recent
|
||||
# directory completion is done; this is because recent directory
|
||||
# completion is expected to be done by cycling through entries menu
|
||||
# fashion. However, if the value of the style is "always", then only
|
||||
# recent directories will be completed; in that case, use the cd
|
||||
# command when you want to complete other directories. If the value is
|
||||
# "fallback", recent directories will be tried first, then normal
|
||||
# directory completion is performed if recent directory completion
|
||||
# failed to find a match. Finally, if the value is "both" then both
|
||||
# sets of completions are presented; the usual tag mechanism can be
|
||||
# used to distinguish results, with recent directories tagged as
|
||||
# "recent-dirs". Note that the recent directories inserted are
|
||||
# abbreviated with directory names where appropriate.
|
||||
#
|
||||
# recent-dirs-max
|
||||
# The maximum number of directories to save to the file. If
|
||||
# this is zero or negative there is no maximum. The default is 20.
|
||||
# Note this includes the current directory, which isn't offered,
|
||||
# so the highest number of directories you will be offered
|
||||
# is one less than the maximum.
|
||||
#
|
||||
# recent-dirs-prune
|
||||
# This style is an array determining what directories should (or should
|
||||
# not) be added to the recent list. Elements of the array can include:
|
||||
# parent
|
||||
# Prune parents (more accurately, ancestors) from the recent list.
|
||||
# If present, changing directly down by any number of directories
|
||||
# causes the current directory to be overwritten. For example,
|
||||
# changing from ~pws to ~pws/some/other/dir causes ~pws not to be
|
||||
# left on the recent directory stack. This only applies to direct
|
||||
# changes to descendant diretories; earlier directories on the
|
||||
# list are not pruned. For example, changing from ~pws/yet/another
|
||||
# to ~pws/some/other/dir does not cause ~pws to be pruned.
|
||||
# pattern:<pattern>
|
||||
# Gives a zsh pattern for directories that should not be
|
||||
# added to the recent list (if not already there). This element
|
||||
# can be repeated to add different patterns. For example,
|
||||
# 'pattern:/tmp(|/*)' stops /tmp or its descendants from being
|
||||
# added. The EXTENDED_GLOB option is always turned on for
|
||||
# these patterns.
|
||||
#
|
||||
# recent-dirs-pushd
|
||||
# If set to true, cdr will use pushd instead of cd to change the
|
||||
# directory, so the directory is saved on the directory stack. As the
|
||||
# directory stack is completely separate from the list of files saved
|
||||
# by the mechanism used in this file there is no obvious reason to do
|
||||
# this.
|
||||
#
|
||||
# Use with dynamic directory naming
|
||||
# =================================
|
||||
#
|
||||
# It is possible to refer to recent directories using the dynamic directory
|
||||
# name syntax that appeared in zsh version 4.3.7. If you create and
|
||||
# autoload a function zsh_directory_name containing the following code,
|
||||
# ~[1] will refer to the most recent directory other than $PWD, and so on.
|
||||
# This also includes completion (version 4.3.11 is required for this to
|
||||
# work; previous versions needed the file _dynamic_directory_name to
|
||||
# be overloaded).
|
||||
#
|
||||
# if [[ $1 = n ]]; then
|
||||
# if [[ $2 = <-> ]]; then
|
||||
# # Recent directory
|
||||
# typeset -ga reply
|
||||
# autoload -Uz cdr
|
||||
# cdr -r
|
||||
# if [[ -n ${reply[$2]} ]]; then
|
||||
# reply=(${reply[$2]})
|
||||
# return 0
|
||||
# else
|
||||
# reply=()
|
||||
# return 1
|
||||
# fi
|
||||
# fi
|
||||
# elif [[ $1 = c ]]; then
|
||||
# if [[ $PREFIX = <-> || -z $PREFIX ]]; then
|
||||
# typeset -a keys values
|
||||
#
|
||||
# values=(${${(f)"$(cdr -l)"}/ ##/:})
|
||||
# keys=(${values%%:*})
|
||||
#
|
||||
# _describe -t dir-index 'recent directory index' \
|
||||
# values keys -V unsorted -S']'
|
||||
# return
|
||||
# fi
|
||||
# fi
|
||||
# return 1
|
||||
|
||||
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
autoload -Uz chpwd_recent_filehandler chpwd_recent_add
|
||||
|
||||
integer list set_reply i bad edit
|
||||
local opt dir
|
||||
local -aU dirs
|
||||
|
||||
while getopts "elr" opt; do
|
||||
case $opt in
|
||||
(e)
|
||||
edit=1
|
||||
;;
|
||||
|
||||
(l)
|
||||
list=1
|
||||
;;
|
||||
|
||||
(r)
|
||||
set_reply=1
|
||||
;;
|
||||
|
||||
(*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $(( OPTIND - 1 ))
|
||||
|
||||
if (( set_reply )); then
|
||||
typeset -ga reply
|
||||
else
|
||||
local -a reply
|
||||
fi
|
||||
|
||||
if (( list || set_reply || edit )); then
|
||||
(( $# )) && bad=1
|
||||
else
|
||||
if [[ $#1 -eq 0 ]]; then
|
||||
1=1
|
||||
elif [[ $# -ne 1 || $1 != <-> ]]; then
|
||||
if zstyle -t ':chpwd:' recent-dirs-default; then
|
||||
cd "$@"
|
||||
return
|
||||
else
|
||||
bad=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( bad )); then
|
||||
print "Usage: $0 [-l | -r | <dir-num> ]
|
||||
Use $0 -l or completion to see possible directories."
|
||||
return 1
|
||||
fi
|
||||
|
||||
chpwd_recent_filehandler
|
||||
|
||||
if [[ $PWD != $reply[1] ]]; then
|
||||
# When we first start we don't have the current directory.
|
||||
# Add it now for consistency.
|
||||
chpwd_recent_add $PWD && chpwd_recent_filehandler $reply
|
||||
fi
|
||||
|
||||
if (( edit )); then
|
||||
local compcontext='directories:directory:_path_files -/'
|
||||
IFS='
|
||||
' vared reply || return 1
|
||||
chpwd_recent_filehandler $reply
|
||||
fi
|
||||
|
||||
# Skip current directory if present (may have been pruned).
|
||||
[[ $reply[1] = $PWD ]] && reply=($reply[2,-1])
|
||||
|
||||
if (( list )); then
|
||||
dirs=($reply)
|
||||
for (( i = 1; i <= ${#dirs}; i++ )); do
|
||||
print -n ${(r.5.)i}
|
||||
print -D ${dirs[i]}
|
||||
done
|
||||
return
|
||||
fi
|
||||
|
||||
(( set_reply || edit )) && return
|
||||
|
||||
if (( $1 > ${#reply} )); then
|
||||
print "Not enough directories ($(( ${#dirs} - 1)) possibilities)" >&2
|
||||
return 1
|
||||
fi
|
||||
dir=${reply[$1]}
|
||||
|
||||
if zstyle -t ':chpwd:' recent-dirs-pushd; then
|
||||
pushd -- $dir
|
||||
else
|
||||
cd -- $dir
|
||||
fi
|
24
Functions/Chpwd/chpwd_recent_add
Normal file
24
Functions/Chpwd/chpwd_recent_add
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Helper for chpwd_recent_dirs.
|
||||
# Add a directory to the reply array unless we're skipping it.
|
||||
# If skipping, return non-zero status.
|
||||
|
||||
local pat
|
||||
local add=$1
|
||||
local -a prune patterns
|
||||
|
||||
zstyle -a ':chpwd:' recent-dirs-prune prune
|
||||
if (( ${#prune} )); then
|
||||
patterns=(${${prune:#^pattern:*}##pattern:})
|
||||
fi
|
||||
|
||||
for pat in $patterns; do
|
||||
if [[ $add =~ ${~pat} ]]; then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${prune[(I)parent]} -ne 0 && $add = $reply[1]/* ]]; then
|
||||
# replace
|
||||
reply=($reply[2,-1])
|
||||
fi
|
||||
reply=($add $reply)
|
49
Functions/Chpwd/chpwd_recent_dirs
Normal file
49
Functions/Chpwd/chpwd_recent_dirs
Normal file
|
@ -0,0 +1,49 @@
|
|||
# Save the current directory in the stack of most recently used directories.
|
||||
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
local -aU reply
|
||||
integer changed
|
||||
|
||||
autoload -Uz chpwd_recent_filehandler chpwd_recent_add
|
||||
|
||||
# Don't save if this is not interactive, or is in a subshell.
|
||||
# Don't save if this is not being called directly from the top level
|
||||
# of the shell via a straightforward sequence of shell functions.
|
||||
# So this is called
|
||||
# - on any straightforward cd or pushd (including AUTO_CD)
|
||||
# - any time cd or pushd is called from a function invoked directly
|
||||
# or indirectly from the command line, e.g. if pushd is a function
|
||||
# fixing the order of directories that got broken years ago
|
||||
# but it is not called any time
|
||||
# - the shell is not interactive
|
||||
# - we forked
|
||||
# - we are being eval'd, including for some special purpose such
|
||||
# as a style
|
||||
# - we are not called from the top-level command loop, for example
|
||||
# we are in a completion function (which is called from zle
|
||||
# when the main top-level command interpreter isn't running)
|
||||
# - obviously, when cd -q is in use (that's what the option is for).
|
||||
#
|
||||
# For compatibility with older shells, skip this test if $ZSH_EVAL_CONTEXT
|
||||
# isn't set. This will never be the case inside a shell function when
|
||||
# the variable is implemented.
|
||||
if [[ ! -o interactive || $ZSH_SUBSHELL -ne 0 || \
|
||||
( -n $ZSH_EVAL_CONTEXT && \
|
||||
$ZSH_EVAL_CONTEXT != toplevel(:[a-z]#func|)# ) ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
chpwd_recent_filehandler
|
||||
|
||||
if [[ $reply[1] != $PWD ]]; then
|
||||
if [[ -n $OLDPWD && $reply[1] != $OLDPWD ]]; then
|
||||
# The first time we change directory we probably don't have
|
||||
# the initial directory.
|
||||
chpwd_recent_add $OLDPWD && changed=1
|
||||
fi
|
||||
chpwd_recent_add $PWD && changed=1
|
||||
|
||||
(( changed )) && chpwd_recent_filehandler $reply
|
||||
fi
|
42
Functions/Chpwd/chpwd_recent_filehandler
Normal file
42
Functions/Chpwd/chpwd_recent_filehandler
Normal file
|
@ -0,0 +1,42 @@
|
|||
# With arguments, output those files to the recent directory file.
|
||||
# With no arguments, read in the directories from the file into $reply.
|
||||
#
|
||||
# Handles recent-dirs-file and recent-dirs-max styles.
|
||||
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
integer max
|
||||
local file
|
||||
local -a files
|
||||
local default=${ZDOTDIR:-$HOME}/.chpwd-recent-dirs
|
||||
|
||||
if zstyle -a ':chpwd:' recent-dirs-file files; then
|
||||
files=(${files//(#s)+(#e)/$default})
|
||||
fi
|
||||
if (( ${#files} == 0 )); then
|
||||
files=($default)
|
||||
fi
|
||||
|
||||
zstyle -s ':chpwd:' recent-dirs-max max || max=20
|
||||
|
||||
if (( $# )); then
|
||||
if (( max > 0 && ${#argv} > max )); then
|
||||
argv=(${argv[1,max]})
|
||||
fi
|
||||
# Quote on write.
|
||||
# Use $'...' quoting... this fixes newlines and other nastiness.
|
||||
print -rl ${(qqqq)argv} >${files[1]}
|
||||
else
|
||||
typeset -g reply
|
||||
# Unquote on read.
|
||||
reply=()
|
||||
for file in $files; do
|
||||
[[ -r $file ]] || continue
|
||||
reply+=(${(Q)${(f)"$(<$file)"}})
|
||||
if (( max > 0 && ${#reply} >= max )); then
|
||||
reply=(${reply[1,max]})
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
|
@ -2,7 +2,7 @@ name=zsh/main
|
|||
link=static
|
||||
load=yes
|
||||
# load=static should replace use of alwayslink
|
||||
functions='Functions/Exceptions/* Functions/Misc/* Functions/MIME/* Functions/Prompts/* Functions/VCS_Info/* Functions/VCS_Info/Backends/*'
|
||||
functions='Functions/Chpwd/* Functions/Exceptions/* Functions/Misc/* Functions/MIME/* Functions/Prompts/* Functions/VCS_Info/* Functions/VCS_Info/Backends/*'
|
||||
|
||||
nozshdep=1
|
||||
alwayslink=1
|
||||
|
|
Loading…
Reference in a new issue