changeset 71436:d51a5dc58935

(PC-do-completion): Retain capitalization of user input, when possible, even if completion-ignore-case is set.
author Eli Zaretskii <eliz@gnu.org>
date Fri, 23 Jun 2006 13:05:03 +0000
parents f5b76c613075
children 69a8381b4597
files lisp/complete.el
diffstat 1 files changed, 50 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/complete.el	Fri Jun 23 12:41:15 2006 +0000
+++ b/lisp/complete.el	Fri Jun 23 13:05:03 2006 +0000
@@ -196,7 +196,7 @@
 For example, M-x p-c-m expands to M-x partial-completion-mode since no other
 command begins with that sequence of characters, and
 \\[find-file] f_b.c TAB might complete to foo_bar.c if that file existed and no
-other file in that directory begin with that sequence of characters.
+other file in that directory begins with that sequence of characters.
 
 Unless `PC-disable-includes' is non-nil, the `<...>' sequence is interpreted
 specially in \\[find-file].  For example,
@@ -358,13 +358,36 @@
 The function takes no arguments, and typically looks at the value
 of `minibuffer-completion-table' and the minibuffer contents.")
 
+;; Returns the sequence of non-delimiter characters that follow regexp in string.
+(defun PC-chunk-after (string regexp)
+  (if (not (string-match regexp string))
+      (let ((message (format "String %s didn't match regexp %s" string regexp)))
+	(message message)
+	(error message)))
+  (let ((result (substring string (match-end 0))))
+    ;; result may contain multiple chunks
+    (if (string-match PC-delim-regex result)
+	(setq result (substring result 0 (match-beginning 0))))
+    result))
+
+(defun test-completion-ignore-case (str table pred)
+  "Like `test-completion', but ignores case when possible."
+  ;; Binding completion-ignore-case to nil ensures, for compatibility with
+  ;; standard completion, that the return value is exactly one of the
+  ;; possibilities.  Do this binding only if pred is nil, out of paranoia;
+  ;; perhaps it is safe even if pred is non-nil.
+  (if pred
+      (test-completion str table pred)
+    (let ((completion-ignore-case nil))
+      (test-completion str table pred))))
+
 (defun PC-do-completion (&optional mode beg end)
   (or beg (setq beg (minibuffer-prompt-end)))
   (or end (setq end (point-max)))
   (let* ((table minibuffer-completion-table)
 	 (pred minibuffer-completion-predicate)
 	 (filename (funcall PC-completion-as-file-name-predicate))
-	 (dirname nil)
+	 (dirname nil)		; non-nil only if a filename is being completed
 	 (dirlength 0)
 	 (str (buffer-substring beg end))
 	 (incname (and filename (string-match "<\\([^\"<>]*\\)>?$" str)))
@@ -379,7 +402,7 @@
 
     ;; Check if buffer contents can already be considered complete
     (if (and (eq mode 'exit)
-	     (test-completion str table pred))
+	     (test-completion-ignore-case str table pred))
 	'complete
 
       ;; Do substitutions in directory names
@@ -598,35 +621,38 @@
 
 	    ;; Check if next few letters are the same in all cases
 	    (if (and (not (eq mode 'help))
-		     (setq prefix (try-completion "" (mapcar 'list poss))))
+		     (setq prefix (try-completion (PC-chunk-after basestr skip) (mapcar 'list poss))))
 		(let ((first t) i)
+		  ;; Retain capitalization of user input even if
+		  ;; completion-ignore-case is set.
 		  (if (eq mode 'word)
 		      (setq prefix (PC-chop-word prefix basestr)))
 		  (goto-char (+ beg (length dirname)))
 		  (while (and (progn
-				(setq i 0)
+				(setq i 0) ; index into prefix string
 				(while (< i (length prefix))
 				  (if (and (< (point) end)
-					   (eq (aref prefix i)
-					       (following-char)))
+					   (eq (downcase (aref prefix i))
+					       (downcase (following-char))))
+				      ;; same char (modulo case); no action
 				      (forward-char 1)
 				    (if (and (< (point) end)
-					     (or (and (looking-at " ")
+					     (and (looking-at " ")
 						      (memq (aref prefix i)
-							    PC-delims-list))
-						 (eq (downcase (aref prefix i))
-						     (downcase
-						      (following-char)))))
+							PC-delims-list)))
+					;; replace " " by the actual delimiter
 					(progn
 					  (delete-char 1)
-					  (setq end (1- end)))
+					  (insert (substring prefix i (1+ i))))
+				      ;; insert a new character
+				      (progn
 				      (and filename (looking-at "\\*")
 					   (progn
 					     (delete-char 1)
 					     (setq end (1- end))))
-				      (setq improved t))
+					(setq improved t)
 				    (insert (substring prefix i (1+ i)))
-				    (setq end (1+ end)))
+					(setq end (1+ end)))))
 				  (setq i (1+ i)))
 				(or pt (setq pt (point)))
 				(looking-at PC-delim-regex))
@@ -634,7 +660,12 @@
 						 (regexp-quote prefix)
 						 PC-ndelims-regex)
 				    prefix (try-completion
-					    ""
+					    (PC-chunk-after
+					     ;; not basestr, because that does
+					     ;; not reflect insertions
+					     (buffer-substring
+					      (+ beg (length dirname)) end)
+					     skip)
 					    (mapcar
 					     (function
 					      (lambda (x)
@@ -666,7 +697,7 @@
 
 		  ;; We changed it... enough to be complete?
 		  (and (eq mode 'exit)
-		       (test-completion (field-string) table pred))
+		       (test-completion-ignore-case (field-string) table pred))
 
 		;; If totally ambiguous, display a list of completions
 		(if (or (eq completion-auto-help t)
@@ -950,11 +981,10 @@
   (if (string-match "<\\([^\"<>]*\\)>?\\'" (ad-get-arg 0))
       (let* ((string (ad-get-arg 0))
              (action (ad-get-arg 2))
-             (name (match-string 1 string))
+             (name (substring string (match-beginning 1) (match-end 1)))
 	     (str2 (substring string (match-beginning 0)))
 	     (completion-table
-	      (mapcar (lambda (x)
-			(format (if (string-match "/\\'" x) "<%s" "<%s>") x))
+	      (mapcar (lambda (x) (format "<%s>" x))
 		      (PC-include-file-all-completions
 		       name (PC-include-file-path)))))
         (setq ad-return-value