aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2012-10-28 14:48:17 -0400
committerStefan Monnier2012-10-28 14:48:17 -0400
commit86957a0cd3f273a83ce6584dcbaf513c2db429dc (patch)
tree0966ccd69b87bbe74eef2a57f95c01ed7b5332e1
parent640bf8ad44027d37f917d0927e50c2dfea254917 (diff)
downloademacs-86957a0cd3f273a83ce6584dcbaf513c2db429dc.tar.gz
emacs-86957a0cd3f273a83ce6584dcbaf513c2db429dc.zip
* lisp/minibuffer.el (completion--sifn-requote): Rewrite to handle things
like Tramp's "/foo:~bar//baz" -> "/scpc:foo:/baz" mapping. Fixes: debbugs:11714
-rw-r--r--lisp/ChangeLog3
-rw-r--r--lisp/minibuffer.el80
2 files changed, 42 insertions, 41 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index c52ed5e6e8b..74e63b140c4 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,8 @@
12012-10-28 Stefan Monnier <monnier@iro.umontreal.ca> 12012-10-28 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * minibuffer.el (completion--sifn-requote): Rewrite to handle things
4 like Tramp's "/foo:~bar//baz" -> "/scpc:foo:/baz" mapping (bug#11714).
5
3 * tmm.el (tmm-prompt): Use map-keymap (bug#12744). 6 * tmm.el (tmm-prompt): Use map-keymap (bug#12744).
4 7
52012-10-27 Eli Zaretskii <eliz@gnu.org> 82012-10-27 Eli Zaretskii <eliz@gnu.org>
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 52c3a0ba659..420d8f9d0fd 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -378,6 +378,8 @@ Note: TABLE needs to be a proper completion table which obeys predicates."
378 ;; that `concat' and `unquote' commute (which tends to be the case). 378 ;; that `concat' and `unquote' commute (which tends to be the case).
379 ;; And we ask `requote' to do the work of mapping from unquoted positions 379 ;; And we ask `requote' to do the work of mapping from unquoted positions
380 ;; back to quoted positions. 380 ;; back to quoted positions.
381 ;; FIXME: For some forms of "quoting" such as the truncation behavior of
382 ;; substitute-in-file-name, it would be desirable not to requote completely.
381 "Return a new completion table operating on quoted text. 383 "Return a new completion table operating on quoted text.
382TABLE operates on the unquoted text. 384TABLE operates on the unquoted text.
383UNQUOTE is a function that takes a string and returns a new unquoted string. 385UNQUOTE is a function that takes a string and returns a new unquoted string.
@@ -2161,53 +2163,49 @@ same as `substitute-in-file-name'."
2161 "use the regular PRED argument" "23.2") 2163 "use the regular PRED argument" "23.2")
2162 2164
2163(defun completion--sifn-requote (upos qstr) 2165(defun completion--sifn-requote (upos qstr)
2164 ;; We're looking for `qupos' such that: 2166 ;; We're looking for `qpos' such that:
2165 ;; (equal (substring (substitute-in-file-name qstr) 0 upos) 2167 ;; (equal (substring (substitute-in-file-name qstr) 0 upos)
2166 ;; (substitute-in-file-name (substring qstr 0 qupos))) 2168 ;; (substitute-in-file-name (substring qstr 0 qpos)))
2167 ;; Big problem here: we have to reverse engineer substitute-in-file-name to 2169 ;; Big problem here: we have to reverse engineer substitute-in-file-name to
2168 ;; find the position corresponding to UPOS in QSTR, but 2170 ;; find the position corresponding to UPOS in QSTR, but
2169 ;; substitute-in-file-name can do anything, depending on file-name-handlers. 2171 ;; substitute-in-file-name can do anything, depending on file-name-handlers.
2172 ;; substitute-in-file-name does the following kind of things:
2173 ;; - expand env-var references.
2174 ;; - turn backslashes into slashes.
2175 ;; - truncate some prefix of the input.
2176 ;; - rewrite some prefix.
2177 ;; Some of these operations are written in external libraries and we'd rather
2178 ;; not hard code any assumptions here about what they actually do. IOW, we
2179 ;; want to treat substitute-in-file-name as a black box, as much as possible.
2170 ;; Kind of like in rfn-eshadow-update-overlay, only worse. 2180 ;; Kind of like in rfn-eshadow-update-overlay, only worse.
2171 ;; FIXME: example of thing we do not handle: Tramp's makes 2181 ;; Example of things we need to handle:
2172 ;; (substitute-in-file-name "/foo:~/bar//baz") -> "/scpc:foo:/baz". 2182 ;; - Tramp (substitute-in-file-name "/foo:~/bar//baz") => "/scpc:foo:/baz".
2173 ;; FIXME: One way to try and handle "all" cases is to require 2183 ;; - Cygwin (substitute-in-file-name "C:\bin") => "/usr/bin"
2174 ;; substitute-in-file-name to preserve text-properties, so we could 2184 ;; (substitute-in-file-name "C:\") => "/"
2175 ;; apply text-properties to the input string and then look for them in 2185 ;; (substitute-in-file-name "C:\bi") => "/bi"
2176 ;; the output to understand what comes from where. 2186 (let* ((ustr (substitute-in-file-name qstr))
2177 (let ((qpos 0)) 2187 (uprefix (substring ustr 0 upos))
2178 ;; Handle substitute-in-file-name's truncation behavior. 2188 qprefix)
2179 (let (tpos) 2189 ;; Main assumption: nothing after qpos should affect the text before upos,
2180 (while (and (string-match "[\\/][~/\\]" qstr qpos) 2190 ;; so we can work our way backward from the end of qstr, one character
2181 ;; Hopefully our regexp covers all truncation cases. 2191 ;; at a time.
2182 ;; Also let's make sure sifn indeed truncates here. 2192 ;; Second assumptions: If qpos is far from the end this can be a bit slow,
2193 ;; so we speed it up by doing a first loop that skips a word at a time.
2194 ;; This word-sized loop is careful not to cut in the middle of env-vars.
2195 (while (let ((boundary (string-match "\\(\\$+{?\\)?\\w+\\W*\\'" qstr)))
2196 (and boundary
2183 (progn 2197 (progn
2184 (setq tpos (1+ (match-beginning 0))) 2198 (setq qprefix (substring qstr 0 boundary))
2185 (equal (substitute-in-file-name qstr) 2199 (string-prefix-p uprefix
2186 (substitute-in-file-name (substring qstr tpos))))) 2200 (substitute-in-file-name qprefix)))))
2187 (setq qpos tpos))) 2201 (setq qstr qprefix))
2188 ;; `upos' is relative to the position corresponding to `qpos' in 2202 (let ((qpos (length qstr)))
2189 ;; (substitute-in-file-name qstr), so as qpos moves forward, upos 2203 (while (and (> qpos 0)
2190 ;; gets smaller. 2204 (string-prefix-p uprefix
2191 (while (and (> upos 0) 2205 (substitute-in-file-name
2192 (string-match "\\$\\(\\$\\|\\([[:alnum:]_]+\\|{[^}]*}\\)\\)?" 2206 (substring qstr 0 (1- qpos)))))
2193 qstr qpos)) 2207 (setq qpos (1- qpos)))
2194 (cond 2208 (cons qpos #'minibuffer--double-dollars))))
2195 ((>= (- (match-beginning 0) qpos) upos) ; UPOS is before current match.
2196 (setq qpos (+ qpos upos))
2197 (setq upos 0))
2198 ((not (match-end 1)) ;A sole $: probably an error.
2199 (setq upos (- upos (- (match-end 0) qpos)))
2200 (setq qpos (match-end 0)))
2201 (t
2202 (setq upos (- upos (- (match-beginning 0) qpos)))
2203 (setq qpos (match-end 0))
2204 (setq upos (- upos (length (substitute-in-file-name
2205 (match-string 0 qstr))))))))
2206 ;; If `upos' is negative, it's because it's within the expansion of an
2207 ;; envvar, i.e. there is no exactly matching qpos, so we just use the next
2208 ;; available qpos right after the envvar.
2209 (cons (if (>= upos 0) (+ qpos upos) qpos)
2210 #'minibuffer--double-dollars)))
2211 2209
2212(defalias 'completion--file-name-table 2210(defalias 'completion--file-name-table
2213 (completion-table-with-quoting #'completion-file-name-table 2211 (completion-table-with-quoting #'completion-file-name-table