Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find the relative path of a file in a project

Tags:

emacs

elisp

I have my project files set in this format:

/home/user/proj/source
/home/user/proj/source/src1
/home/user/proj/source/src1
/home/user/proj/header ...etc

I have a way to find the project path when viewing any source file

"/home/user/proj"

Also, (buffer-file-name) gives the full absolute path of a given source file.

How to write a lisp function that extract the relative path of a source file?

Meaning, if I am viewing

/home/user/proj/source/src1/file.c

I would like to have the path

"source/src1/file.c"

The following function gives me the project path:

(defun upward-find-file (filename &optional startdir)
  (let ((dirname (expand-file-name
          (if startdir startdir ".")))
    (found nil) ; found is set as a flag to leave loop if we find it
    (top nil))  ; top is set when we get
            ; to / so that we only check it once
    ; While we've neither been at the top last time nor have we found
    ; the file.
    (while (not (or found top))
      ; If we're at / set top flag.
      (if (string= (expand-file-name dirname) "/")
      (setq top t))
      ; Check for the file
      (if (file-exists-p (expand-file-name filename dirname))
      (setq found t)
    ; If not, move up a directory
    (setq dirname (expand-file-name ".." dirname))))
    ; return statement
    (if found (concat dirname "/") nil)))

I always have "Makefile" in the main project folder, so

(setq dirname (upward-find-file "Makefile" startdir))

Takes care of that.

like image 787
SFbay007 Avatar asked Sep 20 '25 01:09

SFbay007


1 Answers

Try locate-dominating-file and file-relative-name.

(let ((fname (buffer-file-name)))
  (file-relative-name fname (locate-dominating-file fname "Makefile")))

N.B. locate-dominiating-file returns nil if it can't find anything.

like image 143
jpkotta Avatar answered Sep 23 '25 12:09

jpkotta