I'm creating a mapping which is supposed to navigate to a specific window (call TEST_WIN), focus in on the terminal and then delete a single character.

The goal of this command is to navigate to the terminal buffer and execute the last line that was executed, but to remove the last word of the command which will be an argument -d or -rd.

The mapping looks like this:

noremap ';  :let curWin = win_getid()<CR>:call win_gotoid(TEST_WIN)<CR>A<C-c><C-l><up><BS>

I have substituted <BS> in with <C-w> and both of these delete the entire line instead of a single charater/word.

How can I get it to just delete a single word or character?

I should add that when I am controlling the terminal without the command, <C-w> and the backspace key on my Mac both work as expected. The problem only arises during the command.

  • I'm having trouble with some of this. What does "I have substituted in with and both of these..." mean? "In with"? Also, you need to separate different commands with | (\| in mappings). And what is the A at the end supposed to do? Please provide full and accurate details. Thanks.
    – B Layer
    Dec 9 '20 at 6:07
  • Well, by formatting the code I answered some of my questions. :)
    – B Layer
    Dec 9 '20 at 6:15
  • @BLayer edited with command explanation.
    – libby
    Dec 9 '20 at 6:35
  • Welcome to Vi and Vim!
    – D. Ben Knoble
    Dec 9 '20 at 17:34

Since it seems the OP is using bash, here's a non-mapping, non-vim solution that should work in the shell:


From man bash:

       !!     Refer to the previous command.  This is a synonym for `!-1'.
       x-y    A range of words; `-y' abbreviates `0-y'.
       x-     Abbreviates x-$ like x*, but omits the last word.

I think you can even omit the colon, since the word-designator starts with -.

This also has far less "special characters" like Up that need to be handled specially in vim, though see filbranden's answer for how to send the sequence to a :terminal.

  • I can't believe I didn't know this before. Incredible. Thanks so much.
    – libby
    Dec 9 '20 at 19:58
  • @libby man bash and search for the history expansion header
    – D. Ben Knoble
    Dec 9 '20 at 20:00
  • Save a keystroke: !!-.
    – B Layer
    Dec 14 '20 at 2:11
  • I did mention omitting the colon @BLayer but youre correct
    – D. Ben Knoble
    Dec 14 '20 at 5:07
  • Sorry. Missed that.
    – B Layer
    Dec 15 '20 at 2:56

Previously answered here.

Terminal windows are special, you can't just have a mapping use a command to switch to insert mode and then include characters to type in the terminal directly.

Instead, you should call function term_sendkeys() to interact with the terminal.

Something like the following should work:

function! TermHistory()
  call win_gotoid(TEST_WIN)
  call term_sendkeys('', "\<C-c>\<C-l>\<Up>\<BS>")
nnoremap <silent> '; :call TermHistory()<CR>

UPDATE: NeoVim doesn't have term_sendkeys() available, so on NeoVim you need feedkeys(). For the keys from feedkeys() to go to the program running in the terminal, you also need startinsert.

This function definition seems to work in NeoVim:

function! TermHistory()
  call win_gotoid(TEST_WIN)
  call feedkeys("\<C-c>\<C-l>\<Up>\<BS>")
  • when I do that it's giving me some really weird output. If I open up my buffer and run echo Hello World, then I get out of the terminal and navigate over it and run call chansend(b:terminal_job_id, "\<C-c>\<C-l>\<up>\<BS>\<CR>") I get: bash-3.2$ �ku�kb bash: �ku�kb: command not found bash-3.2$
    – libby
    Dec 9 '20 at 18:16
  • it doesn't like the "\<BS>" we're sending it
    – libby
    Dec 9 '20 at 18:21
  • And "\<Up>", that's what the ?ku is... Looks like chansend() sends it in a different way than expected... I really don't know the right answer to this one. Let's see if someone else can come up with something better. If I have some time, I may take a look at it, I can probably find a NeoVim somewhere (I'm usually a Vim user myself.)
    – filbranden
    Dec 9 '20 at 18:22
  • I'm just as happy with a solution that saves the last terminal command to a variable, removes the last word and then sends it back into the terminal (without backspace and up)
    – libby
    Dec 9 '20 at 18:25
  • It seems feedkeys() works. I updated my answer now.
    – filbranden
    Dec 9 '20 at 18:35

Your Answer

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

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