I am trying to write a little function to get the projectile relative path of a buffer. My idea is to delete the substring projectile-project-root from the string buffer-file-name.

For example:

root-file-path: ~/src/dotfiles
buffer-file-name: ~/src/dotfiles/emacs.d/conf.org
relative-file-name: emacs.d/conf.org

my current code is this:

(setq buffer-file-name (string-remove-prefix projectile-project-root

but I can't get it working. Any ideas?

  • Could you detail what isn't working? Looking at your code, you have at least two issues: you are quoting your call to string-remove-prefix, and kill-new should probably be called with only one argument
    – rpluim
    Commented Oct 17, 2018 at 7:32
  • The step to generate the buffer relative file path, sorry I was trying in the eval buffer and didn't test the function. I will fix the question.
    – rafaelleru
    Commented Oct 17, 2018 at 7:44
  • buffer-file-name must be an absolute, not relative, file name. If you want to change the buffer's user-visible name you should use rename-buffer instead. See (elisp) Buffer Names. If that is not what you're trying to do, then please elaborate on what your ultimate goal is, as it's not very clear from your question.
    – Basil
    Commented Oct 17, 2018 at 12:28
  • I wnat to get the file path relative to the current project, to put it in the clipboard @Basil it was I said at the beggining of the question.
    – rafaelleru
    Commented Oct 17, 2018 at 12:30
  • @rafaelleru Your question makes no mention of the kill ring or clipboard, but thanks for clarifying.
    – Basil
    Commented Oct 17, 2018 at 12:31

2 Answers 2


I think the reason your code is not working as hoped for is because you are using the buffer-local variable projectile-project-root instead of the eponymous function.

C-hvprojectile-project-rootRET reveals:

projectile-project-root is a variable defined in ‘projectile.el’.
Its value is nil

  Automatically becomes buffer-local when set.

Defines a custom Projectile project root.
This is intended to be used as a file local variable.

In other words, projectile.el never sets this variable itself; it is provided only in case users want to set it buffer- or file-locally (see (emacs) Locals and (emacs) File Variables, respectively).

This explains why

(file-relative-name buffer-file-name projectile-project-root)

(which you mentioned in a comment) returns the non-directory part of buffer-file-name, as opposed to the desired relative path.

Compare this with C-hfprojectile-project-rootRET:

projectile-project-root is a compiled Lisp function in

(projectile-project-root &optional DIR)

Retrieves the root directory of a project if available.
If DIR is not supplied its set to the current directory by default.

Combining this knowledge with dakra's good suggestion to use file-relative-name instead of manipulating file names as strings (which should and almost always can be avoided), we arrive at the following means of killing the current buffer's absolute file name relative to its projectile root:

(kill-new (file-relative-name buffer-file-name (projectile-project-root)))

You want file-relative-name:

(file-relative-name "~/src/dotfiles/emacs.d/conf.org" "~/src/dotfiles")
  • when I run as (file-relative-name buffer-file-name projectile-project-root) it returns only the buffer file name conf.org and not the relative path.
    – rafaelleru
    Commented Oct 17, 2018 at 8:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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