diff options
| author | Stefan Monnier | 2011-04-20 19:31:06 -0300 |
|---|---|---|
| committer | Stefan Monnier | 2011-04-20 19:31:06 -0300 |
| commit | c0a193ea2017fbaa6fb3e64a07125878656da156 (patch) | |
| tree | 52ecaae3b27b33e9de36b354cbc2d17e2334f411 | |
| parent | 201133802956936332f1c4ce04eac42dfd1cf1c6 (diff) | |
| download | emacs-c0a193ea2017fbaa6fb3e64a07125878656da156.tar.gz emacs-c0a193ea2017fbaa6fb3e64a07125878656da156.zip | |
* lisp/shell.el: Use lexical-binding and std completion UI.
(shell-filter-ctrl-a-ctrl-b): Work as a preoutput filter.
(shell-mode): Put shell-filter-ctrl-a-ctrl-b on
comint-preoutput-filter-functions rather than on
comint-output-filter-functions.
(shell-command-completion, shell--command-completion-data)
(shell-filename-completion, shell-environment-variable-completion)
(shell-c-a-p-replace-by-expanded-directory): New functions.
(shell-dynamic-complete-functions, shell-dynamic-complete-command)
(shell-dynamic-complete-filename, shell-replace-by-expanded-directory)
(shell-dynamic-complete-environment-variable): Use them.
(shell-dynamic-complete-as-environment-variable)
(shell-dynamic-complete-as-command): Remove.
(shell-match-partial-variable): Match past point.
* lisp/comint.el: Clean up use of completion-at-point-functions.
(comint-completion-at-point): New function.
(comint-mode): Use it completion-at-point-functions.
(comint-dynamic-complete): Make it obsolete.
(comint-replace-by-expanded-history-before-point): Add dry-run arg.
(comint-c-a-p-replace-by-expanded-history): New function.
(comint-dynamic-complete-functions)
(comint-replace-by-expanded-history): Use it.
* lisp/minibuffer.el (completion-table-with-terminator): Allow dynamic
termination strings. Try harder to avoid second try-completion.
(completion-in-region-mode-map): Disable bindings that don't work yet.
| -rw-r--r-- | etc/NEWS | 2 | ||||
| -rw-r--r-- | lisp/ChangeLog | 27 | ||||
| -rw-r--r-- | lisp/comint.el | 63 | ||||
| -rw-r--r-- | lisp/minibuffer.el | 24 | ||||
| -rw-r--r-- | lisp/shell.el | 217 |
5 files changed, 208 insertions, 125 deletions
| @@ -370,6 +370,8 @@ $ESHELL nor variable `explicit-shell-file-name' is set. | |||
| 370 | 370 | ||
| 371 | * Changes in Specialized Modes and Packages in Emacs 24.1 | 371 | * Changes in Specialized Modes and Packages in Emacs 24.1 |
| 372 | 372 | ||
| 373 | ** comint and modes derived from it use the generic completion code. | ||
| 374 | |||
| 373 | ** The compile.el mode can be used without font-lock-mode. | 375 | ** The compile.el mode can be used without font-lock-mode. |
| 374 | `compilation-parse-errors-function' is now obsolete. | 376 | `compilation-parse-errors-function' is now obsolete. |
| 375 | 377 | ||
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 214376b817c..70bb631df9e 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,31 @@ | |||
| 1 | 2011-04-20 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2011-04-20 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 2 | ||
| 3 | * shell.el: Use lexical-binding and std completion UI. | ||
| 4 | (shell-filter-ctrl-a-ctrl-b): Work as a preoutput filter. | ||
| 5 | (shell-mode): Put shell-filter-ctrl-a-ctrl-b on | ||
| 6 | comint-preoutput-filter-functions rather than on | ||
| 7 | comint-output-filter-functions. | ||
| 8 | (shell-command-completion, shell--command-completion-data) | ||
| 9 | (shell-filename-completion, shell-environment-variable-completion) | ||
| 10 | (shell-c-a-p-replace-by-expanded-directory): New functions. | ||
| 11 | (shell-dynamic-complete-functions, shell-dynamic-complete-command) | ||
| 12 | (shell-dynamic-complete-filename, shell-replace-by-expanded-directory) | ||
| 13 | (shell-dynamic-complete-environment-variable): Use them. | ||
| 14 | (shell-dynamic-complete-as-environment-variable) | ||
| 15 | (shell-dynamic-complete-as-command): Remove. | ||
| 16 | (shell-match-partial-variable): Match past point. | ||
| 17 | * comint.el: Clean up use of completion-at-point-functions. | ||
| 18 | (comint-completion-at-point): New function. | ||
| 19 | (comint-mode): Use it completion-at-point-functions. | ||
| 20 | (comint-dynamic-complete): Make it obsolete. | ||
| 21 | (comint-replace-by-expanded-history-before-point): Add dry-run arg. | ||
| 22 | (comint-c-a-p-replace-by-expanded-history): New function. | ||
| 23 | (comint-dynamic-complete-functions) | ||
| 24 | (comint-replace-by-expanded-history): Use it. | ||
| 25 | * minibuffer.el (completion-table-with-terminator): Allow dynamic | ||
| 26 | termination strings. Try harder to avoid second try-completion. | ||
| 27 | (completion-in-region-mode-map): Disable bindings that don't work yet. | ||
| 28 | |||
| 3 | * comint.el: Use lexical-binding. Require CL. | 29 | * comint.el: Use lexical-binding. Require CL. |
| 4 | (comint-dynamic-complete-functions): Use comint-filename-completion. | 30 | (comint-dynamic-complete-functions): Use comint-filename-completion. |
| 5 | (comint-completion-addsuffix): Tweak custom type. | 31 | (comint-completion-addsuffix): Tweak custom type. |
| @@ -9,6 +35,7 @@ | |||
| 9 | (comint-dynamic-complete-as-filename, comint-dynamic-complete-filename) | 35 | (comint-dynamic-complete-as-filename, comint-dynamic-complete-filename) |
| 10 | (comint-dynamic-list-filename-completions): Use them. | 36 | (comint-dynamic-list-filename-completions): Use them. |
| 11 | (comint-dynamic-simple-complete): Make obsolete. | 37 | (comint-dynamic-simple-complete): Make obsolete. |
| 38 | |||
| 12 | * minibuffer.el (completion-in-region-mode): | 39 | * minibuffer.el (completion-in-region-mode): |
| 13 | Keep completion-in-region-mode--predicate global. | 40 | Keep completion-in-region-mode--predicate global. |
| 14 | (completion-in-region--postch): | 41 | (completion-in-region--postch): |
diff --git a/lisp/comint.el b/lisp/comint.el index 735770a8908..8608c0d31e9 100644 --- a/lisp/comint.el +++ b/lisp/comint.el | |||
| @@ -367,7 +367,7 @@ text matching `comint-prompt-regexp', depending on the value of | |||
| 367 | `comint-use-prompt-regexp'.") | 367 | `comint-use-prompt-regexp'.") |
| 368 | 368 | ||
| 369 | (defvar comint-dynamic-complete-functions | 369 | (defvar comint-dynamic-complete-functions |
| 370 | '(comint-replace-by-expanded-history comint-filename-completion) | 370 | '(comint-c-a-p-replace-by-expanded-history comint-filename-completion) |
| 371 | "List of functions called to perform completion. | 371 | "List of functions called to perform completion. |
| 372 | Works like `completion-at-point-functions'. | 372 | Works like `completion-at-point-functions'. |
| 373 | See also `comint-dynamic-complete'. | 373 | See also `comint-dynamic-complete'. |
| @@ -493,7 +493,7 @@ executed once when the buffer is created." | |||
| 493 | (define-key map [menu-bar completion complete-file] | 493 | (define-key map [menu-bar completion complete-file] |
| 494 | '("Complete File Name" . comint-dynamic-complete-filename)) | 494 | '("Complete File Name" . comint-dynamic-complete-filename)) |
| 495 | (define-key map [menu-bar completion complete] | 495 | (define-key map [menu-bar completion complete] |
| 496 | '("Complete Before Point" . comint-dynamic-complete)) | 496 | '("Complete at Point" . completion-at-point)) |
| 497 | ;; Input history: | 497 | ;; Input history: |
| 498 | (define-key map [menu-bar inout] | 498 | (define-key map [menu-bar inout] |
| 499 | (cons "In/Out" (make-sparse-keymap "In/Out"))) | 499 | (cons "In/Out" (make-sparse-keymap "In/Out"))) |
| @@ -683,6 +683,7 @@ Entry to this mode runs the hooks on `comint-mode-hook'." | |||
| 683 | (setq font-lock-defaults '(nil t)) | 683 | (setq font-lock-defaults '(nil t)) |
| 684 | (add-hook 'change-major-mode-hook 'font-lock-defontify nil t) | 684 | (add-hook 'change-major-mode-hook 'font-lock-defontify nil t) |
| 685 | (add-hook 'isearch-mode-hook 'comint-history-isearch-setup nil t) | 685 | (add-hook 'isearch-mode-hook 'comint-history-isearch-setup nil t) |
| 686 | (add-hook 'completion-at-point-functions 'comint-completion-at-point nil t) | ||
| 686 | ;; This behavior is not useful in comint buffers, and is annoying | 687 | ;; This behavior is not useful in comint buffers, and is annoying |
| 687 | (set (make-local-variable 'next-line-add-newlines) nil)) | 688 | (set (make-local-variable 'next-line-add-newlines) nil)) |
| 688 | 689 | ||
| @@ -1231,6 +1232,12 @@ See `comint-magic-space' and `comint-replace-by-expanded-history-before-point'. | |||
| 1231 | 1232 | ||
| 1232 | Returns t if successful." | 1233 | Returns t if successful." |
| 1233 | (interactive) | 1234 | (interactive) |
| 1235 | (let ((f (comint-c-a-p-replace-by-expanded-history silent start))) | ||
| 1236 | (if f (funcall f)))) | ||
| 1237 | |||
| 1238 | (defun comint-c-a-p-replace-by-expanded-history (&optional silent start) | ||
| 1239 | "Expand input command history at point. | ||
| 1240 | For use on `completion-at-point-functions'." | ||
| 1234 | (if (and comint-input-autoexpand | 1241 | (if (and comint-input-autoexpand |
| 1235 | (if comint-use-prompt-regexp | 1242 | (if comint-use-prompt-regexp |
| 1236 | ;; Use comint-prompt-regexp | 1243 | ;; Use comint-prompt-regexp |
| @@ -1240,20 +1247,28 @@ Returns t if successful." | |||
| 1240 | ;; Use input fields. User input that hasn't been entered | 1247 | ;; Use input fields. User input that hasn't been entered |
| 1241 | ;; yet, at the end of the buffer, has a nil `field' property. | 1248 | ;; yet, at the end of the buffer, has a nil `field' property. |
| 1242 | (and (null (get-char-property (point) 'field)) | 1249 | (and (null (get-char-property (point) 'field)) |
| 1243 | (string-match "!\\|^\\^" (field-string))))) | 1250 | (string-match "!\\|^\\^" (field-string)))) |
| 1244 | ;; Looks like there might be history references in the command. | 1251 | (catch 'dry-run |
| 1245 | (let ((previous-modified-tick (buffer-modified-tick))) | 1252 | (comint-replace-by-expanded-history-before-point |
| 1246 | (comint-replace-by-expanded-history-before-point silent start) | 1253 | silent start 'dry-run))) |
| 1247 | (/= previous-modified-tick (buffer-modified-tick))))) | 1254 | (lambda () |
| 1248 | 1255 | ;; Looks like there might be history references in the command. | |
| 1249 | 1256 | (let ((previous-modified-tick (buffer-modified-tick))) | |
| 1250 | (defun comint-replace-by-expanded-history-before-point (silent &optional start) | 1257 | (comint-replace-by-expanded-history-before-point silent start) |
| 1258 | (/= previous-modified-tick (buffer-modified-tick)))))) | ||
| 1259 | |||
| 1260 | |||
| 1261 | (defun comint-replace-by-expanded-history-before-point | ||
| 1262 | (silent &optional start dry-run) | ||
| 1251 | "Expand directory stack reference before point. | 1263 | "Expand directory stack reference before point. |
| 1252 | See `comint-replace-by-expanded-history'. Returns t if successful. | 1264 | See `comint-replace-by-expanded-history'. Returns t if successful. |
| 1253 | 1265 | ||
| 1254 | If the optional argument START is non-nil, that specifies the | 1266 | If the optional argument START is non-nil, that specifies the |
| 1255 | start of the text to scan for history references, rather | 1267 | start of the text to scan for history references, rather |
| 1256 | than the logical beginning of line." | 1268 | than the logical beginning of line. |
| 1269 | |||
| 1270 | If DRY-RUN is non-nil, throw to DRY-RUN before performing any | ||
| 1271 | actual side-effect." | ||
| 1257 | (save-excursion | 1272 | (save-excursion |
| 1258 | (let ((toend (- (line-end-position) (point))) | 1273 | (let ((toend (- (line-end-position) (point))) |
| 1259 | (start (or start (comint-line-beginning-position)))) | 1274 | (start (or start (comint-line-beginning-position)))) |
| @@ -1274,10 +1289,12 @@ than the logical beginning of line." | |||
| 1274 | (goto-char (1+ (point)))) | 1289 | (goto-char (1+ (point)))) |
| 1275 | ((looking-at "![0-9]+\\($\\|[^-]\\)") | 1290 | ((looking-at "![0-9]+\\($\\|[^-]\\)") |
| 1276 | ;; We cannot know the interpreter's idea of input line numbers. | 1291 | ;; We cannot know the interpreter's idea of input line numbers. |
| 1292 | (if dry-run (throw dry-run 'message)) | ||
| 1277 | (goto-char (match-end 0)) | 1293 | (goto-char (match-end 0)) |
| 1278 | (message "Absolute reference cannot be expanded")) | 1294 | (message "Absolute reference cannot be expanded")) |
| 1279 | ((looking-at "!-\\([0-9]+\\)\\(:?[0-9^$*-]+\\)?") | 1295 | ((looking-at "!-\\([0-9]+\\)\\(:?[0-9^$*-]+\\)?") |
| 1280 | ;; Just a number of args from `number' lines backward. | 1296 | ;; Just a number of args from `number' lines backward. |
| 1297 | (if dry-run (throw dry-run 'history)) | ||
| 1281 | (let ((number (1- (string-to-number | 1298 | (let ((number (1- (string-to-number |
| 1282 | (buffer-substring (match-beginning 1) | 1299 | (buffer-substring (match-beginning 1) |
| 1283 | (match-end 1)))))) | 1300 | (match-end 1)))))) |
| @@ -1293,6 +1310,7 @@ than the logical beginning of line." | |||
| 1293 | (message "Relative reference exceeds input history size")))) | 1310 | (message "Relative reference exceeds input history size")))) |
| 1294 | ((or (looking-at "!!?:?\\([0-9^$*-]+\\)") (looking-at "!!")) | 1311 | ((or (looking-at "!!?:?\\([0-9^$*-]+\\)") (looking-at "!!")) |
| 1295 | ;; Just a number of args from the previous input line. | 1312 | ;; Just a number of args from the previous input line. |
| 1313 | (if dry-run (throw dry-run 'expand)) | ||
| 1296 | (replace-match (comint-args (comint-previous-input-string 0) | 1314 | (replace-match (comint-args (comint-previous-input-string 0) |
| 1297 | (match-beginning 1) (match-end 1)) | 1315 | (match-beginning 1) (match-end 1)) |
| 1298 | t t) | 1316 | t t) |
| @@ -1301,6 +1319,7 @@ than the logical beginning of line." | |||
| 1301 | "!\\??\\({\\(.+\\)}\\|\\(\\sw+\\)\\)\\(:?[0-9^$*-]+\\)?") | 1319 | "!\\??\\({\\(.+\\)}\\|\\(\\sw+\\)\\)\\(:?[0-9^$*-]+\\)?") |
| 1302 | ;; Most recent input starting with or containing (possibly | 1320 | ;; Most recent input starting with or containing (possibly |
| 1303 | ;; protected) string, maybe just a number of args. Phew. | 1321 | ;; protected) string, maybe just a number of args. Phew. |
| 1322 | (if dry-run (throw dry-run 'expand)) | ||
| 1304 | (let* ((mb1 (match-beginning 1)) (me1 (match-end 1)) | 1323 | (let* ((mb1 (match-beginning 1)) (me1 (match-end 1)) |
| 1305 | (mb2 (match-beginning 2)) (me2 (match-end 2)) | 1324 | (mb2 (match-beginning 2)) (me2 (match-end 2)) |
| 1306 | (exp (buffer-substring (or mb2 mb1) (or me2 me1))) | 1325 | (exp (buffer-substring (or mb2 mb1) (or me2 me1))) |
| @@ -1322,6 +1341,7 @@ than the logical beginning of line." | |||
| 1322 | (message "History item: %d" (1+ pos))))) | 1341 | (message "History item: %d" (1+ pos))))) |
| 1323 | ((looking-at "\\^\\([^^]+\\)\\^?\\([^^]*\\)\\^?") | 1342 | ((looking-at "\\^\\([^^]+\\)\\^?\\([^^]*\\)\\^?") |
| 1324 | ;; Quick substitution on the previous input line. | 1343 | ;; Quick substitution on the previous input line. |
| 1344 | (if dry-run (throw dry-run 'expand)) | ||
| 1325 | (let ((old (buffer-substring (match-beginning 1) (match-end 1))) | 1345 | (let ((old (buffer-substring (match-beginning 1) (match-end 1))) |
| 1326 | (new (buffer-substring (match-beginning 2) (match-end 2))) | 1346 | (new (buffer-substring (match-beginning 2) (match-end 2))) |
| 1327 | (pos nil)) | 1347 | (pos nil)) |
| @@ -1334,7 +1354,8 @@ than the logical beginning of line." | |||
| 1334 | (replace-match new t t) | 1354 | (replace-match new t t) |
| 1335 | (message "History item: substituted")))) | 1355 | (message "History item: substituted")))) |
| 1336 | (t | 1356 | (t |
| 1337 | (forward-char 1))))))) | 1357 | (forward-char 1))))) |
| 1358 | nil)) | ||
| 1338 | 1359 | ||
| 1339 | 1360 | ||
| 1340 | (defun comint-magic-space (arg) | 1361 | (defun comint-magic-space (arg) |
| @@ -1740,9 +1761,9 @@ Similarly for Soar, Scheme, etc." | |||
| 1740 | (insert copy) | 1761 | (insert copy) |
| 1741 | copy))) | 1762 | copy))) |
| 1742 | (input (if (not (eq comint-input-autoexpand 'input)) | 1763 | (input (if (not (eq comint-input-autoexpand 'input)) |
| 1743 | ;; Just whatever's already there | 1764 | ;; Just whatever's already there. |
| 1744 | intxt | 1765 | intxt |
| 1745 | ;; Expand and leave it visible in buffer | 1766 | ;; Expand and leave it visible in buffer. |
| 1746 | (comint-replace-by-expanded-history t pmark) | 1767 | (comint-replace-by-expanded-history t pmark) |
| 1747 | (buffer-substring pmark (point)))) | 1768 | (buffer-substring pmark (point)))) |
| 1748 | (history (if (not (eq comint-input-autoexpand 'history)) | 1769 | (history (if (not (eq comint-input-autoexpand 'history)) |
| @@ -2990,16 +3011,12 @@ Magic characters are those in `comint-file-name-quote-list'." | |||
| 2990 | (setq i (+ 1 (match-beginning 0))))) | 3011 | (setq i (+ 1 (match-beginning 0))))) |
| 2991 | filename))) | 3012 | filename))) |
| 2992 | 3013 | ||
| 3014 | (defun comint-completion-at-point () | ||
| 3015 | (run-hook-with-args-until-success 'comint-dynamic-complete-functions)) | ||
| 2993 | 3016 | ||
| 2994 | (defun comint-dynamic-complete () | 3017 | (define-obsolete-function-alias |
| 2995 | "Dynamically perform completion at point. | 3018 | 'comint-dynamic-complete |
| 2996 | Calls the functions in `comint-dynamic-complete-functions' to perform | 3019 | 'completion-at-point "24.1") |
| 2997 | completion until a function returns non-nil, at which point completion is | ||
| 2998 | assumed to have occurred." | ||
| 2999 | (interactive) | ||
| 3000 | (let ((completion-at-point-functions comint-dynamic-complete-functions)) | ||
| 3001 | (completion-at-point))) | ||
| 3002 | |||
| 3003 | 3020 | ||
| 3004 | (defun comint-dynamic-complete-filename () | 3021 | (defun comint-dynamic-complete-filename () |
| 3005 | "Dynamically complete the filename at point. | 3022 | "Dynamically complete the filename at point. |
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 0adf2a1d8b8..e012c324012 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -247,7 +247,9 @@ TERMINATOR can also be a cons cell (TERMINATOR . TERMINATOR-REGEXP) | |||
| 247 | in which case TERMINATOR-REGEXP is a regular expression whose submatch | 247 | in which case TERMINATOR-REGEXP is a regular expression whose submatch |
| 248 | number 1 should match TERMINATOR. This is used when there is a need to | 248 | number 1 should match TERMINATOR. This is used when there is a need to |
| 249 | distinguish occurrences of the TERMINATOR strings which are really terminators | 249 | distinguish occurrences of the TERMINATOR strings which are really terminators |
| 250 | from others (e.g. escaped)." | 250 | from others (e.g. escaped). In this form, the car of TERMINATOR can also be, |
| 251 | instead of a string, a function that takes the completion and returns the | ||
| 252 | \"terminated\" string." | ||
| 251 | ;; FIXME: This implementation is not right since it only adds the terminator | 253 | ;; FIXME: This implementation is not right since it only adds the terminator |
| 252 | ;; in try-completion, so any completion-style that builds the completion via | 254 | ;; in try-completion, so any completion-style that builds the completion via |
| 253 | ;; all-completions won't get the terminator, and selecting an entry in | 255 | ;; all-completions won't get the terminator, and selecting an entry in |
| @@ -258,22 +260,28 @@ from others (e.g. escaped)." | |||
| 258 | (bounds (completion-boundaries string table pred suffix)) | 260 | (bounds (completion-boundaries string table pred suffix)) |
| 259 | (terminator-regexp (if (consp terminator) | 261 | (terminator-regexp (if (consp terminator) |
| 260 | (cdr terminator) (regexp-quote terminator))) | 262 | (cdr terminator) (regexp-quote terminator))) |
| 261 | (max (string-match terminator-regexp suffix))) | 263 | (max (and terminator-regexp |
| 264 | (string-match terminator-regexp suffix)))) | ||
| 262 | (list* 'boundaries (car bounds) | 265 | (list* 'boundaries (car bounds) |
| 263 | (min (cdr bounds) (or max (length suffix)))))) | 266 | (min (cdr bounds) (or max (length suffix)))))) |
| 264 | ((eq action nil) | 267 | ((eq action nil) |
| 265 | (let ((comp (try-completion string table pred))) | 268 | (let ((comp (try-completion string table pred))) |
| 266 | (if (consp terminator) (setq terminator (car terminator))) | 269 | (if (consp terminator) (setq terminator (car terminator))) |
| 267 | (if (eq comp t) | 270 | (if (eq comp t) |
| 268 | (concat string terminator) | 271 | (if (functionp terminator) |
| 269 | (if (and (stringp comp) | 272 | (funcall terminator string) |
| 270 | ;; FIXME: Try to avoid this second call, especially since | 273 | (concat string terminator)) |
| 274 | (if (and (stringp comp) (not (zerop (length comp))) | ||
| 275 | ;; Try to avoid the second call to try-completion, since | ||
| 271 | ;; it may be very inefficient (because `comp' made us | 276 | ;; it may be very inefficient (because `comp' made us |
| 272 | ;; jump to a new boundary, so we complete in that | 277 | ;; jump to a new boundary, so we complete in that |
| 273 | ;; boundary with an empty start string). | 278 | ;; boundary with an empty start string). |
| 274 | ;; completion-boundaries might help. | 279 | (let ((newbounds (completion-boundaries comp table pred ""))) |
| 280 | (< (car newbounds) (length comp))) | ||
| 275 | (eq (try-completion comp table pred) t)) | 281 | (eq (try-completion comp table pred) t)) |
| 276 | (concat comp terminator) | 282 | (if (functionp terminator) |
| 283 | (funcall terminator comp) | ||
| 284 | (concat comp terminator)) | ||
| 277 | comp)))) | 285 | comp)))) |
| 278 | ((eq action t) | 286 | ((eq action t) |
| 279 | ;; FIXME: We generally want the `try' and `all' behaviors to be | 287 | ;; FIXME: We generally want the `try' and `all' behaviors to be |
| @@ -1294,6 +1302,8 @@ Point needs to be somewhere between START and END." | |||
| 1294 | 1302 | ||
| 1295 | (defvar completion-in-region-mode-map | 1303 | (defvar completion-in-region-mode-map |
| 1296 | (let ((map (make-sparse-keymap))) | 1304 | (let ((map (make-sparse-keymap))) |
| 1305 | ;; FIXME: Only works if completion-in-region-mode was activated via | ||
| 1306 | ;; completion-at-point called directly. | ||
| 1297 | (define-key map "?" 'completion-help-at-point) | 1307 | (define-key map "?" 'completion-help-at-point) |
| 1298 | (define-key map "\t" 'completion-at-point) | 1308 | (define-key map "\t" 'completion-at-point) |
| 1299 | map) | 1309 | map) |
diff --git a/lisp/shell.el b/lisp/shell.el index 57187b6d7f9..d6bc685618c 100644 --- a/lisp/shell.el +++ b/lisp/shell.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; shell.el --- specialized comint.el for running the shell | 1 | ;;; shell.el --- specialized comint.el for running the shell -*- lexical-binding: t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1988, 1993-1997, 2000-2011 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1988, 1993-1997, 2000-2011 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -79,7 +79,7 @@ | |||
| 79 | 79 | ||
| 80 | ;; Shell Mode Commands: | 80 | ;; Shell Mode Commands: |
| 81 | ;; shell Fires up the shell process | 81 | ;; shell Fires up the shell process |
| 82 | ;; tab comint-dynamic-complete Complete filename/command/history | 82 | ;; tab completion-at-point Complete filename/command/history |
| 83 | ;; m-? comint-dynamic-list-filename-completions | 83 | ;; m-? comint-dynamic-list-filename-completions |
| 84 | ;; List completions in help buffer | 84 | ;; List completions in help buffer |
| 85 | ;; m-c-f shell-forward-command Forward a shell command | 85 | ;; m-c-f shell-forward-command Forward a shell command |
| @@ -96,6 +96,7 @@ | |||
| 96 | 96 | ||
| 97 | ;;; Code: | 97 | ;;; Code: |
| 98 | 98 | ||
| 99 | (eval-when-compile (require 'cl)) | ||
| 99 | (require 'comint) | 100 | (require 'comint) |
| 100 | 101 | ||
| 101 | ;;; Customization and Buffer Variables | 102 | ;;; Customization and Buffer Variables |
| @@ -181,12 +182,12 @@ shell buffer. The value may depend on the operating system or shell. | |||
| 181 | This is a fine thing to set in your `.emacs' file.") | 182 | This is a fine thing to set in your `.emacs' file.") |
| 182 | 183 | ||
| 183 | (defvar shell-dynamic-complete-functions | 184 | (defvar shell-dynamic-complete-functions |
| 184 | '(comint-replace-by-expanded-history | 185 | '(comint-c-a-p-replace-by-expanded-history |
| 185 | shell-dynamic-complete-environment-variable | 186 | shell-environment-variable-completion |
| 186 | shell-dynamic-complete-command | 187 | shell-command-completion |
| 187 | shell-replace-by-expanded-directory | 188 | shell-c-a-p-replace-by-expanded-directory |
| 188 | shell-dynamic-complete-filename | 189 | shell-filename-completion |
| 189 | comint-dynamic-complete-filename) | 190 | comint-filename-completion) |
| 190 | "List of functions called to perform completion. | 191 | "List of functions called to perform completion. |
| 191 | This variable is used to initialize `comint-dynamic-complete-functions' in the | 192 | This variable is used to initialize `comint-dynamic-complete-functions' in the |
| 192 | shell buffer. | 193 | shell buffer. |
| @@ -312,7 +313,7 @@ This mirrors the optional behavior of tcsh (its autoexpand and histlit). | |||
| 312 | If the value is `input', then the expansion is seen on input. | 313 | If the value is `input', then the expansion is seen on input. |
| 313 | If the value is `history', then the expansion is only when inserting | 314 | If the value is `history', then the expansion is only when inserting |
| 314 | into the buffer's input ring. See also `comint-magic-space' and | 315 | into the buffer's input ring. See also `comint-magic-space' and |
| 315 | `comint-dynamic-complete'. | 316 | `comint-dynamic-complete-functions'. |
| 316 | 317 | ||
| 317 | This variable supplies a default for `comint-input-autoexpand', | 318 | This variable supplies a default for `comint-input-autoexpand', |
| 318 | for Shell mode only." | 319 | for Shell mode only." |
| @@ -339,7 +340,7 @@ Thus, this does not include the shell's current directory.") | |||
| 339 | (let ((map (nconc (make-sparse-keymap) comint-mode-map))) | 340 | (let ((map (nconc (make-sparse-keymap) comint-mode-map))) |
| 340 | (define-key map "\C-c\C-f" 'shell-forward-command) | 341 | (define-key map "\C-c\C-f" 'shell-forward-command) |
| 341 | (define-key map "\C-c\C-b" 'shell-backward-command) | 342 | (define-key map "\C-c\C-b" 'shell-backward-command) |
| 342 | (define-key map "\t" 'comint-dynamic-complete) | 343 | (define-key map "\t" 'completion-at-point) |
| 343 | (define-key map (kbd "M-RET") 'shell-resync-dirs) | 344 | (define-key map (kbd "M-RET") 'shell-resync-dirs) |
| 344 | (define-key map "\M-?" 'comint-dynamic-list-filename-completions) | 345 | (define-key map "\M-?" 'comint-dynamic-list-filename-completions) |
| 345 | (define-key map [menu-bar completion] | 346 | (define-key map [menu-bar completion] |
| @@ -486,7 +487,7 @@ buffer." | |||
| 486 | (t "dirs"))) | 487 | (t "dirs"))) |
| 487 | ;; Bypass a bug in certain versions of bash. | 488 | ;; Bypass a bug in certain versions of bash. |
| 488 | (when (string-equal shell "bash") | 489 | (when (string-equal shell "bash") |
| 489 | (add-hook 'comint-output-filter-functions | 490 | (add-hook 'comint-preoutput-filter-functions |
| 490 | 'shell-filter-ctrl-a-ctrl-b nil t))) | 491 | 'shell-filter-ctrl-a-ctrl-b nil t))) |
| 491 | (when shell-dir-cookie-re | 492 | (when shell-dir-cookie-re |
| 492 | ;; Watch for magic cookies in the output to track the current dir. | 493 | ;; Watch for magic cookies in the output to track the current dir. |
| @@ -494,7 +495,7 @@ buffer." | |||
| 494 | 'shell-dir-cookie-watcher nil t)) | 495 | 'shell-dir-cookie-watcher nil t)) |
| 495 | (comint-read-input-ring t))) | 496 | (comint-read-input-ring t))) |
| 496 | 497 | ||
| 497 | (defun shell-filter-ctrl-a-ctrl-b (_string) | 498 | (defun shell-filter-ctrl-a-ctrl-b (string) |
| 498 | "Remove `^A' and `^B' characters from comint output. | 499 | "Remove `^A' and `^B' characters from comint output. |
| 499 | 500 | ||
| 500 | Bash uses these characters as internal quoting characters in its | 501 | Bash uses these characters as internal quoting characters in its |
| @@ -504,15 +505,10 @@ started with the `--noediting' option and Select Graphic | |||
| 504 | Rendition (SGR) control sequences (formerly known as ANSI escape | 505 | Rendition (SGR) control sequences (formerly known as ANSI escape |
| 505 | sequences) are used to color the prompt. | 506 | sequences) are used to color the prompt. |
| 506 | 507 | ||
| 507 | This function can be put on `comint-output-filter-functions'. | 508 | This function can be put on `comint-preoutput-filter-functions'." |
| 508 | The argument STRING is ignored." | 509 | (if (string-match "[\C-a\C-b]" string) |
| 509 | (let ((pmark (process-mark (get-buffer-process (current-buffer))))) | 510 | (replace-regexp-in-string "[\C-a\C-b]" "" string t t) |
| 510 | (save-excursion | 511 | string)) |
| 511 | (goto-char (or (and (markerp comint-last-output-start) | ||
| 512 | (marker-position comint-last-output-start)) | ||
| 513 | (point-min))) | ||
| 514 | (while (re-search-forward "[\C-a\C-b]" pmark t) | ||
| 515 | (replace-match ""))))) | ||
| 516 | 512 | ||
| 517 | (defun shell-write-history-on-exit (process event) | 513 | (defun shell-write-history-on-exit (process event) |
| 518 | "Called when the shell process is stopped. | 514 | "Called when the shell process is stopped. |
| @@ -1011,30 +1007,36 @@ candidates. Note that this may not be the same as the shell's idea of the | |||
| 1011 | path. | 1007 | path. |
| 1012 | 1008 | ||
| 1013 | Completion is dependent on the value of `shell-completion-execonly', plus | 1009 | Completion is dependent on the value of `shell-completion-execonly', plus |
| 1014 | those that effect file completion. See `shell-dynamic-complete-as-command'. | 1010 | those that effect file completion. |
| 1015 | 1011 | ||
| 1016 | Returns t if successful." | 1012 | Returns t if successful." |
| 1017 | (interactive) | 1013 | (interactive) |
| 1014 | (let ((data (shell-command-completion))) | ||
| 1015 | (if data | ||
| 1016 | (prog2 (unless (window-minibuffer-p (selected-window)) | ||
| 1017 | (message "Completing command name...")) | ||
| 1018 | (apply #'completion-in-region data))))) | ||
| 1019 | |||
| 1020 | (defun shell-command-completion () | ||
| 1021 | "Return the completion data for the command at point, if any." | ||
| 1018 | (let ((filename (comint-match-partial-filename))) | 1022 | (let ((filename (comint-match-partial-filename))) |
| 1019 | (if (and filename | 1023 | (if (and filename |
| 1020 | (save-match-data (not (string-match "[~/]" filename))) | 1024 | (save-match-data (not (string-match "[~/]" filename))) |
| 1021 | (eq (match-beginning 0) | 1025 | (eq (match-beginning 0) |
| 1022 | (save-excursion (shell-backward-command 1) (point)))) | 1026 | (save-excursion (shell-backward-command 1) (point)))) |
| 1023 | (prog2 (unless (window-minibuffer-p (selected-window)) | 1027 | (shell--command-completion-data)))) |
| 1024 | (message "Completing command name...")) | ||
| 1025 | (shell-dynamic-complete-as-command))))) | ||
| 1026 | 1028 | ||
| 1027 | 1029 | (defun shell--command-completion-data () | |
| 1028 | (defun shell-dynamic-complete-as-command () | 1030 | "Return the completion data for the command at point." |
| 1029 | "Dynamically complete at point as a command. | ||
| 1030 | See `shell-dynamic-complete-filename'. Returns t if successful." | ||
| 1031 | (let* ((filename (or (comint-match-partial-filename) "")) | 1031 | (let* ((filename (or (comint-match-partial-filename) "")) |
| 1032 | (start (if (zerop (length filename)) (point) (match-beginning 0))) | ||
| 1033 | (end (if (zerop (length filename)) (point) (match-end 0))) | ||
| 1032 | (filenondir (file-name-nondirectory filename)) | 1034 | (filenondir (file-name-nondirectory filename)) |
| 1033 | (path-dirs (cdr (reverse exec-path))) | 1035 | (path-dirs (cdr (reverse exec-path))) ;FIXME: Why `cdr'? |
| 1034 | (cwd (file-name-as-directory (expand-file-name default-directory))) | 1036 | (cwd (file-name-as-directory (expand-file-name default-directory))) |
| 1035 | (ignored-extensions | 1037 | (ignored-extensions |
| 1036 | (and comint-completion-fignore | 1038 | (and comint-completion-fignore |
| 1037 | (mapconcat (function (lambda (x) (concat (regexp-quote x) "$"))) | 1039 | (mapconcat (function (lambda (x) (concat (regexp-quote x) "\\'"))) |
| 1038 | comint-completion-fignore "\\|"))) | 1040 | comint-completion-fignore "\\|"))) |
| 1039 | (dir "") (comps-in-dir ()) | 1041 | (dir "") (comps-in-dir ()) |
| 1040 | (file "") (abs-file-name "") (completions ())) | 1042 | (file "") (abs-file-name "") (completions ())) |
| @@ -1058,18 +1060,31 @@ See `shell-dynamic-complete-filename'. Returns t if successful." | |||
| 1058 | (setq comps-in-dir (cdr comps-in-dir))) | 1060 | (setq comps-in-dir (cdr comps-in-dir))) |
| 1059 | (setq path-dirs (cdr path-dirs))) | 1061 | (setq path-dirs (cdr path-dirs))) |
| 1060 | ;; OK, we've got a list of completions. | 1062 | ;; OK, we've got a list of completions. |
| 1061 | (let ((success (let ((comint-completion-addsuffix nil)) | 1063 | (list |
| 1062 | (comint-dynamic-simple-complete filenondir completions)))) | 1064 | start end |
| 1063 | (if (and (memq success '(sole shortest)) comint-completion-addsuffix | 1065 | (lambda (string pred action) |
| 1064 | (not (file-directory-p (comint-match-partial-filename)))) | 1066 | (completion-table-with-terminator |
| 1065 | (insert " ")) | 1067 | " " (lambda (string pred action) |
| 1066 | success))) | 1068 | (if (string-match "/" string) |
| 1069 | (completion-file-name-table string pred action) | ||
| 1070 | (complete-with-action action completions string pred))) | ||
| 1071 | string pred action))))) | ||
| 1072 | |||
| 1073 | ;; (defun shell-dynamic-complete-as-command () | ||
| 1074 | ;; "Dynamically complete at point as a command. | ||
| 1075 | ;; See `shell-dynamic-complete-filename'. Returns t if successful." | ||
| 1076 | ;; (apply #'completion-in-region shell--command-completion-data)) | ||
| 1067 | 1077 | ||
| 1068 | (defun shell-dynamic-complete-filename () | 1078 | (defun shell-dynamic-complete-filename () |
| 1069 | "Dynamically complete the filename at point. | 1079 | "Dynamically complete the filename at point. |
| 1070 | This completes only if point is at a suitable position for a | 1080 | This completes only if point is at a suitable position for a |
| 1071 | filename argument." | 1081 | filename argument." |
| 1072 | (interactive) | 1082 | (interactive) |
| 1083 | (let ((data (shell-filename-completion))) | ||
| 1084 | (if data (apply #'completion-in-region data)))) | ||
| 1085 | |||
| 1086 | (defun shell-filename-completion () | ||
| 1087 | "Return the completion data for file name at point, if any." | ||
| 1073 | (let ((opoint (point)) | 1088 | (let ((opoint (point)) |
| 1074 | (beg (comint-line-beginning-position))) | 1089 | (beg (comint-line-beginning-position))) |
| 1075 | (when (save-excursion | 1090 | (when (save-excursion |
| @@ -1077,24 +1092,21 @@ filename argument." | |||
| 1077 | (match-end 0) | 1092 | (match-end 0) |
| 1078 | beg)) | 1093 | beg)) |
| 1079 | (re-search-forward "[^ \t][ \t]" opoint t)) | 1094 | (re-search-forward "[^ \t][ \t]" opoint t)) |
| 1080 | (comint-dynamic-complete-as-filename)))) | 1095 | (comint-filename-completion)))) |
| 1081 | 1096 | ||
| 1082 | (defun shell-match-partial-variable () | 1097 | (defun shell-match-partial-variable () |
| 1083 | "Return the shell variable at point, or nil if none is found." | 1098 | "Return the shell variable at point, or nil if none is found." |
| 1084 | (save-excursion | 1099 | (save-excursion |
| 1085 | (let ((limit (point))) | 1100 | (if (re-search-backward "[^A-Za-z0-9_{(]" nil 'move) |
| 1086 | (if (re-search-backward "[^A-Za-z0-9_{}]" nil 'move) | 1101 | (or (looking-at "\\$") (forward-char 1))) |
| 1087 | (or (looking-at "\\$") (forward-char 1))) | 1102 | (if (or (eolp) (looking-at "[^A-Za-z0-9_{($]")) |
| 1088 | ;; Anchor the search forwards. | 1103 | nil |
| 1089 | (if (or (eolp) (looking-at "[^A-Za-z0-9_{}$]")) | 1104 | (looking-at "\\$?[{(]?[A-Za-z0-9_]*[})]?") |
| 1090 | nil | 1105 | (buffer-substring (match-beginning 0) (match-end 0))))) |
| 1091 | (re-search-forward "\\$?{?[A-Za-z0-9_]*}?" limit) | ||
| 1092 | (buffer-substring (match-beginning 0) (match-end 0)))))) | ||
| 1093 | 1106 | ||
| 1094 | (defun shell-dynamic-complete-environment-variable () | 1107 | (defun shell-dynamic-complete-environment-variable () |
| 1095 | "Dynamically complete the environment variable at point. | 1108 | "Dynamically complete the environment variable at point. |
| 1096 | Completes if after a variable, i.e., if it starts with a \"$\". | 1109 | Completes if after a variable, i.e., if it starts with a \"$\". |
| 1097 | See `shell-dynamic-complete-as-environment-variable'. | ||
| 1098 | 1110 | ||
| 1099 | This function is similar to `comint-dynamic-complete-filename', except that it | 1111 | This function is similar to `comint-dynamic-complete-filename', except that it |
| 1100 | searches `process-environment' for completion candidates. Note that this may | 1112 | searches `process-environment' for completion candidates. Note that this may |
| @@ -1106,38 +1118,69 @@ called `shell-dynamic-complete-process-environment-variable'. | |||
| 1106 | 1118 | ||
| 1107 | Returns non-nil if successful." | 1119 | Returns non-nil if successful." |
| 1108 | (interactive) | 1120 | (interactive) |
| 1109 | (let ((variable (shell-match-partial-variable))) | 1121 | (let ((data (shell-environment-variable-completion))) |
| 1110 | (if (and variable (string-match "^\\$" variable)) | 1122 | (if data |
| 1111 | (prog2 (unless (window-minibuffer-p (selected-window)) | 1123 | (prog2 (unless (window-minibuffer-p (selected-window)) |
| 1112 | (message "Completing variable name...")) | 1124 | (message "Completing variable name...")) |
| 1113 | (shell-dynamic-complete-as-environment-variable))))) | 1125 | (apply #'completion-in-region data))))) |
| 1114 | 1126 | ||
| 1115 | 1127 | ||
| 1116 | (defun shell-dynamic-complete-as-environment-variable () | 1128 | (defun shell-environment-variable-completion () |
| 1117 | "Dynamically complete at point as an environment variable. | 1129 | "Completion data for an environment variable at point, if any." |
| 1118 | Used by `shell-dynamic-complete-environment-variable'. | 1130 | (let* ((var (shell-match-partial-variable)) |
| 1119 | Uses `comint-dynamic-simple-complete'." | 1131 | (end (match-end 0))) |
| 1120 | (let* ((var (or (shell-match-partial-variable) "")) | 1132 | (when (and (not (zerop (length var))) (eq (aref var 0) ?$)) |
| 1121 | (variable (substring var (or (string-match "[^$({]\\|$" var) 0))) | 1133 | (let* ((start |
| 1122 | (variables (mapcar (function (lambda (x) | 1134 | (save-excursion |
| 1123 | (substring x 0 (string-match "=" x)))) | 1135 | (goto-char (match-beginning 0)) |
| 1124 | process-environment)) | 1136 | (looking-at "\\$?[({]*") |
| 1125 | (addsuffix comint-completion-addsuffix) | 1137 | (match-end 0))) |
| 1126 | (comint-completion-addsuffix nil) | 1138 | (variables (mapcar (lambda (x) |
| 1127 | (success (comint-dynamic-simple-complete variable variables))) | 1139 | (substring x 0 (string-match "=" x))) |
| 1128 | (if (memq success '(sole shortest)) | 1140 | process-environment)) |
| 1129 | (let* ((var (shell-match-partial-variable)) | 1141 | (suffix (case (char-before start) (?\{ "}") (?\( ")") (t "")))) |
| 1130 | (variable (substring var (string-match "[^$({]" var))) | 1142 | (list |
| 1131 | (protection (cond ((string-match "{" var) "}") | 1143 | start end |
| 1132 | ((string-match "(" var) ")") | 1144 | (apply-partially |
| 1133 | (t ""))) | 1145 | #'completion-table-with-terminator |
| 1134 | (suffix (cond ((null addsuffix) "") | 1146 | (cons (lambda (comp) |
| 1135 | ((file-directory-p | 1147 | (concat comp |
| 1136 | (comint-directory (getenv variable))) "/") | 1148 | suffix |
| 1137 | (t " ")))) | 1149 | (if (file-directory-p |
| 1138 | (insert protection suffix))) | 1150 | (comint-directory (getenv comp))) |
| 1139 | success)) | 1151 | "/"))) |
| 1140 | 1152 | "\\`a\\`") | |
| 1153 | variables)))))) | ||
| 1154 | |||
| 1155 | |||
| 1156 | (defun shell-c-a-p-replace-by-expanded-directory () | ||
| 1157 | "Expand directory stack reference before point. | ||
| 1158 | For use on `completion-at-point-functions'." | ||
| 1159 | (when (comint-match-partial-filename) | ||
| 1160 | (save-excursion | ||
| 1161 | (goto-char (match-beginning 0)) | ||
| 1162 | (let ((stack (cons default-directory shell-dirstack)) | ||
| 1163 | (index (cond ((looking-at "=-/?") | ||
| 1164 | (length shell-dirstack)) | ||
| 1165 | ((looking-at "=\\([0-9]+\\)/?") | ||
| 1166 | (string-to-number | ||
| 1167 | (buffer-substring | ||
| 1168 | (match-beginning 1) (match-end 1))))))) | ||
| 1169 | (when index | ||
| 1170 | (let ((start (match-beginning 0)) | ||
| 1171 | (end (match-end 0)) | ||
| 1172 | (replacement (file-name-as-directory (nth index stack)))) | ||
| 1173 | (lambda () | ||
| 1174 | (cond | ||
| 1175 | ((>= index (length stack)) | ||
| 1176 | (error "Directory stack not that deep")) | ||
| 1177 | (t | ||
| 1178 | (save-excursion | ||
| 1179 | (goto-char start) | ||
| 1180 | (insert replacement) | ||
| 1181 | (delete-char (- end start))) | ||
| 1182 | (message "Directory item: %d" index) | ||
| 1183 | t))))))))) | ||
| 1141 | 1184 | ||
| 1142 | (defun shell-replace-by-expanded-directory () | 1185 | (defun shell-replace-by-expanded-directory () |
| 1143 | "Expand directory stack reference before point. | 1186 | "Expand directory stack reference before point. |
| @@ -1146,24 +1189,8 @@ See `default-directory' and `shell-dirstack'. | |||
| 1146 | 1189 | ||
| 1147 | Returns t if successful." | 1190 | Returns t if successful." |
| 1148 | (interactive) | 1191 | (interactive) |
| 1149 | (if (comint-match-partial-filename) | 1192 | (let ((f (shell-c-a-p-replace-by-expanded-directory))) |
| 1150 | (save-excursion | 1193 | (if f (funcall f)))) |
| 1151 | (goto-char (match-beginning 0)) | ||
| 1152 | (let ((stack (cons default-directory shell-dirstack)) | ||
| 1153 | (index (cond ((looking-at "=-/?") | ||
| 1154 | (length shell-dirstack)) | ||
| 1155 | ((looking-at "=\\([0-9]+\\)/?") | ||
| 1156 | (string-to-number | ||
| 1157 | (buffer-substring | ||
| 1158 | (match-beginning 1) (match-end 1))))))) | ||
| 1159 | (cond ((null index) | ||
| 1160 | nil) | ||
| 1161 | ((>= index (length stack)) | ||
| 1162 | (error "Directory stack not that deep")) | ||
| 1163 | (t | ||
| 1164 | (replace-match (file-name-as-directory (nth index stack)) t t) | ||
| 1165 | (message "Directory item: %d" index) | ||
| 1166 | t)))))) | ||
| 1167 | 1194 | ||
| 1168 | (provide 'shell) | 1195 | (provide 'shell) |
| 1169 | 1196 | ||