]> code.delx.au - gnu-emacs-elpa/blob - packages/load-relative/load-relative.el
409c3c5899866191dbbb7da1fdedd2805075c09d
[gnu-emacs-elpa] / packages / load-relative / load-relative.el
1 ;;; load-relative.el --- relative file load (within a multi-file Emacs package)
2
3 ;; Author: Rocky Bernstein
4 ;; Version: 1.0
5 ;; Keywords: internal
6 ;; URL: http://github.com/rocky/emacs-load-relative
7 ;; Compatibility: GNU Emacs 23.x
8
9 ;; Copyright (C) 2009-2010, 2012-2014 Rocky Bernstein <rocky@gnu.org>
10
11 ;; This program is free software: you can redistribute it and/or
12 ;; modify it under the terms of the GNU General Public License as
13 ;; published by the Free Software Foundation, either version 3 of the
14 ;; License, or (at your option) any later version.
15
16 ;; This program is distributed in the hope that it will be useful, but
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ;; General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with this program. If not, see
23 ;; <http://www.gnu.org/licenses/>.
24
25 ;;; Commentary:
26
27 ;; Here we provide functions which facilitate writing multi-file Emacs
28 ;; packages and facilitate running from the source tree without having
29 ;; to "install" code or fiddle with evil `load-path'. See
30 ;; https://github.com/rocky/emacs-load-relative/wiki/NYC-Lisp-talk for
31 ;; the the rationale behind this.
32 ;;
33 ;; The functions we add are relative versions of `load', and `require'
34 ;; and versions which take list arguments. We also add a `__FILE__'
35 ;; function and a `provide-me' macro.
36
37 ;; The latest version of this code is at:
38 ;; http://github.com/rocky/emacs-load-relative/
39
40 ;; `__FILE__' returns the file name that that the calling program is
41 ;; running. If you are `eval''ing a buffer then the file name of that
42 ;; buffer is used. The name was selected to be analogous to the name
43 ;; used in C, Perl, Python, and Ruby.
44
45 ;; `load-relative' loads an Emacs Lisp file relative to another
46 ;; (presumably currently running) Emacs Lisp file. For example suppose
47 ;; you have Emacs Lisp files "foo.el" and "bar.el" in the same
48 ;; directory. To load "bar.el" from inside Emacs lisp file "foo.el":
49 ;;
50 ;; (require 'load-relative)
51 ;; (load-relative "baz")
52 ;;
53 ;; The above `load-relative' line could above have also been written as:
54 ;;
55 ;; (load-relative "./baz")
56 ;; or:
57 ;; (load-relative "baz.el") # if you want to exclude any byte-compiled files
58 ;;
59 ;; Use `require-relative' if you want to `require' the file instead of
60 ;; `load'ing it:
61 ;;
62 ;; (require-relative "baz")
63 ;;
64 ;; or:
65 ;;
66 ;; (require-relative "./baz")
67 ;;
68 ;; The above not only does a `require' on 'baz', but makes sure you
69 ;; get that from the same file as you would have if you had issued
70 ;; `load_relative'.
71 ;;
72 ;; Use `require-relative-list' when you have a list of files you want
73 ;; to `require'. To `require-relative' them all in one shot:
74 ;;
75 ;; (require-relative-list '("dbgr-init" "dbgr-fringe"))
76 ;;
77 ;; Finally, macro `provide-me' saves you the trouble of adding a
78 ;; symbol after `provide' using the file basename (without directory
79 ;; or file extension) as the name of the thing you want to
80 ;; provide.
81 ;;
82 ;; Using this constrains the `provide' name to be the same as
83 ;; the filename, but I consider that a good thing.
84
85 ;;; Code:
86
87 ;;;###autoload
88 (defun __FILE__ (&optional symbol)
89 "Return the string name of file/buffer that is currently begin executed.
90
91 The first approach for getting this information is perhaps the
92 most pervasive and reliable. But it the most low-level and not
93 part of a public API, so it might change in future
94 implementations. This method uses the name that is recorded by
95 readevalloop of `lread.c' as the car of variable
96 `current-load-list'.
97
98 Failing that, we use `load-file-name' which should work in some
99 subset of the same places that the first method works. However
100 `load-file-name' will be nil for code that is eval'd. To cover
101 those cases, we try `buffer-file-name' which is initially
102 correct, for eval'd code, but will change and may be wrong if the
103 code sets or switches buffers after the initial execution.
104
105 As a last resort, you can pass in SYMBOL which should be some
106 symbol that has been previously defined if none of the above
107 methods work we will use the file-name value find via
108 `symbol-file'."
109 ;; Not used right now:
110 ;; Failing the above the next approach we try is to use the value of
111 ;; $# - 'the name of this file as a string'. Although it doesn't
112 ;; work for eval-like things, it has the advantage that this value
113 ;; persists after loading or evaluating a file. So it would be
114 ;; suitable if __FILE__ were called from inside a function.
115
116
117 (cond
118 ;; lread.c's readevalloop sets (car current-load-list)
119 ;; via macro LOADHIST_ATTACH of lisp.h. At least in Emacs
120 ;; 23.0.91 and this code goes back to '93.
121 ((stringp (car-safe current-load-list)) (car current-load-list))
122
123 ;; load-like things. 'relative-file-expand' tests in
124 ;; test/test-load.el indicates we should put this ahead of
125 ;; $#.
126 (load-file-name)
127
128 ;; Pick up "name of this file as a string" which is set on
129 ;; reading and persists. In contrast, load-file-name is set only
130 ;; inside eval. As such, it won't work when not in the middle of
131 ;; loading.
132 ;; (#$)
133
134 ;; eval-like things
135 ((buffer-file-name))
136
137 ;; When byte compiling. FIXME: use a more thorough precondition like
138 ;; byte-compile-file is somehwere in the backtrace or that
139 ;; bytecomp-filename comes from that routine?
140 ((boundp 'bytecomp-filename) bytecomp-filename)
141
142 (t (symbol-file symbol)) ;; last resort
143 ))
144
145 (defun autoload-relative (function-or-list
146 file &optional docstring interactive type
147 symbol)
148 "Autoload an Emacs Lisp file relative to Emacs Lisp code that is in
149 the process of being loaded or eval'd.
150
151
152 Define FUNCTION to autoload from FILE. FUNCTION is a symbol.
153
154 FILE is a string to pass to `load'.
155
156 DOCSTRING is documentation for the function.
157
158 INTERACATIVE if non-nil says function can be called
159 interactively.
160
161 TYPE indicates the type of the object: nil or omitted says
162 function is a function, `keymap' says function is really a
163 keymap, and `macro' or t says function is really a macro. Third
164 through fifth args give info about the real definition. They
165 default to nil. If function is already defined other than as an
166 autoload, this does nothing and returns nil.
167
168 SYMBOL is the location of of the file of where that was
169 defined (as given by `symbol-file' is used if other methods of
170 finding __FILE__ don't work."
171
172 (if (listp function-or-list)
173 (mapcar (lambda(function)
174 (autoload function-or-list
175 (relative-expand-file-name file symbol)
176 docstring interactive type))
177 file)
178 (autoload function-or-list (relative-expand-file-name file symbol)
179 docstring interactive type))
180 )
181
182 ;;;###autoload
183 (defun load-relative (file-or-list &optional symbol)
184 "Load an Emacs Lisp file relative to Emacs Lisp code that is in
185 the process of being loaded or eval'd.
186
187 FILE-OR-LIST is either a string or a list of strings containing
188 files that you want to loaded. If SYMBOL is given, the location of
189 of the file of where that was defined (as given by `symbol-file' is used
190 if other methods of finding __FILE__ don't work."
191
192 (if (listp file-or-list)
193 (mapcar (lambda(relative-file)
194 (load (relative-expand-file-name relative-file symbol)))
195 file-or-list)
196 (load (relative-expand-file-name file-or-list symbol)))
197 )
198
199 (defun relative-expand-file-name(relative-file &optional opt-file)
200 "Expand RELATIVE-FILE relative to the Emacs Lisp code that is in
201 the process of being loaded or eval'd.
202
203 WARNING: it is best to to run this function before any
204 buffer-setting or buffer changing operations."
205 (let ((file (or opt-file (__FILE__) default-directory))
206 (prefix))
207 (unless file
208 (error "Can't expand __FILE__ here and no file name given"))
209 (setq prefix (file-name-directory file))
210 (expand-file-name (concat prefix relative-file))))
211
212 ;;;###autoload
213 (defun require-relative (relative-file &optional opt-file opt-prefix)
214 "Run `require' on an Emacs Lisp file relative to the Emacs Lisp code
215 that is in the process of being loaded or eval'd. The symbol used in require
216 is the base file name (without directory or file extension) treated as a
217 symbol.
218
219 WARNING: it is best to to run this function before any
220 buffer-setting or buffer changing operations."
221 (let ((require-string-name
222 (concat opt-prefix (file-name-sans-extension
223 (file-name-nondirectory relative-file)))))
224 (require (intern require-string-name)
225 (relative-expand-file-name relative-file opt-file))))
226
227 ;;;###autoload
228 (defmacro require-relative-list (list &optional opt-prefix)
229 "Run `require-relative' on each name in LIST which should be a list of
230 strings, each string being the relative name of file you want to run."
231 `(progn
232 (eval-when-compile
233 (require 'cl
234 (dolist (rel-file ,list)
235 (require-relative rel-file (__FILE__) ,opt-prefix))))
236 (dolist (rel-file ,list)
237 (require-relative rel-file (__FILE__) ,opt-prefix))))
238
239 ;;;###autoload
240 (defmacro provide-me ( &optional prefix )
241 "Call `provide' with the feature's symbol name made from
242 source-code's file basename sans extension. For example if you
243 write (provide-me) inside file ~/lisp/foo.el, this is the same as
244 writing: (provide 'foo).
245
246 With a prefix, that prefix is prepended to the `provide' So in
247 the previous example, if you write (provide-me \"bar-\") this is the
248 same as writing (provide 'bar-foo)
249 "
250 `(provide (intern (concat ,prefix (file-name-sans-extension
251 (file-name-nondirectory (__FILE__)))))))
252
253 (provide-me)
254
255 ;;; load-relative.el ends here