How to get returned value from python functions in vim scripts ?

612 views
Skip to first unread message

Lenin

unread,
Jun 6, 2011, 5:43:58 AM6/6/11
to vim...@googlegroups.com
Hi,

I want to get returned value from python functions in vim scripts, how can I make it ?

Thanks

Alec Tica

unread,
Jun 6, 2011, 5:59:17 AM6/6/11
to vim...@googlegroups.com
Hi,

In ruby is something like:

VIM::command("return #{my_ruby_var.inspect}")

I expect to be the same in python.

> --
> You received this message from the "vim_use" maillist.
> Do not top-post! Type your reply below the text you are replying to.
> For more information, visit http://www.vim.org/maillist.php
>

--
talek

Marcin Szamotulski

unread,
Jun 6, 2011, 7:04:01 AM6/6/11
to vim...@googlegroups.com
Hi,

You can do

import vim

and then use

vim.command("let g:return="+str(value))

This works also with dictionaries and lists (though I've encountered that some
times singe quotes inside value when it is a dictionary or a list may couse
troubles). So I would like to know a better method.

Best,
Marcin

Lenin

unread,
Jun 7, 2011, 12:47:36 AM6/7/11
to vim...@googlegroups.com
Alec: It seems :py vim.command('return 1') will throw an error that says "return not inside a function".

Marcin: Yes, I am using vim variables to transfer values from python functions currently, but I think this method is ugly, I'd like to know a better solution.

Thank you both.

2011/6/6 Marcin Szamotulski <msz...@gmail.com>

Ivan Krasilnikov

unread,
Jun 7, 2011, 2:36:58 AM6/7/11
to vim...@googlegroups.com
On Tue, Jun 7, 2011 at 08:47, Lenin <leni...@gmail.com> wrote:
> Alec: It seems :py vim.command('return 1') will throw an error that says
> "return not inside a function".

It works fine if you call it inside a vim function:

:function Func()
: py vim.command('return 1')
:endfunction

Marko Mahnič

unread,
Jun 7, 2011, 3:26:02 AM6/7/11
to vim_use
On Jun 7, 8:36 am, Ivan Krasilnikov <inf...@gmail.com> wrote:
> On Tue, Jun 7, 2011 at 08:47, Lenin <lenin....@gmail.com> wrote:
> > Alec: It seems :py vim.command('return 1') will throw an error that says
> > "return not inside a function".
>
> It works fine if you call it inside a vim function:
>
> :function Func()
> :  py vim.command('return 1')
> :endfunction

The script vimuiex (2606 on vim.org) uses callbacks to process the
returned values:

In Vim:
function g:MyCallback(param)
" process the parameter
endfunc

In Python:
vim.eval("g:MyCallback(%d)", retval)

The script doesn't actually use global functions, they are always
local to the script. The drawback is that you have to pass to Python
the name of the function to call:

In vim:
exec vxlib#plugin#MakeSID() " this is defined in VxLib, script 3061;
it defines s:SNR
function s:MyCallback(param)
" process
endfunc
python DoSomething(s:SNR . 'MyCallback', ...)

In Python:
def DoSomething(fnToCall, ...)
#...
vim.eval("%s(%d)" % (fnToCall, retval))

Marko

Marko Mahnič

unread,
Jun 7, 2011, 3:31:29 AM6/7/11
to vim_use
This should probably be:
exec "python DoSomething(\"" . s:SNR . "MyCallback\", ...)"

Marko

Tony Mechelynck

unread,
Jun 7, 2011, 7:39:33 AM6/7/11
to vim...@googlegroups.com, Marko Mahnič

This last one cannot be right: as a minimum, it lacks a backslash left
of "MyCallback".

Best regards,
Tony.
--
Ducharme's Axiom:
If you view your problem closely enough you will recognize
yourself as part of the problem.

Marko Mahnič

unread,
Jun 7, 2011, 7:55:34 AM6/7/11
to Tony Mechelynck, vim...@googlegroups.com
On 07. 06. 2011 13:39, Tony Mechelynck wrote:
> On 07/06/11 09:31, Marko Mahnič wrote:
>> On Jun 7, 9:26 am, Marko Mahnič<marko.mah...@gmail.com> wrote:
>>> On Jun 7, 8:36 am, Ivan Krasilnikov<inf...@gmail.com> wrote:
>>>
>>> function s:MyCallback(param)
>>> " process
>>> endfunc
>>> python DoSomething(s:SNR . 'MyCallback', ...)
>>
>> This should probably be:
>> exec "python DoSomething(\"" . s:SNR . "MyCallback\", ...)"
>>
>> Marko
>>
>
> This last one cannot be right: as a minimum, it lacks a backslash left
> of "MyCallback".
>

If you keep the quotes and backsalshes, but change the rest you can write (
s:SNR -> getcwd(), MyCallback -> /. ) :

:python import os
:exec "python print os.path.exists(\"" . getcwd() . "/.\")"

which works for me (Vim 7.3). If getcwd() returns "/home/user", the generated
Python statement is:

print os.path.exists("/home/user/.")

In the above case you would get the Python statement:

DoSomething("32_MyCallback", ...)


Marko

> Best regards,
> Tony.

Tony Mechelynck

unread,
Jun 7, 2011, 8:56:18 AM6/7/11
to Marko Mahnič, vim...@googlegroups.com

no, you would get:
E???: invalid expression
because


>>> exec "python DoSomething(\"" . s:SNR . "MyCallback\", ...)"

string ^---------------------------------^
something Vim cannot understand ^--------...

>
>
> Marko
>
>> Best regards,
>> Tony.
--
Honk if you hate bumper stickers that say "Honk if ..."

Tony Mechelynck

unread,
Jun 7, 2011, 9:13:43 AM6/7/11
to vim...@googlegroups.com, Marko Mahnič

P.S. I think you should have written

:exec 'python DoSomething("' . s:SNR . 'MyCallback", ...)'

>
>>
>>
>> Marko
>>
>>> Best regards,
>>> Tony.
--
There's nothing wrong with America that a good erection wouldn't cure.
-- David Mairowitz

Marko Mahnič

unread,
Jun 7, 2011, 9:14:55 AM6/7/11
to Tony Mechelynck, vim...@googlegroups.com
Let's break it down:

1. exec accepts a string
2. the string is a concatenation of 3 strings:
- "python DoSomething(\""
- s:SNR
- "MyCallback\", ...)"

The double quote is preceeded by a backslash in the first and the third string
and is treated as a part of the string. We could rewrite them as:
- 'python DoSomething("'
- 'MyCallback", ...)'

s:SNR is the SID of the script, I think it looks sth. like '42_'.

Now we concatenate:
'python DoSomething("' . '42_' . 'MyCallback", ...)'
to get
'python DoSomething("42_MyCallback", ...)'
which is a perfectly valid string for exec (but not for Python, because of the
dots which should be replaced by the actual parameters, if any).

Marko

Marko Mahnič

unread,
Jun 7, 2011, 9:17:49 AM6/7/11
to Tony Mechelynck, vim...@googlegroups.com

This is equivalent to the above. Note that Vim treats "" and '' strings
differently: single-quote strings are accepted as they are written while
double-quote strings undergo some fancy parsing and escaping. The following
strings are equivalent:
"\""
'"'

Marko

Tony Mechelynck

unread,
Jun 7, 2011, 9:30:04 AM6/7/11
to Marko Mahnič, vim...@googlegroups.com

you forgot to backslash-escape the opening quote of "MyCallback". Third
edition. Are you blind or what? Or do you need some coffee?

>
> Marko
>

Best regards,
Tony.
--
"It was pleasant to me to get a letter from you the other day. Perhaps
I should have found it pleasanter if I had been able to decipher it. I
don't think that I mastered anything beyond the date (which I knew) and
the signature (which I guessed at). There's a singular and a perpetual
charm in a letter of yours; it never grows old, it never loses its
novelty .... Other letters are read and thrown away and forgotten, but
yours are kept forever -- unread. One of them will last a reasonable
man a lifetime."
-- Thomas Aldrich

Tony Mechelynck

unread,
Jun 7, 2011, 9:32:35 AM6/7/11
to vim...@googlegroups.com, Marko Mahnič

Sorry, it's me. You're right, I'm wrong. The string ends at the second
quote after the first backslash.

>
>>
>> Marko
>>
>
> Best regards,
> Tony.
--

Please try to limit the amount of "this room doesn't have any bazingas"
until you are told that those rooms are "punched out". Once punched
out, we have a right to complain about atrocities, missing bazingas,
and such.
-- N. Meyrowitz

Marko Mahnič

unread,
Jun 7, 2011, 9:38:14 AM6/7/11
to Tony Mechelynck, vim...@googlegroups.com

Not blind. No need for coffee. Thanks :)

Let me describe it again:

exec "python DoSomething(\"" . s:SNR . "MyCallback\", ...)"

"python ... the opening quote for a Vim string
DoSomething(\" ... the opening quote for a Python string
" ... the closing quote for the Vim string
. s:SNR . ... concatenation
"Mycallback ... the opening quote for the 2nd Vim string
\" ... the closing quote for the Python string
, ...)" ... the closing quote for the 2nd Vim string

It's all there.

Marko

Vlad Irnov

unread,
Jun 7, 2011, 4:39:45 PM6/7/11
to vim_use


On Jun 7, 12:47 am, Lenin <lenin....@gmail.com> wrote:
> Alec: It seems :py vim.command('return 1') will throw an error that says
> "return not inside a function".
>
> Marcin: Yes, I am using vim variables to transfer values from python
> functions currently, but I think this method is ugly, I'd like to know a
> better solution.

It may be ugly but it's perfectly serviceable. It can also be tricky
because the exact syntax depends on the type of value being
transfered.
For strings
:py vim.command("let g:vim_var='%s'" %python_var.replace("'", "''"))
For integers, simple dictionaries and lists:
:py vim.command("let g:vim_var=%s" %python_var)
:py vim.command("let g:vim_var=%s" %({'a':1,'b':2}))

With strings, backslashes and quotes need to be taken care of. The
easiest is to use single quotes in Vim assignment and double all
single quotes in strings. Example:

python << EOF
import vim
def py_func(): return """a'b"c\nd\t\\e"""
EOF
py print repr(py_func())
py vim.command("let g:py_var='%s'" %py_func().replace("'", "''"))
echo g:py_var

Script-local or function-local variable can be used to avoid polluting
Vim's global namespace. Python function can create Vim function-local
var when it is called from Vim function. That is, inside a Python
function:
vim.command("let l:result='%s'" %result.replace("'", "''"))

I don't think there is better solution.

Lenin

unread,
Jun 7, 2011, 9:32:10 PM6/7/11
to vim...@googlegroups.com
Thank you all, it's very helpful.

2011/6/8 Vlad Irnov <vlad....@gmail.com>

--
Reply all
Reply to author
Forward
0 new messages