Function: locate-file-completion-table

locate-file-completion-table is a byte-compiled function defined in files.el.gz.

Signature

(locate-file-completion-table DIRS SUFFIXES STRING PRED ACTION)

Documentation

Do completion for file names passed to locate-file.

Source Code

;; Defined in /usr/src/emacs/lisp/files.el.gz
(defun locate-file-completion-table (dirs suffixes string pred action)
  "Do completion for file names passed to `locate-file'."
  (cond
   ((file-name-absolute-p string)
    ;; FIXME: maybe we should use completion-file-name-table instead,
    ;; tho at least for `load', the arg is passed through
    ;; substitute-in-file-name for historical reasons.
    (read-file-name-internal string pred action))
   ((eq (car-safe action) 'boundaries)
    (let ((suffix (cdr action)))
      `(boundaries
        ,(length (file-name-directory string))
        ,@(let ((x (file-name-directory suffix)))
            (if x (1- (length x)) (length suffix))))))
   (t
    (let ((names '())
          ;; If we have files like "foo.el" and "foo.elc", we could load one of
          ;; them with "foo.el", "foo.elc", or "foo", where just "foo" is the
          ;; preferred way.  So if we list all 3, that gives a lot of redundant
          ;; entries for the poor soul looking just for "foo".  OTOH, sometimes
          ;; the user does want to pay attention to the extension.  We try to
          ;; diffuse this tension by stripping the suffix, except when the
          ;; result is a single element (i.e. usually we list only "foo" unless
          ;; it's the only remaining element in the list, in which case we do
          ;; list "foo", "foo.elc" and "foo.el").
          (fullnames '())
	  (suffix (concat (regexp-opt suffixes t) "\\'"))
	  (string-dir (file-name-directory string))
          (string-file (file-name-nondirectory string)))
      (dolist (dir dirs)
        (unless dir
          (setq dir default-directory))
        (if string-dir (setq dir (expand-file-name string-dir dir)))
        (when (file-directory-p dir)
          (dolist (file (file-name-all-completions
                         string-file dir))
            (if (not (string-match suffix file))
                (push file names)
              (push file fullnames)
              (push (substring file 0 (match-beginning 0)) names)))))
      ;; Switching from names to names+fullnames creates a non-monotonicity
      ;; which can cause problems with things like partial-completion.
      ;; To minimize the problem, filter out completion-regexp-list, so that
      ;; M-x load-library RET t/x.e TAB finds some files.  Also remove elements
      ;; from `names' that matched `string' only when they still had
      ;; their suffix.
      (setq names (all-completions string-file names))
      ;; Remove duplicates of the first element, so that we can easily check
      ;; if `names' really contains only a single element.
      (when (cdr names) (setcdr names (delete (car names) (cdr names))))
      (unless (cdr names)
        ;; There's no more than one matching non-suffixed element, so expand
        ;; the list by adding the suffixed elements as well.
        (setq names (nconc names fullnames)))
      (completion-table-with-context
       string-dir names string-file pred action)))))