I am trying to return this :GrepperAck ''<Left> from a Python function and use it in the following mapping

def invoke_search_command():
  return ":GrepperAck ''<Left>"
:nnoremap <expr> <leader>f py3eval('invoke_search_command()')

But the <Left> is printed literally like :GrepperGit ''<Left>.

But if I use :nnoremap <expr> <leader>f py3eval('invoke_search_command()') . '<Left>', it works. I tried escaping the returned string like ":GrepperAck ''\<Left>", but it is still getting printed literally. What am I doing wrong?

  • 1
    @BLayer Sorry, that was my bad. Commented Jun 28, 2019 at 11:40
  • Did you see my updated answer?
    – B Layer
    Commented Aug 8, 2019 at 5:33
  • I am just checking that out. My bad, I am not getting any notifications. Commented Aug 8, 2019 at 6:41

1 Answer 1


You definitely need the backslash version \<Left>. Is use of py3eval necessary? Unless you need to translate data structures from Python to Vim or something it would be better to return a straight string. You need to make sure the string :GrepperAck ''\<Left> is passed literally to the command line. Then it will be processed as an expression due to <expr>.

I don't have a Python installation but I can demonstrate the fundamental workings without it. Given...

func! Foo()
    return ":GrepperAck ''\<Left>"

And this mapping...

nnoremap <expr> <leader>f Foo()

Then when I enter leader key and f this is what I'll see on the command line..

:GrepperAck ''

...and the cursor will be inside the quotes.

If you must use py3eval then one thing you might try is to wrap that in a string() function call.

nnoremap <expr> <leader>f string(py3eval(..))

Update: In retrospect the reason \<Left> doesn't work is almost certainly because the parsing of the mapping occurs in a certain order, i.e. the phase that substitutes actual keys for <xxx> tokens occurs before any external programs are executed. I haven't confirmed this by looking at the Vim source code or anything but as a veteran software developer I can tell you that it's a solid theory. It wouldn't make much sense for the parser to have multiple passes with <xxx> resolution nor, generally speaking, to make such a pass over external (non-Vim originated) runtime data.

Can anything be done? Well, I thought that substituting the actual key code would do the trick....

def invoke_search_command():
    return ":GrepperAck ''<C-V><Left>"

That means rather than type \<Left> you actually enter Ctrl+V followed by (left arrow key). (For me the combo comes out looking like ^[OD.) Unfortunately, I'm getting an error: Not an editor command: GrepperAck ''. But I know I'm on the right track because if I replace with Ctrl+H (commonly the same function as the backspace key) then the cursor is actually moved on the resulting GrepperAck command line (erasing the last ' as expected).

So why isn't the left arrow key code working? Dunno. It might be that we can substitute something else in the terminal codes but that's a stretch and getting into possibly non-portable behavior. I'll play around with that for a bit but unfortunately, unless your system behaves differently than mine (try it out) I believe the ultimate answer to your question is "this is not possible".

  • I will try the string function call and let you know if this works, and accept this answer if it works. Thanks. Commented Jun 28, 2019 at 11:44
  • @RajaRaviVarma Thank you. If it doesn't work and there are any additional details that might help let me know. I like to see a question/answer through to the end if I'm able.
    – B Layer
    Commented Jun 28, 2019 at 12:24
  • Wrapping the whole expression with string() throws Unknown mark error. Sorry that didn't work. Commented Jun 28, 2019 at 14:01
  • 1
    Yup, the pure vim function worked fine. Commented Jul 1, 2019 at 4:29
  • 1
    When I try the <Ctrl-V><Left>, I get ^[OD just like you said. For me it opens the quickfix and inserts the D character in my last cursor position. But you explanation makes sense and I will accept it. Thanks for all the work. Commented Aug 8, 2019 at 6:52

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.