I would like to be able to see the location of the current file's parent directory, independent of the current buffer name.

  • Maybe using uniquify library is desired solution (see Gilles answer) – alex_1948511 Oct 16 '15 at 16:10

You can configure the mode line format as you wish. If you want to show the parent directory together with the buffer name (which is usually the file name, for a buffer that's visiting a file), modify mode-line-buffer-identification; otherwise, add an entry to mode-line-format. There isn't a built-in construct for “parent directory of the current file”, so you'll need to build that yourself, for example with :eval. Here's an example that adds the directory name after the buffer name, and does nothing in buffers that aren't visiting files (including Dired); you may want to refine it with formatting.

(defun mode-line-buffer-file-parent-directory ()
  (when buffer-file-name
    (concat "[" (file-name-nondirectory (directory-file-name (file-name-directory buffer-file-name))) "]")))
(setq-default mode-line-buffer-identification
      (cons (car mode-line-buffer-identification) '((:eval (mode-line-buffer-file-parent-directory)))))

Another method would be to set a variable containing the text you want in find-file-hooks. I also show how you can set properties with the :propertize construct.

(defvar buffer-file-parent-directory nil
  "Parent directory of the current directory.
This variable is nil if the current buffer isn't visiting a file.")
(make-variable-buffer-local 'buffer-file-parent-directory)
(put 'buffer-file-parent-directory 'permanent-local t)
(defconst mode-line-buffer-file-parent-directory
  '(:propertize (list buffer-file-parent-directory "/") face mode-line-buffer-id))
(defun set-buffer-file-parent-directory ()
  (when buffer-file-name
    (setq buffer-file-parent-directory
          (file-name-as-directory (file-name-nondirectory (directory-file-name (file-name-directory buffer-file-name)))))))
(add-hook 'find-file-hook 'set-buffer-file-parent-directory)
(let ((list mode-line-format))
  (while (not (eq (car list) 'mode-line-buffer-identification))
    (setq list (cdr list)))
  (setcdr list (cons (car list) (cdr list)))
  (setcar list 'mode-line-buffer-file-parent-directory))

If what you really wanted was to have the directory name in case you have multiple files with the same name in different directories, Emacs has this built in, with the uniquify library. When there would be multiple buffers with the same name, this library causes the buffer name to look like file.ext<foo> and file.ext<bar> instead of file.ext and file.ext<2>. You can fine-tune the format by customizing uniquify-buffer-name-style.

(require 'uniquify)
| improve this answer | |

I assume you mean that you want to see the directory instead of the buffer name.

(setq-default mode-line-buffer-identification
              '(:eval default-directory))

Or if you want your home directory abbreviated to ~/ (instead of an absolute file name, from the root), then:

(setq-default mode-line-buffer-identification
              '(:eval (abbreviate-file-name default-directory)))

Or if you want only the parent directory name, as a single directory-component name, then:

(setq-default mode-line-buffer-identification
              '(:eval (file-name-nondirectory
                        (directory-file-name default-directory))))

Or if you do want to keep also the buffer name, as @Malabarba supposes, then:

(setq-default mode-line-buffer-identification
              (let ((orig  (car mode-line-buffer-identification)))
                `(:eval (cons (concat ,orig (abbreviate-file-name default-directory))
                              (cdr mode-line-buffer-identification)))))

The point is that you just need to use the value of default-directory (possibly simplified from an absolute name, if you want) in mode-line-buffer-identification. You can set that variable to just the directory name, or you can set it to a value that keeps also the buffer name.

If what you ask is all you want, it is simple to configure the mode line to include the default-directory, however you want it to appear. No need to load multiple libraries for this (which is what smart-mode-line does).

| improve this answer | |
  • 1
    Despite his wording, I think he meant "in addition to" not "instead". Of course, I could be wrong. – Malabarba Oct 19 '14 at 9:01
  • 1
    @Malabarba: Maybe. If so, the difference is trivial - added. – Drew Oct 19 '14 at 14:07

You install use smart-mode-line. It's configured to display the file path in the mode-line, whenever that's relevant.

dark theme

Just install it, and then turn it on with (sml/setup).

It also has a lot of features to make that display more concise. For instance, “~/.emacs.d/” gets replaced with “:ED:” (and you can configure further replacements).

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.