1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
1 |
;;; mew-complete.el --- Completion magic for Mew
|
2 |
||
3 |
;; Author: Kazu Yamamoto <Kazu@Mew.org>
|
|
4 |
;; Created: May 30, 1997
|
|
5 |
||
6 |
;;; Code:
|
|
7 |
||
8 |
(require 'mew) |
|
9 |
||
10 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
11 |
;;;
|
|
12 |
;;; Low level functions
|
|
13 |
;;;
|
|
14 |
||
15 |
(defun mew-draft-on-field-p () |
|
16 |
(if (bolp) |
|
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
17 |
(if (bobp) |
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
18 |
t
|
19 |
(save-excursion |
|
20 |
(forward-line -1) |
|
21 |
(if (looking-at ".*,[ \t]?$") nil t))) |
|
22 |
(let ((pos (point))) |
|
23 |
(save-excursion |
|
24 |
(beginning-of-line) |
|
25 |
(if (looking-at mew-lwsp) |
|
26 |
nil
|
|
27 |
(if (search-forward ":" pos t) nil t)))))) |
|
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
28 |
|
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
29 |
(defun mew-draft-on-value-p (switch) |
30 |
(save-excursion |
|
31 |
(beginning-of-line) |
|
32 |
(while (and (< (point-min) (point)) (looking-at mew-lwsp)) |
|
33 |
(forward-line -1)) |
|
34 |
(if (looking-at "\\([^:]*:\\)") |
|
35 |
(mew-field-get-func (match-string 1) switch) |
|
1.1.1
by Tatsuya Kinoshita
Import upstream version 4.2.52 |
36 |
nil))) ;; what a case reaches here? |
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
37 |
|
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
38 |
;;
|
39 |
;; Window management for completion candidates
|
|
40 |
;;
|
|
41 |
||
42 |
(defvar mew-complete-candidates nil) |
|
43 |
||
1.1.10
by Tatsuya Kinoshita
Import upstream version 5.2.51+0.20071129 |
44 |
(defun mew-complete-window-delete (&optional force) |
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
45 |
(when (mew-ainfo-get-win-cfg) |
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
46 |
;; (mew-ainfo-get-win-cfg) remains when the last completion
|
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
47 |
;; finished with multiple candidates.
|
48 |
;; (e.g. foo<RET> when foo and foobar are displayed.)
|
|
49 |
;; In this case, this function is called in another
|
|
50 |
;; completion thread but setting window configuration is not
|
|
51 |
;; desired. If we set window configuration with the old
|
|
52 |
;; (mew-ainfo-get-win-cfg), the cursor jumps to mini buffer.
|
|
53 |
;; This was a stupid bug of Mew. So, let's see if the complete
|
|
54 |
;; buffer is displayed or not.
|
|
1.1.10
by Tatsuya Kinoshita
Import upstream version 5.2.51+0.20071129 |
55 |
(if (or force (get-buffer-window mew-buffer-completions)) |
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
56 |
(set-window-configuration (mew-ainfo-get-win-cfg))) |
57 |
(mew-ainfo-set-win-cfg nil)) |
|
58 |
(mew-remove-buffer mew-buffer-completions) |
|
59 |
(setq mew-complete-candidates nil)) |
|
60 |
||
1.1.10
by Tatsuya Kinoshita
Import upstream version 5.2.51+0.20071129 |
61 |
(defun mew-complete-insert-folder-function (choice buffer mini-p base-size) |
1.1.11
by Tatsuya Kinoshita
Import upstream version 5.2.52 |
62 |
(let ((start (mew-minibuf-point-min)) |
63 |
(proto (substring choice 0 1)) |
|
64 |
(pos (point))) |
|
65 |
(while (not (or (= start (point)) |
|
66 |
(not (char-before)) |
|
67 |
(char-equal (char-before) ?,))) |
|
68 |
(forward-char -1)) |
|
69 |
(if (and (member proto mew-folder-prefixes) |
|
70 |
(looking-at (concat "\\(" |
|
71 |
(regexp-opt mew-config-cases t) |
|
72 |
":\\)"
|
|
73 |
(regexp-quote proto)))) |
|
1.1.10
by Tatsuya Kinoshita
Import upstream version 5.2.51+0.20071129 |
74 |
(progn |
1.1.11
by Tatsuya Kinoshita
Import upstream version 5.2.52 |
75 |
(delete-region (match-end 1) pos) |
76 |
(goto-char (match-end 1))) |
|
77 |
(delete-region (point) pos)) |
|
1.1.10
by Tatsuya Kinoshita
Import upstream version 5.2.51+0.20071129 |
78 |
(insert choice) |
79 |
(remove-text-properties start (point-max) '(mouse-face nil)) |
|
80 |
(mew-complete-window-delete 'force) |
|
81 |
t)) |
|
82 |
||
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
83 |
(defun mew-complete-window-show (all) |
84 |
(unless (mew-ainfo-get-win-cfg) |
|
85 |
(mew-ainfo-set-win-cfg (current-window-configuration))) |
|
86 |
(if (and (get-buffer-window mew-buffer-completions) |
|
87 |
(equal mew-complete-candidates all)) |
|
88 |
(let ((win (get-buffer-window mew-buffer-completions))) |
|
89 |
(save-excursion |
|
90 |
(set-buffer mew-buffer-completions) |
|
91 |
(if (pos-visible-in-window-p (point-max) win) |
|
92 |
(set-window-start win 1) |
|
93 |
(scroll-other-window)))) |
|
94 |
(setq mew-complete-candidates all) |
|
1.1.10
by Tatsuya Kinoshita
Import upstream version 5.2.51+0.20071129 |
95 |
(with-output-to-temp-buffer mew-buffer-completions |
96 |
(when mew-inherit-complete-folder |
|
97 |
(make-local-variable 'choose-completion-string-functions) |
|
98 |
(add-hook 'choose-completion-string-functions |
|
99 |
'mew-complete-insert-folder-function)) |
|
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
100 |
(display-completion-list all)))) |
101 |
||
102 |
(defun mew-complete-backscroll () |
|
103 |
"Backscroll the *Completion* buffer."
|
|
104 |
(interactive) |
|
105 |
(let* ((win (get-buffer-window mew-buffer-completions)) |
|
106 |
(height (and win (window-height win)))) |
|
107 |
(and win (scroll-other-window (- 3 height))))) |
|
108 |
||
109 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
110 |
;;;
|
|
111 |
;;; Completion function for a draft only
|
|
112 |
;;;
|
|
113 |
||
114 |
(defun mew-draft-set-completion-ignore-case (case) |
|
115 |
;; Need to set the global variable "completion-ignore-case",
|
|
116 |
;; since clicking a candidate on a completion buffer checks
|
|
117 |
;; the global variable.
|
|
118 |
;; Yes, this has side-effect.
|
|
119 |
(when (mew-draft-or-header-p) |
|
120 |
(setq completion-ignore-case case))) |
|
121 |
||
122 |
(defun mew-draft-header-comp () |
|
123 |
"Complete and expand address short names.
|
|
124 |
First, a short name is completed. When completed solely or the @ character
|
|
125 |
is inserted before the cursor, the short name is expanded to its address."
|
|
126 |
(interactive) |
|
127 |
(if (mew-draft-on-field-p) |
|
128 |
(mew-complete-field) |
|
129 |
(let ((func (mew-draft-on-value-p mew-field-completion-switch))) |
|
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
130 |
(if func |
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
131 |
(funcall func) |
132 |
(tab-to-tab-stop))))) ;; default keybinding |
|
133 |
||
134 |
(defun mew-complete-field () |
|
135 |
"Field complete function."
|
|
136 |
(interactive) |
|
137 |
(let ((word (mew-delete-key))) ;; capitalized |
|
138 |
(if (null word) |
|
139 |
(mew-complete-window-show mew-fields) |
|
140 |
(mew-complete |
|
141 |
word
|
|
142 |
(mapcar (lambda (x) (list (concat (mew-capitalize x) " "))) mew-fields) |
|
143 |
"field"
|
|
144 |
nil)))) |
|
145 |
||
146 |
(defun mew-complete-newsgroups () |
|
147 |
"Newsgroup complete function."
|
|
148 |
(interactive) |
|
149 |
(let ((word (mew-delete-backward-char))) |
|
150 |
(if (null word) |
|
151 |
(tab-to-tab-stop) |
|
152 |
(mew-complete |
|
153 |
word
|
|
154 |
(mew-nntp-folder-alist2 (mew-tinfo-get-case)) |
|
155 |
"newsgroup"
|
|
156 |
nil)))) |
|
157 |
||
158 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
159 |
;;;
|
|
160 |
;;; Completion function for both a draft and the minibuffer
|
|
161 |
;;;
|
|
162 |
||
163 |
(defun mew-complete-address () |
|
164 |
"Complete and expand an address short name.
|
|
165 |
First alias key is completed. When completed solely or the @ character
|
|
166 |
is inserted before the cursor, the short name is expanded to its address."
|
|
167 |
(interactive) |
|
168 |
(mew-draft-set-completion-ignore-case mew-complete-address-ignore-case) |
|
169 |
(let ((word (mew-delete-backward-char)) |
|
170 |
(completion-ignore-case mew-complete-address-ignore-case)) |
|
171 |
(if (null word) |
|
172 |
(tab-to-tab-stop) |
|
173 |
(if mew-use-full-alias |
|
174 |
(mew-complete |
|
175 |
word mew-addrbook-alist "alias" nil nil nil |
|
176 |
'mew-addrbook-alias-get
|
|
177 |
'mew-addrbook-alias-hit) |
|
178 |
(if (string-match "@." word) |
|
179 |
(insert (or (mew-addrbook-alias-next word mew-addrbook-alist) word)) |
|
180 |
(mew-complete |
|
181 |
word mew-addrbook-alist "alias" ?@ nil nil |
|
182 |
'mew-addrbook-alias-get
|
|
183 |
'mew-addrbook-alias-hit)))))) |
|
184 |
||
185 |
(defun mew-draft-addrbook-expand () |
|
186 |
(interactive) |
|
187 |
(mew-draft-set-completion-ignore-case mew-complete-address-ignore-case) |
|
188 |
(let ((word (mew-delete-backward-char)) |
|
189 |
(completion-ignore-case mew-complete-address-ignore-case) |
|
190 |
try) |
|
191 |
(if (null word) |
|
192 |
(message "No expand key") |
|
193 |
(setq try (try-completion word mew-addrbook-alist)) |
|
194 |
(if (or (eq try t) |
|
195 |
(and (stringp try) (string= word try))) |
|
196 |
(insert (mew-addrbook-alias-get word mew-addrbook-alist)) |
|
197 |
(insert word) |
|
198 |
(message "'%s' cannot be expanded" word))))) |
|
199 |
||
1.2.2
by Tatsuya Kinoshita
Import upstream version 6.0.51 |
200 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
201 |
;;;
|
|
202 |
;;; Completing folders
|
|
203 |
;;;
|
|
204 |
||
205 |
(defmacro mew-complete-proto-folder (sym &rest body) |
|
206 |
;; (declare (indent 1))
|
|
207 |
`(if mew-input-folder-search-direction |
|
208 |
(mew-input-folder-search-complete) |
|
209 |
(mew-draft-set-completion-ignore-case mew-complete-folder-ignore-case) |
|
210 |
(let ((,sym (mew-delete-backward-char)) |
|
211 |
(completion-ignore-case mew-complete-folder-ignore-case) |
|
212 |
(mew-inherit-complete-folder t)) |
|
213 |
,@body))) |
|
214 |
||
215 |
(put 'mew-complete-proto-folder 'lisp-indent-function 1) |
|
216 |
||
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
217 |
(defun mew-complete-local-folder () |
218 |
"Local folder complete function."
|
|
219 |
(interactive) |
|
1.2.2
by Tatsuya Kinoshita
Import upstream version 6.0.51 |
220 |
(mew-complete-proto-folder word |
221 |
(if (null word) |
|
222 |
(mew-complete-window-show (list "+")) |
|
223 |
(if (and (mew-folder-absolutep word) |
|
224 |
(not (mew-draft-or-header-p))) |
|
225 |
(mew-complete word (mew-complete-directory-alist word) "directory" nil) |
|
226 |
(mew-complete word (mew-local-folder-alist) "folder" nil))))) |
|
227 |
||
228 |
;; case is specified by mew-inherit-case.
|
|
229 |
(defun mew-complete-imap-folder () |
|
230 |
"IMAP folder complete function."
|
|
231 |
(interactive) |
|
232 |
(mew-complete-proto-folder word |
|
233 |
(if (null word) |
|
234 |
(mew-complete-window-show (list "%")) |
|
235 |
(mew-complete |
|
236 |
word
|
|
237 |
(mew-imap-folder-alist mew-inherit-case) ;; ie mew-sinfo-get-case |
|
238 |
"mailbox"
|
|
239 |
nil)))) |
|
240 |
||
241 |
(defun mew-complete-fcc-folder () |
|
242 |
"Fcc: folder complete function."
|
|
243 |
(interactive) |
|
244 |
(mew-complete-proto-folder word |
|
245 |
(if (null word) |
|
246 |
(mew-complete-window-show (list "+" "%")) |
|
247 |
(cond |
|
248 |
((and (mew-folder-absolutep word) (not (mew-draft-or-header-p))) |
|
249 |
(mew-complete word (mew-complete-directory-alist word) "directory" nil)) |
|
250 |
((mew-folder-imapp word) |
|
251 |
(mew-complete word (mew-imap-folder-alist (mew-tinfo-get-case)) "mailbox" nil)) |
|
252 |
(t |
|
253 |
(mew-complete word (mew-local-folder-alist) "folder" nil)))))) |
|
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
254 |
|
255 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
256 |
;;;
|
|
257 |
;;; Completion function for the minibuffer only
|
|
258 |
;;;
|
|
259 |
||
260 |
(defun mew-complete-folder () |
|
261 |
"Folder complete function."
|
|
262 |
(interactive) |
|
263 |
(if mew-input-folder-search-direction |
|
264 |
(mew-input-folder-search-complete) |
|
265 |
(mew-complete-folder2))) |
|
266 |
||
267 |
(defun mew-input-folder-search-complete () |
|
1.1.10
by Tatsuya Kinoshita
Import upstream version 5.2.51+0.20071129 |
268 |
(let ((mew-inherit-complete-folder t) |
269 |
keys) |
|
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
270 |
(save-excursion |
271 |
(set-buffer mew-input-folder-search-buf) |
|
272 |
(save-excursion |
|
273 |
(goto-char (point-min)) |
|
274 |
(while (search-forward (or mew-input-folder-search-key "\n") nil t) |
|
275 |
(setq keys |
|
276 |
(cons (buffer-substring (progn (beginning-of-line) (point)) |
|
277 |
(progn (end-of-line) (point))) |
|
278 |
keys))))) |
|
279 |
(mew-complete-window-show (nreverse (delete "" keys))) |
|
280 |
(mew-highlight-folder-comp-search-window))) |
|
281 |
||
282 |
(defun mew-complete-folder2 () |
|
283 |
(let ((word (mew-delete-backward-char nil ", \t\n")) |
|
284 |
(completion-ignore-case mew-complete-folder-ignore-case) |
|
1.1.10
by Tatsuya Kinoshita
Import upstream version 5.2.51+0.20071129 |
285 |
(mew-inherit-complete-folder t) |
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
286 |
case folder) |
287 |
(cond |
|
288 |
((null word) |
|
289 |
(mew-complete-window-show mew-config-cases2)) |
|
290 |
((setq case (mew-case:folder-case word)) |
|
291 |
(setq folder (mew-case:folder-folder word)) |
|
292 |
(cond |
|
293 |
((mew-folder-localp folder) |
|
294 |
(mew-complete2 folder (mew-local-folder-alist) case)) |
|
295 |
((mew-folder-popp folder) |
|
296 |
(mew-complete2 folder (mew-pop-folder-alist) case)) |
|
297 |
((mew-folder-nntpp folder) |
|
298 |
(mew-complete2 folder (mew-nntp-folder-alist case) case)) |
|
299 |
((mew-folder-imapp folder) |
|
300 |
(mew-complete2 folder (mew-imap-folder-alist case) case)) |
|
301 |
((mew-folder-virtualp folder) |
|
302 |
(mew-complete |
|
303 |
word (mew-buffer-list "^\\*" t 'mew-virtual-mode) "folder" nil)) |
|
304 |
((string= folder "") |
|
305 |
(insert word) |
|
306 |
(mew-complete-window-show |
|
307 |
(mapcar (lambda (x) (concat case ":" x)) mew-folder-prefixes))) |
|
308 |
(t |
|
309 |
(insert word) |
|
310 |
(if (window-minibuffer-p (get-buffer-window (current-buffer))) |
|
311 |
(mew-temp-minibuffer-message " [No matching folder]") |
|
312 |
(message "No matching folder"))))) |
|
313 |
(t |
|
314 |
(cond |
|
315 |
((mew-folder-localp word) |
|
316 |
(mew-complete word (mew-local-folder-alist) "folder" nil)) |
|
317 |
((mew-folder-popp word) |
|
318 |
(mew-complete word (mew-pop-folder-alist) "folder" nil)) |
|
319 |
((mew-folder-nntpp word) |
|
320 |
(mew-complete word (mew-nntp-folder-alist nil) "newsgroup" nil)) |
|
321 |
((mew-folder-imapp word) |
|
322 |
(mew-complete word (mew-imap-folder-alist nil) "mailbox" nil)) |
|
323 |
((mew-folder-virtualp word) |
|
324 |
(mew-complete |
|
325 |
word (mew-buffer-list "^\\*" t 'mew-virtual-mode) "folder" nil)) |
|
326 |
((mew-folder-absolutep word) |
|
327 |
(mew-complete word (mew-complete-directory-alist word) "directory" nil)) |
|
328 |
(t |
|
329 |
(mew-complete |
|
330 |
word
|
|
331 |
(mapcar (lambda (x) (list (concat x ":"))) mew-config-cases) |
|
332 |
"case"
|
|
333 |
nil))))))) |
|
334 |
||
335 |
(defun mew-complete-case () |
|
336 |
"Complete function for cases."
|
|
337 |
(interactive) |
|
338 |
(let ((word (or (mew-delete-backward-char) "")) |
|
339 |
(completion-ignore-case mew-complete-case-ignore-case)) |
|
340 |
(mew-complete |
|
341 |
word
|
|
342 |
(mapcar 'list mew-config-cases) |
|
343 |
"case"
|
|
344 |
nil))) |
|
345 |
||
346 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
347 |
;;;
|
|
348 |
;;; Circular completion function for a draft only
|
|
349 |
;;;
|
|
350 |
||
351 |
(defun mew-draft-circular-comp () |
|
352 |
"Switch function for circular complete functions."
|
|
353 |
(interactive) |
|
354 |
(let ((func (mew-draft-on-value-p mew-field-circular-completion-switch))) |
|
355 |
(if func |
|
356 |
(funcall func) |
|
357 |
(message "No circular completion here")))) |
|
358 |
||
359 |
(defun mew-circular-complete-domain () |
|
360 |
"Circular completion of domains for To:, Cc:, etc.
|
|
361 |
If the @ character does not exist, the first value of
|
|
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
362 |
mew-mail-domain-list is inserted. If exists, the next value of
|
363 |
mew-mail-domain-list concerned with the string between @ and
|
|
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
364 |
the cursor is inserted."
|
365 |
(interactive) |
|
366 |
(mew-draft-set-completion-ignore-case |
|
367 |
mew-circular-complete-domain-ignore-case) |
|
368 |
(let ((word (mew-delete-backward-char "@")) |
|
369 |
(completion-ignore-case mew-circular-complete-domain-ignore-case)) |
|
370 |
(cond |
|
371 |
((eq word nil) ;; @ does not exist. |
|
372 |
(if (null mew-mail-domain-list) |
|
373 |
(message "For domain circular completion, set mew-mail-domain-list") |
|
374 |
(insert "@") |
|
375 |
(insert (car mew-mail-domain-list)) |
|
376 |
(mew-complete-window-delete))) |
|
377 |
((eq word t) ;; just after @ |
|
378 |
(if (null mew-mail-domain-list) |
|
379 |
(message "For domain circular completion, set mew-mail-domain-list") |
|
380 |
(insert (car mew-mail-domain-list)) |
|
381 |
(mew-complete-window-delete))) |
|
382 |
(t |
|
383 |
;; cannot use mew-get-next since completion is necessary sometime.
|
|
384 |
(mew-complete |
|
385 |
word
|
|
386 |
(mew-slide-pair mew-mail-domain-list) |
|
387 |
"domain"
|
|
388 |
t))))) ;; use cdr |
|
389 |
||
390 |
(defun mew-circular-complete (msg sym &optional minibuf) ;; xxx msg |
|
391 |
"General circular complete function."
|
|
392 |
(interactive) |
|
393 |
(let ((name (symbol-name sym)) |
|
394 |
(val (symbol-value sym)) |
|
395 |
str alst match) |
|
396 |
(if (null val) |
|
397 |
(mew-temp-minibuffer-message (format "[Set '%s']" name)) |
|
398 |
(setq str (mew-delete-value nil minibuf)) |
|
399 |
(setq alst (mew-slide-pair val)) |
|
400 |
(if (or (null str) ;; draft |
|
401 |
(and (string= str "") (null (assoc "" alst)))) ;; minibuf |
|
402 |
(insert (car val)) |
|
403 |
(setq match (assoc str alst)) |
|
404 |
(if match |
|
405 |
(insert (cdr match)) |
|
406 |
(insert str) |
|
407 |
(mew-temp-minibuffer-message (format "[No matching %s]" msg))))))) |
|
408 |
||
409 |
(defun mew-circular-complete-from () |
|
410 |
"Circular complete function for From:."
|
|
411 |
(interactive) |
|
412 |
(mew-circular-complete "from" 'mew-from-list)) |
|
413 |
||
414 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
415 |
;;;
|
|
416 |
;;; Circular completion function for the minibuffer only
|
|
417 |
;;;
|
|
418 |
||
419 |
(defvar mew-circular-complete-function nil) |
|
420 |
||
421 |
(defun mew-circular-complete-switch () |
|
422 |
"A switch function to call a function defined to
|
|
423 |
'mew-circular-complete-function'."
|
|
424 |
(interactive) |
|
425 |
(if mew-circular-complete-function (funcall mew-circular-complete-function))) |
|
426 |
||
427 |
(defun mew-circular-complete-pick-pattern () |
|
428 |
(mew-circular-complete "pick pattern" 'mew-pick-pattern-list 'minibuf)) |
|
429 |
||
430 |
(defun mew-circular-complete-case () |
|
431 |
(mew-circular-complete "case" 'mew-config-cases 'minibuf)) |
|
432 |
||
433 |
(defun mew-circular-complete-case: () |
|
434 |
(cond |
|
435 |
((eq mew-input-complete-function 'mew-complete-local-folder) |
|
436 |
())
|
|
437 |
(mew-input-folder-search-direction |
|
438 |
(mew-input-folder-self-insert)) |
|
439 |
(t |
|
440 |
(let (cases oldcase newcase insert-:) |
|
441 |
(save-excursion |
|
442 |
(if (search-backward "," nil t) |
|
443 |
(forward-char 1) |
|
444 |
(beginning-of-line)) |
|
445 |
(if (looking-at mew-regex-case2) |
|
446 |
(progn |
|
447 |
(setq oldcase (mew-match-string 1)) |
|
448 |
(delete-region (match-beginning 1) (match-end 1))) |
|
449 |
(setq oldcase mew-case-default) |
|
450 |
(setq insert-: t)) |
|
451 |
(if (setq cases (member oldcase mew-config-cases)) |
|
452 |
(if (> (length cases) 1) |
|
453 |
(setq newcase (nth 1 cases)) |
|
454 |
(setq newcase (car mew-config-cases))) |
|
455 |
(setq newcase mew-case-default)) |
|
456 |
(if (string= newcase mew-case-default) |
|
457 |
(unless insert-: (delete-char 1)) |
|
458 |
(insert newcase) |
|
459 |
(if insert-: (insert ":")))) |
|
460 |
(if (or (= (point) (mew-minibuf-point-min)) |
|
461 |
(save-excursion |
|
462 |
(forward-char -1) |
|
463 |
(looking-at "[:,]"))) |
|
464 |
(if (search-forward "," nil t) |
|
465 |
(forward-char -1) |
|
466 |
(goto-char (point-max)))))))) |
|
467 |
||
468 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
469 |
;;;
|
|
470 |
;;; Expansion for a draft only
|
|
471 |
;;;
|
|
472 |
||
473 |
(defun mew-draft-expand () |
|
474 |
"Switch function for expand functions."
|
|
475 |
(interactive) |
|
476 |
(let ((func (mew-draft-on-value-p mew-field-expansion-switch))) |
|
477 |
(if func |
|
478 |
(funcall func) |
|
479 |
(message "No expansion here")))) |
|
480 |
||
481 |
(defun mew-expand-address () |
|
482 |
"Address expansion function for To:, Cc:, etc.
|
|
483 |
'user@domain' will be expands 'name <user@domain>' if
|
|
484 |
the name exists."
|
|
485 |
(interactive) |
|
486 |
(let ((word (mew-delete-backward-char)) func name) |
|
487 |
(if (null word) |
|
488 |
(message "No address here") |
|
489 |
(setq func (mew-addrbook-func mew-addrbook-for-address-expansion)) |
|
490 |
(if (null func) |
|
491 |
(insert word) |
|
492 |
(setq name (funcall func word)) |
|
493 |
(insert (if name (format "%s <%s>" name word) word)))))) |
|
494 |
||
495 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
496 |
;;;
|
|
497 |
;;; Other completion stuff
|
|
498 |
;;;
|
|
499 |
||
500 |
;; dummy
|
|
501 |
(defvar mew-ext-host "") |
|
502 |
(defvar mew-ext-user "") |
|
503 |
||
504 |
(defun mew-complete-rfile () |
|
505 |
"Complete a remote file."
|
|
506 |
(interactive) |
|
507 |
(let* ((path-file (mew-delete-file-name)) |
|
508 |
(path (car path-file)) |
|
509 |
(file (cdr path-file)) |
|
510 |
rpath) |
|
511 |
(setq rpath (format "/%s@%s:%s" mew-ext-user mew-ext-host path)) |
|
512 |
(mew-complete |
|
513 |
file
|
|
514 |
rpath
|
|
515 |
"remote file"
|
|
516 |
nil
|
|
517 |
'mew-ext-file-name-completion
|
|
518 |
'mew-ext-file-name-all-completions))) |
|
519 |
||
520 |
(defun mew-complete-pick-pattern () |
|
521 |
"Complete pick patterns."
|
|
522 |
(interactive) |
|
523 |
(let* ((pat (mew-delete-pattern)) |
|
524 |
(clist (append '("(" "!") |
|
525 |
mew-pick-field-list
|
|
526 |
(mapcar 'car mew-pick-macro-alist)))) |
|
527 |
(if (null pat) |
|
528 |
(mew-complete-window-show clist) |
|
529 |
(mew-complete |
|
530 |
pat
|
|
531 |
(mapcar 'list clist) |
|
532 |
"pick pattern"
|
|
533 |
nil)))) |
|
534 |
||
535 |
(defun mew-complete-sort-key () |
|
536 |
"Complete sort keys."
|
|
537 |
(interactive) |
|
538 |
(let* ((word (mew-delete-line)) |
|
539 |
field alist) |
|
540 |
(if (string-match ":" word) |
|
541 |
(progn |
|
542 |
;; If WORD contains ':', change alist for completion.
|
|
543 |
(setq field (car (mew-split word ?:))) |
|
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
544 |
(setq alist |
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
545 |
(mapcar (lambda (str) (list (concat field ":" str))) mew-sort-modes))) |
546 |
;; Otherwise, alist is mew-sort-key-alist itself.
|
|
547 |
(setq alist mew-sort-key-alist)) |
|
548 |
(mew-complete word alist "sort key" nil))) |
|
549 |
||
550 |
(defun mew-complete-directory-alist (dir) |
|
551 |
"Return alist of directories for completion."
|
|
552 |
(let ((odir dir) odir1 dirs1 sub dirs2) |
|
553 |
(setq dir (mew-file-chase-links (expand-file-name dir))) |
|
554 |
(when (file-directory-p dir) |
|
555 |
(setq odir1 (file-name-as-directory odir)) |
|
556 |
(setq dirs1 (mapcar |
|
557 |
(lambda (x) |
|
558 |
(when (file-directory-p (expand-file-name x dir)) |
|
559 |
(cons (concat odir1 (file-name-as-directory x)) x))) |
|
560 |
(directory-files dir nil "[^.]" 'nosort)))) |
|
561 |
(setq sub (file-name-nondirectory dir)) |
|
562 |
(setq odir (file-name-directory odir)) |
|
563 |
(setq dir (file-name-directory dir)) |
|
564 |
(when (and dir odir sub (not (string= sub ""))) |
|
565 |
(setq odir (file-name-as-directory odir)) |
|
566 |
(setq dirs2 (mapcar |
|
567 |
(lambda (x) |
|
568 |
(when (file-directory-p (expand-file-name x dir)) |
|
569 |
(cons (concat odir (file-name-as-directory x)) x))) |
|
570 |
(directory-files dir nil |
|
571 |
(concat "^" (regexp-quote sub)) |
|
572 |
'nosort)))) |
|
573 |
(sort (delq nil (append dirs2 dirs1)) |
|
574 |
(lambda (x y) (string< (car x) (car y)))))) |
|
575 |
||
576 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
577 |
;;;
|
|
578 |
;;; Hart function for completions
|
|
579 |
;;;
|
|
580 |
||
581 |
(defalias 'mew-complete-hit 'assoc) |
|
582 |
||
583 |
(defun mew-complete-get (key alist) |
|
584 |
(cdr (mew-complete-hit key alist))) |
|
585 |
||
586 |
(defun mew-complete (WORD ALIST MSG EXPAND-CHAR &optional TRY ALL GET HIT) |
|
587 |
(let* ((ftry (or TRY 'try-completion)) |
|
588 |
(fall (or ALL 'all-completions)) |
|
589 |
(fget (or GET 'mew-complete-get)) |
|
590 |
(fhit (or HIT 'mew-complete-hit)) |
|
591 |
(cmp (funcall ftry WORD ALIST)) |
|
592 |
(all (funcall fall WORD ALIST)) |
|
593 |
(len (length WORD)) |
|
594 |
subkey) |
|
595 |
(cond |
|
596 |
;; already completed
|
|
597 |
((eq cmp t) |
|
598 |
(if EXPAND-CHAR ;; may be "t" |
|
599 |
(insert (funcall fget WORD ALIST)) ;; use cdr |
|
600 |
(insert WORD)) ;; use car |
|
601 |
(mew-complete-window-delete)) |
|
602 |
;; EXPAND
|
|
603 |
((and (mew-characterp EXPAND-CHAR) |
|
604 |
(char-equal (aref WORD (1- len)) EXPAND-CHAR) |
|
605 |
(setq subkey (substring WORD 0 (1- len))) |
|
606 |
(funcall fhit subkey ALIST)) |
|
607 |
(insert (funcall fget subkey ALIST)) ;; use cdr |
|
608 |
(mew-complete-window-delete)) |
|
609 |
;; just one candidate
|
|
610 |
((= 1 (length all)) |
|
611 |
(insert cmp) |
|
612 |
(if (window-minibuffer-p (get-buffer-window (current-buffer))) |
|
613 |
(mew-temp-minibuffer-message " [Sole completion]") |
|
614 |
(message "Sole completion")) |
|
615 |
(mew-complete-window-delete)) |
|
616 |
;; two or more candidates
|
|
617 |
((stringp cmp) ;; (length all) > 1 |
|
618 |
(insert cmp) |
|
619 |
(mew-complete-window-show all) |
|
620 |
(if (and (mew-characterp EXPAND-CHAR) (funcall fhit cmp ALIST)) |
|
621 |
(message |
|
622 |
"To expand '%s', type '%c' then '%s'"
|
|
623 |
cmp EXPAND-CHAR |
|
624 |
(substitute-command-keys |
|
625 |
"\\<mew-draft-header-map>\\[mew-draft-header-comp]")))) |
|
626 |
;; no candidate
|
|
627 |
(t |
|
628 |
(insert WORD) |
|
629 |
;;(mew-complete-window-delete)
|
|
630 |
(if (window-minibuffer-p (get-buffer-window (current-buffer))) |
|
631 |
(mew-temp-minibuffer-message (format " [No matching %s]" MSG)) |
|
632 |
(message "No matching %s" MSG)))))) |
|
633 |
||
634 |
(defun mew-complete2-insert (case word) |
|
635 |
(if case |
|
636 |
(insert case ":" word) |
|
637 |
(insert word))) |
|
638 |
||
639 |
(defun mew-complete2 (word alist case) |
|
640 |
(let* ((cmp (try-completion word alist)) |
|
641 |
(all (all-completions word alist))) |
|
642 |
(cond |
|
643 |
;; already completed
|
|
644 |
((eq cmp t) |
|
645 |
(mew-complete2-insert case word) ;; use car |
|
646 |
(mew-complete-window-delete)) |
|
647 |
;; just one candidate
|
|
648 |
((= 1 (length all)) |
|
649 |
(mew-complete2-insert case cmp) |
|
650 |
(if (window-minibuffer-p (get-buffer-window (current-buffer))) |
|
651 |
(mew-temp-minibuffer-message " [Sole completion]") |
|
652 |
(message "Sole completion")) |
|
653 |
(mew-complete-window-delete)) |
|
654 |
;; two or more candidates
|
|
655 |
((stringp cmp) ;; (length all) > 1 |
|
656 |
(mew-complete2-insert case cmp) |
|
657 |
(mew-complete-window-show all)) |
|
658 |
;; no candidate
|
|
659 |
(t |
|
660 |
(mew-complete2-insert case word) |
|
661 |
;;(mew-complete-window-delete)
|
|
662 |
(if (window-minibuffer-p (get-buffer-window (current-buffer))) |
|
663 |
(mew-temp-minibuffer-message " [No matching folder]") |
|
664 |
(message "No matching folder")))))) |
|
665 |
||
666 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
667 |
;;;
|
|
668 |
;;; Minibuf magic
|
|
669 |
;;;
|
|
670 |
||
671 |
(defun mew-temp-minibuffer-message (m) |
|
672 |
(let ((savemax (point-max))) |
|
673 |
(save-excursion |
|
674 |
(goto-char (point-max)) |
|
675 |
(insert m)) |
|
676 |
(let ((inhibit-quit t)) |
|
677 |
(mew-let-user-read) |
|
678 |
(delete-region savemax (point-max)) |
|
1.1.1
by Tatsuya Kinoshita
Import upstream version 4.2.52 |
679 |
(when quit-flag |
680 |
(setq quit-flag nil) |
|
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
681 |
(setq unread-command-events (list 7)))))) ;; 7 == C-g |
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
682 |
|
683 |
;;
|
|
684 |
;; Extracting completion key
|
|
685 |
;;
|
|
686 |
||
687 |
(defun mew-delete-backward-char (&optional here sep) |
|
688 |
"Delete appropriate preceding word and return it."
|
|
689 |
(interactive) |
|
690 |
(let ((case-fold-search t) |
|
691 |
(start nil) |
|
692 |
(end (point)) |
|
693 |
(regex (concat "[^" (or sep mew-address-separator) "]"))) |
|
694 |
(save-excursion |
|
695 |
(while (and (not (bobp)) |
|
696 |
(string-match regex (mew-buffer-substring (1- (point)) (point)))) |
|
697 |
(forward-char -1)) |
|
698 |
(if (and here (not (re-search-forward (regexp-quote here) end t))) |
|
699 |
nil ;; "here" does not exist. |
|
700 |
(setq start (point)) |
|
701 |
(if (= start end) |
|
702 |
(if here t nil) ;; just after "here", just after separator |
|
703 |
(prog1 |
|
704 |
(mew-buffer-substring start end) |
|
705 |
(delete-region start end))))))) |
|
706 |
||
707 |
(defun mew-delete-file-name () |
|
708 |
(if (search-backward mew-path-separator nil t) |
|
709 |
(forward-char 1) |
|
710 |
(beginning-of-line)) |
|
711 |
(prog1 |
|
712 |
(cons (mew-buffer-substring (mew-minibuf-point-min) (point)) |
|
713 |
(mew-buffer-substring (point) (point-max))) |
|
714 |
(delete-region (point) (point-max)))) |
|
715 |
||
716 |
(defun mew-delete-pattern () |
|
717 |
(let ((pos (point))) |
|
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
718 |
(if (re-search-backward " \\|(\\|&\\||\\|!\\|," nil t) |
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
719 |
(forward-char 1) |
720 |
(beginning-of-line)) |
|
721 |
(prog1 |
|
722 |
(mew-buffer-substring (point) pos) |
|
723 |
(delete-region (point) pos)))) |
|
724 |
||
725 |
(defun mew-delete-line () |
|
726 |
(let ((pos (point))) |
|
727 |
(beginning-of-line) |
|
728 |
(prog1 |
|
729 |
(mew-buffer-substring (point) pos) |
|
730 |
(delete-region (point) pos)))) |
|
731 |
||
732 |
(defun mew-delete-key () |
|
733 |
(let ((pos (point))) |
|
734 |
(beginning-of-line) |
|
735 |
(prog1 |
|
736 |
(mew-capitalize (mew-buffer-substring (point) pos)) |
|
737 |
(delete-region (point) pos)))) |
|
738 |
||
739 |
(defun mew-delete-value (&optional here minibuf) |
|
740 |
(beginning-of-line) |
|
741 |
(if minibuf |
|
742 |
(let ((start (point)) ret) |
|
743 |
(end-of-line) |
|
744 |
(setq ret (mew-buffer-substring start (point))) |
|
745 |
(delete-region start (point)) |
|
746 |
ret) |
|
747 |
(when (looking-at "[^:]+:") |
|
748 |
(goto-char (match-end 0)) |
|
749 |
(if (looking-at "[ \t]") |
|
750 |
(forward-char 1) |
|
751 |
(insert " ")) |
|
752 |
(if (eolp) |
|
753 |
nil
|
|
754 |
(let ((start (point)) ret) |
|
755 |
(end-of-line) |
|
756 |
(if (and here (re-search-backward (regexp-quote here) start t)) |
|
757 |
(progn |
|
758 |
(setq start (1+ (point))) |
|
759 |
(end-of-line))) |
|
760 |
(setq ret (mew-buffer-substring start (point))) |
|
761 |
(delete-region start (point)) |
|
762 |
ret))))) |
|
763 |
||
764 |
;;
|
|
765 |
;; Making alist
|
|
766 |
;;
|
|
767 |
||
768 |
(defun mew-slide-pair (x) |
|
769 |
(let ((len (length x)) |
|
770 |
(ret nil) |
|
771 |
(first (car x))) |
|
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
772 |
(cond |
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
773 |
((= len 0) nil) |
774 |
((= len 1) (list (cons first first))) |
|
775 |
(t |
|
776 |
(while (cdr x) |
|
777 |
(setq ret (cons (cons (nth 0 x) (nth 1 x)) ret)) |
|
778 |
(setq x (cdr x))) |
|
779 |
(setq ret (cons (cons (car x) first) ret)) |
|
780 |
(nreverse ret))))) |
|
781 |
||
782 |
(provide 'mew-complete) |
|
783 |
||
784 |
;;; Copyright Notice:
|
|
785 |
||
1.2.3
by Tatsuya Kinoshita
Import upstream version 6.2.51 |
786 |
;; Copyright (C) 1997-2009 Mew developing team.
|
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
787 |
;; All rights reserved.
|
788 |
||
789 |
;; Redistribution and use in source and binary forms, with or without
|
|
790 |
;; modification, are permitted provided that the following conditions
|
|
791 |
;; are met:
|
|
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
792 |
;;
|
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
793 |
;; 1. Redistributions of source code must retain the above copyright
|
794 |
;; notice, this list of conditions and the following disclaimer.
|
|
795 |
;; 2. Redistributions in binary form must reproduce the above copyright
|
|
796 |
;; notice, this list of conditions and the following disclaimer in the
|
|
797 |
;; documentation and/or other materials provided with the distribution.
|
|
798 |
;; 3. Neither the name of the team nor the names of its contributors
|
|
799 |
;; may be used to endorse or promote products derived from this software
|
|
800 |
;; without specific prior written permission.
|
|
1.1.12
by Tatsuya Kinoshita
Import upstream version 6.0.51~0.20080421 |
801 |
;;
|
1
by Tatsuya Kinoshita
Import upstream version 4.0.65 |
802 |
;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND
|
803 |
;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
804 |
;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
805 |
;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE
|
|
806 |
;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
807 |
;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
808 |
;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
809 |
;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
810 |
;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
811 |
;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
|
812 |
;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
813 |
||
814 |
;;; mew-complete.el ends here
|