aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2009-10-23 17:37:09 +0000
committerStefan Monnier2009-10-23 17:37:09 +0000
commit48feed599b8460b2ed757cf99e77fc895f0c5575 (patch)
treecf9612e0979f330f3be71a099dd2bda310e80cc2
parente8903e00e348b76a4409bf1a96d2d981b74f5be0 (diff)
downloademacs-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/ChangeLog10
-rw-r--r--lisp/pcomplete.el133
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 @@
12009-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
12009-10-23 Chong Yidong <cyd@stupidchicken.com> 112009-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.
407When TABLE, S1 and S2 are provided by `apply-partially', the result
408is a completion table which completes strings of the form (concat S1 S)
409in 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.
399Same as `pcomplete' but using the standard completion UI." 441Same 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,
625this is `comint-dynamic-complete-functions'." 701this 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