refactor: split WIN_EXECUTE() into two functions (#26627)

This commit is contained in:
zeertzjq 2023-12-18 09:05:59 +08:00 committed by GitHub
parent e164f4c271
commit 6abdc1ac1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 90 additions and 68 deletions

View File

@ -154,7 +154,6 @@ iwyu: build/.ran-cmake
|src/nvim/eval/typval.h\
|src/nvim/eval/typval_defs.h\
|src/nvim/eval/userfunc.h\
|src/nvim/eval/window.h\
|src/nvim/event/libuv_process.h\
|src/nvim/event/loop.h\
|src/nvim/event/process.h\

View File

@ -912,7 +912,6 @@ def CheckIncludes(filename, lines, error):
"src/nvim/eval/typval.h",
"src/nvim/eval/typval_defs.h",
"src/nvim/eval/userfunc.h",
"src/nvim/eval/window.h",
"src/nvim/event/libuv_process.h",
"src/nvim/event/loop.h",
"src/nvim/event/process.h",

View File

@ -435,10 +435,12 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
try_start();
Object res = OBJECT_INIT;
WIN_EXECUTE(win, tabpage, {
win_execute_T win_execute_args;
if (win_execute_before(&win_execute_args, win, tabpage)) {
Array args = ARRAY_DICT_INIT;
res = nlua_call_ref(fun, NULL, args, true, err);
});
}
win_execute_after(&win_execute_args);
try_end(err);
return res;
}

View File

@ -9,7 +9,6 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/cursor.h"
#include "nvim/eval/funcs.h"
#include "nvim/eval/typval.h"
@ -19,9 +18,12 @@
#include "nvim/gettext.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
#include "nvim/pos_defs.h"
#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
@ -480,6 +482,68 @@ void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = nr;
}
/// Switch to a window for executing user code.
/// Caller must call win_execute_after() later regardless of return value.
///
/// @return whether switching the window succeded.
bool win_execute_before(win_execute_T *args, win_T *wp, tabpage_T *tp)
{
args->wp = wp;
args->curpos = wp->w_cursor;
args->cwd_status = FAIL;
args->apply_acd = false;
// Getting and setting directory can be slow on some systems, only do
// this when the current or target window/tab have a local directory or
// 'acd' is set.
if (curwin != wp
&& (curwin->w_localdir != NULL || wp->w_localdir != NULL
|| (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL))
|| p_acd)) {
args->cwd_status = os_dirname(args->cwd, MAXPATHL);
}
// If 'acd' is set, check we are using that directory. If yes, then
// apply 'acd' afterwards, otherwise restore the current directory.
if (args->cwd_status == OK && p_acd) {
do_autochdir();
char autocwd[MAXPATHL];
if (os_dirname(autocwd, MAXPATHL) == OK) {
args->apply_acd = strcmp(args->cwd, autocwd) == 0;
}
}
if (switch_win_noblock(&args->switchwin, wp, tp, true) == OK) {
check_cursor();
return true;
}
return false;
}
/// Restore the previous window after executing user code.
void win_execute_after(win_execute_T *args)
{
restore_win_noblock(&args->switchwin, true);
if (args->apply_acd) {
do_autochdir();
} else if (args->cwd_status == OK) {
os_chdir(args->cwd);
}
// Update the status line if the cursor moved.
if (win_valid(args->wp) && !equalpos(args->curpos, args->wp->w_cursor)) {
args->wp->w_redr_status = true;
}
// In case the command moved the cursor or changed the Visual area,
// check it is valid.
check_cursor();
if (VIsual_active) {
check_pos(curbuf, &VIsual);
}
}
/// "win_execute(win_id, command)" function
void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
@ -494,7 +558,11 @@ void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, 1));
win_execute_T win_execute_args;
if (win_execute_before(&win_execute_args, wp, tp)) {
execute_common(argvars, rettv, 1);
}
win_execute_after(&win_execute_args);
}
/// "win_findbuf()" function
@ -914,16 +982,16 @@ int switch_win_noblock(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool n
return OK;
}
// Restore current tabpage and window saved by switch_win(), if still valid.
// When "no_display" is true the display won't be affected, no redraw is
// triggered.
/// Restore current tabpage and window saved by switch_win(), if still valid.
/// When "no_display" is true the display won't be affected, no redraw is
/// triggered.
void restore_win(switchwin_T *switchwin, bool no_display)
{
restore_win_noblock(switchwin, no_display);
unblock_autocmds();
}
// As restore_win() but without unblocking autocommands.
/// As restore_win() but without unblocking autocommands.
void restore_win_noblock(switchwin_T *switchwin, bool no_display)
{
if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab)) {

View File

@ -1,20 +1,12 @@
#pragma once
#include <stdbool.h>
#include <string.h>
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/cursor.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/globals.h"
#include "nvim/mark.h"
#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/os/os_defs.h"
#include "nvim/pos_defs.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
#include "nvim/types_defs.h" // IWYU pragma: keep
/// Structure used by switch_win() to pass values to restore_win()
typedef struct {
@ -24,53 +16,15 @@ typedef struct {
bool sw_visual_active;
} switchwin_T;
/// Execute a block of code in the context of window `wp` in tabpage `tp`.
/// Ensures the status line is redrawn and cursor position is valid if it is moved.
#define WIN_EXECUTE(wp, tp, block) \
do { \
win_T *const wp_ = (wp); \
const pos_T curpos_ = wp_->w_cursor; \
char cwd_[MAXPATHL]; \
char autocwd_[MAXPATHL]; \
bool apply_acd_ = false; \
int cwd_status_ = FAIL; \
/* Getting and setting directory can be slow on some systems, only do */ \
/* this when the current or target window/tab have a local directory or */ \
/* 'acd' is set. */ \
if (curwin != wp \
&& (curwin->w_localdir != NULL || wp->w_localdir != NULL \
|| (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL)) \
|| p_acd)) { \
cwd_status_ = os_dirname(cwd_, MAXPATHL); \
} \
/* If 'acd' is set, check we are using that directory. If yes, then */ \
/* apply 'acd' afterwards, otherwise restore the current directory. */ \
if (cwd_status_ == OK && p_acd) { \
do_autochdir(); \
apply_acd_ = os_dirname(autocwd_, MAXPATHL) == OK && strcmp(cwd_, autocwd_) == 0; \
} \
switchwin_T switchwin_; \
if (switch_win_noblock(&switchwin_, wp_, (tp), true) == OK) { \
check_cursor(); \
block; \
} \
restore_win_noblock(&switchwin_, true); \
if (apply_acd_) { \
do_autochdir(); \
} else if (cwd_status_ == OK) { \
os_chdir(cwd_); \
} \
/* Update the status line if the cursor moved. */ \
if (win_valid(wp_) && !equalpos(curpos_, wp_->w_cursor)) { \
wp_->w_redr_status = true; \
} \
/* In case the command moved the cursor or changed the Visual area, */ \
/* check it is valid. */ \
check_cursor(); \
if (VIsual_active) { \
check_pos(curbuf, &VIsual); \
} \
} while (false)
/// Structure used by win_execute_before() to pass values to win_execute_after()
typedef struct {
win_T *wp;
pos_T curpos;
char cwd[MAXPATHL];
int cwd_status;
bool apply_acd;
switchwin_T switchwin;
} win_execute_T;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/window.h.generated.h"