aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/api/ui_events.in.h3
-rw-r--r--src/nvim/event/process.c1
-rw-r--r--src/nvim/ex_docmd.c4
-rw-r--r--src/nvim/tui/tui.c16
-rw-r--r--src/nvim/ui_client.h3
5 files changed, 24 insertions, 3 deletions
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index fc70215352..6ca5024a04 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -167,4 +167,7 @@ void msg_history_show(Array entries)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
void msg_history_clear(void)
FUNC_API_SINCE(10) FUNC_API_REMOTE_ONLY;
+
+void error_exit(Integer status)
+ FUNC_API_SINCE(12);
#endif // NVIM_API_UI_EVENTS_IN_H
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index 95bf4d1c3b..00ba1334b0 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -423,6 +423,7 @@ static void exit_event(void **argv)
if (!exiting) {
if (ui_client_channel_id) {
+ ui_client_exit_status = status;
os_exit(status);
} else {
assert(status == 0); // Called from rpc_close(), which passes 0 as status.
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 44610c81d8..0a0f7c244d 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -4591,7 +4591,9 @@ static void ex_cquit(exarg_T *eap)
FUNC_ATTR_NORETURN
{
// this does not always pass on the exit code to the Manx compiler. why?
- getout(eap->addr_count > 0 ? (int)eap->line2 : EXIT_FAILURE);
+ int status = eap->addr_count > 0 ? (int)eap->line2 : EXIT_FAILURE;
+ ui_call_error_exit(status);
+ getout(status);
}
/// Do preparations for "qall" and "wqall".
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 9fea6442a9..4097b770c9 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -145,6 +145,7 @@ struct TUIData {
} unibi_ext;
char *space_buf;
bool stopped;
+ int seen_error_exit;
int width;
int height;
bool rgb;
@@ -162,6 +163,7 @@ void tui_start(TUIData **tui_p, int *width, int *height, char **term)
tui->is_starting = true;
tui->screenshot = NULL;
tui->stopped = false;
+ tui->seen_error_exit = 0;
tui->loop = &main_loop;
kv_init(tui->invalid_regions);
signal_watcher_init(tui->loop, &tui->winch_handle, tui);
@@ -384,8 +386,13 @@ static void terminfo_stop(TUIData *tui)
unibi_out_ext(tui, tui->unibi_ext.disable_extended_keys);
// May restore old title before exiting alternate screen.
tui_set_title(tui, (String)STRING_INIT);
- // Exit alternate screen.
- unibi_out(tui, unibi_exit_ca_mode);
+ // if nvim exited with nonzero status, without indicated this was an
+ // intentional exit (like `:1cquit`), it likely was an internal failure.
+ // Don't clobber the stderr error message in this case.
+ if (ui_client_exit_status == tui->seen_error_exit) {
+ // Exit alternate screen.
+ unibi_out(tui, unibi_exit_ca_mode);
+ }
if (tui->cursor_color_changed) {
unibi_out_ext(tui, tui->unibi_ext.reset_cursor_color);
}
@@ -443,6 +450,11 @@ static void tui_terminal_stop(TUIData *tui)
terminfo_stop(tui);
}
+void tui_error_exit(TUIData *tui, Integer status)
+{
+ tui->seen_error_exit = (int)status;
+}
+
void tui_stop(TUIData *tui)
{
tui_terminal_stop(tui);
diff --git a/src/nvim/ui_client.h b/src/nvim/ui_client.h
index 7e5f847039..05964422f3 100644
--- a/src/nvim/ui_client.h
+++ b/src/nvim/ui_client.h
@@ -23,6 +23,9 @@ EXTERN sattr_T *grid_line_buf_attr INIT(= NULL);
// ID of the ui client channel. If zero, the client is not running.
EXTERN uint64_t ui_client_channel_id INIT(= 0);
+// exit status from embedded nvim process
+EXTERN int ui_client_exit_status INIT(= 0);
+
// TODO(bfredl): the current structure for how tui and ui_client.c communicate is a bit awkward.
// This will be restructured as part of The UI Devirtualization Project.