1##
2# The "keeper" function suite originally appeared in several zsh-users
3# posts in the fall of 2004.  It was published in summary form in the
4# Shell Corner column on UnixReview.com in January 2005 at the URL
5# <http://www.unixreview.com/documents/s=9513/ur0501a/ur0501a.htm>
6#
7# Article still available on the Wayback Machine:
8# <http://web.archive.org/web/20050207041146/http://www.unixreview.com/documents/s=9513/ur0501a/ur0501a.htm>
9#
10# A few minor edits have been made to those functions for this file.  Key
11# bindings are commented out to avoid clashes with any existing bindings.
12##
13
14declare -a kept
15
16# The "keep" function accepts a set of file patterns as the positional
17# parameters or a series of lines (expected to represent file names) on
18# standard input.  It stores the expansion of those patterns, or the input
19# lines, in the global variable $kept, and then displays the result
20# formatted in columns, similar to an "ls" listing.  Its alias, also named
21# "keep", prevents the file patterns from being expanded when the command
22# line is executed; they're expanded in the assignment to $kept instead,
23# so that the local settings of nonomatch etc. are applied.
24
25function keep {
26    setopt localoptions nomarkdirs nonomatch nocshnullglob nullglob
27    setopt noksharrays noshwordsplit
28    kept=($~*)
29    if [[ ! -t 0 ]]; then
30        local line
31        while read -r line; do
32            kept+=( $line )
33        done
34    fi
35    print -Rc - ${^kept%/}(T)
36}
37alias keep='noglob keep'
38
39# The function "_insert_kept" copies the value of $kept to the cursor
40# position.  If a prefix of a name is immediately to the left of the
41# cursor, then only the subset of $kept that matches that prefix is
42# copied, as is usual for completion.  The examples bind it to two
43# different widgets, "insert-kept-result" and "expand-kept-result".  If
44# invoked via the "expand-kept-result" widget, it replaces a pattern on
45# the command line with the matching words from the $kept array.
46
47_insert_kept() {
48    (( $#kept )) || return 1
49    local action
50    zstyle -s :completion:$curcontext insert-kept action
51    if [[ -n $action ]]
52    then compstate[insert]=$action
53    elif [[ $WIDGET = *expand* ]]
54    then compstate[insert]=all
55    fi
56    if [[ $WIDGET = *expand* ]]
57    then compadd -U ${(M)kept:#${~words[CURRENT]}}
58    else compadd -a kept
59    fi
60}
61
62zle -C insert-kept-result complete-word _generic
63zstyle ':completion:insert-kept-result:*' completer _insert_kept
64# bindkey '^Xk' insert-kept-result
65
66zle -C expand-kept-result complete-word _generic
67zstyle ':completion:expand-kept-result:*' completer _insert_kept
68# bindkey '^XK' expand-kept-result
69
70# The "_expand_word_and_keep" function stores the expansions computed by
71# the "_expand" completer in the global $kept for later retrieval by
72# "_insert_kept".
73
74_expand_word_and_keep() {
75    {
76        function compadd {
77            local -A args
78            zparseopts -E -A args J:
79            if [[ $args[-J] == all-expansions ]]
80            then
81                builtin compadd -A kept "$@"
82                kept=( ${(Q)${(z)kept}} )
83            fi
84            builtin compadd "$@"
85        }
86        _expand_word
87    } always {
88        unfunction compadd
89    }
90}
91
92zle -C _expand_word complete-word _expand_word_and_keep
93
94# This style is required to segregate the all-expansions group for
95# purposes of _expand_word_and_keep.
96zstyle ':completion:expand-word:expand:::all-expansions' group-name ''
97