Function: completion--sifn-requote

completion--sifn-requote is a byte-compiled function defined in minibuffer.el.gz.

Signature

(completion--sifn-requote UPOS QSTR)

Source Code

;; Defined in /usr/src/emacs/lisp/minibuffer.el.gz
    (file-error nil)))               ;PCM often calls with invalid directories.

(defun completion--sifn-requote (upos qstr)
  ;; We're looking for `qpos' such that:
  ;; (equal (substring (substitute-in-file-name qstr) 0 upos)
  ;;        (substitute-in-file-name (substring qstr 0 qpos)))
  ;; Big problem here: we have to reverse engineer substitute-in-file-name to
  ;; find the position corresponding to UPOS in QSTR, but
  ;; substitute-in-file-name can do anything, depending on file-name-handlers.
  ;; substitute-in-file-name does the following kind of things:
  ;; - expand env-var references.
  ;; - turn backslashes into slashes.
  ;; - truncate some prefix of the input.
  ;; - rewrite some prefix.
  ;; Some of these operations are written in external libraries and we'd rather
  ;; not hard code any assumptions here about what they actually do.  IOW, we
  ;; want to treat substitute-in-file-name as a black box, as much as possible.
  ;; Kind of like in rfn-eshadow-update-overlay, only worse.
  ;; Example of things we need to handle:
  ;; - Tramp (substitute-in-file-name "/foo:~/bar//baz") => "/scpc:foo:/baz".
  ;; - Cygwin (substitute-in-file-name "C:\bin") => "/usr/bin"
  ;;          (substitute-in-file-name "C:\") => "/"
  ;;          (substitute-in-file-name "C:\bi") => "/bi"
  (let* ((ustr (substitute-in-file-name qstr))
         (uprefix (substring ustr 0 upos))
         qprefix)
    ;; Main assumption: nothing after qpos should affect the text before upos,
    ;; so we can work our way backward from the end of qstr, one character
    ;; at a time.
    ;; Second assumptions: If qpos is far from the end this can be a bit slow,
    ;; so we speed it up by doing a first loop that skips a word at a time.
    ;; This word-sized loop is careful not to cut in the middle of env-vars.
    (while (let ((boundary (string-match "\\(\\$+{?\\)?\\w+\\W*\\'" qstr)))
             (and boundary
                  (progn
                    (setq qprefix (substring qstr 0 boundary))
                    (string-prefix-p uprefix
                                   (substitute-in-file-name qprefix)))))
      (setq qstr qprefix))
    (let ((qpos (length qstr)))
      (while (and (> qpos 0)
                  (string-prefix-p uprefix
                                   (substitute-in-file-name
                                    (substring qstr 0 (1- qpos)))))
        (setq qpos (1- qpos)))
      (cons qpos #'minibuffer-maybe-quote-filename))))