]> code.delx.au - gnu-emacs-elpa/blob - load-relative.el
Go over __FILE__ test ordering and more comments to as to why we do what we do.
[gnu-emacs-elpa] / load-relative.el
1 (provide 'load-relative)
2 (defun __FILE__ (&optional symbol)
3 "Return the string name of file/buffer that is currently begin executed.
4
5 The first approach for getting this information is perhaps the
6 most pervasive and reliable. But it the most low-level and not
7 part of a public API, so it might change in future
8 implementations. This method uses the name that is recorded by
9 readevalloop of `lread.c' as the car of variable
10 `current-load-list'.
11
12 Failing that, we use `load-file-name' which should work in some
13 subset of the same places that the first method works. However
14 `load-file-name' will be nil for code that is eval'd. To cover
15 those cases, we try `buffer-file-name' which is initially
16 correct, for eval'd code, but will change and may be wrong if the
17 code sets or switches buffers after the initial execution.
18
19 Failing the above the next approach we try is to use the value of
20 $# - 'the name of this file as a string'. Although it doesn't
21 work for eval-like things, it has the advantage that this value
22 persists after loading or evaluating a file. So it would be
23 suitable if __FILE__ were called from inside a function.
24
25 As a last resort, you can pass in SYMBOL which should be some
26 symbol that has been previously defined if none of the above
27 methods work we will use the file-name value find via
28 `symbol-file'."
29 (cond
30 ;; lread.c's readevalloop sets (car current-load-list)
31 ;; via macro LOADHIST_ATTACH of lisp.h. At least in Emacs
32 ;; 23.0.91 and this code goes back to '93.
33 ((stringp (car-safe current-load-list)) (car current-load-list))
34
35 ;; load-like things. 'relative-file-expand' tests in
36 ;; test/test-load.el indicates we should put this ahead of
37 ;; $#.
38 (load-file-name)
39
40 ;; Pick up "name of this file as a string" which is set on
41 ;; reading and persists. In contrast, load-file-name is set only
42 ;; inside eval. As such, it won't work when not in the middle of
43 ;; loading.
44 (#$)
45
46 ((buffer-file-name)) ;; eval-like things
47 (t (symbol-file symbol)) ;; last resort
48 ))
49
50 (defun load-relative (file-or-list &optional symbol)
51 "Load an Emacs Lisp file relative to Emacs Lisp code that is in
52 the process of being loaded or eval'd.
53
54 FILE-OR-LIST is either a string or a list of strings containing
55 files that you want to loaded.
56
57 WARNING: it is best to to run this function before any
58 buffer-setting or buffer changing operations."
59
60 (if (listp file-or-list)
61 (mapcar (lambda(relative-file)
62 (load (relative-expand-file-name relative-file symbol)))
63 file-or-list)
64 (load (relative-expand-file-name file-or-list symbol))))
65
66 (defun relative-expand-file-name(relative-file &optional symbol)
67 "Expand RELATIVE-FILE relative to the Emacs Lisp code that is in
68 the process of being loaded or eval'd."
69 (let ((prefix (file-name-directory
70 (or (__FILE__ symbol) default-directory))))
71 (expand-file-name (concat prefix relative-file))))
72
73 (defun require-relative (relative-file &optional symbol)
74 "Run `require' on an Emacs Lisp file relative to the Emacs Lisp code
75 that is in the process of being loaded or eval'd.
76
77 WARNING: it is best to to run this function before any
78 buffer-setting or buffer changing operations."
79 (let ((require-string-name
80 (file-name-sans-extension
81 (file-name-nondirectory relative-file))))
82 (require (intern require-string-name)
83 (relative-expand-file-name relative-file symbol))))