Emacs Lisp: Get Script Name at Run Time, Call by Relative Path

By Xah Lee. Date: . Last updated: .

Get Current Script's Name Programmatically

;; get the current elisp script's name at run time
(or load-file-name buffer-file-name)

Explanation: If user ran your script by eval-buffer, then load-file-name's value would be nil. So, using both {load-file-name, buffer-file-name } is a good way to get the script name regardless whether the script is executed by load or eval buffer.

If you want the directory, call file-name-directory on the result.

Get Full Path from Relative Path at Run Time

If you have file A, that calls load to load a file at B, and B calls load on file C using a relative path, then Emacs will complain about unable to find C. Because, emacs does not switch current directory with load.

The following function solves this problem.

(defun xah-get-fullpath (@file-relative-path)
  "Return the full path of *file-relative-path, relative to caller's file location.

Example: If you have this line
 (xah-get-fullpath \"../xyz.el\")
in the file at
 /home/joe/emacs/emacs_lib.el
then the return value is
 /home/joe/xyz.el
Regardless how or where emacs_lib.el is called.

This function solves 2 problems.

(1) If you have file A, that calls the `load' on a file at B, and B calls `load' on file C using a relative path, then Emacs will complain about unable to find C. Because, emacs does not switch current directory with `load'.

To solve this problem, when your code only knows the relative path of another file C, you can use the variable `load-file-name' to get the current file's full path, then use that with the relative path to get a full path of the file you are interested.

(2) To know the current file's full path, emacs has 2 ways: `load-file-name' and `buffer-file-name'. If the file is loaded by `load', then `load-file-name' works but `buffer-file-name' doesn't. If the file is called by `eval-buffer', then `load-file-name' is nil. You want to be able to get the current file's full path regardless the file is run by `load' or interactively by `eval-buffer'."

  (concat (file-name-directory (or load-file-name buffer-file-name)) @file-relative-path)
)

See also: What is the difference between load-file, load, require, autoload?.