Load file with a relative path
Asked Answered
H

2

10

I am trying to load a file in Lisp from a file in the same directory using a relative path.

My file structure looks like this:

repo/
    subdir/
        main.lisp
        test.lisp

In main.lisp I have a number of function definitions, and in test.lisp I want to test the functions.

I have tried using (load "main.lisp") and (load "main") in test.lisp, as well as a number of variations on the pathname (i.e., including ./ before the filename) but both times I get the following error (where <filename> is the filename passed to the load function):

File-error in function LISP::INTERNAL-LOAD: "<filename>" does not exist.

Is it possible to load main.lisp using a relative path?

It may be worth noting that I am running CMUCL and executing the code using SublimeREPL inside of Sublime Text 3.

Hodden answered 12/9, 2014 at 3:32 Comment(0)
S
11

When a file is being loaded, the variable *LOAD-PATHNAME* is bound to the pathname of the file being loaded, and *LOAD-TRUENAME* to its truename.

So, to load a file in the same directory with the file currently being loaded, you can say

(load (merge-pathnames "main.lisp" *load-truename*))
Sigil answered 12/9, 2014 at 5:53 Comment(3)
Will this only work when contained in a file being loaded? I tried executing this via the REPL, but the value of *load-truename* was nil. However, it did work when I used (load "path-to-test.lisp").Hodden
Yes, *load-truename* is only bound during a load operation. Similarly, there are *compile-file-pathname* and *compile-file-truename* that are only bound during the execution of compile-file.Sigil
Sadly this does not work in SLIME, because *load-truename* is set to /tmp.Satterfield
D
5

jlahd's answer is excellent.

If you need to make different pathname calculations, you can do it with the built-in functions:

(let* ((p1    (pathname "test.lisp"))   ; not fully specified
       (name1 (pathname-name p1))       ; the name "test"
       (type1 (pathname-type p1))       ; the type "lisp"
       (p2 #p"/Users/joswig/Documents/bar.text")  ; a complete pathname
       (dir2  (pathname-directory p2))) ; (:ABSOLUTE "Users" "joswig" "Documents")

  ; now let's construct a new pathname

  (make-pathname :name name1
                 :type type1
                 :directory (append dir2 (list "Lisp"))   ; we append a dir
                 :defaults p2))         ; all the defaults
                                        ; relevant when the filesystem supports
                                        ; host, device or version

The result: #P"/Users/joswig/Documents/Lisp/test.lisp".

Usually to reuse something like above, one turn it into a utility function...

Drear answered 12/9, 2014 at 6:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.