From dccb0688651388531f00de3c8b365cdabcf54aa2 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sun, 4 May 2014 21:46:47 -0400 Subject: [PATCH] * lisp/minibuffer.el (completion-table-with-quoting) : Make sure the new point we return is within the new string. Fixes: debbugs:17239 --- lisp/ChangeLog | 5 +++++ lisp/minibuffer.el | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index e1a0ee66dd..bef5f1ba71 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2014-05-05 Stefan Monnier + + * minibuffer.el (completion-table-with-quoting) : + Make sure the new point we return is within the new string (bug#17239). + 2014-05-03 Eli Zaretskii * mail/rmailsum.el (rmail-new-summary-1): Fix a typo in a comment. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 9dd4ef9fe0..87ba8a22e6 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -519,11 +519,35 @@ for use at QPOS." completions)) ((eq action 'completion--unquote) - (let ((ustring (funcall unquote string)) - (uprefix (funcall unquote (substring string 0 pred)))) - ;; We presume (more or less) that `concat' and `unquote' commute. - (cl-assert (string-prefix-p uprefix ustring)) - (list ustring table (length uprefix) + ;; PRED is really a POINT in STRING. + ;; We should return a new set (STRING TABLE POINT REQUOTE) + ;; where STRING is a new (unquoted) STRING to match against the new TABLE + ;; using a new POINT inside it, and REQUOTE is a requoting function which + ;; should reverse the unquoting, (i.e. it receives the completion result + ;; of using the new TABLE and should turn it into the corresponding + ;; quoted result). + (let* ((qpos pred) + (ustring (funcall unquote string)) + (uprefix (funcall unquote (substring string 0 qpos))) + ;; FIXME: we really should pass `qpos' to `unuote' and have that + ;; function give us the corresponding `uqpos'. But for now we + ;; presume (more or less) that `concat' and `unquote' commute. + (uqpos (if (string-prefix-p uprefix ustring) + ;; Yay!! They do seem to commute! + (length uprefix) + ;; They don't commute this time! :-( + ;; Maybe qpos is in some text that disappears in the + ;; ustring (bug#17239). Let's try a second chance guess. + (let ((usuffix (funcall unquote (substring string qpos)))) + (if (string-suffix-p usuffix ustring) + ;; Yay!! They still "commute" in a sense! + (- (length ustring) (length usuffix)) + ;; Still no luck! Let's just choose *some* position + ;; within ustring. + (/ (+ (min (length uprefix) (length ustring)) + (max (- (length ustring) (length usuffix)) 0)) + 2)))))) + (list ustring table uqpos (lambda (unquoted-result op) (pcase op (1 ;;try @@ -853,6 +877,7 @@ completing buffer and file names, respectively." (setq string (pop new)) (setq table (pop new)) (setq point (pop new)) + (cl-assert (<= point (length string))) (pop new)))) (result (completion--some (lambda (style) -- 2.20.1