1

I would like to correctly intepret the <cr> in a command that is created based on user input.

For example, this function runs correctly and it will split the line a the location where the cursor is.

function NewLine()
  execute "normal! r\<cr>"
endfunction

But if I convert it to accept user input:

function NewLine()
  let l:cmd = input('Your command: ')
  execute "normal! " . l:cmd
endfunction

if the input is r\<cr> then it just replaces the character the current cursor is on, with \ instead of spliting the line.

How to make it interpret the whole thing, as it seems it stops at \.

3
  • 3
    I would use r CTRL-V ENTER in your input
    – Maxim Kim
    Commented Nov 13, 2020 at 14:12
  • 2
    Welcome to Vi and Vim!
    – D. Ben Knoble
    Commented Nov 13, 2020 at 16:12
  • @D.BenKnoble Thanks 👋
    – skamsie
    Commented Nov 25, 2020 at 21:04

1 Answer 1

1

If you want the user to be able to enter a sequence such as r\<cr> or r\r and have Vim interpret that the same way as it interprets sequences in a double quoted string, the easiest way to do so is to actually assemble it into a double quoted string and use eval() to have Vim interpret it.

In your particular case:

execute "normal! " . eval('"' . l:cmd . '"')

Note that there's potential for the produced string to be invalid. For example, if l:cmd includes a single double quote in it. So you might want to make sure you're using the try command to catch any errors when evaluating the string you produced.

It's also important to notice that there's potential that a clever user might exploit this to have l:cmd evaluate to a function that has potential side effects, so make sure you make some due diligence to prevent expression injection in this scheme, particularly if you're interpreting sequences coming from a file that might have been downloaded from the web. (There was a recent security vulnerability in Vim that could be exploited by simply opening a file with a specially crafted modeline. When you're using something like eval(), make sure you're not creating something that's opening the door to such types of exploits.)

2
  • 1
    For the double quote, couldn’t you use something like escape(..., '"\')?
    – D. Ben Knoble
    Commented Nov 25, 2020 at 21:17
  • 1
    @Ben Yes, you can escape things such as " and backslash, but since the question was using r\<cr> as an example, escaping backslash would have prevented this from solving that particular case... eval() is evil, so I'd rather just point out that dragons lie ahead rather than try to take on them myself 😉
    – filbranden
    Commented Nov 25, 2020 at 21:34

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.