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