Is there a function like setpos that lets change the cursor position in a different window (split), given the window number?

Or, even better, is there a command to execute a command in specific window?

  • 1
    Have a look in :help window-functions and see if any fit your need; I'm not aware of any that exactly do what you describe though – D. Ben Knoble Mar 29 '20 at 16:15
  • @D.BenKnoble If i have 2 splits, when i change from one split to another, the position where the cursor was is memorized. i want to change the position of the cursor in a specific split. none of those functions seems to help, unless i make the script switch to a window, move the cursor and then switch back to the original, i'm asking if there's a better way, – user27528 Mar 29 '20 at 19:28

You should use the win_execute() command to run commands in a different window.

It takes your command to be executed as a string, or it can also take a list of strings to execute multiple commands.

The main advantage of using win_execute() over switching to a window is that it will avoid pitfalls such as window event triggers, modifications to the previous window, modifications to the height of squashed windows. It's also necessary for popup windows, as switching to those windows is not allowed.

Using setpos() by itself didn't trigger an update on the other window. Even though the cursor position was changed, the view didn't reflect it until I changed to that window. One option is to run both that command and a redraw to force that to happen:

call win_execute(1010, ['call setpos(".", [0, 1, 1, 1])', 'redraw'])

Another option is to use winrestview(), since that command seems to work correctly without any redraws:

call win_execute(1010, 'call winrestview({"col": 1, "lnum": 1})')

(Another advantage of winrestview() is that it also offers control of the first line and column of the window, not just the cursor position.)

One thing to watch for with win_execute() is that it will fail silently if the window doesn't exist, you don't get any indication that the command failed because the window id is invalid. So make sure you get a valid window id before you execute that command.

  • 1
    the view doesn't reflect it until you change to that window: add a redraw after setpos(); e.g. :call win_execute(winid, ['call setpos(".", [1, 2, 3, 4])', 'redraw']). – user938271 Mar 29 '20 at 23:57
  • 2
    Overall, I think the option of switching to the window, running the command there and switching back is still the best alternative. No, win_execute() is the best alternative. Focusing a window triggers events, alters the previous window, alters the height of a squashed window, and is disallowed for popup windows; win_execute() avoids all these pitfalls. – user938271 Mar 29 '20 at 23:57
  • Alright, thanks a lot for the feedback @user938271 ! I reworked my answer completely to incorporate your suggestions. Please take another look. (BTW, always love your comments and answers, you're really very knowledgeable of Vim! Thanks for raising the bar here at Vi & Vim SE!) – filbranden Mar 30 '20 at 22:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy