* lisp/eshell/em-cmpl.el: Corrected "context-related help"
[bpt/emacs.git] / lisp / eshell / em-cmpl.el
CommitLineData
60370d40 1;;; em-cmpl.el --- completion using the TAB key
affbf647 2
ab422c4d 3;; Copyright (C) 1999-2013 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;;
4b9f0b67 66;; Finally, context-related help can be accessed by pressing <C-c M-h>.
affbf647
GM
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
a464a6c7 73 (require 'cl-lib)
dbba8a04
GM
74 (require 'eshell))
75(require 'esh-util)
76
3146b070 77;;;###autoload
35ff222c
GM
78(progn
79(defgroup eshell-cmpl nil
dbba8a04
GM
80 "This module provides a programmable completion function bound to
81the TAB key, which allows for completing command names, file names,
82variable names, arguments, etc."
83 :tag "Argument completion"
35ff222c 84 :group 'eshell-module))
dbba8a04 85
affbf647
GM
86;;; User Variables:
87
d783d303 88(defcustom eshell-cmpl-load-hook nil
ec60da52 89 "A list of functions to run when `eshell-cmpl' is loaded."
d783d303 90 :version "24.1" ; removed eshell-cmpl-initialize
affbf647
GM
91 :type 'hook
92 :group 'eshell-cmpl)
93
94(defcustom eshell-show-lisp-completions nil
ec60da52 95 "If non-nil, include Lisp functions in the command completion list.
affbf647
GM
96If this variable is nil, Lisp completion can still be done in command
97position by using M-TAB instead of TAB."
98 :type 'boolean
99 :group 'eshell-cmpl)
100
101(defcustom eshell-show-lisp-alternatives t
ec60da52 102 "If non-nil, and no other completions found, show Lisp functions.
affbf647
GM
103Setting this variable means nothing if `eshell-show-lisp-completions'
104is non-nil."
105 :type 'boolean
106 :group 'eshell-cmpl)
107
108(defcustom eshell-no-completion-during-jobs t
ec60da52 109 "If non-nil, don't allow completion while a process is running."
affbf647
GM
110 :type 'boolean
111 :group 'eshell-cmpl)
112
113(defcustom eshell-command-completions-alist
114 '(("acroread" . "\\.pdf\\'")
115 ("xpdf" . "\\.pdf\\'")
116 ("ar" . "\\.[ao]\\'")
117 ("gcc" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
118 ("g++" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
119 ("cc" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
120 ("CC" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
121 ("acc" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
122 ("bcc" . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
d7da23c9
JW
123 ("readelf" . "\\(\\`[^.]*\\|\\.\\([ao]\\|so\\)\\)\\'")
124 ("objdump" . "\\(\\`[^.]*\\|\\.\\([ao]\\|so\\)\\)\\'")
125 ("nm" . "\\(\\`[^.]*\\|\\.\\([ao]\\|so\\)\\)\\'")
affbf647
GM
126 ("gdb" . "\\`\\([^.]*\\|a\\.out\\)\\'")
127 ("dbx" . "\\`\\([^.]*\\|a\\.out\\)\\'")
128 ("sdb" . "\\`\\([^.]*\\|a\\.out\\)\\'")
129 ("adb" . "\\`\\([^.]*\\|a\\.out\\)\\'"))
ec60da52 130 "An alist that defines simple argument type correlations.
affbf647
GM
131This is provided for common commands, as a simplistic alternative
132to writing a completion function."
133 :type '(repeat (cons string regexp))
134 :group 'eshell-cmpl)
135
136(defcustom eshell-cmpl-file-ignore "~\\'"
137 (documentation-property 'pcomplete-file-ignore
138 'variable-documentation)
139 :type (get 'pcomplete-file-ignore 'custom-type)
140 :group 'eshell-cmpl)
141
6b0e3e4d 142(defcustom eshell-cmpl-dir-ignore "\\`\\(\\.\\.?\\|CVS\\)/\\'"
affbf647
GM
143 (documentation-property 'pcomplete-dir-ignore
144 'variable-documentation)
145 :type (get 'pcomplete-dir-ignore 'custom-type)
146 :group 'eshell-cmpl)
147
70a06174 148(defcustom eshell-cmpl-ignore-case (eshell-under-windows-p)
affbf647
GM
149 (documentation-property 'pcomplete-ignore-case
150 'variable-documentation)
151 :type (get 'pcomplete-ignore-case 'custom-type)
152 :group 'eshell-cmpl)
153
154(defcustom eshell-cmpl-autolist nil
155 (documentation-property 'pcomplete-autolist
156 'variable-documentation)
157 :type (get 'pcomplete-autolist 'custom-type)
158 :group 'eshell-cmpl)
159
6b0e3e4d 160(defcustom eshell-cmpl-suffix-list (list ?/ ?:)
affbf647
GM
161 (documentation-property 'pcomplete-suffix-list
162 'variable-documentation)
163 :type (get 'pcomplete-suffix-list 'custom-type)
164 :group 'pcomplete)
165
166(defcustom eshell-cmpl-recexact nil
167 (documentation-property 'pcomplete-recexact
168 'variable-documentation)
169 :type (get 'pcomplete-recexact 'custom-type)
170 :group 'eshell-cmpl)
171
172(defcustom eshell-cmpl-man-function 'man
173 (documentation-property 'pcomplete-man-function
174 'variable-documentation)
175 :type (get 'pcomplete-man-function 'custom-type)
176 :group 'eshell-cmpl)
177
178(defcustom eshell-cmpl-compare-entry-function 'file-newer-than-file-p
179 (documentation-property 'pcomplete-compare-entry-function
180 'variable-documentation)
181 :type (get 'pcomplete-compare-entry-function 'custom-type)
182 :group 'eshell-cmpl)
183
184(defcustom eshell-cmpl-expand-before-complete nil
185 (documentation-property 'pcomplete-expand-before-complete
186 'variable-documentation)
187 :type (get 'pcomplete-expand-before-complete 'custom-type)
188 :group 'eshell-cmpl)
189
190(defcustom eshell-cmpl-cycle-completions t
191 (documentation-property 'pcomplete-cycle-completions
192 'variable-documentation)
193 :type (get 'pcomplete-cycle-completions 'custom-type)
194 :group 'eshell-cmpl)
195
196(defcustom eshell-cmpl-cycle-cutoff-length 5
197 (documentation-property 'pcomplete-cycle-cutoff-length
198 'variable-documentation)
199 :type (get 'pcomplete-cycle-cutoff-length 'custom-type)
200 :group 'eshell-cmpl)
201
202(defcustom eshell-cmpl-restore-window-delay 1
203 (documentation-property 'pcomplete-restore-window-delay
204 'variable-documentation)
205 :type (get 'pcomplete-restore-window-delay 'custom-type)
206 :group 'eshell-cmpl)
207
208(defcustom eshell-command-completion-function
209 (function
210 (lambda ()
211 (pcomplete-here (eshell-complete-commands-list))))
212 (documentation-property 'pcomplete-command-completion-function
213 'variable-documentation)
214 :type (get 'pcomplete-command-completion-function 'custom-type)
215 :group 'eshell-cmpl)
216
217(defcustom eshell-cmpl-command-name-function
218 'eshell-completion-command-name
219 (documentation-property 'pcomplete-command-name-function
220 'variable-documentation)
221 :type (get 'pcomplete-command-name-function 'custom-type)
222 :group 'eshell-cmpl)
223
224(defcustom eshell-default-completion-function
225 (function
226 (lambda ()
227 (while (pcomplete-here
228 (pcomplete-dirs-or-entries
229 (cdr (assoc (funcall eshell-cmpl-command-name-function)
230 eshell-command-completions-alist)))))))
231 (documentation-property 'pcomplete-default-completion-function
232 'variable-documentation)
233 :type (get 'pcomplete-default-completion-function 'custom-type)
ca7aae91
JW
234 :group 'eshell-cmpl)
235
236(defcustom eshell-cmpl-use-paring t
237 (documentation-property 'pcomplete-use-paring 'variable-documentation)
238 :type (get 'pcomplete-use-paring 'custom-type)
239 :group 'eshell-cmpl)
affbf647
GM
240
241;;; Functions:
242
243(defun eshell-cmpl-initialize ()
244 "Initialize the completions module."
245 (unless (fboundp 'pcomplete)
246 (load "pcmpl-auto" t t))
247 (set (make-local-variable 'pcomplete-command-completion-function)
248 eshell-command-completion-function)
249 (set (make-local-variable 'pcomplete-command-name-function)
250 eshell-cmpl-command-name-function)
251 (set (make-local-variable 'pcomplete-default-completion-function)
252 eshell-default-completion-function)
253 (set (make-local-variable 'pcomplete-parse-arguments-function)
254 'eshell-complete-parse-arguments)
255 (set (make-local-variable 'pcomplete-file-ignore)
256 eshell-cmpl-file-ignore)
257 (set (make-local-variable 'pcomplete-dir-ignore)
258 eshell-cmpl-dir-ignore)
259 (set (make-local-variable 'pcomplete-ignore-case)
260 eshell-cmpl-ignore-case)
261 (set (make-local-variable 'pcomplete-autolist)
262 eshell-cmpl-autolist)
263 (set (make-local-variable 'pcomplete-suffix-list)
264 eshell-cmpl-suffix-list)
265 (set (make-local-variable 'pcomplete-recexact)
266 eshell-cmpl-recexact)
267 (set (make-local-variable 'pcomplete-man-function)
268 eshell-cmpl-man-function)
269 (set (make-local-variable 'pcomplete-compare-entry-function)
270 eshell-cmpl-compare-entry-function)
271 (set (make-local-variable 'pcomplete-expand-before-complete)
272 eshell-cmpl-expand-before-complete)
273 (set (make-local-variable 'pcomplete-cycle-completions)
274 eshell-cmpl-cycle-completions)
275 (set (make-local-variable 'pcomplete-cycle-cutoff-length)
276 eshell-cmpl-cycle-cutoff-length)
277 (set (make-local-variable 'pcomplete-restore-window-delay)
278 eshell-cmpl-restore-window-delay)
ca7aae91
JW
279 (set (make-local-variable 'pcomplete-use-paring)
280 eshell-cmpl-use-paring)
affbf647
GM
281 ;; `pcomplete-arg-quote-list' should only be set after all the
282 ;; load-hooks for any other extension modules have been run, which
283 ;; is true at the time `eshell-mode-hook' is run
affbf647
GM
284 (add-hook 'eshell-mode-hook
285 (function
286 (lambda ()
287 (set (make-local-variable 'pcomplete-arg-quote-list)
288 eshell-special-chars-outside-quoting))) nil t)
affbf647
GM
289 (add-hook 'pcomplete-quote-arg-hook 'eshell-quote-backslash nil t)
290 (define-key eshell-mode-map [(meta tab)] 'lisp-complete-symbol)
291 (define-key eshell-mode-map [(meta control ?i)] 'lisp-complete-symbol)
292 (define-key eshell-command-map [(meta ?h)] 'eshell-completion-help)
293 (define-key eshell-command-map [tab] 'pcomplete-expand-and-complete)
294 (define-key eshell-command-map [(control ?i)]
295 'pcomplete-expand-and-complete)
296 (define-key eshell-command-map [space] 'pcomplete-expand)
297 (define-key eshell-command-map [? ] 'pcomplete-expand)
17c083ac
GM
298 (define-key eshell-mode-map [tab] 'eshell-pcomplete)
299 (define-key eshell-mode-map [(control ?i)] 'eshell-pcomplete)
93b05041
SM
300 (add-hook 'completion-at-point-functions
301 #'pcomplete-completions-at-point nil t)
affbf647 302 ;; jww (1999-10-19): Will this work on anything but X?
a3269bc4 303 (if (featurep 'xemacs)
affbf647 304 (define-key eshell-mode-map [iso-left-tab] 'pcomplete-reverse)
01d972a9 305 (define-key eshell-mode-map [backtab] 'pcomplete-reverse))
affbf647
GM
306 (define-key eshell-mode-map [(meta ??)] 'pcomplete-list))
307
308(defun eshell-completion-command-name ()
309 "Return the command name, possibly sans globbing."
310 (let ((cmd (file-name-nondirectory (pcomplete-arg 'first))))
311 (setq cmd (if (and (> (length cmd) 0)
a129972c 312 (eq (aref cmd 0) eshell-explicit-command-char))
affbf647
GM
313 (substring cmd 1)
314 cmd))
315 (if (eshell-under-windows-p)
316 (file-name-sans-extension cmd)
317 cmd)))
318
319(defun eshell-completion-help ()
320 (interactive)
321 (if (= (point) eshell-last-output-end)
322 (describe-prefix-bindings)
323 (call-interactively 'pcomplete-help)))
324
325(defun eshell-complete-parse-arguments ()
326 "Parse the command line arguments for `pcomplete-argument'."
327 (when (and eshell-no-completion-during-jobs
328 (eshell-interactive-process))
329 (insert-and-inherit "\t")
330 (throw 'pcompleted t))
331 (let ((end (point-marker))
332 (begin (save-excursion (eshell-bol) (point)))
333 (posns (list t))
334 args delim)
335 (when (memq this-command '(pcomplete-expand
336 pcomplete-expand-and-complete))
337 (run-hook-with-args 'eshell-expand-input-functions begin end)
338 (if (= begin end)
339 (end-of-line))
340 (setq end (point-marker)))
341 (if (setq delim
342 (catch 'eshell-incomplete
343 (ignore
344 (setq args (eshell-parse-arguments begin end)))))
345 (cond ((memq (car delim) '(?\{ ?\<))
346 (setq begin (1+ (cadr delim))
347 args (eshell-parse-arguments begin end)))
348 ((eq (car delim) ?\()
349 (lisp-complete-symbol)
350 (throw 'pcompleted t))
351 (t
352 (insert-and-inherit "\t")
353 (throw 'pcompleted t))))
354 (when (get-text-property (1- end) 'comment)
355 (insert-and-inherit "\t")
356 (throw 'pcompleted t))
357 (let ((pos begin))
358 (while (< pos end)
359 (if (get-text-property pos 'arg-begin)
360 (nconc posns (list pos)))
361 (setq pos (1+ pos))))
362 (setq posns (cdr posns))
a464a6c7 363 (cl-assert (= (length args) (length posns)))
affbf647
GM
364 (let ((a args)
365 (i 0)
366 l final)
367 (while a
368 (if (and (consp (car a))
369 (eq (caar a) 'eshell-operator))
370 (setq l i))
371 (setq a (cdr a) i (1+ i)))
372 (and l
373 (setq args (nthcdr (1+ l) args)
374 posns (nthcdr (1+ l) posns))))
a464a6c7 375 (cl-assert (= (length args) (length posns)))
34204d80
JW
376 (when (and args (eq (char-syntax (char-before end)) ? )
377 (not (eq (char-before (1- end)) ?\\)))
affbf647
GM
378 (nconc args (list ""))
379 (nconc posns (list (point))))
380 (cons (mapcar
381 (function
382 (lambda (arg)
383 (let ((val
384 (if (listp arg)
385 (let ((result
386 (eshell-do-eval
387 (list 'eshell-commands arg) t)))
a464a6c7 388 (cl-assert (eq (car result) 'quote))
affbf647
GM
389 (cadr result))
390 arg)))
391 (if (numberp val)
392 (setq val (number-to-string val)))
393 (or val ""))))
394 args)
395 posns)))
396
397(defun eshell-complete-commands-list ()
398 "Generate list of applicable, visible commands."
399 (let ((filename (pcomplete-arg)) glob-name)
400 (if (file-name-directory filename)
401 (pcomplete-executables)
402 (if (and (> (length filename) 0)
a129972c 403 (eq (aref filename 0) eshell-explicit-command-char))
affbf647
GM
404 (setq filename (substring filename 1)
405 pcomplete-stub filename
406 glob-name t))
605a20a9 407 (let* ((paths (eshell-parse-colon-path eshell-path-env))
affbf647
GM
408 (cwd (file-name-as-directory
409 (expand-file-name default-directory)))
410 (path "") (comps-in-path ())
411 (file "") (filepath "") (completions ()))
412 ;; Go thru each path in the search path, finding completions.
413 (while paths
414 (setq path (file-name-as-directory
415 (expand-file-name (or (car paths) ".")))
416 comps-in-path
417 (and (file-accessible-directory-p path)
418 (file-name-all-completions filename path)))
419 ;; Go thru each completion found, to see whether it should
420 ;; be used.
421 (while comps-in-path
422 (setq file (car comps-in-path)
423 filepath (concat path file))
424 (if (and (not (member file completions)) ;
425 (or (string-equal path cwd)
426 (not (file-directory-p filepath)))
427 (file-executable-p filepath))
428 (setq completions (cons file completions)))
429 (setq comps-in-path (cdr comps-in-path)))
430 (setq paths (cdr paths)))
431 ;; Add aliases which are currently visible, and Lisp functions.
432 (pcomplete-uniqify-list
433 (if glob-name
434 completions
435 (setq completions
436 (append (and (eshell-using-module 'eshell-alias)
437 (funcall (symbol-function 'eshell-alias-completions)
438 filename))
439 (eshell-winnow-list
440 (mapcar
441 (function
442 (lambda (name)
443 (substring name 7)))
444 (all-completions (concat "eshell/" filename)
445 obarray 'functionp))
446 nil '(eshell-find-alias-function))
447 completions))
448 (append (and (or eshell-show-lisp-completions
449 (and eshell-show-lisp-alternatives
450 (null completions)))
451 (all-completions filename obarray 'functionp))
452 completions)))))))
453
5ee1772e 454(defun eshell-pcomplete (&optional interactively)
17c083ac 455 "Eshell wrapper for `pcomplete'."
5ee1772e
GM
456 (interactive "p")
457 ;; Pretend to be pcomplete so that cycling works (bug#13293).
458 (setq this-command 'pcomplete)
93b05041 459 (condition-case nil
5ee1772e
GM
460 (if interactively
461 (call-interactively 'pcomplete)
462 (pcomplete))
93b05041 463 (text-read-only (completion-at-point)))) ; Workaround for bug#12838.
17c083ac 464
dbba8a04 465(provide 'em-cmpl)
affbf647 466
3146b070
GM
467;; Local Variables:
468;; generated-autoload-file: "esh-groups.el"
469;; End:
470
affbf647 471;;; em-cmpl.el ends here