[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] 01/04: packages/names: Ready for GNU Elpa release

From: Artur Malabarba
Subject: [elpa] 01/04: packages/names: Ready for GNU Elpa release
Date: Sat, 15 Nov 2014 12:03:46 +0000

malabarba pushed a commit to branch master
in repository elpa.

commit 74de0fb3d70545b46b5ffebd85258838874931a2
Author: Artur Malabarba <address@hidden>
Date:   Thu Nov 13 12:09:15 2014 +0000

    packages/names: Ready for GNU Elpa release
 Other-Packages.org  |   25 +
 Readme.org          |  124 +++++
 TheNittyGritty.org  |  162 +++++++
 Todo.org            |   38 ++
 UsageExample.org    |  228 ++++++++++
 names-dev.el        |  239 ++++++++++
 names.el            | 1243 +++++++++++++++++++++++++++++++++++++++++++++++++++
 package-example.png |  Bin 0 -> 83634 bytes
 8 files changed, 2059 insertions(+), 0 deletions(-)

diff --git a/Other-Packages.org b/Other-Packages.org
new file mode 100644
index 0000000..910615e
--- /dev/null
+++ b/Other-Packages.org
@@ -0,0 +1,25 @@
+* Other Packages
+*Names* isn't the first package to try patching up namespaces in
+Emacs. Here we link to descriptions and provide short comparisons of
+previous packages attempting similar things.
+** [[https://github.com/Wilfred/with-namespace.el][with-namespace]]
+The closest to *Names* in terms of ideology. It performs simple
+namespacing of symbols inside =defun= forms and alike.
+The difference is that *Names* performs intelligent namespacing (it
+understand which symbols are vars, which are functions, and which are
+not fit for namespacing) and applies to any form under the sun.
+** [[https://github.com/sigma/codex][Codex]]
+A robust and somewhat similar option. Notable differences are that
+*Names* does have edebug integration (which greatly facilitates actual
+development) and is generally more focused on being practical (write
+code as you would, just without the prefix).
+** [[https://github.com/skeeto/elisp-fakespace/][Fakespace]]
+Focuses on the global obarray clobbering, not on code clobbering. It
+uninterns defined symbols, while *Names* actually simplifies the code
+that you write.
+** [[https://github.com/chrisbarrett/elisp-namespaces][elisp-namespaces]]
+Possibly the safest and faciest of the bunch. It's a great way to
+avoid clobbering the global obarray if you're willing to use its
+syntax. Like above, the difference it that *Names* actually simplifies
+that you type.
diff --git a/Readme.org b/Readme.org
new file mode 100644
index 0000000..2de1b31
--- /dev/null
+++ b/Readme.org
@@ -0,0 +1,124 @@
+#+OPTIONS: toc:nil num:nil
+* Names [[https://secure.travis-ci.org/Bruce-Connor/names.png?branch=master]]
+*Names* is designed as a practical, complete, robust, and debuggable
+tool which writes your namespaces for you.
+/Example usage of Names to namespace an emacs-lisp function./
+*** A Namespace implementation for Emacs-Lisp
+The *Names* package aims to provide an implementation of
+namespaces in Emacs with four guiding principles:
+- Practical :: Actually useful and easy to grasp.
+- Completeness :: Support any macro/function/special-form available in
+                  emacs-lisp, even the ones defined by you or a third
+                  party.
+- Robustness :: No-surprises, well-tested, and with clearly stated
+            limitations. Yes, as complete as we aim to be,
+            there will be limitations.
+- Debuggable :: Support *edebug* and =eval-defun=, as well as any
+                other essential tools for package developers.
+See [[https://github.com/Bruce-Connor/spaces#why-a-namespace-package][Why a 
namespace package?]] for a description on why this is
+necessary, and see 
 for a description and comparison
+of previous packages attempting similar things.
+**** Version Compatibility
+Currently, *Names* is being supported on the entire Emacs 24 family
+(24.1--24.4). Any new changes or pull requests are tested on a
+[[https://travis-ci.org/Bruce-Connor/names][Travis-CI machine]]. See the 
/“tests”/ subdirectory for our test suite,
+and see .
+** Usage
 file clearly displays and explains how to use *Names*
+in your package. There are few simple measures to take. Go have a look
+if you’re interested, I promise it’s worth it!
+If you want deeper descriptions of use-cases, see 
+** Developer Tools
+*Names* offers a series of tools to make package writing more
+convenient inside a namespace. These developer facilities are on this
+separate file, so the file isn't loaded on the user's computer when
+your package calls =(require 'names)=.
+To access them add the following line to your init file.
+#+begin_src emacs-lisp
+(require 'names-dev)
+*** Edebug and eval-defun support
+First and foremost, the =edebug-eval-defun= command (bound to =C-u
+C-M-x=) is an essential tool for any package developer. *Names*
+wouldn't be a very useful utility if it prevented you from using this
+Therefore, it provides the =names-eval-defun= command, which is
+identical to =edebug-eval-defun= except it also works inside
+namespaces. It will automatically be added to your
+*** Font-locking 
+Font-lock for =define-namespace= and =:autoload=.
+*** Expansion and comparison functions
+=names-compare-forms= and =names-print= offer information when
+something just doesn't seem to make sense.
+** Nomenclature
+The name of this package is *Names*, always with a capital “N”.
+Despite the word being plural, refer to it in the singular (e.g.,
+“Names is an amazing achievement”). If possible consider giving it a
+slight emphasis, such as: /Names/.
+When there's a risk of confusion or ambiguity, be it due to context or
+lack of knowledge by the reader, =names.el= is also acceptable.
+** Why a namespace package?
+Plain and simple: Emacs doesn't have namespaces, and it needs them.
+Nic Ferrier has a 
[[http://nic.ferrier.me.uk/blog/2013_06/adding-namespaces-to-elisp][great essay 
on the subject]]. Note that
+*Names* is very different from the solution he proposes, but it does
+solve the problem he had with other alternatives which left the
+debugger unusable.
+Emacs takes the approach of prefixing every symbol name with the name
+of the package. This successfully avoids name clashes between
+packages, but it quickly leads to code that's repetitive and annoying
+to write. Below is an example from =package.el=, the word "/package/"
+is repeated 7 times in a 10-line function.
+*Names* doesn't change this overall approach. It adheres to Emacs
+standards and is completely invisible to the end-user. *Names* simply
+gives /you/ (the developer) a convenient way of writing code that
+adheres to this standard.
+/Example usage of Names to namespace an emacs-lisp function./
+- At runtime, the right-hand-side will create the same definitions as the 
+- At compilation, it will create the exact same compiled file (with no 
left-over reference to =names.el= functions).
+*** Tested On:
+Below are the packages on which I've tested *Names*. If you're
+interested, try using it on one of your packages and 
[[https://github.com/Bruce-Connor/names/issues][let me know how
+it goes]].
+**** elnode
+- *Number of ert tests passed:* Same as before namespacing (62).
+- *Reduction in code size:* Approx. 2000 characters.
+**** s.el
+- *Number of ert tests passed:* All.
+- *Reduction in code size:* Approx. 1000 characters (8%). 
+1000 characters is a lot when you consider /s.el/ has the second
+shortest namespace possible, =s-=.
+**** dash.el
+- *Number of ert tests passed:* Same as before namespacing (104).
+**** latex-extra
+- *Number of ert tests passed:* ALL.
+**** aggressive-indent
+No actual tests defined, but this package actually uses /Names/ for
+real! And it's alive and well.
diff --git a/TheNittyGritty.org b/TheNittyGritty.org
new file mode 100644
index 0000000..78bf88b
--- /dev/null
+++ b/TheNittyGritty.org
@@ -0,0 +1,162 @@
+* The Nitty Gritty
+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, here's
+the nitty gritty of how it happens.
+** Quoted Lists
+Quoted lists (be it with =quote= or =function=) are namespaced *only*
+of the list is a =lambda= form (or a =macro= form). Arbitrary lists
+are returned untouched (they are way too arbitrary to be handled
+sanely). That is:
+#+begin_src emacs-lisp
+(define-namespace foo-
+(defun infinite (y)
+  (mapcar
+   '(lambda (x) (infinite x))
+   '(not a lambda (infinite x))))
+expands to
+#+begin_src emacs-lisp
+(defun foo-infinite (y)
+  (mapcar
+   '(lambda (x) (foo-infinite x))
+   '(not a lambda (infinite x))))
+Note that = '(lambda ...)= is bad practice in Emacs, you should use
+=(lambda ...)= instead (which is also namespaced just fine).
+** Symbols Quoted with Quote
+A symbol quoted with =quote= (or = ' =) is never namespaced.
+#+begin_src emacs-lisp
+(define-namespace foo-
+(defvar var nil)
+(defvaralias 'varalias 'var)
+(defun fun nil)
+(defalias 'alias 'fun)
+(defalias 'otheralias 'var)
+expands to
+#+begin_src emacs-lisp
+(defvar foo-var nil)
+(defvaralias 'varalias 'var)
+(defun foo-fun nil)
+(defalias 'alias 'fun)
+;;; foo-var is not a function, so:
+(defalias 'otheralias 'var)
+If you provide the =:assume-var-quote= keyword, quoted symbols will be
+namespaced as variables instead.
+** Symbols Quoted with Function
+A symbol quoted with =function= (or =#' =) is assumed to be the name of a
+function, and will be namespaced as such if possible. You may provide
+the =:dont-assume-function-quote= keyword to disable this behaviour,
+=function= will then be treated like =quote=.
+#+begin_src emacs-lisp
+(define-namespace foo-
+(defun fun (x) x)
+(mapcar 'fun somelist)
+(mapcar #'fun somelist)
+expands to
+#+begin_src emacs-lisp
+(defun foo-fun (x) x)
+(mapcar 'fun somelist)
+(mapcar #'foo-fun somelist)
+** Backticks (quasi-quotes)
+Backticks (or =`=) are handled as you would expect. Lists or simbles
+quoted with a backtick are treated the same as those quoted with
+regular quotes ([[#quoted-lists][see above]]), except anything prefixed by a 
comma (which
+is effectively not quoted) is namespaced as usual.
+** Local Variables Take Precedence
+Local variables take precedence over namespace variables.
+For instance
+#+begin_src emacs-lisp
+(define-namespace foo-
+(defvar bar "2")
+(defun funca (bar)
+  (string-to-int bar))
+expands to 
+#+begin_src emacs-lisp
+(defvar foo-bar "2")
+(defun funca (bar)
+  (string-to-int bar))
+Note how the last =bar= isn't namespaced. That's because it is local
+to the =funca= function, and takes precedence over the global
+=foo-bar=. The argument list of functions, macros, and lambdas are
+all local definitions.
+By default, this does not happen with let bindings, they are
+namespaced as usual (if the variable name in question has a global
+definition). The reason is that let bindings are commonly used to
+temporarily override global bindings. 
+You can customize this behaviour with the =:no-let-vars= keyword.
+#+begin_src emacs-lisp
+(define-namespace foo- :no-let-vars
+(defvar bar "2")
+(let ((bar "1"))
+  (string-to-int bar))
+will expand to 
+#+begin_src emacs-lisp
+(defvar foo-bar "2")
+(let ((bar "1"))
+  (string-to-int bar))
+** Macros
+Macros are handled in a very intelligent manner. 
+*Names* needs to know which parts of a macro's arguments are
+evaluatable forms, and which are just arbitrary symbols. This presents
+a challenge because macro arguments could be absolutely anything.
+Fortunately, (good) macros already provide that information in their
+=debug= declaration.
+Thus, *Names* uses the macro's =edebug-spec-list= to find out which
+arguments are evaluatable forms, and namespaces only those. Other
+arguments are left untouched. Usually, this is not something you'll
+need to worry about, it should just do what you expect from it. 
+This is only relevant if you write your own macros. If you do,
+remember to add a debug declaration in them.
+** Accessing Global Symbols
+If one of your definitions shadows a global definition, you can still
+access it by prefixing it with =::=.
+#+begin_src emacs-lisp
+(define-namespace foo-
+(defun message ()  
+  (message)
+  (::message "Hi"))
+expands to 
+#+begin_src emacs-lisp
+(defun foo-message ()  
+  (foo-message)
+  (message "Hi"))
+When in doubt feel free to use =::=, it will always get removed (as
+long as it's not inside a =quote=). You may also change this prefix to
+something else with the =:prefix= keyword.
diff --git a/Todo.org b/Todo.org
new file mode 100644
index 0000000..6face42
--- /dev/null
+++ b/Todo.org
@@ -0,0 +1,38 @@
+* Bugs
+** DONE Outside macros that depend on your macro will throw errors
+   CLOSED: [2014-11-09 Sun 18:10]
+This happens because we have to wrap everything in a progn, which the
+compiler/interpreter expands then evaluates. So the outside macro is
+expanded before YOUR macro has been evaluated (and thus defined).
+#+begin_src emacs-lisp
+(require 'cl-lib)
+(defspace name-
+(defmacro cas (string)
+  (declare (debug t))
+  `(cdr (assoc-string ,string '(("a" . 1) ("b" . 0)))))
+(defun incf ()
+  "Increment the count of packages in STATUS."
+  (cl-incf (cas "a")))
+Not sure how to fix, given it's limited by our use of progn, which I
+don't think we can get around.
+* Not sure how to do:
+** DONE Make eval-defun work inside namespaces.
+   CLOSED: [2014-11-09 Sun 18:10]
+** TODO Special treatment for defstruct.
+Right now it's simply being handled as a macro
+* Just do it
+** TODO Add a :use keyword to defspace.
+** TODO Namespace symbols in doc strings.
+   Should include =`symbol'=, =\\<symbol>= and =\\{symbol}=.
+** TODO Namespace the 
 of cl arglists.
+** DONE Don't call edebug if debug-spec is t or 0.
+   CLOSED: [2014-07-17 Thu 19:14]
+** TODO Describe keywords in an info manual, and refer to it instead of the 
+* Not sure whether should be done:
diff --git a/UsageExample.org b/UsageExample.org
new file mode 100644
index 0000000..9c0ceb4
--- /dev/null
+++ b/UsageExample.org
@@ -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))
+(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:
+(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
+** 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))
+(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!
+      )))
+* Usage Instructions
+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
+(define-namespace foo-
+(defvar bar 1 "docs")
+(defun free ()
+  "DOC"
+  (message "hi"))
+expands to
+#+begin_src emacs-lisp
+(defvar foo-bar 1 "docs")
+(defun foo-free ()
+  "DOC"
+  (message "hi"))
+*** 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))
+ ((::infinite 2) (message "Global function call"))
+ ((something-else t) (message "Global function call"))
+ ((infinite var) (message "Local function call."))
+ (infinite (message "Variable.")))
+expands to
+#+begin_src emacs-lisp
+(defvar foo-myvar infinite)
+(defun foo-infinite (x)
+  (foo-infinite x))
+ ((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.")))
+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)
+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 
+* 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
 for a description with examples.
diff --git a/names-dev.el b/names-dev.el
new file mode 100644
index 0000000..bc9552b
--- /dev/null
+++ b/names-dev.el
@@ -0,0 +1,239 @@
+;;; names-dev.el --- Developer Functions to facilitate use of names.el with 
your package.
+;; Copyright (C) 2014 Artur Malabarba <address@hidden>
+;; Author: Artur Malabarba <address@hidden>
+;; URL: http://github.com/Bruce-Connor/names
+;; Prefix: names
+;; Separator: -
+;;; Commentary:
+;; This package has some convenient functions for developers working
+;; with names.el.
+;; This package is installed along with names.el, but to use its
+;; features you must require it explicitly:
+;;     (require 'names-dev)
+;;; License:
+;; This file is part of GNU Emacs.
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; GNU General Public License for more details.
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+;;; Code:
+(require 'names)
+(require 'elisp-mode nil t)
+(require 'lisp-mode nil t)
+;;; ---------------------------------------------------------------
+;;; Developer Utility Functions
+(defmacro names-compare-forms (name form-a form-b)
+  "Test if (namespace NAME FORM-A) is the same as FORM-B."
+  (declare (indent (lambda (&rest x) 0))
+           (debug (symbolp sexp form)))
+  `(equal
+    (macroexpand-all '(define-namespace ,name :global :verbose ,form-a))
+    (macroexpand-all ',form-b)))
+(defmacro names-compare-forms-assert (name form-a form-b)
+  "Assert if (namespace NAME FORM-A) is the same as FORM-B."
+  (declare (indent (lambda (&rest x) 0))
+           (debug (symbolp sexp form)))
+  (cl-assert
+   (names-compare-forms name form-a form-b)
+    t))
+(defmacro names-print (name &rest forms)
+  "Return the expanded results of (namespace NAME :global :verbose FORMS).
+Ideal for determining why a specific form isn't being parsed
+  (declare (indent (lambda (&rest x) 0)) (debug 0))
+  `(let ((eval-expression-print-level (max eval-expression-print-level 300))
+         (eval-expression-print-length (max eval-expression-print-length 300)))
+     (macroexpand '(define-namespace ,name :global :verbose ,@forms))))
+(defvar names-font-lock
+  '(("^:autoload\\_>" 0 'font-lock-warning-face prepend)
+    ("(\\(\\_<define-namespace\\_>\\)[\t \n]+\\([^\t \n]+\\)"
+     (1 'font-lock-keyword-face)
+     (2 'font-lock-variable-name-face))))
+(when (boundp 'lisp-el-font-lock-keywords-2)
+  (setq lisp-el-font-lock-keywords-2
+        (append names-font-lock
+                lisp-el-font-lock-keywords-2)))
+;;; The backbone
+(defun names--looking-at-namespace ()
+  "Non-nil if point is at a `define-namespace' form or an alias to it."
+  (when (looking-at "(\\_<")
+    (save-excursion
+      (forward-char 1)
+      (ignore-errors
+        (equal (indirect-function (intern (thing-at-point 'symbol)))
+               (indirect-function 'define-namespace))))))
+(defun names--generate-new-buffer (name &optional form)
+  "Generate and return a new buffer.
+NAME is current namespace name.
+If FORM is provided, also try to use it to decide an informative
+buffer name."
+  (get-buffer-create
+   (concat
+    " *names "
+    (format "%s %s"
+            (or (car-safe form) (random 10000))
+            (or (car-safe (cdr-safe form)) (random 10000)))
+    "*")))
+(defmacro names--wrapped-in-namespace (command form &optional kill &rest body)
+  "Call COMMAND, except in a namespace.
+In a namespace, expand FORM in a separate buffer then execute
+BODY. If BODY is nil, call COMMAND instead.
+If KILL is non-nil, kill the temp buffer afterwards."
+  (declare (indent defun)
+           (debug (sexp form form body)))
+  ;; Get the namespace, if we're in one.
+  `(let ((evaled-form ,form)
+         (invocation
+          ',(if (commandp command t)
+                `(call-interactively #',command)
+              command))
+         (entire-namespace
+          (save-excursion
+            (when (progn
+                    (end-of-defun)
+                    (beginning-of-defun)
+                    (ignore-errors
+                      (backward-up-list)
+                      (names--looking-at-namespace)))
+              (cdr (read (current-buffer))))))
+         b keylist spec name expanded-form)
+     ;; If we're not in a namespace, call the regular `eval-defun'.
+     (if (null entire-namespace)
+         (eval invocation)
+       ;; If we are, expand the function in a temp buffer
+       (setq name (pop entire-namespace))
+       (while (setq spec (names--next-keyword entire-namespace))
+         (setq keylist (append keylist spec)))
+       ;; Prepare the (possibly) temporary buffer.
+       (setq b (names--generate-new-buffer name evaled-form))
+       (unwind-protect
+           (with-current-buffer b
+             (cl-letf (((symbol-function #'message) #'ignore))
+               (erase-buffer)
+               (emacs-lisp-mode)
+               ;; Print everything inside the `progn'.
+               (mapc
+                (lambda (it) (pp it (current-buffer)))
+                (cdr
+                 (setq expanded-form
+                       (macroexpand
+                        `(define-namespace ,name :global :clean-output 
,@keylist ,evaled-form)))))
+               (when (fboundp 'font-lock-ensure)
+                 (font-lock-ensure)))
+             ;; Return value
+             ,@(or body '((eval invocation))))
+         ;; Kill the buffer if we won't need it.
+         (when (and ,kill (buffer-live-p b))
+           (kill-buffer b))))))
+(defun names-eval-defun (edebug-it)
+  "Identical to `eval-defun', except it works for forms inside namespaces.
+Argument EDEBUG-IT is the same as `eval-defun', causes the form
+to be edebugged."
+  (interactive "P")
+  (require 'font-lock) ; just in case
+  (let ((form
+         (save-excursion
+           (end-of-defun)
+           (beginning-of-defun)
+           (read (current-buffer)))))
+    (names--wrapped-in-namespace
+      eval-defun form (null edebug-it))))
+;;; eval-last-sexp
+(defalias 'names--preceding-sexp-original
+  (symbol-function 'elisp--preceding-sexp))
+(defun names--preceding-sexp ()
+  "Like `elisp--preceding-sexp', but expand namespaces."
+  (names--wrapped-in-namespace
+    (names--preceding-sexp-original) (names--preceding-sexp-original) t
+    expanded-form))
+(defun names-eval-last-sexp (eval-last-sexp-arg-internal)
+  "Identical to `eval-last-sexp', except it works for forms inside namespaces.
+Argument EVAL-LAST-SEXP-ARG-INTERNAL is the same as `eval-last-sexp'."
+  (interactive "P")
+  (cl-letf (((symbol-function 'elisp--preceding-sexp)
+             #'names--preceding-sexp))
+    (eval-last-sexp eval-last-sexp-arg-internal)))
+(defun names-eval-print-last-sexp (eval-last-sexp-arg-internal)
+  "Identical to `eval-print-last-sexp', except it works for forms inside 
+Argument EVAL-LAST-SEXP-ARG-INTERNAL is the same as `eval-print-last-sexp'."
+  (interactive "P")
+  (cl-letf (((symbol-function 'elisp--preceding-sexp)
+             #'names--preceding-sexp))
+    (eval-print-last-sexp eval-last-sexp-arg-internal)))
+;; (pp (symbol-function 'names-eval-defun) (current-buffer))
+;;; Find stuff
+(require 'find-func nil t)
+(defalias 'names--fboundp-original (symbol-function 'fboundp))
+(defalias 'names--boundp-original (symbol-function 'boundp))
+(defalias 'names--find-function-read-original (symbol-function 
+(defalias 'find-function-read 'names--find-function-read)
+(defun names--find-function-read (&optional type)
+  "Identical to `eval-print-last-sexp', except it works for forms inside 
+Argument EVAL-LAST-SEXP-ARG-INTERNAL is the same as `eval-print-last-sexp'."
+  (interactive "P")
+  (let ((buf (current-buffer)))
+    (names--wrapped-in-namespace
+      (names--find-function-read-original type) nil t
+      (set-buffer buf)
+      (let ((names--name name))
+        (cl-letf (((symbol-function 'fboundp) #'names--dev-fboundp)
+                  ((symbol-function 'boundp) #'names--dev-boundp))
+          (names--find-function-read-original type))))))
+(defun names--dev-fboundp (sym)
+  (or (names--fboundp-original sym)
+      (names--fboundp-original (names--prepend sym))))
+(defun names--dev-boundp (sym)
+  (or (names--boundp-original sym)
+      (names--boundp-original (names--prepend sym))))
+;;; The keys
+(eval-after-load 'lisp-mode
+  '(let ((map emacs-lisp-mode-map))
+     (define-key map [remap eval-defun] #'names-eval-defun)
+     (define-key map [remap eval-last-sexp] #'names-eval-last-sexp)
+     (define-key map [remap eval-print-last-sexp] 
+(provide 'names-dev)
+;;; names-dev.el ends here
diff --git a/names.el b/names.el
new file mode 100644
index 0000000..924cc8d
--- /dev/null
+++ b/names.el
@@ -0,0 +1,1243 @@
+;;; names.el --- Namespaces for emacs-lisp. Avoid name clobbering without 
hiding symbols.
+;; Copyright (C) 2011, 2013 Free Software Foundation, Inc.
+;; Author: Artur Malabarba <address@hidden>
+;; URL: http://github.com/Bruce-Connor/names
+;; Version: 0
+;; Package-Requires: ((emacs "24.1") (cl-lib "0.5"))
+;; Keywords: extensions lisp
+;; Prefix: names
+;; Separator: -
+;;; Commentary:
+;; The description is way too large to sanely write here, below is a
+;; summary. For a complete description, please visit the package's
+;; frontpage with `M-x names-view-manual', or see the Readme file on
+;; https://raw.githubusercontent.com/Bruce-Connor/names/master/Readme.org
+;;; License:
+;; This file is part of GNU Emacs.
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; GNU General Public License for more details.
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+;;; Change Log:
+;;; Code:
+(require 'cl-lib)
+(require 'edebug)
+(require 'bytecomp)
+(require 'advice)
+;;; Support
+(declare-function names--autoload-do-load "names" 2)
+(if (fboundp 'function-get)
+    (defalias 'names--function-get #'function-get)
+  (defun names--function-get (f prop &rest _)
+    "Return the value of property PROP of function F.
+If F is an autoloaded macro, try to autoload it in the hope that
+it will set PROP."
+    (let ((val nil))
+      (while (and (symbolp f)
+                  (null (setq val (get f prop)))
+                  (fboundp f))
+        (let ((fundef (symbol-function f)))
+          (if (and (names--autoloadp fundef)
+                   (not (equal fundef (names--autoload-do-load fundef f))))
+              nil ;Re-try `get' on the same `f'.
+            (setq f fundef))))
+      val))
+  (defun names--autoload-do-load (def name)
+    "Load autoloaded definition DEF from function named NAME."
+    (unless (load (cadr def) 'noerror)
+      (error "Macro `%s' is autoloaded, but its file (%s) couldn't be loaded"
+             name (cadr def)))
+    (symbol-function name)))
+(if (fboundp 'macrop)
+    (defalias 'names--compat-macrop #'macrop)
+  (defun names--compat-macrop (object)
+    "Non-nil if and only if OBJECT is a macro."
+    (let ((def (indirect-function object t)))
+      (when (consp def)
+        (or (eq 'macro (car def))
+            (and (names--autoloadp def) (memq (nth 4 def) '(macro t))))))))
+(if (fboundp 'autoloadp)
+    (defalias 'names--autoloadp #'autoloadp)
+  (defsubst names--autoloadp (object)
+    "Non-nil if OBJECT is an autoload."
+    (eq 'autoload (car-safe object))))
+(unless (get-edebug-spec 'cl-defun)
+  (def-edebug-spec cl-defun defun*))
+(unless (get-edebug-spec 'cl-defmacro)
+  (def-edebug-spec cl-defmacro defmacro*))
+(unless (get-edebug-spec 'setq-local)
+  (def-edebug-spec setq-local setq))
+(unless (get-edebug-spec 'loop)
+  (def-edebug-spec loop
+    (&rest &or
+           ;; These are usually followed by a symbol, but it can
+           ;; actually be any destructuring-bind pattern, which
+           ;; would erroneously match `form'.
+           [[&or "for" "as" "with" "and"] sexp]
+           ;; These are followed by expressions which could
+           ;; erroneously match `symbolp'.
+           [[&or "from" "upfrom" "downfrom" "to" "upto" "downto"
+                 "above" "below" "by" "in" "on" "=" "across"
+                 "repeat" "while" "until" "always" "never"
+                 "thereis" "collect" "append" "nconc" "sum"
+                 "count" "maximize" "minimize" "if" "unless"
+                 "return"] form]
+           ;; Simple default, which covers 99% of the cases.
+           symbolp form)))
+;;; ---------------------------------------------------------------
+;;; Variables
+(defconst names-version "0.5.5" "Version of the names.el package.")
+(defvar names--name nil
+  "Name of the current namespace inside the `define-namespace' macro.")
+(defvar names--regexp nil "Regexp matching `names--name'.")
+(defvar names--load-file (and load-file-name (expand-file-name load-file-name))
+  "The file where the current version of Names was loaded.
+This is used by `names--check-for-update' to check if a new
+version has been installed.")
+(defvar names--bound nil
+  "List of variables defined in this namespace.")
+(defvar names--fbound nil
+  "List of functions defined in this namespace.")
+(defvar names--macro nil
+  "List of macros defined in this namespace.")
+(defvar names--keywords nil
+  "Keywords that were passed to the current namespace.
+See `names--keyword-list' for a list and description of possible
+(defvar names--local-vars nil
+  "Non-global vars that are let/lambda bound at the moment.
+These won't be namespaced, as local takes priority over namespace.")
+(defvar names--protection nil
+  "Leading chars used to identify protected symbols.
+Don't customise this.
+Instead use the :protection keyword when defining the
+(defvar names--current-run nil
+  "Either 1 or 2, depending on which runthrough we're in.")
+(defvar names--var-list
+  '(names--name names--regexp names--bound
+                names--version
+                names--package names--group-parent
+                names--macro names--current-run
+                names--fbound names--keywords
+                names--local-vars names--protection)
+  "List of variables the user shouldn't touch.")
+(defvar names--inside-make-autoload nil
+  "Used in `make-autoload' to indicate we're making autoloads.")
+(defvar names--package nil
+  "Package, name to be used by the :group and :version keywords.
+Is derived from `load-file-name', unless the :package keyword is
+passed to `define-namespace'.")
+(defvar names--group-parent nil
+  "The name of the parent to be given to `defgroup'.
+Is only non-nil if the :group keyword is passed to `define-namespace'.")
+(defvar names--version nil
+  "The version number given by :version.
+Used to define a constant and a command.")
+(defconst names--keyword-list
+  '((:group
+     1 (lambda (x)
+         (if (symbolp x)
+             (setq names--group-parent x)
+           (names--warn
+            "Argument given to :group is not a symbol: %s" x)))
+     "Indicate `define-namespace' should make a `defgroup' for you.
+The name of the group is the package name (see :package keyword).
+This keyword should be given one argument, the name of the PARENT
+group as an unquoted symbol.
+If this keyword is provided, besides including a defgroup, Names
+will also include a :group keyword in every `defcustom' (and
+similar forms) that don't already contain one.")
+    (:version
+     1
+     (lambda (x)
+       (if (stringp x)
+           (setq names--version x)
+         (names--warn
+          "Argument given to :version is not a string: %s" x)))
+     "Indicate `define-namespace' should define the version number.
+This keyword should be given one argument, a string describing
+the package's version number.
+With this, Names will generate a `defconst' and an interactive
+`defun', each named `PACKAGE-NAME-version'. The function messages
+and returns the version number. See the :package keyword.")
+    (:package
+     1
+     (lambda (x)
+       (if (symbolp x)
+           (setq names--package x)
+         (names--warn
+          "Argument given to :package is not a symbol: %s" x)))
+     "Set the name of this package to the given symbol.
+This keyword should be given one argument, a symbol corresponding
+to the name of this package.
+If this keyword isn't used, the package name is taken as the the
+file's basename, but only if its actually needed. This name is
+needed by the :version and :group keywords.")
+    (:protection
+     1
+     (lambda (x)
+       (let ((val (symbol-name x)))
+         (setq names--protection
+               (format "\\`%s" (regexp-quote val)))))
+     "Change the value of the `names--protection' variable.")
+    (:no-let-vars
+     0 nil
+     "Indicates variables assigned in let-bind are NOT candidates for 
+    (:verbose
+     0 nil
+     "Cause a message to be called on each special form.")
+    (:global
+     0 nil
+     "Accept namespaced names from outside current namespace definition.")
+    (:assume-var-quote
+     0 nil
+     "Indicate symbols quoted with `quote' should be considered variable 
+    (:dont-assume-function-quote
+     0 nil
+     "Indicate symbols quoted with `function' should NOT be considered 
function names.")
+    (:clean-output
+     0 nil
+     "Indicate only forms actually inside the namespace should be present in 
the output.
+This is for internal use. It is used by `names-eval-defun' to
+prevent `define-namespace' from adding things like `defgroup' or
+`defconst's to the output."))
+  "List of keywords used by `define-namespace'.
+Each element is a list containing
+- KEYWORD is the keyword's name, a symbol satifying `keywordp'.
+- N is the number of arguments it takes, an integer.
+- DEFINITION is a function (symbol or lambda) that takes N
+arguments and does whatever you need for implementing the
+- DOCUMENTATION is a string explaining the keyword's
+(defmacro names--prepend (sbl)
+  "Return namespace+SBL."
+  (declare (debug (symbolp)))
+  `(intern (format "%s%s" names--name ,sbl)))
+(defmacro names--filter-if-bound (var &optional pred)
+  "If VAR is bound and is a list, take the car of its elements which satify 
+  (declare (debug (symbolp &optional function-form)))
+  `(when (boundp ',var)
+     (remove
+      nil
+      (mapcar (lambda (x) (when (funcall (or ,pred 'identity) (or (car-safe x) 
+                (or (car-safe x) x)))
+          ,var))))
+(defmacro names--next-keyword (body)
+  "If car of BODY is a known keyword, `pop' it (and its arguments) from body.
+Returns a list (KEYWORD . ARGUMENTLIST)."
+  (declare (debug sexp))
+  `(let ((kar (car-safe ,body))
+         out n)
+     (and kar
+          (keywordp kar)
+          (setq n (assoc kar names--keyword-list))
+          (setq n (cadr n))
+          (dotimes (it (1+ n) out)
+            (push (pop ,body) out))
+          (nreverse out))))
+(defvar names--has-reloaded nil
+  "Whether `names--reload-if-upgraded' has already been called in this run.")
+;;; ---------------------------------------------------------------
+;;; The Main Macro and Main Function.
+(defmacro define-namespace (name &rest body)
+  "Inside the namespace NAME, execute BODY.
+NAME can be any symbol (not quoted), but it's highly recommended
+to use some form of separator (such as :, /, or -). For a
+complete description of this macro, please visit the frontpage
+with \\[names-view-manual].
+In summary, this macro has two main effects:
+1. Any definitions inside BODY will have NAME prepended to the
+symbol given. Ex:
+    (define-namespace foo-
+    (defvar bar 1 \"docs\")
+    )
+expands to
+    (defvar foo-bar 1 \"docs\")
+2. Any function calls and variable names get NAME prepended to
+them if such a variable or function exists. Ex:
+    (define-namespace foo:
+    (defun message (x y) nil)
+    (message \"%s\" my-var)
+    )
+expands to
+    (defun foo:message (x y) nil)
+    (foo:message \"%s\" my-var)
+Note how `message' is expanded to `foo:message' in the second
+form, because that function exists. Meanwhile, `bar' is left
+untouched because `foo:bar' is not a known variable name.
+In order for `define-namespace' to work with \";;;###autoload\"
+comments must replace all instances of \";;;###autoload\" inside
+your `define-namespace' with `:autoload'.
+Afterwards, add an \";;;###autoload\" comment just above your
+Immediately after NAME you may add keywords which customize the
+behaviour of `define-namespace'. For a list of possible keywords
+and a description of their effects, see the variable
+\(fn NAME [KEYWORD ...] BODY)"
+  (declare (indent (lambda (&rest x) 0))
+           (debug (&define name [&rest keywordp &optional [&or symbolp 
(symbolp . symbolp)]] body)))
+  (let ((names--has-reloaded names--has-reloaded))
+    ;; This was to avoid an infinite recursion, but the bug turned out
+    ;; to be somewhere else. Still, I see no reason to erase this.
+    (unless names--has-reloaded
+      (setq names--has-reloaded t)
+      (names--reload-if-upgraded))
+    (names--error-if-using-vars)
+    (names--define-namespace-implementation name body)))
+(defun names--define-namespace-implementation (name body)
+  "Namespace BODY using NAME.
+See `define-namespace' for more information."
+  (unwind-protect
+      (let* ((names--name name)
+             (names--regexp
+              (concat "\\`" (regexp-quote (symbol-name name))))
+             (names--current-run 0)
+             ;; Use the :protection keyword to change this.
+             (names--protection "\\`::")
+             (names--bound
+              (names--remove-namespace-from-list
+               (names--filter-if-bound byte-compile-bound-variables)
+               (names--filter-if-bound byte-compile-variables)))
+             (names--fbound
+              (names--remove-namespace-from-list
+               (names--filter-if-bound byte-compile-macro-environment 
+               (names--filter-if-bound byte-compile-function-environment 
+             (names--macro
+              (names--remove-namespace-from-list
+               (names--filter-if-bound byte-compile-macro-environment (lambda 
(x) (not (names--compat-macrop x))))
+               (names--filter-if-bound byte-compile-function-environment 
(lambda (x) (not (names--compat-macrop x))))))
+             names--keywords names--local-vars key-and-args
+             names--version names--package names--group-parent)
+        ;; Read keywords
+        (while (setq key-and-args (names--next-keyword body))
+          (names--handle-keyword key-and-args)
+          (push key-and-args names--keywords))
+        ;; First have to populate the bound and fbound lists. So we read
+        ;; the entire form (without evaluating it).
+        (mapc 'names-convert-form body)
+        (setq names--current-run (1+ names--current-run))
+        ;; Then we go back and actually namespace the entire form, which
+        ;; we'll later return so that it can be evaluated.
+        (setq body
+              (cons
+               'progn
+               (append
+                (when (and names--group-parent
+                           (null (names--keyword :clean-output)))
+                  (list (names--generate-defgroup)))
+                (when (and names--version
+                           (null (names--keyword :clean-output)))
+                  ;; `names--generate-version' returns a list.
+                  (names--generate-version))
+                (mapcar 'names-convert-form
+                        ;; Unless we're in `make-autoload', then just return 
+                        (if names--inside-make-autoload
+                            (names--extract-autoloads body)
+                          body)))))
+        ;; On emacs-version < 24.4, the byte-compiler cannot expand a
+        ;; macro if it is being called in the same top-level form as
+        ;; it was defined. That's a problem for us, since the entire
+        ;; namespace is a single top-level form (we return a `progn').
+        ;; The solution is for us to add the macros to
+        ;; `byte-compile-macro-environment' ourselves.
+        (if (and (boundp 'byte-compile-current-buffer)
+                 byte-compile-current-buffer
+                 (null names--inside-make-autoload)
+                 (version< emacs-version "24.4"))
+            (let ((byte-compile-macro-environment
+                   (when (boundp 'byte-compile-macro-environment)
+                     byte-compile-macro-environment)))
+              (mapc #'names--add-macro-to-environment (cdr body))
+              (macroexpand-all body byte-compile-macro-environment))
+          body))
+    ;; Exiting the `unwind-protect'.
+    (mapc (lambda (x) (set x nil)) names--var-list)))
+(defun names--reload-if-upgraded ()
+  "Verify if there's a more recent version of Names in the `load-path'.
+If so, evaluate it."
+  (ignore-errors
+    (require 'find-func)
+    (let ((lp (expand-file-name (find-library-name "names")))
+          new-version)
+      (when (and lp
+                 (not (string= lp names--load-file))
+                 (file-readable-p lp))
+        (with-temp-buffer
+          (insert-file-contents-literally lp)
+          (goto-char (point-min))
+          (setq new-version
+                (save-excursion
+                  (when (search-forward-regexp
+                         "(defconst\\s-+names-version\\s-+\"\\([^\"]+\\)\"" 
nil t)
+                    (match-string-no-properties 1))))
+          (when (and new-version (version< names-version new-version))
+            (eval-buffer nil lp)))))))
+(defun names-convert-form (form)
+  "Do namespace conversion on FORM.
+FORM is any legal elisp form.
+Namespace name is defined by the global variable `names--name'.
+See macro `namespace' for more information."
+  (cond
+   ((null form) form)
+   ;; Function calls
+   ((consp form)
+    (let ((kar (car form))
+          func)
+      (cond
+       ;; If symbol is protected, clean it.
+       ((and (symbolp kar)
+             (setq func (names--remove-protection kar)))
+        (names--message "Protected: %s" kar)
+        ;; And decide what to do with it.
+        (names--handle-args func (cdr form)))
+       ;; If kar is a list, either 1) it's a lambda form, 2) it's a
+       ;; macro we don't know about yet, 3) we have a bug.
+       ((consp kar)
+        (when (and (null (functionp kar))
+                   (> names--current-run 1))
+          (names--warn "Ran into the following strange form.
+Either it's an undefined macro, a macro with a bad debug declaration, or we 
have a bug.\n%s" form))
+        (mapcar 'names-convert-form form))
+       ;; Namespaced Functions/Macros
+       ((names--fboundp kar)
+        (names--message "Namespaced: %s" kar)
+        (names--args-of-function-or-macro
+         (names--prepend kar) (cdr form) (names--macrop kar)))
+       ;; General functions/macros/special-forms
+       (t (names--handle-args kar (cdr form))))))
+   ;; Variables
+   ((symbolp form)
+    (names--message "Symbol handling: %s" form)
+    ;; If symbol is protected, clean it and don't namespace it.
+    (or (names--remove-protection form)
+        ;; Otherwise, namespace if possible.
+        (if (names--boundp form)
+            (names--prepend form)
+          form)))
+   ;; Values
+   (t form)))
+;;; ---------------------------------------------------------------
+;;; Some auxiliary functions
+(defun names-view-manual ()
+  "Call `browse-url' to view the manual of the Names package."
+  (interactive)
+  (browse-url "http://github.com/Bruce-Connor/names";))
+(defun names--package-name ()
+  "Return the package name as a symbol.
+Decide package name based on several factors. In order:
+    1. The :package keyword,
+    2. The namespace NAME, removing the final char."
+  (or names--package
+      (let ((package (symbol-name names--name)))
+        (prog1 (setq names--package
+                     (intern (substring package 0 -1)))
+          (names--warn "No :package given. Guessing `%s'"
+                       names--package)))))
+(defun names--generate-defgroup ()
+  "Return a `defgroup' form for the current namespace."
+  (list 'defgroup (names--package-name) nil
+        (format "Customization group for %s." (names--package-name))
+        :prefix (symbol-name names--name)
+        :group `',names--group-parent))
+(defun names--generate-version ()
+  "Return a `defun' and a `defconst' forms declaring the package version.
+Also adds `version' to `names--fbound' and `names--bound'."
+  (add-to-list 'names--fbound 'version)
+  (add-to-list 'names--bound 'version)
+  (list
+   (list 'defconst (names--prepend 'version)
+         names--version
+         (format "Version of the %s package." (names--package-name)))
+   (list 'defun (names--prepend 'version) nil
+         (format "Version of the %s package." (names--package-name))
+         '(interactive)
+         names--version)))
+(defun names--add-macro-to-environment (form)
+  "If FORM declares a macro, add it to `byte-compile-macro-environment'."
+  (let ((expansion form))
+    (while (names--compat-macrop (car-safe expansion))
+      (setq expansion
+            (ignore-errors (macroexpand
+                            expansion byte-compile-macro-environment))))
+    (and expansion
+         (car-safe expansion)
+         (or (and (memq (car-safe expansion) '(progn prog1 prog2))
+                  (mapc #'names--add-macro-to-environment (cdr expansion)))
+             (and (eq 'defalias (car-safe expansion))
+                  (let ((def (ignore-errors (eval (nth 2 expansion)))))
+                    (and (names--compat-macrop def)
+                         (push (cons (ignore-errors
+                                       (eval (nth 1 expansion)))
+                                     (cdr-safe def))
+                               byte-compile-macro-environment))))))))
+(defun names--extract-autoloads (body)
+  "Return a list of the forms in BODY preceded by :autoload."
+  (let (acons)
+    (when (setq acons (memq :autoload body))
+      (cons
+       (cadr acons)
+       (names--extract-autoloads (cdr (cdr acons)))))))
+(defadvice make-autoload (around names-before-make-autoload-advice
+                                 (form file &optional expansion) activate)
+  "Make sure `make-autoload' understands `define-namespace'.
+Use the `names--inside-make-autoload' variable to indicate to
+`define-namespace' that we're generating autoloads."
+  ;; We used to have a letbind here, but this was causing a void
+  ;; variable bug on Emacs 24.3.
+  (require 'names)
+  (if (null (eq (car-safe form) 'define-namespace))
+      ad-do-it
+    (setq names--inside-make-autoload t)
+    (setq form (macroexpand form))
+    (setq names--inside-make-autoload nil)
+    ;; Up to 24.2 `make-autoload' couldn't handle `progn's.
+    (if (version< emacs-version "24.3")
+        (setq ad-return-value
+              (cons 'progn
+                    (mapcar (lambda (x) (names--make-autoload-compat x file))
+                            (cdr form))))
+      (ad-set-arg 2 'expansion)
+      (ad-set-arg 0 form)
+      ad-do-it)))
+(defun names--make-autoload-compat (form file)
+  (if (eq (car-safe form) 'defalias)
+      form
+    (make-autoload form file)))
+(defvar names--ignored-forms '(declare)
+  "The name of functions/macros/special-forms which we return without 
+(defun names--handle-args (func args)
+  "Generic handling for the form (FUNC . ARGS), without namespacing FUNC."
+  (if (memq func names--ignored-forms)
+      (cons func args)
+    ;; TODO: Speed this up. Just change it to an alist or a hash-table.
+    (let ((handler (intern-soft (format "names--convert-%s" func))))
+      ;; Some function-like forms get special handling.
+      ;; That's anything with a names--convert-%s function defined.
+      (if (fboundp handler)
+          (progn (names--message "Special handling: %s" handler)
+                 (funcall handler (cons func args)))
+        ;; If it isn't special, it's either a function or a macro.
+        (names--args-of-function-or-macro func args (names--compat-macrop 
+(defun names--message (f &rest rest)
+  "If :verbose is on, pass F and REST to `message'."
+  (when (names--keyword :verbose)
+    (apply 'message (concat "[names] " f) rest)))
+(defun names--warn (f &rest rest)
+  "Pass F and REST to `message', unless byte-compiling or non-interactive."
+  (unless (and (null (names--keyword :verbose))
+               (and (boundp 'byte-compile-function-environment)
+                    byte-compile-function-environment))
+    (apply 'message (concat "[names] " f) rest)))
+(defun names--error-if-using-vars ()
+  "Remind the developer that variables are not customizable."
+  (mapcar
+   (lambda (x)
+     (when (eval x)
+       (error "[names] Global value of variable %s should be nil! %s"
+              x "Set it using keywords instead")))
+   names--var-list))
+(defun names--remove-namespace-from-list (&rest lists)
+  "Return a concatenated un-namespaced version of LISTS.
+Symbols in LISTS that aren't namespaced are removed, symbols that
+are namespaced become un-namespaced."
+  (delq nil (mapcar 'names--remove-namespace (apply 'append lists))))
+(defun names--remove-namespace (symbol)
+  "Return SYMBOL with namespace removed, or nil if S wasn't namespaced."
+  (names--remove-regexp symbol names--regexp))
+(defun names--remove-protection (symbol)
+  "Remove the leading :: from SYMBOL if possible, otherwise return nil."
+  (names--remove-regexp symbol names--protection))
+(defun names--remove-regexp (s r)
+  "Return S with regexp R removed, or nil if S didn't match."
+  (let ((name (symbol-name s)))
+    (when (string-match r name)
+      (intern (replace-match "" nil nil name)))))
+(defun names--quote-p (sbl)
+  "Is SBL a function which quotes its argument?"
+  (memq sbl '(quote function)))
+(defun names--fboundp (sbl)
+  "Is namespace+SBL a fboundp symbol?"
+  (or (memq sbl names--fbound)
+      (memq sbl names--macro)
+      (and (names--keyword :global)
+           (fboundp (names--prepend sbl)))))
+(defun names--macrop (sbl)
+  "Is namespace+SBL a fboundp symbol?"
+  (or (memq sbl names--macro)
+      (and (names--keyword :global)
+           (names--compat-macrop (names--prepend sbl)))))
+(defun names--keyword (keyword)
+  "Was KEYWORD one of the keywords passed to the `namespace' macro?"
+  (assoc keyword names--keywords))
+(defun names--boundp (sbl)
+  "Is namespace+SBL a boundp symbol?
+If SBL has a let binding, that takes precendence so this also
+returns nil."
+  (and (null (memq sbl names--local-vars))
+       (or (memq sbl names--bound)
+           (and (names--keyword :global)
+                (boundp (names--prepend sbl))))))
+;;; This is calling edebug even on `when' and `unless'
+(defun names--args-of-function-or-macro (function args macro)
+  "Namespace FUNCTION's arguments ARGS, with special treatment if MACRO is 
+  (if macro
+      (let ((it (names--get-edebug-spec function))
+            (names--verbose (eq function 'push)))
+        (names--message "Edebug-spec of `%s' is %s" function it)
+        ;; Macros where we evaluate all arguments are like functions.
+        (if (equal it t)
+            (names--args-of-function-or-macro function args nil)
+          ;; Macros where nothing is evaluated we can just return.
+          (if (equal it 0)
+              (cons function args)
+            ;; Other macros are complicated. Ask edebug for help.
+            (names--macro-args-using-edebug (cons function args)))))
+    ;; We just convert the arguments of functions.
+    (cons function (mapcar 'names-convert-form args))))
+(defun names--get-edebug-spec (name)
+  "Get 'edebug-form-spec property of symbol NAME."
+  ;; Get the spec of symbol resolving all indirection.
+  (let ((spec nil)
+        (indirect name))
+    (while (progn
+             (and (symbolp indirect)
+                  (setq indirect
+                        (names--function-get
+                         indirect 'edebug-form-spec 'macro))))
+      ;; (edebug-trace "indirection: %s" edebug-form-spec)
+      (setq spec indirect))
+    spec))
+(defvar names--is-inside-macro nil
+  "Auxiliary var used in `names--macro-args-using-edebug'.")
+(defvar names--gensym-counter 0
+  "Counter used to uniquify symbols generated `names--gensym'.")
+(defun names--macro-args-using-edebug (form)
+  "Namespace the arguments of macro FORM by hacking into edebug.
+This takes advantage of the fact that macros (should) declare a
+`debug' specification which tells us which arguments are actually
+Elisp forms.
+Ideally, we would read this specification ourselves and see how
+it matches (cdr FORM), but that would take a lot of work and
+we'd be reimplementing something that edebug already does
+phenomenally. So we hack into edebug instead."
+  (require 'edebug)
+  (require 'cl-lib)
+  (cl-letf
+      ((max-lisp-eval-depth 3000)
+       (edebug-all-forms t)
+       (edebug-all-defs t)
+       (names--is-inside-macro form)
+       ;; Prevent excessive messaging.
+       ;; TODO: Don't do this if `message' is advised.
+       ((symbol-function 'message) #'names--edebug-message)
+       ;; Older edebugs have poor `get-edebug-spec'.
+       ((symbol-function 'get-edebug-spec) #'names--get-edebug-spec)
+       ;; Give symbols our own name.
+       ((symbol-function 'cl-gensym) #'names--gensym)
+       ;; Stop at one level deep.
+       ((symbol-function 'edebug-form) #'names--edebug-form)
+       ;; Don't actually wrap anything.
+       ((symbol-function 'edebug-make-enter-wrapper)
+        #'names--edebug-make-enter-wrapper))
+    (condition-case er
+        (with-temp-buffer
+          (pp form 'insert)
+          (goto-char (point-min))
+          ;; Do the magic!
+          (edebug-read-top-level-form))
+      (invalid-read-syntax
+       (names--warn
+        "Couldn't namespace this macro using its (debug ...) declaration: %s"
+        form)
+       form)
+      (error
+       (when (equal (car-safe (cdr-safe er))
+                    "Lisp nesting exceeds `max-lisp-eval-depth'")
+         (names--warn
+          "Lisp nesting exceeded `max-lisp-eval-depth' at the following form: 
+          form))
+       form))))
+(defvar names--message-backup
+  (if (ad-is-advised 'message)
+      (ad-get-orig-definition 'message)
+    (symbol-function 'message))
+  "Where names stores `message's definition while overriding it.")
+(defvar names--verbose nil
+  "If non-nil, verbose message are printed regardless of the :verbose keyword.
+Use this to easily turn on verbosity during tests.")
+(defun names--edebug-message (&rest _)
+  (if (or (names--keyword :verbose) names--verbose)
+      (apply names--message-backup _)
+    (when _ (apply 'format _))))
+(defun names--edebug-make-enter-wrapper (forms)
+  (setq edebug-def-name
+        (or edebug-def-name
+            edebug-old-def-name
+            (names--gensym "edebug-anon")))
+  (cons 'progn forms))
+(defun names--gensym (prefix)
+  "Generate a new uninterned symbol.
+The name is made by appending a number to PREFIX and preppending \"names\", 
default \"G\"."
+  (let ((num (prog1 names--gensym-counter
+               (setq names--gensym-counter
+                     (1+ names--gensym-counter)))))
+    (make-symbol (format "names-%s%d" (if (stringp prefix) prefix "G") num))))
+(defun names--edebug-form (cursor)
+  "Parse form given by CURSOR using edebug, and namespace it if necessary."
+  (require 'edebug)
+  ;; Return the instrumented form for the following form.
+  ;; Add the point offsets to the edebug-offset-list for the form.
+  (let* ((form (edebug-top-element-required cursor "Expected form"))
+         (offset (edebug-top-offset cursor))
+         ;; We don't want to convert the entire form that was passed
+         ;; to `names--macro-args-using-edebug', since the head of
+         ;; that was already converted and it would lead to an
+         ;; infinite loop.
+         ;; So we check for (equal names--is-inside-macro form)
+         ;; Simply incrementing a depth counter didn't work, for a
+         ;; reason I can no longer remember.
+         ;; We DO want to convert the arguments that edebug identifies
+         ;; as forms (level-1). And we do that ourselves, don't pass
+         ;; them to edebug.
+         (func (if (or (eq names--is-inside-macro t)
+                       (equal names--is-inside-macro form))
+                   'identity 'names-convert-form))
+         (names--is-inside-macro
+          (if (eq func 'names-convert-form)
+              t names--is-inside-macro)))
+    (names--message " [Edebug] Ran into this: %S" form)
+    (names--message "          Cursor: %S" cursor)
+    (prog1
+        (cond
+         ((consp form) ;; The first offset for a list form is for the list 
form itself.
+          (if (eq func 'names-convert-form)
+              (names-convert-form form)
+            (let* ((head (car form))
+                   (spec (and (symbolp head) (get-edebug-spec head)))
+                   (new-cursor (edebug-new-cursor form offset)))
+              ;; Find out if this is a defining form from first symbol.
+              ;; An indirect spec would not work here, yet.
+              (if (and (consp spec) (eq '&define (car spec)))
+                  (edebug-defining-form
+                   new-cursor
+                   (car offset) ;; before the form
+                   (edebug-after-offset cursor)
+                   (cons (symbol-name head) (cdr spec)))
+                ;; Wrap a regular form.
+                (edebug-list-form new-cursor)))))
+         ((symbolp form)
+          (funcall func form))
+         ;; Anything else is self-evaluating.
+         (t form))
+      (edebug-move-cursor cursor))))
+(defun names--maybe-append-group (form)
+  "Append (:group `names--package') to FORM.
+Only if the :group keyword was passed to `define-namespace' and
+if the form doesn't already have a :group."
+  (if (or (null names--group-parent) (memq :group form))
+      form
+    (append form `(:group ',(names--package-name)))))
+;;; ---------------------------------------------------------------
+;;; Interpreting keywords passed to the main macro.
+(defun names--handle-keyword (body)
+  "Call the function that handles the keyword at the car of BODY.
+Such function must be listed in `names--keyword-list'. If it is
+nil, this function just returns.
+Regardless of whether a function was called, the keyword is added
+to the variable `names--keywords'.
+The car of BODY is the keyword itself and the other elements are
+the keyword arguments, if any."
+  (let ((func (nth 2 (assoc (car body) names--keyword-list))))
+    (if (functionp func)
+        (apply func (cdr body))
+      nil)))
+;;; ---------------------------------------------------------------
+;;; Interpreting the actual forms found in BODY of the main macro.
+;; This is where the heavy work is done.
+;; If you'd like to implement support for some special form, simply
+;; define a function called `names--convert-FORM-NAME' along the
+;; lines of the functions defined below. It will be automatically used
+;; whenever that form is found.
+;;; Defun, defmacro, and defsubst macros are pretty predictable.
+(defun names--convert-defmacro (form)
+  "Special treatment for `defmacro' FORM."
+  (let* ((names--name-already-prefixed t)
+         (name (cadr form))
+         (spaced-name (names--prepend name))
+         decl)
+    (add-to-list 'names--macro name)
+    (add-to-list 'names--fbound name)
+    ;; Set the macros debug spec if possible. It will be relevant on
+    ;; the next run.
+    (when (setq decl (ignore-errors (cond
+                                     ((eq (car-safe (nth 3 form)) 'declare)
+                                      (nth 3 form))
+                                     ((and (stringp (nth 3 form))
+                                           (eq (car-safe (nth 4 form)) 
+                                      (nth 4 form))
+                                     (t nil))))
+      (setq decl (car (cdr-safe (assoc 'debug (cdr decl)))))
+      (when decl (put spaced-name 'edebug-form-spec decl)))
+    ;; Then convert the macro as a defalias.
+    (cons
+     (car form)
+     (names--convert-lambda
+      (cons spaced-name (cddr form))))))
+(defalias 'names--convert-defmacro* 'names--convert-defmacro)
+(defun names--convert-defvaralias (form)
+  "Special treatment for `defvaralias' FORM."
+  (let ((form (cons (car form)
+                    (mapcar #'names-convert-form (cdr form))))
+        (name))
+    (setq name (names--remove-namespace
+                (ignore-errors (eval (cadr form)))))
+    (when name
+      (add-to-list 'names--bound name))
+    form))
+(defun names--convert-defalias (form)
+  "Special treatment for `defalias' FORM."
+  (let ((form (cons (car form)
+                    (mapcar #'names-convert-form (cdr form))))
+        (name))
+    (setq name (names--remove-namespace
+                (ignore-errors (eval (cadr form)))))
+    (when name
+      (add-to-list 'names--fbound name))
+    form))
+(defun names--convert-defvar (form &optional dont-add)
+  "Special treatment for `defvar' FORM.
+If DONT-ADD is nil, the FORM's `cadr' is added to `names--bound'."
+  (let ((name (cadr form)))
+    (unless dont-add
+      (add-to-list 'names--bound name))
+    (append
+     (list
+      (car form)
+      (names--prepend name))
+     (mapcar 'names-convert-form (cdr (cdr form))))))
+(defalias 'names--convert-defconst 'names--convert-defvar
+  "Special treatment for `defconst' FORM.")
+(defun names--convert-defcustom (form)
+  "Special treatment for `defcustom' FORM."
+  (names--maybe-append-group
+   (names--convert-defvar form)))
+(defun names--convert-custom-declare-variable (form)
+  "Special treatment for `custom-declare-variable' FORM."
+  (let ((name (eval (cadr form))) ;;ignore-errors
+        (val (car (cddr form))))
+    (add-to-list 'names--bound name)
+    (append
+     (list
+      (car form)
+      (list 'quote (names--prepend name)) ;cadr
+      ;; The DEFAULT argument is explicitly evaluated by
+      ;; `custom-declare-variable', so it should be safe to namespace
+      ;; even when quoted. Plus, we need to do this because
+      ;; defcustom quotes this part.
+      (if (names--quote-p (car-safe val))
+          (list (car val) (names-convert-form (cadr val)))
+        (names-convert-form val))
+      (names-convert-form        (car (cdr (cdr (cdr form))))))
+     (mapcar 'names-convert-form (cdr (cdr (cdr (cdr form))))))))
+(defun names--convert-defface (form)
+  "Special treatment for `defface' FORM.
+Identical to defvar, just doesn't add the symbol to the boundp
+list. And maybe use a :group."
+  (names--maybe-append-group
+   (names--convert-defvar form :dont-add)))
+(defun names--convert-define-derived-mode (form)
+  "Special treatment for `define-derived-mode' FORM."
+  (let ((name (cadr form)))
+    (add-to-list 'names--fbound name)
+    (add-to-list 'names--bound name)
+    (add-to-list 'names--bound
+                 (intern (format "%s-map" name)))
+    (add-to-list 'names--bound
+                 (intern (format "%s-hook" name)))
+    (append
+     (names--maybe-append-group
+      ;; And here we namespace it.
+      (list
+       (car form)
+       (names--prepend name)
+       (nth 2 form)
+       (names-convert-form (nth 3 form))
+       (names-convert-form (nth 4 form))))
+     (mapcar #'names-convert-form (cddr form)))))
+(defun names--convert-define-minor-mode (form)
+  "Special treatment for `define-minor-mode' FORM."
+  (let ((name (cadr form))
+        (keymap (nth 5 form)))
+    ;; Register the mode name
+    (add-to-list 'names--fbound name)
+    (add-to-list 'names--bound name)
+    (add-to-list 'names--bound (intern (format "%s-hook" name)))
+    ;; Register the keymap
+    (if (or (null keymap) (null (symbolp keymap)))
+        (add-to-list 'names--bound (intern (format "%s-map" name)))
+      (when (setq keymap (names--remove-namespace keymap))
+        (add-to-list 'names--bound keymap)))
+    (append
+     (names--maybe-append-group
+      ;; And here we namespace it.
+      (list
+       (car form)
+       (names--prepend name)
+       (nth 2 form)
+       (names-convert-form (nth 3 form))
+       (names-convert-form (nth 4 form))
+       (names-convert-form (nth 5 form))
+       (names-convert-form (nth 6 form))))
+     (mapcar #'names-convert-form (cddr form)))))
+(defun names--convert-define-globalized-minor-mode (form)
+  "Special treatment for `define-globalized-minor-mode' FORM.
+The NAME of the global mode will NOT be namespaced, despite being
+a definition. It is kept verbatim.
+This is because people tend to name their global modes as
+`global-foo-mode', and namespacing would make this impossible.
+The MODE and TURN-ON arguments are converted as function names.
+Everything else is converted as regular forms (which usually
+means no conversion will happen since it's usually keywords and
+quoted symbols)."
+  (let ((name (names--remove-namespace (cadr form)))
+        (copy (cl-copy-list form)))
+    ;; Register the mode name
+    (when name
+      (add-to-list 'names--fbound name)
+      (add-to-list 'names--bound name)
+      (add-to-list 'names--bound (intern (format "%s-hook" name))))
+    (names--maybe-append-group
+     ;; And here we namespace it.
+     (append
+      (list
+       (pop copy)
+       (pop copy)
+       (names--handle-symbol-as-function (pop copy))
+       (names--handle-symbol-as-function (pop copy)))
+      (mapcar #'names-convert-form copy)))))
+(defalias #'names--convert-define-global-minor-mode
+  #'names--convert-define-globalized-minor-mode)
+(defalias #'names--convert-easy-mmode-define-global-mode
+  #'names--convert-define-globalized-minor-mode)
+(defun names--convert-quote (form)
+  "Special treatment for `quote' FORM.
+When FORM is (quote argument), argument too arbitrary to be
+logically namespaced and is never parsed for namespacing
+ (but see :assume-var-quote in `names--keyword-list').
+When FORM is (function form), a symbol is namespaced as a
+function name, a list is namespaced as a lambda form."
+  (let ((kadr (cadr form))
+        (this-name (car form))
+        func)
+    (if (and (eq this-name 'function)
+             (listp kadr))
+        (list this-name (names-convert-form kadr))
+      (if (symbolp kadr)
+          (cond
+           ;; A symbol inside a function quote should be a function,
+           ;; unless the user disabled that.
+           ((and (eq this-name 'function)
+                 (null (names--keyword :dont-assume-function-quote)))
+            (list 'function
+                  (names--handle-symbol-as-function kadr)))
+           ;; A symbol inside a regular quote should be a function, if
+           ;; the user asked for that.
+           ((and (eq this-name 'quote)
+                 (names--keyword :assume-var-quote))
+            (list 'quote
+                  (or (names--remove-protection kadr)
+                      (if (names--boundp kadr)
+                          (names--prepend kadr)
+                        kadr))))
+           (t form))
+        form))))
+(defun names--handle-symbol-as-function (s)
+  "Namespace symbol S as a function name."
+  (or (names--remove-protection s)
+      (if (names--fboundp s) (names--prepend s) s)))
+(defalias 'names--convert-function 'names--convert-quote)
+(defun names--convert-macro (form)
+  "Special treatment for `macro' form.
+Return (macro . (names-convert-form (cdr FORM)))."
+  (cons 'macro (names-convert-form (cdr form))))
+(defun names--convert-lambda (form)
+  "Special treatment for `lambda' FORM."
+  (let ((names--local-vars
+         (append (names--vars-from-arglist (cadr form))
+                 names--local-vars))
+        (forms (cdr (cdr form))))
+    (append
+     (list (car form)
+           (cadr form))
+     (when (stringp (car forms))
+       (prog1
+           (list (car forms))
+         (setq forms (cdr forms))))
+     (when (eq 'interactive (car-safe (car forms)))
+       (prog1
+           (list (list (car (car forms))
+                       (names-convert-form (cadr (car forms)))))
+         (setq forms (cdr forms))))
+     (progn
+       ;; (message "%S" forms)
+       (mapcar 'names-convert-form forms)))))
+(defun names--convert-clojure (form)
+  "Special treatment for `clojure' FORM."
+  (names--warn "Found a `closure'! You should use `lambda's instead")
+  (let ((names--local-vars
+         (append (names--vars-from-arglist (cadr form))
+                 names--local-vars))
+        (forms (cdr (cdr form))))
+    (cons
+     (car form)
+     (names--convert-lambda (cdr form)))))
+(defun names--vars-from-arglist (args)
+  "Get a list of local variables from a generalized arglist ARGS."
+  (remove
+   nil
+   (mapcar
+    (lambda (x)
+      (let ((symb (or (cdr-safe (car-safe x)) (car-safe x) x)))
+        (when (and (symbolp symb)
+                   (null (string-match "^&" (symbol-name symb)))
+                   (null (eq symb t)))
+          symb)))
+    args)))
+(defun names--convert-defun (form)
+  "Special treatment for `defun' FORM."
+  (let* ((name (cadr form)))
+    (add-to-list 'names--fbound name)
+    (cons (car form)
+          (names--convert-lambda
+           (cons (names--prepend name) (cddr form))))))
+(defalias 'names--convert-defun* 'names--convert-defun)
+(defalias 'names--convert-defsubst 'names--convert-defun)
+(defalias 'names--convert-defsubst* 'names--convert-defun)
+(defun names--let-var-convert-then-add (sym add)
+  "Try to convert SYM unless :no-let-vars is in use.
+If ADD is non-nil, add resulting symbol to `names--local-vars'."
+  (let ((name (if (null (names--keyword :no-let-vars))
+                  (names-convert-form sym)
+                sym)))
+    (when add (add-to-list 'names--local-vars name))
+    name))
+(defun names--convert-let (form &optional star)
+  "Special treatment for `let' FORM.
+If STAR is non-nil, parse as a `let*'."
+  (let* ((names--local-vars names--local-vars)
+         (vars
+          (mapcar
+           (lambda (x)
+             (if (car-safe x)
+                 (list (names--let-var-convert-then-add (car x) star)
+                       (names-convert-form (cadr x)))
+               (names--let-var-convert-then-add x star)))
+           (cadr form))))
+    ;; Each var defined in a regular `let' only becomes protected after
+    ;; all others have been defined.
+    (unless star
+      (setq names--local-vars
+            (append
+             (mapcar (lambda (x) (or (car-safe x) x)) vars)
+             names--local-vars)))
+    (append
+     (list (car form) vars)
+     (mapcar 'names-convert-form (cddr form)))))
+(defun names--convert-let* (form)
+  "Special treatment for `let' FORM."
+  (names--convert-let form t))
+(defun names--convert-cond (form)
+  "Special treatment for `cond' FORM."
+  (cons
+   (car form)
+   (mapcar
+    (lambda (x) (mapcar #'names-convert-form x))
+    (cdr form))))
+(defun names--convert-condition-case (form)
+  "Special treatment for `condition-case' FORM."
+  (append
+   (list
+    (car form)
+    (cadr form)
+    (names-convert-form (cadr (cdr form))))
+   (mapcar
+    (lambda (x)
+      (cons (car x)
+            (mapcar 'names-convert-form (cdr x))))
+    (cddr (cdr form)))))
+(provide 'names)
+;;; names.el ends here
diff --git a/package-example.png b/package-example.png
new file mode 100644
index 0000000..0ffe970
Binary files /dev/null and b/package-example.png differ

reply via email to

[Prev in Thread] Current Thread [Next in Thread]