em-cmpl.el 16 KB

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