From b85098f06ea61bdf3e58645c47d850761f113a84 Mon Sep 17 00:00:00 2001 From: Adam Saponara Date: Thu, 17 Oct 2024 01:21:32 -0400 Subject: [PATCH] fix bug in `_cmd_pre_close` consider a split bview with unsaved changes, same buffer in both bviews. if `cmd_close` was invoked on the split parent, the editor would close without prompting to save changes. this did not affect `cmd_quit` as it walks the bview tree from the top down. also delete `editor_count_bviews_by_buffer` which is no longer used anywhere. --- cmd.c | 21 +++++++++++++++++---- editor.c | 11 ----------- mle.h | 1 - tests/func/test_close.sh | 6 ++++++ uscript.inc | 16 ---------------- 5 files changed, 23 insertions(+), 32 deletions(-) create mode 100755 tests/func/test_close.sh diff --git a/cmd.c b/cmd.c index 6382778..47d0fe6 100644 --- a/cmd.c +++ b/cmd.c @@ -54,6 +54,7 @@ static void _cmd_get_input(cmd_context_t *ctx, kinput_t *ret_input); static int _cmd_fsearch_inner(cmd_context_t *ctx, char *shell_cmd); static int _cmd_get_char_param(cmd_context_t *ctx, char *ret_ch); static int _cmd_move_page_y(cmd_context_t *ctx, int full_y, int is_up); +static int _cmd_pre_close_ok_to_close_bview(editor_t *editor, bview_t *bview); // Insert data int cmd_insert_data(cmd_context_t *ctx) { @@ -1567,7 +1568,6 @@ static int _cmd_indent_line(bline_t *bline, int use_tabs, int outdent) { return MLE_OK; } - // Recursively close bviews, prompting to save unsaved changes. Return MLE_OK if // it's OK to continue closing, or MLE_ERR if the action was cancelled. static int _cmd_quit_inner(editor_t *editor, bview_t *bview) { @@ -1589,9 +1589,7 @@ static int _cmd_pre_close(editor_t *editor, bview_t *bview) { MLE_RETURN_ERR(editor, "Cannot close non-edit bview %p", (void*)bview); } else if (editor->loop_depth > 1) { MLE_RETURN_ERR(editor, "Cannot close bview %p when loop_depth > 1", (void*)bview); - } else if (!bview->buffer->is_unsaved || MLE_BVIEW_IS_MENU(bview) - || editor_count_bviews_by_buffer(editor, bview->buffer) > 1 - ) { + } else if (_cmd_pre_close_ok_to_close_bview(editor, bview)) { return MLE_OK; } @@ -2225,3 +2223,18 @@ static int _cmd_move_page_y(cmd_context_t *ctx, int full_y, int is_up) { viewport_fn(ctx->bview); return MLE_OK; } + +// Return 1 if OK to close bview immediately without prompting to save +static int _cmd_pre_close_ok_to_close_bview(editor_t *editor, bview_t *bview) { + bview_t *tmp; + if (!bview->buffer->is_unsaved || MLE_BVIEW_IS_MENU(bview)) { + return 1; // OK to close saved bviews, and menus + } + tmp = bview->split_parent; + while (tmp) { + // OK to close if a split_parent has buffer open + if (tmp->buffer == bview->buffer) return 1; + tmp = tmp->split_parent; + } + return 0; +} diff --git a/editor.c b/editor.c index 50670b1..f4a6309 100644 --- a/editor.c +++ b/editor.c @@ -521,17 +521,6 @@ int editor_bview_edit_count(editor_t *editor) { return count; } -// Return number of bviews displaying buffer -int editor_count_bviews_by_buffer(editor_t *editor, buffer_t *buffer) { - int count; - bview_t *bview; - count = 0; - CDL_FOREACH2(editor->all_bviews, bview, all_next) { - if (bview->buffer == buffer) count += 1; - } - return count; -} - // Register a command static int _editor_register_cmd_fn(editor_t *editor, char *name, int (*func)(cmd_context_t *ctx)) { cmd_t cmd = {0}; diff --git a/mle.h b/mle.h index 0a2c2f5..ba5f6f0 100644 --- a/mle.h +++ b/mle.h @@ -429,7 +429,6 @@ int editor_open_bview(editor_t *editor, bview_t *opt_parent, int type, char *opt int editor_close_bview(editor_t *editor, bview_t *bview, int *optret_num_closed); int editor_set_active(editor_t *editor, bview_t *bview); int editor_bview_edit_count(editor_t *editor); -int editor_count_bviews_by_buffer(editor_t *editor, buffer_t *buffer); int editor_register_cmd(editor_t *editor, cmd_t *cmd); int editor_register_observer(editor_t *editor, char *event_patt, void *udata, observer_func_t fn_callback, observer_t **optret_observer); int editor_notify_observers(editor_t *editor, char *event_name, void *event_data); diff --git a/tests/func/test_close.sh b/tests/func/test_close.sh new file mode 100755 index 0000000..1f6910b --- /dev/null +++ b/tests/func/test_close.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +macro='a M-h M-p M-c C-c b' +declare -A expected +expected[close_root_prompted]='^ab$' +source 'test.sh' diff --git a/uscript.inc b/uscript.inc index 75c59c7..2bf55a1 100644 --- a/uscript.inc +++ b/uscript.inc @@ -1353,21 +1353,6 @@ static int _uscript_func_editor_close_bview(lua_State *L) { return 1; } -static int _uscript_func_editor_count_bviews_by_buffer(lua_State *L) { - int rv; - editor_t *editor; - buffer_t *buffer; - editor = (editor_t *)luaL_checkpointer(L, 1); - buffer = (buffer_t *)luaL_checkpointer(L, 2); - rv = editor_count_bviews_by_buffer(editor, buffer); - lua_createtable(L, 0, 1); - lua_pushstring(L, "rv"); - lua_pushinteger(L, (lua_Integer)rv); - lua_settable(L, -3); - lua_pushvalue(L, -1); - return 1; -} - static int _uscript_func_editor_destroy_observer(lua_State *L) { int rv; editor_t *editor; @@ -2636,7 +2621,6 @@ static const struct luaL_Reg mle_lib[] = { { "cursor_uncut", _uscript_func_cursor_uncut }, { "editor_bview_edit_count", _uscript_func_editor_bview_edit_count }, { "editor_close_bview", _uscript_func_editor_close_bview }, - { "editor_count_bviews_by_buffer", _uscript_func_editor_count_bviews_by_buffer }, { "editor_destroy_observer", _uscript_func_editor_destroy_observer }, { "editor_display", _uscript_func_editor_display }, { "editor_force_redraw", _uscript_func_editor_force_redraw },