Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

auto run python result in "EOF when reading a line "

Tags:

python

vim

I have add the line into my .vimrc

map <F4> :w !python<cr>

When I open gvim to edit an unname Python file, there are only two lines in it

x=input("which one do you like ? ")
print(x)

I press F4, and get EOF when reading a line, how to solve it?

When you add map <F4> :w<cr>:!python %<cr> or imap <F4> <Esc>:w <cr>:!python %<cr>, it can only make a named file run, if it is a no named file, the map will not work, how can I make the no named file run?

enter image description here

like image 232
showkey Avatar asked Dec 12 '22 07:12

showkey


2 Answers

@benjifisher's answer is correct. The input (function) is the problem.

The :w !python pipes the program to python through stdin (Basically the same as

echo 'input("x")' | python

which also fails if run in the shell). However input() tries to read from stdin which it can't do because python read the program from stdin and stdin is still trying to read from the pipe. However the pipe is already at the end and won't ever contain new data. So input() just reads EOF.

To see that python is reading from stdin we look at :h :w_c which shows that the file is being passed to stdin of the cmd which in this case is python.

                                                        :w_c :write_c
:[range]w[rite] [++opt] !{cmd}
                        Execute {cmd} with [range] lines as standard input
                        (note the space in front of the '!').  {cmd} is
                        executed like with ":!{cmd}", any '!' is replaced with
                        the previous command :!.

If the buffer had contained something that wasn't reading from stdin your mapping would have worked.

For example if the unnamed buffer contains

print(42)

running the command :w !python in vim prints 42.

So the problem isn't that the mapping fails. The problem is that your program doesn't know how to get input. The solution is use either a named file or don't write interactive programs in vim. Use the python interpreter for that.

like image 94
FDinoff Avatar answered Jan 01 '23 14:01

FDinoff


Since you have :w in your mapping, I am assuming you either want to run the script directly from the insert mode or you want to save it anyways before running it.

Multiple commands in vim require a separator like <bar> i.e. (|) or use <CR> (Carriage Return) between and after commands.

You can put both of the mappings below in your .vimrc and they should meet your requirement on hitting F4, whether you are in normal mode or insert mode.

If you are in normal mode, you are fine with map:

map <F4> :w<cr>:!python %<cr>

While for insert mode, you would need imap and an Esc to get out of insert mode:

imap <F4> <Esc>:w <cr>:!python %<cr>
like image 31
Amit Verma Avatar answered Jan 01 '23 13:01

Amit Verma