       (or (gethash form table)
           (list form)))))
 
-(defun el-patch-resolve-definition (type body new)
-  "Resolves a definition. TYPE is `defun', `defmacro', etc. BODY
-is a list of the forms coming after TYPE in the definition.
-Resolves in favor of the original version if NEW is nil;
-otherwise resolves in favor of the new version."
-  (cons type (cl-mapcan (lambda (form)
-                          (el-patch-resolve form new))
-                        body)))
-
-(defun el-patch-symbol-function (name)
-  "Like `symbol-function' but returns a Lisp form, or nil. If the
-function has been byte-compiled, returns nil."
-  (let ((form (symbol-function name)))
-    (cond
-     ((not (listp form))
-      nil)
-     ((equal (car form) 'macro)
-      (cons 'defmacro (cons name (cddr form))))
-     (t
-      (cons 'defun (cons name (cdr form)))))))
-
-(defun el-patch-find-function (name)
-  "Like `find-function-noselect' but returns a Lisp form, or nil.
-If the function definition cannot be found, returns nil."
-  (let* ((buffer-point (condition-case nil
-                           (save-excursion
-                             ;; This horrifying bit of hackery
-                             ;; prevents `find-function-noselect' from
-                             ;; temporarily moving point when the
-                             ;; definition of the function happens to
-                             ;; be in a different part of the current
-                             ;; buffer.
-                             (advice-add #'get-file-buffer :override
-                                         #'ignore)
-                             (find-function-noselect name 'lisp-only)
-                             (advice-remove #'get-file-buffer #'ignore))
-                         ((error nil))))
-         (defun-buffer (car buffer-point))
-         (defun-point (cdr buffer-point)))
-    (and defun-buffer
-         defun-point
-         (with-current-buffer defun-buffer
-           (save-excursion
-             (goto-char defun-point)
-             (read defun-buffer))))))
-
-(defun el-patch-definition (el-patch-type type name args)
-  "Applies a patch to a definition. EL-PATCH-TYPE is
-`el-patch-defun', `el-patch-defmacro', etc. TYPE is `defun',
-`defmacro', etc. NAME is the name of the function being defined,
-and ARGS is the remainder of the forms coming after NAME in the
-body of the definition. If `el-patch-validate' is nil, validation
-is skipped."
-  (let ((patch (append (list el-patch-type name) args))
-        (already-patched nil))
-    (maphash (lambda (patch-name patches)
-               (dolist (patch-data patches)
-                 (when (equal patch (nth 0 patch-data))
-                   (setq already-patched t))))
-             el-patches)
-    (unless el-patch-validate
-      (let ((old-definition (el-patch-resolve-definition
-                             type (cons name args) nil))
-            (new-definition (el-patch-resolve-definition
-                             type (cons name args) t))
-            (actual-definition nil))
-        (unless (when el-patch-validate
-                  (setq actual-definition (or (el-patch-symbol-function name)
-                                              (el-patch-find-function name)))
-                  (or (unless actual-definition
-                        (display-warning
-                         'el-patch
-                         (format (concat "could not find definition "
-                                         "of `%S', not patching")
-                                 name))
-                        t)
-                      (unless (equal actual-definition
-                                     old-definition)
-                        (display-warning
-                         'el-patch
-                         (format (concat "definition of `%S' has changed, not"
-                                         " patching (see `el-patch-inspect')")
-                                 name))
-                        t)))
-          (eval new-definition))
-        (puthash name
-                 ;; Add element to end of list without using
-                 ;; `append-to-list'.
-                 (append (gethash name el-patches)
-                         (list
-                          (list patch
-                                actual-definition
-                                old-definition
-                                new-definition)))
-                 el-patches)))))
-
-(defmacro el-patch-defun (name &rest args)
-  "Patch a function called NAME. The rest of the ARGS are the
-same as in `defun'."
+(defun el-patch--resolve-definition (patch-definition new)
+  "Resolves a patch DEFINITION, a list starting with `defun',
+`defmacro', etc., returning a list of the same format. Resolves
+in favor of the original version if NEW is nil; otherwise
+resolves in favor of the new version."
+  (cl-mapcan (lambda (form)
+               (el-patch--resolve form new))
+             patch-definition))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; Applying patches
+
+(defun el-patch--definition (patch-definition)
+  "Activates a PATCH-DEFINITION, a list starting with `defun',
+`defmacro', etc., installing the new function definition and
+updating `el-patch--patches'."
+  (let ((name (cadr patch-definition)))
+    (puthash name patch-definition el-patch--patches)
+    (eval (el-patch--resolve-definition patch-definition t))))
+
+;;;###autoload
+(defmacro el-patch-defun (&rest args)
+  "Patch a function. The ARGS are the same as for `defun'."
   (declare (indent defun))
-  `(el-patch-definition 'el-patch-defun 'defun ',name ',args))
-
-(defmacro el-patch-defmacro (name &rest args)
+  `(el-patch--definition ,(cons 'defun args)))
+
+;;;###autoload
+(defmacro el-patch-defmacro (&rest args)
   "Patch a macro called NAME. The rest of the ARGS are the same
 as in `defmacro'."
   (declare (indent defun))
-  `(el-patch-definition 'el-patch-defmacro 'defmacro ',name ',args))
-
+  `(el-patch--definition ,(cons 'defmacro args)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; Patch directives
+
+;;;###autoload
 (defmacro el-patch-add (&rest args)
   "Patch directive. In the original definition, the ARGS and
 their containing form are removed. In the new definition, the

  (declare (indent 0))
  (error "Can't use `el-patch-remove' outside of an `el-patch'"))

(defmacro el-patch-swap (old new)
  "Patch directive. In the original definition, OLD is spliced
into the containing s-expression. In the new definition, NEW is

  (declare (indent defun))
  (error "Can't use `el-patch-wrap' outside of an `el-patch'"))

;;;###autoload
(defmacro el-patch-splice (&optional triml &optional trimr args)
  "Patch directive. In the original definition, the ARGS and
their containing form are spliced into the containing
s-expression (but the symbol `el-patch-splice' is removed). In
