Commits

Anonymous committed 81ab77a

Merge JWZ's completer changes, dealing with whitespace.

Comments (0)

Files changed (2)

+2010-01-08  Aidan Kehoe  <kehoea@parhasard.net>
+
+	Merge JWZ's completer changes of
+	942A74E9-346F-4A81-AB11-25672D50EE0C@jwz.org , dealing with
+	backslashes and spaces better.
+	* completer.el (file-system-ignore-case-p):
+	Provide an implementation of this function if it's not available.
+	(completer-matches):
+	Respect case-fold-search in this function. 
+	(completer-region): Revise to understand and skip over
+	backslashes.
+	(completer-file): Canonicalise slashes under windows-nt here;
+	understand and skip over backslashes in the string.
+
 2009-08-14  Norbert Koch  <viteno@xemacs.org>
 
 	* Makefile (VERSION): XEmacs package 1.35 released.
 
 (require 'cl)
 
+(eval-and-compile
+  (or (fboundp 'file-system-ignore-case-p)
+      (defalias 'file-system-ignore-case-p
+	(if (memq 'system-type '(windows-nt cygwin32 darwin cygwin))
+	 #'(lambda (path) t)
+	 #'(lambda (path) nil)))))
+
 ;;;%Globals
 ;;;%%Switches
 (defvar completer-load-hook nil
 	   (pattern nil)
 	   (len (length string))
 	   (matches nil)
+	   (string-equal-function
+	    (if case-fold-search
+		'equalp ;; We require 'cl above, this is always available.
+	      'string-equal))
 	   sub sublen choice word wordlen pat)
       ;; Segment pattern
       (while (< (or from 0) len)
 				end (+ begin wordlen)))
 		      (and (<= end (length choice))
 			   (or (zerop wordlen)
-			       (string-equal 
-				(car pat)
-				(substring choice begin end))))))
+			       (funcall string-equal-function
+					(car pat)
+					(substring choice begin end))))))
 	  (setq from (string-match regexp choice 
 				   (if (and (zerop from) (zerop wordlen))
 				       from
 
 ;;;%Completer
 ;;;%%Utilities
+;; changed to understand and skip over backslashes
 (defun completer-region (delimiters)
   "Return the completion region bounded by characters in DELIMITERS.
 The search is for the current buffer assuming that point is in it."
-  (cons (save-excursion (skip-chars-backward delimiters (minibuffer-prompt-end))
-                        (point))
-	(save-excursion (skip-chars-forward delimiters)
-                        (point))))
-	 
+   (let* ((inv (if (string-match "\\^" delimiters)
+                   (substring delimiters 1)
+                 (concat "^" delimiters)))
+          (re (and (not (equal inv ""))
+                   (concat "\\\\[" inv "]"))))
+     (cons (save-excursion
+             (let ((done nil))
+               (while (not done)
+                 (skip-chars-backward delimiters (minibuffer-prompt-end))
+                 (if (and re
+                          (> (point) (+ (point-min) 2))
+                          (save-excursion
+                            (forward-char -2)
+                            (looking-at re)))
+                     (goto-char (match-beginning 0))
+                   (setq done t))))
+             (point))
+           (save-excursion
+             (let ((done nil))
+               (while (not done)
+                 (skip-chars-forward delimiters)
+                 (if (and re
+                          (> (point) (+ (point-min) 1))
+                          (save-excursion
+                            (forward-char -1)
+                            (looking-at re)))
+                     (goto-char (match-end 0))
+                   (setq done t))))
+             (point)))))
+
 ;;;
 (defun completer-last-component (string)
   "Return the start of the last filename component in STRING."
 delimiters in WORD.  If optional MODE is nil or 'help then possible
 matches will always be returned."
   ;; Canonicalize slashes under windows-nt for proper completion
-  (when (eq system-type 'windows-nt)
-    (setq string (replace-in-string string "/" "\\\\")))
+  (if (eq system-type 'windows-nt)
+      (setq string (replace-in-string string "/" "\\\\"))
+    (setq string (replace-in-string string "\\\\\\(.\\)" "\\1")))
   (let* ((case-fold-search completion-ignore-case)
 	 (last (and (eq mode 'exit-ok) (completer-last-component string)))
 	 (position
 	 (len (length string))
 	 (choices nil)
 	 (end nil)
-	 (old-choices (list nil nil nil nil)))
+	 (old-choices (list nil nil nil nil))
+         match substr re)
     (while position
       (let* ((begin (string-match completer-path-separator-regexp
 				  string
 		(cons (if match (concat "~" (substring match len)))
 		      (cons (if lcs (concat "~" (substring lcs len)))
 			    (cdr (cdr choices)))))))
+    (setq match (nth 0 choices)
+          substr (nth 1 choices)
+          re (concat "\\(["		; "Now you have two problems":
+                     "]["		;   this has to come first;
+                     "\\\\"		;   this is one backslash;
+                     "\""		;   this is one quote;
+                     "^"		        ;   this can't come first;
+                     " \t"		;   whitespace;
+                     "#$&*?;!|'`()<>"	;   easy.
+                     "]\\)"))
+    (if match
+	(setf (nth 0 choices)
+	      (replace-in-string match re "\\\\\\1")))
+    (if substr
+	(setf (nth 1 choices)
+	      (replace-in-string substr re "\\\\\\1")))
     choices))
 
 ;;;%Exported program interface
 expanded.  Optional ANY is a delimiter that can match any delimiter in
 WORDS.  Optional MODE is nil for complete, 'help for help and 'exit
 for exit."
-  (if (and (stringp completer-string) 
-	   (string= string completer-string)
-	   (eq table completer-table)
-	   (eq pred completer-pred)
-	   (not file-p)
-	   (or (eq mode completer-mode)
-	       (not (memq table '(read-file-name-internal
-				  read-directory-name-internal)))))
-      completer-result
+  (let ((completion-ignore-case
+         (or (and file-p (file-system-ignore-case-p string))
+             completion-ignore-case)))
+    (if (and (stringp completer-string) 
+             (string= string completer-string)
+             (eq table completer-table)
+             (eq pred completer-pred)
+             (not file-p)
+             (or (eq mode completer-mode)
+                 (not (memq table '(read-file-name-internal
+                                    read-directory-name-internal)))))
+        completer-result
       (setq 
        completer-string ""
        completer-table table
 		(memq table '(read-file-name-internal
 			      read-directory-name-internal)))
 	   (completer-file string pred words any mode)
-	   (let* ((file-p (or file-p
-			      (memq table
-				    '(read-file-name-internal
-				      read-directory-name-internal))))
-		  (case-fold-search completion-ignore-case)
-		  (pattern (concat "[" words "]"))
-		  (component (if file-p (completer-last-component string)))
-		  (dir (if component (substring string 0 component)))
-		  (string (if dir (substring string component) string))
-		  (has-words (or (string-match pattern string)
-				 (length string))))
-	     (if (and file-p (string-match "^\\$" string))
-		 ;; Handle environment variables
-		 (let ((match
-			(getenv (substring string 1 
-					   ;; (string-match "/" string)))) ; old
-					   (string-match
-					    completer-path-separator-regexp
-					    string))))
-		       )
-		   ;; (if match (setq match (concat match "/"))) ; old
-		   (when match
-		     (setq match
-			   (concat match
-				   completer-path-separator-string)))
+         (let* ((file-p (or file-p
+                            (memq table
+                                  '(read-file-name-internal
+                                    read-directory-name-internal))))
+                (case-fold-search completion-ignore-case)
+                (pattern (concat "[" words "]"))
+                (component (if file-p (completer-last-component string)))
+                (dir (if component (substring string 0 component)))
+                (string (if dir (substring string component) string))
+                (has-words (or (string-match pattern string)
+                               (length string))))
+           (if (and file-p (string-match "^\\$" string))
+               ;; Handle environment variables
+               (let ((match
+                      (getenv (substring string 1 
+                                         ;; (string-match "/" string)))) ; old
+                                         (string-match
+                                          completer-path-separator-regexp
+                                          string))))
+                     )
+                 ;; (if match (setq match (concat match "/"))) ; old
+                 (when match
+                   (setq match
+                         (concat match
+                                 completer-path-separator-string)))
  
-		   (list match match (list match) match))
-		 (let* ((choices
-			 (all-completions 
-			  (concat dir (substring string 0 has-words))
-			  table pred))
-			(regexp (completer-regexp string words any)))
-		   (if choices
-		       (completer-match-record 
-			string 
-			(completer-deleter regexp choices t) 
-			words any dir mode)
-		       (list nil nil nil nil))))))
+                 (list match match (list match) match))
+             (let* ((choices
+                     (all-completions 
+                      (concat dir (substring string 0 has-words))
+                      table pred))
+                    (regexp (completer-regexp string words any)))
+               (if choices
+                   (completer-match-record 
+                    string 
+                    (completer-deleter regexp choices t) 
+                    words any dir mode)
+                 (list nil nil nil nil))))))
        completer-string string)
-      completer-result))
+      completer-result)))
 
 ;;;%%Display choices
 (defun completer-display-choices (choices &optional match message end
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.