{"id":13646488,"url":"https://github.com/radian-software/el-patch","last_synced_at":"2025-04-09T10:10:44.006Z","repository":{"id":39881986,"uuid":"77761932","full_name":"radian-software/el-patch","owner":"radian-software","description":"✨ Future-proof your Emacs Lisp customizations!","archived":false,"fork":false,"pushed_at":"2024-10-18T00:58:14.000Z","size":298,"stargazers_count":261,"open_issues_count":6,"forks_count":13,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-04-05T06:31:55.725Z","etag":null,"topics":["advice","autoload","ediff","elisp","emacs"],"latest_commit_sha":null,"homepage":"","language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/radian-software.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-01T01:36:24.000Z","updated_at":"2025-02-24T08:54:54.000Z","dependencies_parsed_at":"2023-11-23T23:25:28.063Z","dependency_job_id":"0df4cabb-af43-486f-8c3a-db1605076ecd","html_url":"https://github.com/radian-software/el-patch","commit_stats":null,"previous_names":["raxod502/el-patch"],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radian-software%2Fel-patch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radian-software%2Fel-patch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radian-software%2Fel-patch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radian-software%2Fel-patch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/radian-software","download_url":"https://codeload.github.com/radian-software/el-patch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248018061,"owners_count":21034048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["advice","autoload","ediff","elisp","emacs"],"created_at":"2024-08-02T01:02:57.231Z","updated_at":"2025-04-09T10:10:43.979Z","avatar_url":"https://github.com/radian-software.png","language":"Emacs Lisp","funding_links":[],"categories":["Emacs Lisp"],"sub_categories":[],"readme":"# el-patch\n\n\u003e Future-proof your Emacs Lisp customizations!\n\n## Table of contents\n\n\u003c!-- longlines-start --\u003e\n\n\u003c!-- toc --\u003e\n\n- [TL;DR](#tldr)\n  * [How do I get it](#how-do-i-get-it)\n  * [What is it](#what-is-it)\n- [Installation](#installation)\n- [Why does it exist](#why-does-it-exist)\n- [Basic usage](#basic-usage)\n- [Patch directives](#patch-directives)\n- [Defining patches](#defining-patches)\n  * [Defining forks](#defining-forks)\n- [Inspecting patches](#inspecting-patches)\n- [Validating patches](#validating-patches)\n- [Removing patches](#removing-patches)\n- [Lazy-loading packages](#lazy-loading-packages)\n- [Validating patches that are not loaded yet](#validating-patches-that-are-not-loaded-yet)\n- [Integration with `use-package`](#integration-with-use-package)\n- [Templates](#templates)\n- [Patch variants](#patch-variants)\n- [Usage with byte-compiled init-file](#usage-with-byte-compiled-init-file)\n- [But how does it work?](#but-how-does-it-work)\n- [But how does it actually work?](#but-how-does-it-actually-work)\n- [But does it actually work?](#but-does-it-actually-work)\n- [Contributor guide](#contributor-guide)\n\n\u003c!-- tocstop --\u003e\n\n\u003c!-- longlines-stop --\u003e\n\n## TL;DR\n\n### How do I get it\n\nFrom [MELPA][melpa], using your package manager of choice.\nSee [Installation][installation]. Emacs 25 and later is supported,\nplease submit an issue if you want `el-patch` to support Emacs 24.\n\n### What is it\n\nLike the [advice][advice] system, `el-patch` provides a way to\ncustomize the behavior of Emacs Lisp functions that do not provide\nenough variables and hooks to let you make them do what you want. The\nadvantage of using `el-patch` is that you will be notified if the\ndefinition of a function you are customizing changes, so that you are\naware your customizations might need to be updated.\n\nUsing the same mechanism, `el-patch` also\nprovides [a way][lazy-loading] to make lazy-loading packages much more\neasy, powerful, and robust.\n\n## Installation\n\n`el-patch` is available on [MELPA][melpa]. It is easiest to install it\nusing [`straight.el`][straight.el]:\n\n    (straight-use-package 'el-patch)\n\nHowever, you may install using any other package manager if you\nprefer.\n\n## Why does it exist\n\nEmacs provides a comprehensive set of customizable variables and hooks\nas well as a powerful [advice][advice] system. Sometimes, however,\nthese are not enough and you must override an entire function in order\nto change a detail of its implementation.\n\nSuch a situation is not ideal, since the original definition of the\nfunction might change when you update Emacs or one of its packages,\nand your overridden version would then be outdated. This could prevent\nyou from benefitting from bugfixes made to the original function, or\nintroduce new bugs into your configuration. Even worse, there is no\nway to tell when the original definition has changed! The correctness\nof your configuration is basically based on faith.\n\n`el-patch` introduces another way to override Emacs Lisp functions.\nYou can provide a *patch* which simultaneously specifies both the\noriginal and modified definitions of the function. When Emacs starts\nup, your patches act just like you had overridden the functions they\nare modifying. However, you can later ask `el-patch` to *validate*\nyour patches—that is, to make sure that the original function\ndefinitions have not changed since you created the patches. If they\nhave, `el-patch` will show you the difference using Ediff.\n\nOf course, in an ideal world, `el-patch` would not be necessary,\nbecause user options and hooks could be made configurable enough to\nsatisfy everyone's needs. Unfortunately, that will never truly be\npossible (or, arguably, desirable), so—like the advice\nsystem—`el-patch` offers a concession to the practical needs of your\nEmacs configuration.\n\n## Basic usage\n\nConsider the following function defined in\nthe [`company-statistics`][company-statistics] package:\n\n    (defun company-statistics--load ()\n      \"Restore statistics.\"\n      (load company-statistics-file 'noerror nil 'nosuffix))\n\nSuppose we want to change the third argument from `nil` to\n`'nomessage`, to suppress the message that is logged when\n`company-statistics` loads its statistics file. We can do that by\nplacing the following code in our `init.el`:\n\n    (el-patch-feature company-statistics)\n    (with-eval-after-load 'company-statistics\n      (el-patch-defun company-statistics--load ()\n        \"Restore statistics.\"\n        (load company-statistics-file 'noerror\n              (el-patch-swap nil 'nomessage)\n              'nosuffix)))\n\nSimply calling `el-patch-defun` instead of `defun` defines a no-op\npatch: that is, it has no effect (well, not\nquite—see [later][lazy-loading]). However, by including *patch\ndirectives*, you can make the modified version of the function\ndifferent from the original.\n\nIn this case, we use the `el-patch-swap` directive. The\n`el-patch-swap` form is replaced with `nil` in the original definition\n(that is, the version that is compared against the \"official\"\ndefinition in `company-statistics.el`), and with `'nomessage` in the\nmodified definition (that is, the version that is actually evaluated\nin your init-file).\n\nNote that it is important to cause the patch to be loaded *after*\n`company-statistics` is loaded. Otherwise, when `company-statistics`\nis loaded, the patch will be overwritten!\n\nYou may also be wondering what `el-patch-feature` does. The patch will\nstill work without it; however, until `company-statistics` is actually\nloaded, `el-patch` will not be aware that you have defined the patch\n(since the code has not been run yet). Telling `el-patch` that you\ndefine a patch inside a `with-eval-after-load` for\n`company-statistics` allows [`M-x el-patch-validate-all`][validation]\nto make sure to validate *all* your patches, and not just the ones\ncurrently defined. See\nalso [Validating patches that are not loaded yet][not-loaded-yet].\n\n## Patch directives\n\n* `(el-patch-add ARGS...)`\n\n  Insert forms. In the original definition, the entire form is\n  removed, and in the modified definition, each of the `ARGS` is\n  spliced into the surrounding form. For example, the following patch:\n\n      (foo (el-patch-add bar baz) quux)\n\n  resolves to this in the modified definition:\n\n      (foo bar baz quux)\n\n* `(el-patch-remove ARGS...)`\n\n  Remove forms. This is just like `el-patch-add`, except that the\n  roles of the original and modified definitions are exchanged.\n\n* `(el-patch-swap OLD NEW)`\n\n  Replace one form with another. In the original definition, the\n  entire form is replaced with `OLD`, and in the modified definition,\n  the entire form is replaced with `NEW`.\n\n* `(el-patch-wrap [TRIML [TRIMR]] ARGS...)`\n\n  Wrap forms in a list, optionally prepending or postpending\n  additional forms. This is the most complicated directive, so an\n  example will probably be helpful. The following patch:\n\n      (el-patch-wrap 1 1\n        (or\n         (eq (get-text-property (point) 'face) 'font-lock-doc-face)\n         (eq (get-text-property (point) 'face) 'font-lock-string-face)))\n\n  resolves to this in the original definition:\n\n      (eq (get-text-property (point) 'face) 'font-lock-doc-face)\n\n  and this in the modified definition:\n\n      (or\n       (eq (get-text-property (point) 'face) 'font-lock-doc-face)\n       (eq (get-text-property (point) 'face) 'font-lock-string-face)))\n\n  That is, the original `eq` call has been wrapped in an additional\n  list, and also it has had forms inserted before and after it. The\n  first `1` in the call to `el-patch-wrap` is the number of forms to\n  insert before it, and the second `1` is the number of forms to\n  insert after it.\n\n  What you provide to `el-patch-wrap` for `ARGS` is the fully wrapped\n  form, so you can think of `TRIML` and `TRIMR` as the number of forms\n  to trim from each end of the `ARGS` before removing the surrounding\n  parentheses.\n\n  You can omit both `TRIML` and `TRIMR`; each defaults to zero. Notice\n  that `ARGS` is always a list, so the number of arguments is either\n  one, two, or three—thus eliminating any ambiguity about which\n  argument is which.\n\n* `(el-patch-splice [TRIML [TRIMR]] ARGS...)`\n\n  Splice forms into their containing form, optionally removing some\n  from the beginning and end first. This is just like `el-patch-wrap`,\n  except that the roles of the original and modified definitions are\n  exchanged.\n\n* `(el-patch-let VARLIST ARGS...)`\n\n  Sometimes you need to restructure a form in an inconvenient way. For\n  example, suppose you need to turn the following form:\n\n      (if $cond\n          $then\n        $else)\n\n  into the following form:\n\n      (cond\n       ($cond $then)\n       ($new-cond $new-then)\n       (t $else))\n\n  where `$cond`, `$then`, `$new-cond`, `$new-then`, and `$else` are\n  all long forms with many sub-expressions. You could do it in the\n  following way:\n\n      (el-patch-swap\n        (if $cond\n            $then\n          $else)\n        (cond\n         ($cond $then)\n         ($new-cond $new-then)\n         (t $else)))\n\n  However, this is not ideal because you have repeated the forms and\n  violated [DRY][dry].\n\n  You could achieve the patch without any repetition by using the\n  basic patch directives, but that would be hard to read. Wouldn't it\n  be great if you could just do the following?\n\n      (el-patch-let (($cond (... long form ...))\n                     ($then (... another form ...))\n                     ($else (... more code ...))\n                     ($new-cond (... even more ...))\n                     ($new-then (... lots more code ...)))\n        (el-patch-swap\n          (if $cond\n              $then\n            $else)\n          (cond\n           ($cond $then)\n           ($new-cond $new-then)\n           (t $else))))\n\n  Well, you can. Welcome to `el-patch`.\n\n* `(el-patch-literal ARGS...)`\n\n  Hopefully this will never happen, but you might need to use\n  `el-patch` to modify functions that use symbols like `el-patch-add`.\n  In this case, you can wrap a form in `el-patch-literal` to prevent\n  anything within from being interpreted by `el-patch`. For example,\n  the following form:\n\n      (foo (el-patch-literal (el-patch-add bar baz)) quux)\n\n  will be replaced with:\n\n      (foo (el-patch-add bar baz) quux)\n\n  in both the original and modified definitions. Thus, you can happily\n  write `el-patches` that patch other `el-patch` definitions :)\n\n* `(el-patch-concat ARGS...)`\n\n  This patch directive lets you concatenate strings. It is useful for\n  modifying long string literals. For example, let's say that you have\n  a string\n\n      \"Pretend this is a very long string we only want to write once\"\n\n  in a function you are patching. To change just a small part of this\n  string, you could use `el-patch-swap` directly:\n\n      (el-patch-swap\n        \"Pretend this is a very long string we only want to write once\"\n        \"Pretend this is a really long string we only want to write once\")\n\n  But this repeats the rest of the string, violating DRY. Imagine if\n  you just want to add a sentence to a 40-line docstring! Here's an\n  alternative:\n\n      (el-patch-concat\n        \"Pretend this is a \"\n        (el-patch-swap \"very\" \"really\")\n        \" long string we only want to write once\")\n\n  Basically, `el-patch-concat` just resolves all of its arguments,\n  which may contain arbitrary patch directives, and then concatenates\n  them as strings and splices the result into *both* the original and\n  modified definition.\n\n## Defining patches\n\nTo patch a function, start by copying its definition into your\ninit-file, and replace `defun` with `el-patch-defun`. Then modify the\nbody of the function to use patch directives, so that the modified\ndefinition is what you desire.\n\nYou can also patch other types of definitions using:\n\n* `el-patch-defmacro`\n* `el-patch-defsubst`\n* `el-patch-defvar`\n* `el-patch-defconst`\n* `el-patch-defcustom`\n* `el-patch-define-minor-mode`\n\nSome warnings:\n\n* Patching `defmacro`, `defsubst`, and `defconst` forms will not\n  affect usages of them in already-defined functions, due to\n  macroexpansion and byte-compilation. You may need to define no-op\n  patches of client functions to get your changes to show up. Or take\n  a different strategy—figuring out the best way to make a particular\n  change to an internal function is often a complex process. You may\n  also consider using advice, dynamic binding, and just plain forking\n  the package.\n\n* Patching `defvar`, `defconst`, and `defcustom` forms will not affect\n  the value of the variable, if it has already been defined. Thus,\n  they are only useful for lazy-loading by default. To override this\n  behavior and force the patches to reset the value of the variable,\n  even if it is already defined, set `el-patch-use-aggressive-defvar`.\n\nYou can patch any definition form, not just those above. To register\nyour own definition types, use the `el-patch-deftype` macro. For\nexample, the `el-patch-defun` function is defined as follows:\n\n    (el-patch-deftype defun\n      :classify el-patch-classify-function\n      :locate el-patch-locate-function\n      :font-lock el-patch-fontify-as-defun\n      :declare ((doc-string 3)\n                (indent defun)))\n\nSee the docstrings on the macro `el-patch-deftype` and the variable\n`el-patch-deftype-alist` for more detailed information. See also the\nsource code of `el-patch` for examples of how to use\n`el-patch-deftype`.\n\n### Defining forks\n\nSometimes you want to define a *slightly modified* version of a\nfunction, so that you can use the patched version in your own code but\nyou can still use the original version under its original name. This\nis easy to do:\n\n    (el-patch-defun (el-patch-swap my-old-fn my-new-fn) ...)\n\nBe sure to include patch directives in the function body showing how\nyour modified function is derived from the original, just like in any\nother patch.\n\n## Inspecting patches\n\nYou can run Ediff on a patch (original vs. modified definitions) by\nrunning `M-x el-patch-ediff-patch` and selecting the desired patch.\nNote that in this context, the \"original\" definition is the one\nspecified by the patch, not the actual definition that is checked when\nyou validate the patch (see below).\n\n## Validating patches\n\nTo validate a patch, run `M-x el-patch-validate` and select the\ndesired patch. A warning will be printed if there is a difference\nbetween what the patch definition asserts the original definition of\nthe function is and the actual original definition of the function.\n\nIf there is a difference, you can visualize it using Ediff with `M-x\nel-patch-ediff-conflict`.\n\nYou can validate all the patches that have been defined so far using\n`M-x el-patch-validate-all`.\n\nAssuming you are byte-compiling your init-file, you can set\n`el-patch-validate-during-compile` to non-nil to validate patches when\nthey are byte-compiled. There is no option to validate patches at\nruntime during startup because this makes startup incredibly slow.\nHowever, you could manually run `el-patch-validate-all` if such\nbehavior is truly desired.\n\n## Removing patches\n\nUse `M-x el-patch-unpatch`. Note that this does not technically remove\nthe patch: instead, it sets the function or variable definition to the\n\"original\" definition as specified by the patch. These two actions\nwill, however, be equivalent as long as the patch is not outdated\n(i.e., it is validated without errors by `M-x el-patch-validate`).\n\n## Lazy-loading packages\n\n`el-patch` does not mind if you patch a function that is not yet\ndefined. You can therefore use `el-patch` to help lazy-load a package.\n\nAs an example, consider the [Ivy][ivy] package. Ivy provides a minor\nmode called `ivy-mode` that sets `completing-read-function` to\n`ivy-completing-read`. The idea is that you call this function\nimmediately, so that when a `completing-read` happens, it calls into\nthe Ivy code.\n\nNow, `ivy-completing-read` is autoloaded. So Ivy does not need to be\nloaded immediately: as soon as `ivy-completing-read` is called, Ivy\nwill be loaded automatically. However, calling `ivy-mode` will trigger\nthe autoload for Ivy, so we can't do that if we want to lazy-load the\npackage. The natural thing to do is to copy the definition of\n`ivy-mode` into our init-file, but what if the original definition\nchanges? That's where `el-patch` comes in. The code from Ivy looks\nlike this:\n\n    (defvar ivy-mode-map\n      (let ((map (make-sparse-keymap)))\n        (define-key map [remap switch-to-buffer]\n          'ivy-switch-buffer)\n        (define-key map [remap switch-to-buffer-other-window]\n          'ivy-switch-buffer-other-window)\n        map)\n      \"Keymap for `ivy-mode'.\")\n\n    (define-minor-mode ivy-mode\n      \"Toggle Ivy mode on or off.\n    Turn Ivy mode on if ARG is positive, off otherwise.\n    Turning on Ivy mode sets `completing-read-function' to\n    `ivy-completing-read'.\n\n    Global bindings:\n    \\\\{ivy-mode-map}\n\n    Minibuffer bindings:\n    \\\\{ivy-minibuffer-map}\"\n      :group 'ivy\n      :global t\n      :keymap ivy-mode-map\n      :lighter \" ivy\"\n      (if ivy-mode\n          (progn\n            (setq completing-read-function 'ivy-completing-read)\n            (when ivy-do-completion-in-region\n              (setq completion-in-region-function 'ivy-completion-in-region)))\n        (setq completing-read-function 'completing-read-default)\n        (setq completion-in-region-function 'completion--in-region)))\n\nTo enable `ivy-mode` while still lazy-loading Ivy, simply copy those\ndefinitions to your init-file before the call to `ivy-mode`, replacing\n`defvar` with `el-patch-defvar` and replacing `define-minor-mode` with\n`el-patch-define-minor-mode`. That is:\n\n    (el-patch-defvar ivy-mode-map\n      (let ((map (make-sparse-keymap)))\n        (define-key map [remap switch-to-buffer]\n          'ivy-switch-buffer)\n        (define-key map [remap switch-to-buffer-other-window]\n          'ivy-switch-buffer-other-window)\n        map)\n      \"Keymap for `ivy-mode'.\")\n\n    (el-patch-define-minor-mode ivy-mode\n      \"Toggle Ivy mode on or off.\n    Turn Ivy mode on if ARG is positive, off otherwise.\n    Turning on Ivy mode sets `completing-read-function' to\n    `ivy-completing-read'.\n\n    Global bindings:\n    \\\\{ivy-mode-map}\n\n    Minibuffer bindings:\n    \\\\{ivy-minibuffer-map}\"\n      :group 'ivy\n      :global t\n      :keymap ivy-mode-map\n      :lighter \" ivy\"\n      (if ivy-mode\n          (progn\n            (setq completing-read-function 'ivy-completing-read)\n            (when ivy-do-completion-in-region\n              (setq completion-in-region-function 'ivy-completion-in-region)))\n        (setq completing-read-function 'completing-read-default)\n        (setq completion-in-region-function 'completion--in-region)))\n\n    (ivy-mode 1)\n\n    (featurep 'ivy) ;; =\u003e ivy is still not loaded!\n\nIt's really that simple!\n\n## Validating patches that are not loaded yet\n\nIf you want to define a patch for a function provided by an unloaded\nfeature, it is likely that you will just put the patch in a\n`with-eval-after-load` for the feature. But then `el-patch-validate`\nand `el-patch-validate-all` will not be able to validate your patch,\nbecause it is not yet defined.\n\nTo get around this problem, you can add functions to\n`el-patch-pre-validate-hook` in order to make sure all your patches\nare defined (for instance, you might need to require some features or\neven enable a custom minor mode). This hook is run before\n`el-patch-validate-all`, and also before `el-patch-validate` when you\nprovide a prefix argument.\n\nSince defining some patches after a feature is loaded is such a common\noperation, `el-patch` provides a convenience macro for it:\n`el-patch-feature`. You can call this macro with an (unquoted) feature\nname, and it will create a function that loads that feature, and add\nit to `el-patch-pre-validate-hook` for you.\n\nIf you don't want all of your patches to be defined all the time, you\ncan put some functions in `el-patch-post-validate-hook` to disable\nthem again. For some examples of how to use these hooks, check out\n[Radian Emacs][radian].\n\n## Integration with `use-package`\n\nYou can enable the `use-package` integration of `el-patch` by toggling\nthe global minor mode `el-patch-use-package-mode`, but it is more\nconvenient to set the variable\n`el-patch-enable-use-package-integration` (defaults to non-nil) and\nthen the mode will be toggled appropriately once `el-patch` and\n`use-package` have both been loaded.\n\nThe `use-package` integration defines two new `use-package` keywords,\n`:init/el-patch` and `:config/el-patch`. They are analogous to `:init`\nand `:config`, but each top-level form is converted into an `el-patch`\nform: for example, a `defun` will be turned into an `el-patch-defun`,\nand so on. (Definition forms that have no corresponding `el-patch`\nmacro are left as is.) The resulting code is prepended to the code in\n`:init` or `:config`, respectively. Also, if you provide either\nkeyword, then a call to `el-patch-feature` is inserted into the\n`:init` section.\n\n## Templates\n\nIn some cases, you may want to patch one or two forms in a long\ndefinition of a function or a macro. Defining the patch would still\nrequire copying all unpatched forms and updating the patch when these\nforms change. For these cases, it would be better if we can simply\nsearch for the forms that we want to patch in the original definition\nand patch only those. Enter `el-patch` templates.\n\nAs an example, say we want to define a patch of `restart-emacs` so\nthat it starts a new emacs instance without killing the current one.\nInstead of defining a patch that includes the complete definition of\n`restart-emacs`, we can define a template as follows\n\n    (el-patch-define-template\n      (defun (el-patch-swap restart-emacs radian-new-emacs))\n      (el-patch-concat\n        (el-patch-swap\n          \"Restart Emacs.\"\n          \"Start a new Emacs session without killing the current one.\")\n        ...\n        (el-patch-swap \"restarted\" \"started\")\n        ...\n        (el-patch-swap \"restarted\" \"started\")\n        ...\n        (el-patch-swap \"restarted\" \"started\")\n        ...)\n      (restart-args ...)\n      (el-patch-remove (kill-emacs-hook ...))\n      (el-patch-swap\n        (save-buffers-kill-emacs)\n        (restart-emacs--launch-other-emacs restart-args)))\n\nThe first argument is a list that comprises the type, `defun` in this\ncase, and the name of the object that we are patching. Using an\n`el-patch-swap` here allows us to define a fork, `radian-new-emacs`.\nHad we wanted to simply patch the function we would pass `(defun\nrestart-emacs)` as the first argument. Every other argument defines a\ntemplate for a patch. To build the final patch, every argument is\nresolved to figure out the original form which is then matched against\nall forms in the original definition of the object and, if uniquely\nfound, the patch is spliced in its place. The special form `...` is\nused to match one or more forms or, if it is inside `el-patch-concat`\nas above, one or more characters in a string. Patch templates need not\nbe, or even contain, `el-patch-*` directives. For example, the purpose\nof the argument `(restart-args ...)` is to make sure that such a form\nexists in the function definition without actually patching it.\n\nAfter defining the template, you can run the interactive command\n`el-patch-insert-template` to insert the patch definition in the\ncurrent buffer based on the defined template. Alternatively, you may\nuse the command `el-patch-eval-template` which directly evaluates the\npatch. The function `el-patch-define-and-eval-template` defines and\nevaluates a template in one go. It is recommended that you compile\nyour init-file if you use `el-patch-define-and-eval-template` to avoid\nthe overhead of template matching when starting Emacs. `el-patch` will\nissue a warning if `el-patch-define-and-eval-template` is called at\nruntime and `el-patch-warn-on-eval-template` is non-nil (which is the\ndefault).\n\nTemplates assume that the original definition of the object is\naccessible, for example, using `find-function-noselect` for functions.\n\nLike patches, templates can be validated using\n`el-patch-validate-template` and `el-patch-validate-all-templates`.\n\n## Patch variants\n\nYou can define multiple versions of the same patch. Normally,\n(re)defining a patch will just overwrite the old version entirely.\nHowever, if you dynamically bind `el-patch-variant` to a different\n(symbol) value for each call, then the latter patch is still the one\nthat takes effect, but `el-patch` retains a record of both patches,\nmeaning they can be inspected and validated individually. See\n[#29](https://github.com/radian-software/el-patch/issues/29).\n\nYou may also define patches of functions as `:override` advices\ninstead of overriding the original definition. This is done by setting\n`el-patch-use-advice` to a non-nil value (either dynamically around a\npatch or globally). The patched function must have the same name and\nnumber of arguments as the original function.\n\n## Usage with byte-compiled init-file\n\n`el-patch` does not need to be loaded at runtime just to define\npatches. This means that if you byte-compile your init-file, then\n`el-patch` will not be loaded when you load the compiled code.\n\nFor this to work, you will need to stick to defining patches with\n`el-patch-def*` and declaring features with `el-patch-feature`.\nAnything else will cause `el-patch` to be loaded at runtime.\n\nIf you do not byte-compile your init-file, then all of this is\nimmaterial.\n\n## But how does it work?\n\nMagic.\n\n## But how does it actually work?\n\nThe basic idea is simple. When a patch is defined, the patch\ndefinition is resolved to figure out the modified definition is. Then\nthat definition is installed by evaluating it (by using\n`el-patch--stealthy-eval`, so that looking up the function definition\nwill return the original location rather than the `el-patch`\ninvocation location, and also using `makunbound` to override a\nprevious variable definition if `el-patch-use-aggressive-defvar` is\nnon-nil).\n\nThe patch definition is also recorded in the hash `el-patch--patches`.\nThis allows for the functionality of `M-x el-patch-ediff-patch`.\nObtaining the actual original definition of a function is done using a\nmodified version of `find-function-noselect`, which provides for `M-x\nel-patch-validate` and `M-x el-patch-ediff-conflict`.\n\nWhen you call `M-x el-patch-unpatch`, the patch definition is resolved\nagain and the original version is installed by evaluating it.\n\n## But does it actually work?\n\nIt doesn't seem to crash [my Emacs][radian], at least.\n\n## Contributor guide\n\nPlease see [the contributor guide for my\nprojects](https://github.com/radian-software/contributor-guide).\n\n[installation]: #installation\n[lazy-loading]: #lazy-loading-packages\n[not-loaded-yet]: #validating-patches-that-are-not-loaded-yet\n[validation]: #validating-patches\n\n[advice]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Functions.html\n[company-statistics]: https://github.com/company-mode/company-statistics\n[dry]: https://en.wikipedia.org/wiki/Don't_repeat_yourself\n[ivy]: https://github.com/abo-abo/swiper\n[melpa]: http://melpa.org\n[package.el]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Packages.html\n[radian]: https://github.com/radian-software/radian\n[straight.el]: https://github.com/raxod502/straight.el\n[use-package]: https://github.com/jwiegley/use-package\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradian-software%2Fel-patch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fradian-software%2Fel-patch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradian-software%2Fel-patch/lists"}