Add zsh anything.el plugin
[zsh.git] / .zsh / zaw / zaw.zsh
1 #
2 # zaw - zsh anything.el-like widget
3 #
4 # usage:
5 #
6 # add following line to your .zshrc::
7 #
8 # source /path/to/zaw.zsh
9 #
10 # and type "^X;"
11
12 # to create namespace, use anonymous function
13 function() {
14
15 zmodload zsh/parameter
16 autoload -U is-at-least
17
18 local this_file="${funcsourcetrace[1]%:*}"
19 if is-at-least 4.3.10; then
20 # "A" flag (turn a file name into an absolute path with symlink
21 # resolution) is only available on 4.3.10 and latter
22 local cur_dir="${this_file:A:h}"
23 else
24 local cur_dir="${this_file:h}"
25 fi
26 fpath+=("${cur_dir}/functions")
27
28 autoload -U filter-select
29
30 typeset -g -A zaw_sources
31 zaw_sources=()
32
33 function zaw-register-src() {
34 # register zaw source
35 #
36 # zaw-register-src [-n NAME] SOURCE
37 #
38 # SOURCE is function name that define (overrite) these variables
39 #
40 # $candidates -> array of candidates
41 # $cands_assoc -> assoc array of candidates
42 # $cand_descriptions -> (optional) array of candidates descriptions
43 # $cand_descriptions_assoc -> (optional) assoc array of candidates descriptions
44 # $actions -> list of callback function names that receive selected item
45 # $act_descriptions -> (optional) list of callback function descriptions
46 # $options -> (optional) array of options passed to filter-select
47 #
48 # whether one of candidates or cands-assoc is required
49 local name func widget_name opts OPTARG OPTIND
50
51 while getopts 'n:' opts; do
52 name="${OPTARG}"
53 done
54 if (( OPTIND > 1 )); then
55 shift $(( OPTIND - 1 ))
56 fi
57
58 func="$1"
59
60 if [[ -z "${name}" ]]; then
61 name="${func}"
62 fi
63
64 # TODO: check name duplication
65 zaw_sources+=("${name}" "${func}")
66
67 # define shortcut function
68 widget_name="zaw-${(L)name// /-}"
69 eval "function ${widget_name} { zle zaw ${func} \$@ }"
70 eval "zle -N ${widget_name}"
71 }
72
73
74 function zaw() {
75 local action ret func
76 local -a reply candidates actions act_descriptions options selected cand_descriptions
77 local -A cands_assoc
78
79 if [[ $# == 0 ]]; then
80 if zle zaw-select-src; then
81 func="${reply[2]}"
82 reply=()
83 else
84 return 0
85 fi
86 else
87 func="$1"
88 shift
89 fi
90
91 zle -R "now loading ..."
92
93 # call source function to generate candidates
94 "${func}" "$@"
95
96 ret="$?"
97 if [[ "${ret}" != 0 ]]; then
98 return 1
99 fi
100
101 reply=()
102
103 if (( ${#cand_descriptions} )); then
104 options=("-d" "cand_descriptions" "${(@)options}")
105 fi
106 # TODO: cand_descriptions_assoc
107
108 # call filter-select to allow user select item
109 if (( ${#cands_assoc} )); then
110 filter-select -e select-action -A cands_assoc "${(@)options}"
111 else
112 filter-select -e select-action "${(@)options}" -- "${(@)candidates}"
113 fi
114
115 if [[ $? == 0 ]]; then
116 if (( ${#reply_marked} > 0 )); then
117 selected=("${(@)reply_marked}")
118 else
119 selected=("${reply[2]}")
120 fi
121
122 case "${reply[1]}" in
123 accept-line)
124 action="${actions[1]}"
125 ;;
126 accept-search)
127 action="${actions[2]}"
128 ;;
129 select-action)
130 reply=()
131 filter-select -t "select action for '${(j:', ':)selected}'" -d act_descriptions -- "${(@)actions}"
132 ret=$?
133
134 if [[ $ret == 0 ]]; then
135 action="${reply[2]}"
136 else
137 return 1
138 fi
139 ;;
140 esac
141
142 if [[ -n "${action}" ]]; then
143 "${action}" "${(@)selected}"
144 fi
145 fi
146 }
147
148 zle -N zaw
149
150
151 function zaw-select-src() {
152 local name
153 local -a cands descs
154 cands=()
155 descs=()
156 for name in "${(@ko)zaw_sources}"; do
157 cands+="${zaw_sources[${name}]}"
158 descs+="${name}"
159 done
160
161 filter-select -e select-action -d descs -- "${(@)cands}"
162 }
163
164 zle -N zaw-select-src
165
166
167 function zaw-print-src() {
168 local name func widget_name
169 printf '%-16s %s\n' "source name" "shortcut widget name"
170 print -- '----------------------------------------'
171 for name in "${(@ko)zaw_sources}"; do
172 widget_name="zaw-${(L)name// /-}"
173 printf '%-16s %s\n' "${name}" "${widget_name}"
174 done
175 }
176
177
178 # common callbacks
179 function zaw-callback-execute() {
180 BUFFER="${(j:; :)@}"
181 zle accept-line
182 }
183
184 function zaw-callback-replace-buffer() {
185 LBUFFER="${(j:; :)@}"
186 RBUFFER=""
187 }
188
189 function zaw-callback-append-to-buffer() {
190 LBUFFER="${BUFFER}${(j:; :)@}"
191 }
192
193 function zaw-callback-edit-file() {
194 local -a args
195 args=("${(@q)@}")
196
197 if [ ! ${ZAW_EDITOR} ]; then
198 ZAW_EDITOR=${EDITOR}
199 fi
200
201 BUFFER="${ZAW_EDITOR} ${args}"
202 zle accept-line
203 }
204
205
206 # load zaw sources
207 setopt local_options extended_glob
208 local src_dir="${cur_dir}/sources" f
209 if [[ -d "${src_dir}" ]]; then
210 for f in "${src_dir}"/^*.zwc; do
211 source "${f}"
212 done
213 fi
214
215 # dummy function
216 # only used for exit-zle-widget-name
217 function select-action() {}; zle -N select-action
218 filter-select -i
219 bindkey -M filterselect '^i' select-action
220
221 bindkey '^X;' zaw
222
223 }