SimpleVimEval() function isn't working because when you call a function with a range Vim will just call it repeatedly for each line in the range.
In the case of the specific expression you're trying to evaluate, a
for line on its own doesn't make sense, neither does an
endfor, and the line inside the
for will fail since the
key variable won't have been set.
You can fix that by defining the function using the
range modifier, in which case Vim will call it only once when called with a range. It will then pass the function a pair of extra arguments,
a:lastline, to let the function handle the range by itself.
In practice, that means you need to take those into account when executing the
yank command. In this case, you need to use
execute to assemble a command as a string, using the values of those two arguments. (See
:help :execute for more details if you're not familiar with it.)
This function definition will work for evaluating that
for block when called with a range:
function! SimpleVimEval() range
execute a:firstline "," a:lastline "yank"
It turns out that the answer to your original question of how to execute a set of Ex commands without using registers is also
And then you can call it with:
:call ArgVimEval("let inf = getbufinfo()\nfor key in inf\n echo key\nendfor\n")
But it's much easier to call it with
:call ArgVimEval(@") after yanking the visual selection if it's text from your buffer.
If you're trying to create a mapping to execute the current Visual selection, then I'd just use
@" to execute it, but saving and restoring the original contents of the register around the operation.
Also, instead of a range function, I'd use the Normal mode
gv command to select the last visual block, that way the command will still work with a blockwise or characterwise selection skipping some characters in some of the lines.
This implements what I just described:
let save_reg = @"
let save_regtype = getregtype('')
call setreg('', save_reg, save_regtype)
xnoremap <Leader>x :<C-U>call ExecuteVisual()<CR>