Function: abbreviate-file-name

abbreviate-file-name is a byte-compiled function defined in files.el.gz.

Signature

(abbreviate-file-name FILENAME)

Documentation

Return a version of FILENAME shortened using directory-abbrev-alist.

This also substitutes "~" for the user's home directory (unless the home directory is a root directory).

When this function is first called, it caches the user's home directory as a regexp in abbreviated-home-dir, and reuses it afterwards (so long as the home directory does not change; if you want to permanently change your home directory after having started Emacs, set abbreviated-home-dir to nil so it will be recalculated).

Other relevant functions are documented in the file-name group.

View in manual

Probably introduced at or before Emacs version 22.1.

Shortdoc

;; file-name
(abbreviate-file-name "/home/some-user")
    e.g. => "~some-user"

Aliases

viper-abbreviate-file-name (obsolete since 27.1) f-abbrev f-short

Source Code

;; Defined in /usr/src/emacs/lisp/files.el.gz
(defun abbreviate-file-name (filename)
  "Return a version of FILENAME shortened using `directory-abbrev-alist'.
This also substitutes \"~\" for the user's home directory (unless the
home directory is a root directory).

When this function is first called, it caches the user's home
directory as a regexp in `abbreviated-home-dir', and reuses it
afterwards (so long as the home directory does not change;
if you want to permanently change your home directory after having
started Emacs, set `abbreviated-home-dir' to nil so it will be recalculated)."
  ;; Get rid of the prefixes added by the automounter.
  (save-match-data                      ;FIXME: Why?
    (if-let ((handler (find-file-name-handler filename 'abbreviate-file-name)))
        (funcall handler 'abbreviate-file-name filename)
      ;; Avoid treating /home/foo as /home/Foo during `~' substitution.
      (let ((case-fold-search (file-name-case-insensitive-p filename)))
        ;; If any elt of directory-abbrev-alist matches this name,
        ;; abbreviate accordingly.
        (setq filename (directory-abbrev-apply filename))

        ;; Compute and save the abbreviated homedir name.
        ;; We defer computing this until the first time it's needed, to
        ;; give time for directory-abbrev-alist to be set properly.
        (unless abbreviated-home-dir
          (put 'abbreviated-home-dir 'home (expand-file-name "~"))
          (setq abbreviated-home-dir
                (directory-abbrev-make-regexp
                 (let ((abbreviated-home-dir "\\`\\'.")) ;Impossible regexp.
                   (abbreviate-file-name
                    (get 'abbreviated-home-dir 'home))))))

        ;; If FILENAME starts with the abbreviated homedir,
        ;; and ~ hasn't changed since abbreviated-home-dir was set,
        ;; make it start with `~' instead.
        ;; If ~ has changed, we ignore abbreviated-home-dir rather than
        ;; invalidating it, on the assumption that a change in HOME
        ;; is likely temporary (eg for testing).
        ;; FIXME Is it even worth caching abbreviated-home-dir?
        ;; Ref: https://debbugs.gnu.org/19657#20
        (let (mb1)
          (if (and (string-match abbreviated-home-dir filename)
                   (setq mb1 (match-beginning 1))
                   ;; If the home dir is just /, don't change it.
                   (not (and (= (match-end 0) 1)
                             (= (aref filename 0) ?/)))
                   ;; MS-DOS root directories can come with a drive letter;
                   ;; Novell Netware allows drive letters beyond `Z:'.
                   (not (and (memq system-type '(ms-dos windows-nt cygwin))
                             (string-match "\\`[a-zA-`]:/\\'" filename)))
                   (equal (get 'abbreviated-home-dir 'home)
                          (expand-file-name "~")))
              (setq filename
                    (concat "~"
                            (substring filename mb1))))
          filename)))))