~ubuntu-branches/ubuntu/lucid/mew-beta/lucid

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