]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/names/UsageExample.org
Add 'packages/names/' from commit 'b7bb062fc3c5de0c5bdb6dcf60da260d2a169783'
[gnu-emacs-elpa] / packages / names / UsageExample.org
diff --git a/packages/names/UsageExample.org b/packages/names/UsageExample.org
new file mode 100644 (file)
index 0000000..9c0ceb4
--- /dev/null
@@ -0,0 +1,228 @@
+* 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-package.el --- Just an example
+
+;;; You have to add this requirement!!
+;; Package-Requires: ((names "0.5"))
+
+;;; Commentary:
+
+;; Bla Bla Bla Bla Bla Bla Bla Bla Bla Bla Bla Bla Bla Bla Bla Bla Bla
+;; Bla Bla Bla Bla
+
+;;; Code:
+
+;;; Require us. After compilation there will be NO leftover reference
+;;; to the names package.
+
+(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' here 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))
+      ;; Victory!
+      )))
+)
+
+(provide 'example-package)
+;;; example-package.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))
+      ;; Victory!
+      )))
+#+END_SRC
+
+* Usage Instructions
+
+The
+follow these steps:
+
+1. Remember to list =names= as a dependency, and =require= it.
+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.