diff options
| author | Stefan Monnier | 2009-10-23 17:37:09 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2009-10-23 17:37:09 +0000 |
| commit | 48feed599b8460b2ed757cf99e77fc895f0c5575 (patch) | |
| tree | cf9612e0979f330f3be71a099dd2bda310e80cc2 | |
| parent | e8903e00e348b76a4409bf1a96d2d981b74f5be0 (diff) | |
| download | emacs-48feed599b8460b2ed757cf99e77fc895f0c5575.tar.gz emacs-48feed599b8460b2ed757cf99e77fc895f0c5575.zip | |
(pcomplete-common-suffix, pcomplete-table-subvert): New funs.
(pcomplete-std-complete): Use them. Obey pcomplete-termination-string.
(pcomplete-comint-setup): Don't modify a global var via
accidental side-effects.
(pcomplete-shell-setup): Adjust call accordingly.
(pcomplete-parse-comint-arguments): Use push.
| -rw-r--r-- | lisp/ChangeLog | 10 | ||||
| -rw-r--r-- | lisp/pcomplete.el | 133 |
2 files changed, 116 insertions, 27 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 1971496c36d..e90bf7e3c70 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,13 @@ | |||
| 1 | 2009-10-23 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * pcomplete.el (pcomplete-common-suffix, pcomplete-table-subvert): | ||
| 4 | New funs. | ||
| 5 | (pcomplete-std-complete): Use them. Obey pcomplete-termination-string. | ||
| 6 | (pcomplete-comint-setup): Don't modify a global var via | ||
| 7 | accidental side-effects. | ||
| 8 | (pcomplete-shell-setup): Adjust call accordingly. | ||
| 9 | (pcomplete-parse-comint-arguments): Use push. | ||
| 10 | |||
| 1 | 2009-10-23 Chong Yidong <cyd@stupidchicken.com> | 11 | 2009-10-23 Chong Yidong <cyd@stupidchicken.com> |
| 2 | 12 | ||
| 3 | * emacs-lisp/checkdoc.el (checkdoc-proper-noun-region-engine): | 13 | * emacs-lisp/checkdoc.el (checkdoc-proper-noun-region-engine): |
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el index ae2ef4b49ed..f23b219e1e1 100644 --- a/lisp/pcomplete.el +++ b/lisp/pcomplete.el | |||
| @@ -139,6 +139,8 @@ | |||
| 139 | :group 'pcomplete) | 139 | :group 'pcomplete) |
| 140 | 140 | ||
| 141 | (defcustom pcomplete-ignore-case (memq system-type '(ms-dos windows-nt cygwin)) | 141 | (defcustom pcomplete-ignore-case (memq system-type '(ms-dos windows-nt cygwin)) |
| 142 | ;; FIXME: the doc mentions file-name completion, but the code | ||
| 143 | ;; seems to apply it to all completions. | ||
| 142 | "If non-nil, ignore case when doing filename completion." | 144 | "If non-nil, ignore case when doing filename completion." |
| 143 | :type 'boolean | 145 | :type 'boolean |
| 144 | :group 'pcomplete) | 146 | :group 'pcomplete) |
| @@ -394,6 +396,46 @@ completion functions list (it should occur fairly early in the list)." | |||
| 394 | '(sole shortest)) | 396 | '(sole shortest)) |
| 395 | pcomplete-last-completion-raw)))))) | 397 | pcomplete-last-completion-raw)))))) |
| 396 | 398 | ||
| 399 | (defun pcomplete-common-suffix (s1 s2) | ||
| 400 | (assert (not (or (string-match "\n" s1) (string-match "\n" s2)))) | ||
| 401 | (let ((case-fold-search pcomplete-ignore-case)) | ||
| 402 | (string-match ".*?\\(.*\\)\n.*\\1\\'" (concat s1 "\n" s2)) | ||
| 403 | (- (match-end 1) (match-beginning 1)))) | ||
| 404 | |||
| 405 | (defun pcomplete-table-subvert (table s1 s2 string pred action) | ||
| 406 | "Completion table that replaces the prefix S1 with S2 in STRING. | ||
| 407 | When TABLE, S1 and S2 are provided by `apply-partially', the result | ||
| 408 | is a completion table which completes strings of the form (concat S1 S) | ||
| 409 | in the same way as TABLE completes strings of the form (concat S2 S)." | ||
| 410 | (let* ((str (if (eq t (compare-strings string 0 (length s1) s1 nil nil | ||
| 411 | completion-ignore-case)) | ||
| 412 | (concat s2 (substring string (length s1))))) | ||
| 413 | (res (if str (complete-with-action action table str pred)))) | ||
| 414 | (when res | ||
| 415 | (cond | ||
| 416 | ((and (eq (car-safe action) 'boundaries)) | ||
| 417 | (let ((beg (or (and (eq (car-safe res) 'boundaries) (cadr res)) 0))) | ||
| 418 | (list* 'boundaries | ||
| 419 | (max (length s1) | ||
| 420 | (+ beg (- (length s1) (length s2)))) | ||
| 421 | (and (eq (car-safe res) 'boundaries) (cddr res))))) | ||
| 422 | ((stringp res) | ||
| 423 | (if (eq t (compare-strings res 0 (length s2) s2 nil nil | ||
| 424 | completion-ignore-case)) | ||
| 425 | (concat s1 (substring res (length s2))))) | ||
| 426 | ((eq action t) | ||
| 427 | (let ((bounds (completion-boundaries str table pred ""))) | ||
| 428 | (if (>= (car bounds) (length s2)) | ||
| 429 | res | ||
| 430 | (let ((re (concat "\\`" | ||
| 431 | (regexp-quote (substring s2 (car bounds)))))) | ||
| 432 | (delq nil | ||
| 433 | (mapcar (lambda (c) | ||
| 434 | (if (string-match re c) | ||
| 435 | (substring c (match-end 0)))) | ||
| 436 | res)))))))))) | ||
| 437 | |||
| 438 | |||
| 397 | (defun pcomplete-std-complete () | 439 | (defun pcomplete-std-complete () |
| 398 | "Provide standard completion using pcomplete's completion tables. | 440 | "Provide standard completion using pcomplete's completion tables. |
| 399 | Same as `pcomplete' but using the standard completion UI." | 441 | Same as `pcomplete' but using the standard completion UI." |
| @@ -413,21 +455,55 @@ Same as `pcomplete' but using the standard completion UI." | |||
| 413 | ;; (returned indirectly in pcomplete-stub) and the set of | 455 | ;; (returned indirectly in pcomplete-stub) and the set of |
| 414 | ;; possible completions. | 456 | ;; possible completions. |
| 415 | (completions (pcomplete-completions)) | 457 | (completions (pcomplete-completions)) |
| 416 | ;; The pcomplete code seems to presume that pcomplete-stub | 458 | ;; Usually there's some close connection between pcomplete-stub |
| 417 | ;; is always the text before point. | 459 | ;; and the text before point. But depending on what |
| 418 | (ol (make-overlay (- (point) (length pcomplete-stub)) | 460 | ;; pcomplete-parse-arguments-function does, that connection |
| 419 | (point) nil nil t)) | 461 | ;; might not be that close. E.g. in eshell, |
| 420 | (minibuffer-completion-table | 462 | ;; pcomplete-parse-arguments-function expands envvars. |
| 421 | ;; Add a space at the end of completion. Use a terminator-regexp | 463 | ;; |
| 422 | ;; that never matches since the terminator cannot appear | 464 | ;; Since we use minibuffer-complete, which doesn't know |
| 423 | ;; within the completion field anyway. | 465 | ;; pcomplete-stub and works from the buffer's text instead, |
| 424 | (apply-partially 'completion-table-with-terminator | 466 | ;; we need to trick minibuffer-complete, into using |
| 425 | '(" " . "\\`a\\`") completions)) | 467 | ;; pcomplete-stub without its knowledge. To that end, we |
| 426 | (minibuffer-completion-predicate nil)) | 468 | ;; use pcomplete-table-subvert to construct a completion |
| 427 | (overlay-put ol 'field 'pcomplete) | 469 | ;; table which expects strings using a prefix from the |
| 428 | (unwind-protect | 470 | ;; buffer's text but internally uses the corresponding |
| 429 | (call-interactively 'minibuffer-complete) | 471 | ;; prefix from pcomplete-stub. |
| 430 | (delete-overlay ol))))) | 472 | (beg (max (- (point) (length pcomplete-stub)) |
| 473 | ;; Rather than `point-min' we should use the | ||
| 474 | ;; beginning position of the current arg. | ||
| 475 | (point-min))) | ||
| 476 | (buftext (buffer-substring beg (point))) | ||
| 477 | ;; This isn't always strictly right (e.g. if | ||
| 478 | ;; FOO="toto/$FOO", then completion of /$FOO/bar may | ||
| 479 | ;; result in something incorrect), but given the lack of | ||
| 480 | ;; any other info, it's about as good as it gets, and in | ||
| 481 | ;; practice it should work just fine (fingers crossed). | ||
| 482 | (suflen (pcomplete-common-suffix pcomplete-stub buftext))) | ||
| 483 | (unless (= suflen (length pcomplete-stub)) | ||
| 484 | (setq completions | ||
| 485 | (apply-partially | ||
| 486 | 'pcomplete-table-subvert | ||
| 487 | completions | ||
| 488 | (substring buftext 0 (- (length buftext) suflen)) | ||
| 489 | (substring pcomplete-stub | ||
| 490 | 0 (- (length pcomplete-stub) suflen))))) | ||
| 491 | (let ((ol (make-overlay beg (point) nil nil t)) | ||
| 492 | (minibuffer-completion-table | ||
| 493 | ;; Add a space at the end of completion. Use a terminator-regexp | ||
| 494 | ;; that never matches since the terminator cannot appear | ||
| 495 | ;; within the completion field anyway. | ||
| 496 | (if (zerop (length pcomplete-termination-string)) | ||
| 497 | completions | ||
| 498 | (apply-partially 'completion-table-with-terminator | ||
| 499 | (cons pcomplete-termination-string | ||
| 500 | "\\`a\\`") | ||
| 501 | completions))) | ||
| 502 | (minibuffer-completion-predicate nil)) | ||
| 503 | (overlay-put ol 'field 'pcomplete) | ||
| 504 | (unwind-protect | ||
| 505 | (call-interactively 'minibuffer-complete) | ||
| 506 | (delete-overlay ol)))))) | ||
| 431 | 507 | ||
| 432 | ;;;###autoload | 508 | ;;;###autoload |
| 433 | (defun pcomplete-reverse () | 509 | (defun pcomplete-reverse () |
| @@ -625,7 +701,8 @@ dynamic-complete-functions are kept. For comint mode itself, | |||
| 625 | this is `comint-dynamic-complete-functions'." | 701 | this is `comint-dynamic-complete-functions'." |
| 626 | (set (make-local-variable 'pcomplete-parse-arguments-function) | 702 | (set (make-local-variable 'pcomplete-parse-arguments-function) |
| 627 | 'pcomplete-parse-comint-arguments) | 703 | 'pcomplete-parse-comint-arguments) |
| 628 | (make-local-variable completef-sym) | 704 | (set (make-local-variable completef-sym) |
| 705 | (copy-sequence (symbol-value completef-sym))) | ||
| 629 | (let* ((funs (symbol-value completef-sym)) | 706 | (let* ((funs (symbol-value completef-sym)) |
| 630 | (elem (or (memq 'comint-dynamic-complete-filename funs) | 707 | (elem (or (memq 'comint-dynamic-complete-filename funs) |
| 631 | (memq 'shell-dynamic-complete-filename funs)))) | 708 | (memq 'shell-dynamic-complete-filename funs)))) |
| @@ -636,7 +713,7 @@ this is `comint-dynamic-complete-functions'." | |||
| 636 | ;;;###autoload | 713 | ;;;###autoload |
| 637 | (defun pcomplete-shell-setup () | 714 | (defun pcomplete-shell-setup () |
| 638 | "Setup `shell-mode' to use pcomplete." | 715 | "Setup `shell-mode' to use pcomplete." |
| 639 | (pcomplete-comint-setup 'shell-dynamic-complete-functions)) | 716 | (pcomplete-comint-setup 'comint-dynamic-complete-functions)) |
| 640 | 717 | ||
| 641 | (declare-function comint-bol "comint" (&optional arg)) | 718 | (declare-function comint-bol "comint" (&optional arg)) |
| 642 | 719 | ||
| @@ -649,17 +726,16 @@ this is `comint-dynamic-complete-functions'." | |||
| 649 | (goto-char begin) | 726 | (goto-char begin) |
| 650 | (while (< (point) end) | 727 | (while (< (point) end) |
| 651 | (skip-chars-forward " \t\n") | 728 | (skip-chars-forward " \t\n") |
| 652 | (setq begins (cons (point) begins)) | 729 | (push (point) begins) |
| 653 | (let ((skip t)) | 730 | (let ((skip t)) |
| 654 | (while skip | 731 | (while skip |
| 655 | (skip-chars-forward "^ \t\n") | 732 | (skip-chars-forward "^ \t\n") |
| 656 | (if (eq (char-before) ?\\) | 733 | (if (eq (char-before) ?\\) |
| 657 | (skip-chars-forward " \t\n") | 734 | (skip-chars-forward " \t\n") |
| 658 | (setq skip nil)))) | 735 | (setq skip nil)))) |
| 659 | (setq args (cons (buffer-substring-no-properties | 736 | (push (buffer-substring-no-properties (car begins) (point)) |
| 660 | (car begins) (point)) | 737 | args)) |
| 661 | args))) | 738 | (cons (nreverse args) (nreverse begins))))) |
| 662 | (cons (reverse args) (reverse begins))))) | ||
| 663 | 739 | ||
| 664 | (defun pcomplete-parse-arguments (&optional expand-p) | 740 | (defun pcomplete-parse-arguments (&optional expand-p) |
| 665 | "Parse the command line arguments. Most completions need this info." | 741 | "Parse the command line arguments. Most completions need this info." |
| @@ -672,9 +748,9 @@ this is `comint-dynamic-complete-functions'." | |||
| 672 | pcomplete-stub (pcomplete-arg 'last)) | 748 | pcomplete-stub (pcomplete-arg 'last)) |
| 673 | (let ((begin (pcomplete-begin 'last))) | 749 | (let ((begin (pcomplete-begin 'last))) |
| 674 | (if (and pcomplete-cycle-completions | 750 | (if (and pcomplete-cycle-completions |
| 675 | (listp pcomplete-stub) | 751 | (listp pcomplete-stub) ;?? |
| 676 | (not pcomplete-expand-only-p)) | 752 | (not pcomplete-expand-only-p)) |
| 677 | (let* ((completions pcomplete-stub) | 753 | (let* ((completions pcomplete-stub) ;?? |
| 678 | (common-stub (car completions)) | 754 | (common-stub (car completions)) |
| 679 | (c completions) | 755 | (c completions) |
| 680 | (len (length common-stub))) | 756 | (len (length common-stub))) |
| @@ -723,9 +799,9 @@ Magic characters are those in `pcomplete-arg-quote-list'." | |||
| 723 | (cond | 799 | (cond |
| 724 | (replacement | 800 | (replacement |
| 725 | (setq result (concat result replacement))) | 801 | (setq result (concat result replacement))) |
| 726 | ((and (setq char (aref filename index)) | 802 | ((memq (setq char (aref filename index)) |
| 727 | (memq char pcomplete-arg-quote-list)) | 803 | pcomplete-arg-quote-list) |
| 728 | (setq result (concat result "\\" (char-to-string char)))) | 804 | (setq result (concat result (string "\\" char)))) |
| 729 | (t | 805 | (t |
| 730 | (setq result (concat result (char-to-string char))))) | 806 | (setq result (concat result (char-to-string char))))) |
| 731 | (setq index (1+ index))) | 807 | (setq index (1+ index))) |
| @@ -1055,6 +1131,9 @@ Returns non-nil if a space was appended at the end." | |||
| 1055 | (substring entry (length stub))))) | 1131 | (substring entry (length stub))))) |
| 1056 | ;; the stub is not quoted at this time, so to determine the | 1132 | ;; the stub is not quoted at this time, so to determine the |
| 1057 | ;; length of what should be in the buffer, we must quote it | 1133 | ;; length of what should be in the buffer, we must quote it |
| 1134 | ;; FIXME: Here we presume that quoting `stub' gives us the exact | ||
| 1135 | ;; text in the buffer before point, which is not guaranteed; | ||
| 1136 | ;; e.g. it is not the case in eshell when completing ${FOO}tm[TAB]. | ||
| 1058 | (delete-backward-char (length (pcomplete-quote-argument stub))) | 1137 | (delete-backward-char (length (pcomplete-quote-argument stub))) |
| 1059 | ;; if there is already a backslash present to handle the first | 1138 | ;; if there is already a backslash present to handle the first |
| 1060 | ;; character, don't bother quoting it | 1139 | ;; character, don't bother quoting it |