I have function to perform a git diff, after calling git diff I wish to emulate the following keypresses in the terminal window:

  • G move to the end of the file
  • a append
  • q<cr> type q to quit the "terminal scrolling mode" then enter
  • gg return to the top of the file


function GitDiff()
  terminal git diff --word-diff %
  normal Gaq<Esc>gg
:nmap <leader>t :call GitDiff()<cr>

However the keypresses dont seem to be executed as expected. I wonder if it needs a delay to wait for the terminal command to finish executing?

  • Are you trying to quit the pager (such as less) launched by git diff? Why not run git diff using a function like systemlist() and write those contents to a scratch buffer instead? The terminal is quite tricky to automate, why do you think you need to use it here?
    – filbranden
    Commented Mar 2, 2020 at 15:28
  • 2
    You probably need feedkeys or a term specific variant. Normal is a bit different
    – D. Ben Knoble
    Commented Mar 2, 2020 at 16:07
  • @D.BenKnoble Vim at least has term_sendkeys() but the doc says "This requires for the job to be in the right state where it will do the right thing when receiving the keys" which I take it as this will send the keystrokes to the process running on the terminal and won't take normal-mode commands either...
    – filbranden
    Commented Mar 3, 2020 at 0:33
  • @filbranden I tried to placing the contents of an external command to scratch buffer, and tried a host of hi coloring, but at the end of the day I couldnt get the output of git status to be colored. Whereas the terminal command colors it. I have since figured out I seem to be trying to get similar functionality as what magit does in emacs (or vimagit). Commented Mar 4, 2020 at 9:38
  • git status emits color escape sequences when it outputs to a terminal, but not when it outputs to a file. Try fugitive for vim, though.
    – D. Ben Knoble
    Commented Mar 4, 2020 at 20:09

1 Answer 1


Terminal buffer is not modifiable while the child process is running. You must send keys instead.

With Neovim you have to use chansend(). Assuming the terminal runs in the current buffer:

call chansend(&channel, "q\r")
  • This is almost there. call chansend(&channel, "q\r") quits correctly, then normal 7j moves the cursor down 7 lines, but normal 3w, or normal www, or normal 9l does not move the cursor to the right, only moves it down??? I dont understand why? Commented Mar 5, 2020 at 11:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.