From 9a996633ac532dd47615fa454ea49380cca41a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlo=20Marcelo=20Arenas=20Bel=C3=B3n?= Date: Wed, 24 Nov 2021 01:14:21 -0800 Subject: [PATCH] editor: allow for saving/restoring terminal state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When EDITOR is invoked to modify a commit message, it will likely change the terminal settings, and if it misbehaves will leave the terminal output damaged as shown in recent reports from Windows Terminal[1] Instead use the functions provided by compat/terminal to save the settings of the terminal and recover safely, but only do so if instructed by the user through a new configuration "editor.rogue" and the terminal is fully interactive. [1] https://github.com/microsoft/terminal/issues/9359 Helped-by: Johannes Schindelin Signed-off-by: Carlo Marcelo Arenas Belón --- Documentation/config.txt | 2 ++ Documentation/config/editor.txt | 4 ++++ editor.c | 16 ++++++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 Documentation/config/editor.txt diff --git a/Documentation/config.txt b/Documentation/config.txt index 1167e88e341bc3..342f3cc183aa0c 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -361,6 +361,8 @@ include::config/diff.txt[] include::config/difftool.txt[] +include::config/editor.txt[] + include::config/extensions.txt[] include::config/fastimport.txt[] diff --git a/Documentation/config/editor.txt b/Documentation/config/editor.txt new file mode 100644 index 00000000000000..9e42c4168f809b --- /dev/null +++ b/Documentation/config/editor.txt @@ -0,0 +1,4 @@ +editor.rogue:: + A boolean to indicate you might be using an editor + that can't be trusted to clean its terminal state + reliably. Defaults to false. diff --git a/editor.c b/editor.c index fdd3eeafa94791..a51c72b5a1a7f6 100644 --- a/editor.c +++ b/editor.c @@ -3,6 +3,7 @@ #include "strbuf.h" #include "run-command.h" #include "sigchain.h" +#include "compat/terminal.h" #ifndef DEFAULT_EDITOR #define DEFAULT_EDITOR "vi" @@ -54,6 +55,7 @@ static int launch_specified_editor(const char *editor, const char *path, return error("Terminal is dumb, but EDITOR unset"); if (strcmp(editor, ":")) { + int save_and_restore_term = 0; struct strbuf realpath = STRBUF_INIT; const char *args[] = { editor, NULL, NULL }; struct child_process p = CHILD_PROCESS_INIT; @@ -76,6 +78,13 @@ static int launch_specified_editor(const char *editor, const char *path, fflush(stderr); } + if (git_config_get_bool("editor.rogue", &save_and_restore_term) == 0) + { + /* disable unless we are fully interactive */ + if (save_and_restore_term && !isatty(2)) + save_and_restore_term = 0; + } + strbuf_realpath(&realpath, path, 1); args[1] = realpath.buf; @@ -83,7 +92,12 @@ static int launch_specified_editor(const char *editor, const char *path, p.env = env; p.use_shell = 1; p.trace2_child_class = "editor"; + if (save_and_restore_term) + save_and_restore_term = !save_term(1); + if (start_command(&p) < 0) { + if (save_and_restore_term) + restore_term(); strbuf_release(&realpath); return error("unable to start editor '%s'", editor); } @@ -91,6 +105,8 @@ static int launch_specified_editor(const char *editor, const char *path, sigchain_push(SIGINT, SIG_IGN); sigchain_push(SIGQUIT, SIG_IGN); ret = finish_command(&p); + if (save_and_restore_term) + restore_term(); strbuf_release(&realpath); sig = ret - 128; sigchain_pop(SIGINT);