summaryrefslogtreecommitdiff
path: root/docs/with-editor.org
diff options
context:
space:
mode:
authorJonas Bernoulli <jonas@bernoul.li>2021-12-16 19:35:00 +0100
committerJonas Bernoulli <jonas@bernoul.li>2021-12-16 19:35:00 +0100
commita94faeae2ff95235b31c1c1f9447bc95fc527240 (patch)
tree7b535053f07cf64a5839de1c10e769490545696e /docs/with-editor.org
parent93ba7c84a752cd44a8225c4131044635465daddb (diff)
Add lisp/ and docs/ directories
Diffstat (limited to 'docs/with-editor.org')
-rw-r--r--docs/with-editor.org334
1 files changed, 334 insertions, 0 deletions
diff --git a/docs/with-editor.org b/docs/with-editor.org
new file mode 100644
index 0000000..c9a0bcb
--- /dev/null
+++ b/docs/with-editor.org
@@ -0,0 +1,334 @@
+#+TITLE: With-Editor User Manual
+:PREAMBLE:
+#+AUTHOR: Jonas Bernoulli
+#+EMAIL: jonas@bernoul.li
+#+DATE: 2015-{{{year}}}
+#+LANGUAGE: en
+
+#+TEXINFO_DIR_CATEGORY: Emacs
+#+TEXINFO_DIR_TITLE: With-Editor: (with-editor).
+#+TEXINFO_DIR_DESC: Using the Emacsclient as $EDITOR
+#+SUBTITLE: for version {{{version}}}
+
+#+TEXINFO_DEFFN: t
+#+OPTIONS: H:4 num:4 toc:2
+#+PROPERTY: header-args :eval never
+#+MACRO: version (eval (ox-texinfo+-get-version 'mixed))
+#+MACRO: year (eval (format-time-string "%Y"))
+
+The library ~with-editor~ makes it easy to use the Emacsclient as the
+~$EDITOR~ of child processes, making sure they know how to call home.
+For remote processes a substitute is provided, which communicates with
+Emacs on standard output instead of using a socket as the Emacsclient
+does.
+
+This library was written because Magit has to be able to do the above
+to allow the user to edit commit messages gracefully and to edit
+rebase sequences, which wouldn't be possible at all otherwise.
+
+Because other packages can benefit from such functionality, this
+library is made available as a separate package. It also defines some
+additional functionality which makes it useful even for end-users, who
+don't use Magit or another package which uses it internally.
+
+#+TEXINFO: @noindent
+This manual is for With-Editor version {{{version}}}.
+
+#+BEGIN_QUOTE
+Copyright (C) 2015-{{{year}}} Jonas Bernoulli <jonas@bernoul.li>
+
+You can redistribute this document 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.
+
+This document is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+#+END_QUOTE
+:END:
+* Using the With-Editor package
+
+The ~With-Editor~ package is used internally by Magit when editing
+commit messages and rebase sequences. It also provides some commands
+and features which are useful by themselves, even if you don't use
+Magit.
+
+For information about using this library in you own package, see
+[[*Using With-Editor as a library]].
+
+** Configuring With-Editor
+
+With-Editor tries very hard to locate a suitable ~emacsclient~
+executable, so ideally you should never have to customize the option
+~with-editor-emacsclient-executable~. When it fails to do so, then the
+most likely reason is that someone found yet another way to package
+Emacs (most likely on macOS) without putting the executable on ~$PATH~,
+and we have to add another kludge to find it anyway.
+
+- User Option: with-editor-emacsclient-executable
+
+ The ~emacsclient~ executable used as the editor by child process of
+ this Emacs instance. By using this executable, child processes can
+ call home to their parent process.
+
+ This option is automatically set at startup by looking in ~exec-path~,
+ and other places where the executable could be installed, to find
+ the ~emacsclient~ executable most suitable for the current Emacs
+ instance.
+
+ You should *not* customize this option permanently. If you have to do
+ it, then you should consider that a temporary kludge and inform the
+ Magit maintainer as described in [[*Debugging][Debugging]].
+
+ If With-Editor fails to find a suitable ~emacsclient~ on you system,
+ then this should be fixed for all users at once, by teaching
+ ~with-editor-locate-emacsclient~ how to do so on your system and
+ system like yours. Doing it this way has the advantage, that you
+ won't have do it again every time you update Emacs, and that other
+ users who have installed Emacs the same way as you have, won't have
+ to go through the same trouble.
+
+ Note that there also is a nuclear option; setting this variable to
+ ~nil~ causes the "sleeping editor" described below to be used even for
+ local child processes. Obviously we don't recommend that you use
+ this except in "emergencies", i.e. before we had a change to add a
+ kludge appropriate for you setup.
+
+- Function: with-editor-locate-emacsclient
+
+ The function used to set the initial value of the option
+ ~with-editor-emacsclient-executable~. There's a lot of voodoo here.
+
+The ~emacsclient~ cannot be used when using Tramp to run a process on a
+remote machine. (Theoretically it could, but that would be hard to
+setup, very fragile, and rather insecure).
+
+With-Editor provides an alternative "editor" which can be used by
+remote processes in much the same way as local processes use an
+~emacsclient~ executable. This alternative is known as the "sleeping
+editor" because it is implemented as a shell script which sleeps until
+it receives a signal.
+
+- User Option: with-editor-sleeping-editor
+
+ The sleeping editor is a shell script used as the editor of child
+ processes when the ~emacsclient~ executable cannot be used.
+
+ This fallback is used for asynchronous process started inside the
+ macro ~with-editor~, when the process runs on a remote machine or for
+ local processes when ~with-editor-emacsclient-executable~ is ~nil~.
+
+ Where the latter uses a socket to communicate with Emacs' server,
+ this substitute prints edit requests to its standard output on
+ which a process filter listens for such requests. As such it is
+ not a complete substitute for a proper ~emacsclient~, it can only
+ be used as ~$EDITOR~ of child process of the current Emacs instance.
+
+ Some shells do not execute traps immediately when waiting for a
+ child process, but by default we do use such a blocking child
+ process.
+
+ If you use such a shell (e.g. ~csh~ on FreeBSD, but not Debian), then
+ you have to edit this option. You can either replace ~sh~ with ~bash~
+ (and install that), or you can use the older, less performant
+ implementation:
+
+ #+BEGIN_SRC emacs-lisp
+ "sh -c '\
+ echo \"WITH-EDITOR: $$ OPEN $0 IN $(pwd)\"; \
+ trap \"exit 0\" USR1; \
+ trap \"exit 1\" USR2; \
+ while true; do sleep 1; done'"
+ #+END_SRC
+
+ Note that the unit separator character () right after the file
+ name ($0) is required.
+
+ Also note that using this alternative implementation leads to a
+ delay of up to a second. The delay can be shortened by replacing
+ ~sleep 1~ with ~sleep 0.01~, or if your implementation does not support
+ floats, then by using ~nanosleep~ instead.
+
+** Using With-Editor commands
+
+This section describes how to use the ~with-editor~ library /outside/ of
+Magit. You don't need to know any of this just to create commits
+using Magit.
+
+The commands ~with-editor-async-shell-command~ and
+~with-editor-shell-command~ are intended as drop in replacements for
+~async-shell-command~ and ~shell-command~. They automatically export
+~$EDITOR~ making sure the executed command uses the current Emacs
+instance as "the editor". With a prefix argument these commands
+prompt for an alternative environment variable such as ~$GIT_EDITOR~.
+
+- Command: with-editor-async-shell-command
+
+ This command is like ~async-shell-command~, but it runs the shell
+ command with the current Emacs instance exported as ~$EDITOR~.
+
+- Command: with-editor-shell-command
+
+ This command is like ~shell-command~, but if the shell command ends
+ with ~&~ and is therefore run asynchronously, then the current Emacs
+ instance is exported as ~$EDITOR~.
+
+To always use these variants add this to you init file:
+
+#+BEGIN_SRC emacs-lisp
+ (define-key (current-global-map)
+ [remap async-shell-command] 'with-editor-async-shell-command)
+ (define-key (current-global-map)
+ [remap shell-command] 'with-editor-shell-command)
+#+END_SRC
+
+Alternatively use the global ~shell-command-with-editor-mode~.
+
+- Variable: shell-command-with-editor-mode
+
+ When this mode is active, then ~$EDITOR~ is exported whenever
+ ultimately ~shell-command~ is called to asynchronously run some shell
+ command. This affects most variants of that command, whether they
+ are defined in Emacs or in some third-party package.
+
+The command ~with-editor-export-editor~ exports ~$EDITOR~ or another
+such environment variable in ~shell-mode~, ~eshell-mode~, ~term-mode~ and
+~vterm-mode~ buffers. Use this Emacs command before executing a shell
+command which needs the editor set, or always arrange for the current
+Emacs instance to be used as editor by adding it to the appropriate
+mode hooks:
+
+#+BEGIN_SRC emacs-lisp
+ (add-hook 'shell-mode-hook 'with-editor-export-editor)
+ (add-hook 'eshell-mode-hook 'with-editor-export-editor)
+ (add-hook 'term-exec-hook 'with-editor-export-editor)
+ (add-hook 'vterm-exec-hook 'with-editor-export-editor)
+#+END_SRC
+
+Some variants of this function exist; these two forms are equivalent:
+
+#+BEGIN_SRC emacs-lisp
+ (add-hook 'shell-mode-hook
+ (apply-partially 'with-editor-export-editor "GIT_EDITOR"))
+ (add-hook 'shell-mode-hook 'with-editor-export-git-editor)
+#+END_SRC
+
+- Command: with-editor-export-editor
+
+ When invoked in a ~shell-mode~, ~eshell-mode~, ~term-mode~ or ~vterm-mode~
+ buffer, this command teaches shell commands to use the current Emacs
+ instance as the editor, by exporting ~$EDITOR~.
+
+- Command: with-editor-export-git-editor
+
+ This command is like ~with-editor-export-editor~ but exports
+ ~$GIT_EDITOR~.
+
+- Command: with-editor-export-hg-editor
+
+ This command is like ~with-editor-export-editor~ but exports
+ ~$HG_EDITOR~.
+
+* Using With-Editor as a library
+
+This section describes how to use the ~with-editor~ library /outside/ of
+Magit to teach another package how to have its child processes call
+home, just like Magit does. You don't need to know any of this just
+to create commits using Magit. You can also ignore this if you use
+~with-editor~ outside of Magit, but only as an end-user.
+
+For information about interactive use and options that affect both
+interactive and non-interactive use, see [[*Using the With-Editor
+package]].
+
+- Macro: with-editor &rest body
+
+ This macro arranges for the ~emacsclient~ or the sleeping editor to be
+ used as the editor of child processes, effectively teaching them to
+ call home to the current Emacs instance when they require that the
+ user edits a file.
+
+ This is done by establishing a local binding for ~process-environment~
+ and changing the value of the ~EDITOR~ environment variable in that
+ scope. This affects all (asynchronous) processes started by forms
+ (dynamically) inside BODY.
+
+ If BODY begins with a literal string, then that variable is set
+ instead of ~EDITOR~.
+
+- Macro: with-editor envvar &rest body
+
+ This macro is like ~with-editor~ instead that the ENVVAR argument is
+ required and that it is evaluated at run-time.
+
+- Function: with-editor-set-process-filter process filter
+
+ This function is like ~set-process-filter~ but ensures that adding the
+ new FILTER does not remove the ~with-editor-process-filter~. This is
+ done by wrapping the two filter functions using a lambda, which
+ becomes the actual filter. It calls FILTER first, which may or
+ may not insert the text into the PROCESS's buffer. Then it calls
+ ~with-editor-process-filter~, passing t as NO-STANDARD-FILTER.
+
+* Debugging
+
+With-Editor tries very hard to locate a suitable ~emacsclient~
+executable, and then sets option ~with-editor-emacsclient-executable~
+accordingly. In very rare cases this fails. When it does fail, then
+the most likely reason is that someone found yet another way to
+package Emacs (most likely on macOS) without putting the executable on
+~$PATH~, and we have to add another kludge to find it anyway.
+
+If you are having problems using ~with-editor~, e.g. you cannot commit
+in Magit, then please open a new issue at
+https://github.com/magit/with-editor/issues and provide information
+about your Emacs installation. Most importantly how did you install
+Emacs and what is the output of ~M-x with-editor-debug RET~.
+
+* Command Index
+:PROPERTIES:
+:APPENDIX: t
+:INDEX: cp
+:END:
+* Function Index
+:PROPERTIES:
+:APPENDIX: t
+:INDEX: fn
+:END:
+* Variable Index
+:PROPERTIES:
+:APPENDIX: t
+:INDEX: vr
+:END:
+* Copying
+:PROPERTIES:
+:COPYING: t
+:END:
+
+#+BEGIN_QUOTE
+Copyright (C) 2015-{{{year}}} Jonas Bernoulli <jonas@bernoul.li>
+
+You can redistribute this document 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.
+
+This document is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+#+END_QUOTE
+
+# LocalWords: LocalWords
+# LocalWords: Magit Emacs emacsclient FreeBSD macOS texinfo
+# LocalWords: async eval hg init performant rebase startup
+
+# IMPORTANT: Also update ORG_ARGS and ORG_EVAL in the Makefile.
+# Local Variables:
+# eval: (require 'magit-utils nil t)
+# eval: (require 'ox-texinfo+ nil t)
+# indent-tabs-mode: nil
+# org-src-preserve-indentation: nil
+# End: