aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval/window.c')
-rw-r--r--src/nvim/eval/window.c94
1 files changed, 82 insertions, 12 deletions
diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c
index e0abbad477..b8aa0c9641 100644
--- a/src/nvim/eval/window.c
+++ b/src/nvim/eval/window.c
@@ -9,19 +9,22 @@
#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"
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/window.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
+#include "nvim/mark_defs.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 +483,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 succeeded.
+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 +559,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
@@ -607,13 +676,13 @@ static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags
// Remove the old window and frame from the tree of frames
int dir;
- (void)winframe_remove(wp, &dir, NULL);
+ winframe_remove(wp, &dir, NULL);
win_remove(wp, NULL);
last_status(false); // may need to remove last status line
- (void)win_comp_pos(); // recompute window positions
+ win_comp_pos(); // recompute window positions
// Split a window on the desired side and put the old window there
- (void)win_split_ins(size, flags, wp, dir);
+ win_split_ins(size, flags, wp, dir);
// If splitting horizontally, try to preserve height
if (size == 0 && !(flags & WSP_VERT)) {
@@ -642,7 +711,8 @@ void f_win_splitmove(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
- int flags = 0, size = 0;
+ int flags = 0;
+ int size = 0;
if (argvars[2].v_type != VAR_UNKNOWN) {
dict_T *d;
@@ -685,7 +755,7 @@ void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_string = xstrdup("preview");
} else if (wp->w_floating) {
rettv->vval.v_string = xstrdup("popup");
- } else if (wp == curwin && cmdwin_type != 0) {
+ } else if (wp == cmdwin_win) {
rettv->vval.v_string = xstrdup("command");
} else if (bt_quickfix(wp->w_buffer)) {
rettv->vval.v_string = xstrdup((wp->w_llist_ref != NULL ? "loclist" : "quickfix"));
@@ -914,16 +984,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)) {