Convert consecutive FSF copyright years to ranges.
[bpt/emacs.git] / lisp / eshell / em-cmpl.el
CommitLineData
60370d40 1;;; em-cmpl.el --- completion using the TAB key
affbf647 2
73b0cd50 3;; Copyright (C) 1999-2011 Free Software Foundation, Inc.
affbf647 4
7de5b421
GM
5;; Author: John Wiegley <johnw@gnu.org>
6
affbf647
GM
7;; This file is part of GNU Emacs.
8
4ee57b2a 9;; GNU Emacs is free software: you can redistribute it and/or modify
affbf647 10;; it under the terms of the GNU General Public License as published by
4ee57b2a
GM
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
affbf647
GM
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
4ee57b2a 20;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
affbf647 21
affbf647
GM
22;;; Commentary:
23
24;; Eshell, by using the pcomplete package, provides a full
25;; programmable completion facility that is comparable to shells like
26;; tcsh or zsh.
27;;
28;; Completions are context-sensitive, which means that pressing <TAB>
29;; after the command 'rmdir' will result in a list of directories,
30;; while doing so after 'rm' will result in a list of all file
31;; entries.
32;;
33;; Many builtin completion rules are provided, for commands such as
34;; `cvs', or RedHat's `rpm' utility. Adding new completion rules is
35;; no more difficult than writing a plain Lisp functions, and they can
36;; be debugged, profiled, and compiled using exactly the same
37;; facilities (since in fact, they *are* just Lisp functions). See
38;; the definition of the function `pcomplete/make' for an example of
39;; how to write a completion function.
40;;
41;; The completion facility is very easy to use. Just press TAB. If
42;; there are a large number of possible completions, a buffer will
2696c102 43;; appear showing a list of them. Completions may be selected from
affbf647
GM
44;; that buffer using the mouse. If no completion is selected, and the
45;; user starts doing something else, the display buffer will
46;; automatically disappear.
47;;
48;; If the list of possible completions is very small, Eshell will
49;; "cycle" through them, selecting a different entry each time <TAB>
50;; is pressed. <S-TAB> may be used to cycle in the opposite
51;; direction.
52;;
53;; Glob patterns can also be cycled. For example, entering 'echo
54;; x*<tab>' will cycle through all the filenames beginning with 'x'.
55;; This is done because the glob list is treated as though it were a
56;; list of possible completions. Pressing <C-c SPC> will insert all
57;; of the matching glob patterns at point.
58;;
59;; If a Lisp form is being entered, <TAB> will complete the Lisp
60;; symbol name, in exactly the same way that <M-TAB> does in Emacs
61;; Lisp mode.
62;;
63;; The list of possible completions can be viewed at any point by
64;; pressing <M-?>.
65;;
66;; Finally, context-related help can be accessed by pressing <C-c i>.
67;; This only works well if the completion function has provided Eshell
68;; with sufficient pointers to locate the relevant help text.
69
dbba8a04
GM
70;;; Code:
71
72(eval-when-compile
fc17acd1 73 (require 'cl)
dbba8a04
GM
74 (require 'eshell))
75(require 'esh-util)
76
3146b070
GM
77;;;###autoload
78(eshell-defgroup eshell-cmpl nil
dbba8a04
GM
79 "This module provides a programmable completion function bound to
80the TAB key, which allows for completing command names, file names,
81variable names, arguments, etc."
82 :tag "Argument completion"
83 :group 'eshell-module)
84
affbf647
GM
85;;; User Variables:
86
87(defcustom eshell-cmpl-load-hook '(eshell-cmpl-initialize)
ec60da52 88 "A list of functions to run when `eshell-cmpl' is loaded."
affbf647
GM
89 :type 'hook
90 :group 'eshell-cmpl)
91
92(defcustom eshell-show-lisp-completions nil
ec60da52 93 "If non-nil, include Lisp functions in the command completion list.
affbf647
GM
94If this variable is nil, Lisp completion can still be done in command
95position by using M-TAB instead of TAB."
96 :type 'boolean
97 :group 'eshell-cmpl)
98
99(defcustom eshell-show-lisp-alternatives t
ec60da52 100 "If non-nil, and no other completions found, show Lisp functions.
affbf647
GM
101Setting this variable means nothing if `eshell-show-lisp-completions'
102is non-nil."
103 :type 'boolean
104 :group 'eshell-cmpl)
105
106(defcustom eshell-no-completion-during-jobs t
ec60da52 107 "If non-nil, don't allow completion while a process is running."
affbf647
GM
108 :type 'boolean
109 :group 'eshell-cmpl)
110
111(defcustom eshell-command-completions-alist
112 '(("acroread" . "\\.pdf\\'")
113 ("xpdf" . "\\.pdf\\'")
114 ("ar" . "\\.[ao]\\'")
115 ("gcc" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
116 ("g++" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
117 ("cc" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
118 ("CC" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
119 ("acc" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
120 ("bcc" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
d7da23c9
JW
121 ("readelf" . "\\(\\`[^.]*\\|\\.\\([ao]\\|so\\)\\)\\'")
122 ("objdump" . "\\(\\`[^.]*\\|\\.\\([ao]\\|so\\)\\)\\'")
123 ("nm" . "\\(\\`[^.]*\\|\\.\\([ao]\\|so\\)\\)\\'")
affbf647
GM
124 ("gdb" . "\\`\\([^.]*\\|a\\.out\\)\\'")
125 ("dbx" . "\\`\\([^.]*\\|a\\.out\\)\\'")
126 ("sdb" . "\\`\\([^.]*\\|a\\.out\\)\\'")
127 ("adb" . "\\`\\([^.]*\\|a\\.out\\)\\'"))
ec60da52 128 "An alist that defines simple argument type correlations.
affbf647
GM
129This is provided for common commands, as a simplistic alternative
130to writing a completion function."
131 :type '(repeat (cons string regexp))
132 :group 'eshell-cmpl)
133
134(defcustom eshell-cmpl-file-ignore "~\\'"
135 (documentation-property 'pcomplete-file-ignore
136 'variable-documentation)
137 :type (get 'pcomplete-file-ignore 'custom-type)
138 :group 'eshell-cmpl)
139
6b0e3e4d 140(defcustom eshell-cmpl-dir-ignore "\\`\\(\\.\\.?\\|CVS\\)/\\'"
affbf647
GM
141 (documentation-property 'pcomplete-dir-ignore
142 'variable-documentation)
143 :type (get 'pcomplete-dir-ignore 'custom-type)
144 :group 'eshell-cmpl)
145
70a06174 146(defcustom eshell-cmpl-ignore-case (eshell-under-windows-p)
affbf647
GM
147 (documentation-property 'pcomplete-ignore-case
148 'variable-documentation)
149 :type (get 'pcomplete-ignore-case 'custom-type)
150 :group 'eshell-cmpl)
151
152(defcustom eshell-cmpl-autolist nil
153 (documentation-property 'pcomplete-autolist
154 'variable-documentation)
155 :type (get 'pcomplete-autolist 'custom-type)
156 :group 'eshell-cmpl)
157
6b0e3e4d 158(defcustom eshell-cmpl-suffix-list (list ?/ ?:)
affbf647
GM
159 (documentation-property 'pcomplete-suffix-list
160 'variable-documentation)
161 :type (get 'pcomplete-suffix-list 'custom-type)
162 :group 'pcomplete)
163
164(defcustom eshell-cmpl-recexact nil
165 (documentation-property 'pcomplete-recexact
166 'variable-documentation)
167 :type (get 'pcomplete-recexact 'custom-type)
168 :group 'eshell-cmpl)
169
170(defcustom eshell-cmpl-man-function 'man
171 (documentation-property 'pcomplete-man-function
172 'variable-documentation)
173 :type (get 'pcomplete-man-function 'custom-type)
174 :group 'eshell-cmpl)
175
176(defcustom eshell-cmpl-compare-entry-function 'file-newer-than-file-p
177 (documentation-property 'pcomplete-compare-entry-function
178 'variable-documentation)
179 :type (get 'pcomplete-compare-entry-function 'custom-type)
180 :group 'eshell-cmpl)
181
182(defcustom eshell-cmpl-expand-before-complete nil
183 (documentation-property 'pcomplete-expand-before-complete
184 'variable-documentation)
185 :type (get 'pcomplete-expand-before-complete 'custom-type)
186 :group 'eshell-cmpl)
187
188(defcustom eshell-cmpl-cycle-completions t
189 (documentation-property 'pcomplete-cycle-completions
190 'variable-documentation)
191 :type (get 'pcomplete-cycle-completions 'custom-type)
192 :group 'eshell-cmpl)
193
194(defcustom eshell-cmpl-cycle-cutoff-length 5
195 (documentation-property 'pcomplete-cycle-cutoff-length
196 'variable-documentation)
197 :type (get 'pcomplete-cycle-cutoff-length 'custom-type)
198 :group 'eshell-cmpl)
199
200(defcustom eshell-cmpl-restore-window-delay 1
201 (documentation-property 'pcomplete-restore-window-delay
202 'variable-documentation)
203 :type (get 'pcomplete-restore-window-delay 'custom-type)
204 :group 'eshell-cmpl)
205
206(defcustom eshell-command-completion-function
207 (function
208 (lambda ()
209 (pcomplete-here (eshell-complete-commands-list))))
210 (documentation-property 'pcomplete-command-completion-function
211 'variable-documentation)
212 :type (get 'pcomplete-command-completion-function 'custom-type)
213 :group 'eshell-cmpl)
214
215(defcustom eshell-cmpl-command-name-function
216 'eshell-completion-command-name
217 (documentation-property 'pcomplete-command-name-function
218 'variable-documentation)
219 :type (get 'pcomplete-command-name-function 'custom-type)
220 :group 'eshell-cmpl)
221
222(defcustom eshell-default-completion-function
223 (function
224 (lambda ()
225 (while (pcomplete-here
226 (pcomplete-dirs-or-entries
227 (cdr (assoc (funcall eshell-cmpl-command-name-function)
228 eshell-command-completions-alist)))))))
229 (documentation-property 'pcomplete-default-completion-function
230 'variable-documentation)
231 :type (get 'pcomplete-default-completion-function 'custom-type)
ca7aae91
JW
232 :group 'eshell-cmpl)
233
234(defcustom eshell-cmpl-use-paring t
235 (documentation-property 'pcomplete-use-paring 'variable-documentation)
236 :type (get 'pcomplete-use-paring 'custom-type)
237 :group 'eshell-cmpl)
affbf647
GM
238
239;;; Functions:
240
241(defun eshell-cmpl-initialize ()
242 "Initialize the completions module."
243 (unless (fboundp 'pcomplete)
244 (load "pcmpl-auto" t t))
245 (set (make-local-variable 'pcomplete-command-completion-function)
246 eshell-command-completion-function)
247 (set (make-local-variable 'pcomplete-command-name-function)
248 eshell-cmpl-command-name-function)
249 (set (make-local-variable 'pcomplete-default-completion-function)
250 eshell-default-completion-function)
251 (set (make-local-variable 'pcomplete-parse-arguments-function)
252 'eshell-complete-parse-arguments)
253 (set (make-local-variable 'pcomplete-file-ignore)
254 eshell-cmpl-file-ignore)
255 (set (make-local-variable 'pcomplete-dir-ignore)
256 eshell-cmpl-dir-ignore)
257 (set (make-local-variable 'pcomplete-ignore-case)
258 eshell-cmpl-ignore-case)
259 (set (make-local-variable 'pcomplete-autolist)
260 eshell-cmpl-autolist)
261 (set (make-local-variable 'pcomplete-suffix-list)
262 eshell-cmpl-suffix-list)
263 (set (make-local-variable 'pcomplete-recexact)
264 eshell-cmpl-recexact)
265 (set (make-local-variable 'pcomplete-man-function)
266 eshell-cmpl-man-function)
267 (set (make-local-variable 'pcomplete-compare-entry-function)
268 eshell-cmpl-compare-entry-function)
269 (set (make-local-variable 'pcomplete-expand-before-complete)
270 eshell-cmpl-expand-before-complete)
271 (set (make-local-variable 'pcomplete-cycle-completions)
272 eshell-cmpl-cycle-completions)
273 (set (make-local-variable 'pcomplete-cycle-cutoff-length)
274 eshell-cmpl-cycle-cutoff-length)
275 (set (make-local-variable 'pcomplete-restore-window-delay)
276 eshell-cmpl-restore-window-delay)
ca7aae91
JW
277 (set (make-local-variable 'pcomplete-use-paring)
278 eshell-cmpl-use-paring)
affbf647
GM
279 ;; `pcomplete-arg-quote-list' should only be set after all the
280 ;; load-hooks for any other extension modules have been run, which
281 ;; is true at the time `eshell-mode-hook' is run
affbf647
GM
282 (add-hook 'eshell-mode-hook
283 (function
284 (lambda ()
285 (set (make-local-variable 'pcomplete-arg-quote-list)
286 eshell-special-chars-outside-quoting))) nil t)
affbf647
GM
287 (add-hook 'pcomplete-quote-arg-hook 'eshell-quote-backslash nil t)
288 (define-key eshell-mode-map [(meta tab)] 'lisp-complete-symbol)
289 (define-key eshell-mode-map [(meta control ?i)] 'lisp-complete-symbol)
290 (define-key eshell-command-map [(meta ?h)] 'eshell-completion-help)
291 (define-key eshell-command-map [tab] 'pcomplete-expand-and-complete)
292 (define-key eshell-command-map [(control ?i)]
293 'pcomplete-expand-and-complete)
294 (define-key eshell-command-map [space] 'pcomplete-expand)
295 (define-key eshell-command-map [? ] 'pcomplete-expand)
296 (define-key eshell-mode-map [tab] 'pcomplete)
297 (define-key eshell-mode-map [(control ?i)] 'pcomplete)
298 ;; jww (1999-10-19): Will this work on anything but X?
a3269bc4 299 (if (featurep 'xemacs)
affbf647
GM
300 (define-key eshell-mode-map [iso-left-tab] 'pcomplete-reverse)
301 (define-key eshell-mode-map [(shift iso-lefttab)] 'pcomplete-reverse)
302 (define-key eshell-mode-map [(shift control ?i)] 'pcomplete-reverse))
303 (define-key eshell-mode-map [(meta ??)] 'pcomplete-list))
304
305(defun eshell-completion-command-name ()
306 "Return the command name, possibly sans globbing."
307 (let ((cmd (file-name-nondirectory (pcomplete-arg 'first))))
308 (setq cmd (if (and (> (length cmd) 0)
a129972c 309 (eq (aref cmd 0) eshell-explicit-command-char))
affbf647
GM
310 (substring cmd 1)
311 cmd))
312 (if (eshell-under-windows-p)
313 (file-name-sans-extension cmd)
314 cmd)))
315
316(defun eshell-completion-help ()
317 (interactive)
318 (if (= (point) eshell-last-output-end)
319 (describe-prefix-bindings)
320 (call-interactively 'pcomplete-help)))
321
322(defun eshell-complete-parse-arguments ()
323 "Parse the command line arguments for `pcomplete-argument'."
324 (when (and eshell-no-completion-during-jobs
325 (eshell-interactive-process))
326 (insert-and-inherit "\t")
327 (throw 'pcompleted t))
328 (let ((end (point-marker))
329 (begin (save-excursion (eshell-bol) (point)))
330 (posns (list t))
331 args delim)
332 (when (memq this-command '(pcomplete-expand
333 pcomplete-expand-and-complete))
334 (run-hook-with-args 'eshell-expand-input-functions begin end)
335 (if (= begin end)
336 (end-of-line))
337 (setq end (point-marker)))
338 (if (setq delim
339 (catch 'eshell-incomplete
340 (ignore
341 (setq args (eshell-parse-arguments begin end)))))
342 (cond ((memq (car delim) '(?\{ ?\<))
343 (setq begin (1+ (cadr delim))
344 args (eshell-parse-arguments begin end)))
345 ((eq (car delim) ?\()
346 (lisp-complete-symbol)
347 (throw 'pcompleted t))
348 (t
349 (insert-and-inherit "\t")
350 (throw 'pcompleted t))))
351 (when (get-text-property (1- end) 'comment)
352 (insert-and-inherit "\t")
353 (throw 'pcompleted t))
354 (let ((pos begin))
355 (while (< pos end)
356 (if (get-text-property pos 'arg-begin)
357 (nconc posns (list pos)))
358 (setq pos (1+ pos))))
359 (setq posns (cdr posns))
360 (assert (= (length args) (length posns)))
361 (let ((a args)
362 (i 0)
363 l final)
364 (while a
365 (if (and (consp (car a))
366 (eq (caar a) 'eshell-operator))
367 (setq l i))
368 (setq a (cdr a) i (1+ i)))
369 (and l
370 (setq args (nthcdr (1+ l) args)
371 posns (nthcdr (1+ l) posns))))
372 (assert (= (length args) (length posns)))
34204d80
JW
373 (when (and args (eq (char-syntax (char-before end)) ? )
374 (not (eq (char-before (1- end)) ?\\)))
affbf647
GM
375 (nconc args (list ""))
376 (nconc posns (list (point))))
377 (cons (mapcar
378 (function
379 (lambda (arg)
380 (let ((val
381 (if (listp arg)
382 (let ((result
383 (eshell-do-eval
384 (list 'eshell-commands arg) t)))
385 (assert (eq (car result) 'quote))
386 (cadr result))
387 arg)))
388 (if (numberp val)
389 (setq val (number-to-string val)))
390 (or val ""))))
391 args)
392 posns)))
393
394(defun eshell-complete-commands-list ()
395 "Generate list of applicable, visible commands."
396 (let ((filename (pcomplete-arg)) glob-name)
397 (if (file-name-directory filename)
398 (pcomplete-executables)
399 (if (and (> (length filename) 0)
a129972c 400 (eq (aref filename 0) eshell-explicit-command-char))
affbf647
GM
401 (setq filename (substring filename 1)
402 pcomplete-stub filename
403 glob-name t))
605a20a9 404 (let* ((paths (eshell-parse-colon-path eshell-path-env))
affbf647
GM
405 (cwd (file-name-as-directory
406 (expand-file-name default-directory)))
407 (path "") (comps-in-path ())
408 (file "") (filepath "") (completions ()))
409 ;; Go thru each path in the search path, finding completions.
410 (while paths
411 (setq path (file-name-as-directory
412 (expand-file-name (or (car paths) ".")))
413 comps-in-path
414 (and (file-accessible-directory-p path)
415 (file-name-all-completions filename path)))
416 ;; Go thru each completion found, to see whether it should
417 ;; be used.
418 (while comps-in-path
419 (setq file (car comps-in-path)
420 filepath (concat path file))
421 (if (and (not (member file completions)) ;
422 (or (string-equal path cwd)
423 (not (file-directory-p filepath)))
424 (file-executable-p filepath))
425 (setq completions (cons file completions)))
426 (setq comps-in-path (cdr comps-in-path)))
427 (setq paths (cdr paths)))
428 ;; Add aliases which are currently visible, and Lisp functions.
429 (pcomplete-uniqify-list
430 (if glob-name
431 completions
432 (setq completions
433 (append (and (eshell-using-module 'eshell-alias)
434 (funcall (symbol-function 'eshell-alias-completions)
435 filename))
436 (eshell-winnow-list
437 (mapcar
438 (function
439 (lambda (name)
440 (substring name 7)))
441 (all-completions (concat "eshell/" filename)
442 obarray 'functionp))
443 nil '(eshell-find-alias-function))
444 completions))
445 (append (and (or eshell-show-lisp-completions
446 (and eshell-show-lisp-alternatives
447 (null completions)))
448 (all-completions filename obarray 'functionp))
449 completions)))))))
450
dbba8a04 451(provide 'em-cmpl)
affbf647 452
3146b070
GM
453;; Local Variables:
454;; generated-autoload-file: "esh-groups.el"
455;; End:
456
affbf647 457;;; em-cmpl.el ends here