1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
* Usage Example
The following code shows how you can write a package using *Names*.
The important items are already listed in the Readme:
1. List =names= as a dependency.
2. Wrap all code that’s to be namespaced inside a =(define-namespace NAME ...)= macro.
#+BEGIN_SRC emacs-lisp
;;; example.el --- Just an example
;;; You have to add this requirement!!
;; Package-Requires: ((names "Lookup.Latest.Version") (emacs "24"))
;;; Code:
;; `define-namespace' is autoloaded, so there's no need to require
;; `names'. However, requiring it here means it will also work for
;; people who don't install through package.el.
(eval-when-compile (require 'names))
;;;###autoload
(define-namespace example-
(defvar has-courage nil)
(defmacro with-courage (name &rest body)
"Evaluate BODY, don't evaluate NAME."
(declare (debug (sexp body-form))
(indent defun))
;; `example-has-courage' is inside a quoted form, so it needs to be
;; written explicitly.
`(let ((example-has-courage ',name))
,@body))
;;; this is how you autoload:
:autoload
(defun fight (evil)
"Fight EVIL!"
(with-courage evil
(-fight-internal)))
(defun -fight-internal ()
"Called by `example-fight'"
(when has-courage
;; `has-courage' here is will be expanded to `example-has-courage'.
(let ((has-courage nil))
(message "Victory!"))))
)
(provide 'example)
;;; example.el ends here
#+END_SRC
** Expands to this
To see this expansion yourself.
1. Replace the =define-namespace= above with a =names-print= (a macro designed to help developers like you).
2. Make sure you load the /“names-dev.el”/ file included here.
3. evaluate the whole thing.
#+BEGIN_SRC emacs-lisp
(defvar example-has-courage nil)
(defmacro example-with-courage (name &rest body)
"Evaluate BODY, don't evaluate NAME."
(declare (debug (sexp body))
(indent defun))
`(let ((example-has-courage ',name))
,@body))
;;;###autoload
(defun example-fight (evil)
"Fight EVIL!"
(example-with-courage evil
(example--fight-internal)))
(defun example--fight-internal nil
"Called by `example-fight'"
(when example-has-courage
(let ((has-courage nil))
(message "Victory!"))))
#+END_SRC
* Usage Instructions
Follow these steps:
1. Remember to list =names= as a dependency.
2. Wrap all code that's to be namespaced inside a =(define-namespace NAME ...)= macro.
3. Pleasantly remove all that redundant repetition from you code!
4. When quoting function names, use =#' = instead of = ' =.
5. If you have =;;;###autoload= comments inside your =define-namespace=:
1. Replace them with =:autoload= keywords
2. Add an =;;;###autoload= tag immediately above your =define-namespace=.
*What you need to know:* There are essentially three rules that are
applied when namespacing.
*** 1. Every definition gets namespaced
Any definitions inside =BODY= will have =NAME= prepended to the
symbol given:
#+begin_src emacs-lisp
;;;###autoload
(define-namespace foo-
(defvar bar 1 "docs")
:autoload
(defun free ()
"DOC"
(message "hi"))
)
#+end_src
expands to
#+begin_src emacs-lisp
(defvar foo-bar 1 "docs")
;;;###autoload
(defun foo-free ()
"DOC"
(message "hi"))
#+end_src
*** 2. Functions and variables are namespaced if defined
Any function calls (or variable names) get NAME prepended to them if
the symbol in question is defined as a function (or a variable,
respectively) inside the current =define-namespace= form. It doesn't
matter if the function/variable is called before actually being
defined, *Names* will find it.
In other words, a function call or variable name is /“looked up
locally”/. If it is not found, it is assumed /“global”/. You can force
a symbol to be global, by preppending it with =::=.
That is:
#+begin_src emacs-lisp
(define-namespace foo-
(defvar var infinite)
(defun infinite (x)
(infinite x))
(cond
((::infinite 2) (message "Global function call"))
((something-else t) (message "Global function call"))
((infinite var) (message "Local function call."))
(infinite (message "Variable.")))
)
#+end_src
expands to
#+begin_src emacs-lisp
(defvar foo-myvar infinite)
(defun foo-infinite (x)
(foo-infinite x))
(cond
((infinite 2) (message "Global function call"))
((something-else t) (message "Global function call"))
((foo-infinite foo-var) (message "That was a function call."))
(infinite (message "That was a variable.")))
#+end_src
Note how:
- The =infinite= symbol gets namespaced only as a function name (/not/
when it's used as a variable), because =define-namespace= knowns
that =foo-infinite= is not a variable.
- The symbol inside =(infinite 2)= is not namespaced, because it had
been protected with =::=.
- =something-else= is not namespaced, because it is not a locally
defined function, so it must be global.
*** 3. Forms not meant for evaluation are not namespaced.
Whenever a form is not meant for evaluation, it is left completely
untouched. Some examples where this applies are:
- Lists and symbols quoted with a simple quote (e.g. = 'foo=), these are regarded as data, not code;
- Any argument of a macro which doesn't get evaluated, e.g, the =KEYLIST= arguments of =cl-case=.
Some examples of the opposite:
- Symbols quoted with a function quote (e.g. =#'foo=) are regarded as
function names, and are namespaced as explained in [[#2-functions-and-variables-are-namespaced-if-defined][item 2]]. That's
why we recommend you always use function quotes for functions.
- Comma forms inside a backtick form (e.g. =`(nothing ,@(function)
,variable)=) *are* meant for evaluation and so *will* be namespaced.
*** Limitations
The main effect of [[#3-forms-not-meant-for-evaluation-are-not-namespaced][item 3]] is that the usual way of writing
=defalias= and =defvaralias= won't be namespaced. That is
#+begin_src emacs-lisp
(define-namespace test-
(defalias 'yell #'message)
)
;; simply expands to this
(defalias 'yell #'message)
;; instead of this
(defalias 'test-yell #'message)
#+end_src
This is not considered a bug. The =SYMBOL= argument of a defalias
could just as well be an arbitrary form whose value isn't even defined
until runtime. Therefore, there is no consistent way of handling a
defalias, and we choose to just treat it as any other function call.
Just remember to add the namespace in your defalias and defvaralias forms.
*** Case-by-case Examples
In general, =define-namespace= should work as you expect it to. But if you
need to understand why something is or isn't being namespaced, have a
look at [[https://github.com/Bruce-Connor/emacs-lisp-namespaces/blob/master/TheNittyGritty.org][TheNittyGritty.org]]
* Keywords - Customizing the behaviour
Immediately after the name of your space you may add keywords which
customize the behaviour of =define-namespace=. See the variable
=names--keyword-list= for a description of each possible keyword, or
visit [[https://github.com/Bruce-Connor/emacs-lisp-namespaces/blob/master/TheNittyGritty.org][TheNittyGritty.org]] for a description with examples.
|