aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoam Postavsky2016-10-27 22:17:11 -0400
committerNoam Postavsky2016-12-11 21:36:08 -0500
commita92a027d58cb4df5bb6c7e3c546a72183a192f45 (patch)
tree6de406718d319b0a8d514548852a48c7583bcd96
parent2783e0e3899cf92910e97dc8bfda3e47b3df1478 (diff)
downloademacs-a92a027d58cb4df5bb6c7e3c546a72183a192f45.tar.gz
emacs-a92a027d58cb4df5bb6c7e3c546a72183a192f45.zip
Quote filenames containing '~' in prompts
When in a directory named '~', the default value given by `read-file-name' should be quoted by prepending '/:', in order to prevent it from being interpreted as referring to the $HOME directory (Bug#16984). * lisp/minibuffer.el (minibuffer-maybe-quote-filename): New function. (completion--sifn-requote, read-file-name-default): Use it instead of `minibuffer--double-dollars'. * test/lisp/files-tests.el (files-test-read-file-in-~): Test it.
-rw-r--r--lisp/minibuffer.el25
-rw-r--r--test/lisp/files-tests.el23
2 files changed, 41 insertions, 7 deletions
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 175189c1b48..576b8041be9 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2251,6 +2251,17 @@ This is only used when the minibuffer area has no active minibuffer.")
2251 (replace-regexp-in-string "\\$" (lambda (dollar) (concat dollar dollar)) 2251 (replace-regexp-in-string "\\$" (lambda (dollar) (concat dollar dollar))
2252 str)) 2252 str))
2253 2253
2254(defun minibuffer-maybe-quote-filename (filename)
2255 "Protect FILENAME from `substitute-in-file-name', as needed.
2256Useful to give the user default values that won't be substituted."
2257 (if (and (not (file-name-quoted-p filename))
2258 (file-name-absolute-p filename)
2259 (string-match-p (if (memq system-type '(windows-nt ms-dos))
2260 "[/\\\\]~" "/~")
2261 (file-local-name filename)))
2262 (file-name-quote filename)
2263 (minibuffer--double-dollars filename)))
2264
2254(defun completion--make-envvar-table () 2265(defun completion--make-envvar-table ()
2255 (mapcar (lambda (enventry) 2266 (mapcar (lambda (enventry)
2256 (substring enventry 0 (string-match-p "=" enventry))) 2267 (substring enventry 0 (string-match-p "=" enventry)))
@@ -2420,7 +2431,7 @@ same as `substitute-in-file-name'."
2420 (substitute-in-file-name 2431 (substitute-in-file-name
2421 (substring qstr 0 (1- qpos))))) 2432 (substring qstr 0 (1- qpos)))))
2422 (setq qpos (1- qpos))) 2433 (setq qpos (1- qpos)))
2423 (cons qpos #'minibuffer--double-dollars)))) 2434 (cons qpos #'minibuffer-maybe-quote-filename))))
2424 2435
2425(defalias 'completion--file-name-table 2436(defalias 'completion--file-name-table
2426 (completion-table-with-quoting #'completion-file-name-table 2437 (completion-table-with-quoting #'completion-file-name-table
@@ -2596,10 +2607,10 @@ See `read-file-name' for the meaning of the arguments."
2596 (let ((insdef (cond 2607 (let ((insdef (cond
2597 ((and insert-default-directory (stringp dir)) 2608 ((and insert-default-directory (stringp dir))
2598 (if initial 2609 (if initial
2599 (cons (minibuffer--double-dollars (concat dir initial)) 2610 (cons (minibuffer-maybe-quote-filename (concat dir initial))
2600 (length (minibuffer--double-dollars dir))) 2611 (length (minibuffer-maybe-quote-filename dir)))
2601 (minibuffer--double-dollars dir))) 2612 (minibuffer-maybe-quote-filename dir)))
2602 (initial (cons (minibuffer--double-dollars initial) 0))))) 2613 (initial (cons (minibuffer-maybe-quote-filename initial) 0)))))
2603 2614
2604 (let ((completion-ignore-case read-file-name-completion-ignore-case) 2615 (let ((completion-ignore-case read-file-name-completion-ignore-case)
2605 (minibuffer-completing-file-name t) 2616 (minibuffer-completing-file-name t)
@@ -2693,7 +2704,7 @@ See `read-file-name' for the meaning of the arguments."
2693 ;; with what we will actually return. As an exception, 2704 ;; with what we will actually return. As an exception,
2694 ;; if that's the same as the second item in 2705 ;; if that's the same as the second item in
2695 ;; file-name-history, it's really a repeat (Bug#4657). 2706 ;; file-name-history, it's really a repeat (Bug#4657).
2696 (let ((val1 (minibuffer--double-dollars val))) 2707 (let ((val1 (minibuffer-maybe-quote-filename val)))
2697 (if history-delete-duplicates 2708 (if history-delete-duplicates
2698 (setcdr file-name-history 2709 (setcdr file-name-history
2699 (delete val1 (cdr file-name-history)))) 2710 (delete val1 (cdr file-name-history))))
@@ -2703,7 +2714,7 @@ See `read-file-name' for the meaning of the arguments."
2703 (if add-to-history 2714 (if add-to-history
2704 ;; Add the value to the history--but not if it matches 2715 ;; Add the value to the history--but not if it matches
2705 ;; the last value already there. 2716 ;; the last value already there.
2706 (let ((val1 (minibuffer--double-dollars val))) 2717 (let ((val1 (minibuffer-maybe-quote-filename val)))
2707 (unless (and (consp file-name-history) 2718 (unless (and (consp file-name-history)
2708 (equal (car file-name-history) val1)) 2719 (equal (car file-name-history) val1))
2709 (setq file-name-history 2720 (setq file-name-history
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 80d5e5befbc..f4ccd5c2044 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -220,5 +220,28 @@ form.")
220 (should-not yes-or-no-p-prompts) 220 (should-not yes-or-no-p-prompts)
221 (should (equal kill-emacs-args '(nil))))) 221 (should (equal kill-emacs-args '(nil)))))
222 222
223(ert-deftest files-test-read-file-in-~ ()
224 "Test file prompting in directory named '~'.
225If we are in a directory named '~', the default value should not
226be $HOME."
227 (cl-letf (((symbol-function 'completing-read)
228 (lambda (_prompt _coll &optional _pred _req init _hist def _)
229 (or def init)))
230 (dir (make-temp-file "read-file-name-test" t)))
231 (unwind-protect
232 (let ((subdir (expand-file-name "./~/")))
233 (make-directory subdir t)
234 (with-temp-buffer
235 (setq default-directory subdir)
236 (should-not (equal
237 (expand-file-name (read-file-name "File: "))
238 (expand-file-name "~/")))
239 ;; Don't overquote either!
240 (setq default-directory (concat "/:" subdir))
241 (should-not (equal
242 (expand-file-name (read-file-name "File: "))
243 (concat "/:/:" subdir)))))
244 (delete-directory dir 'recursive))))
245
223(provide 'files-tests) 246(provide 'files-tests)
224;;; files-tests.el ends here 247;;; files-tests.el ends here