1

I want to be able to set up the hot key \\ to be able to write and run python script from VIM without each time having to type in

:w
:! python3 file.py

What I have done so far is pasted the following into my vimrc file:

"{{{ The following is for sourcing command.vim whenever exists.
" Function to source only if the file command.vim exists
" https://devel.tech/snippets/n/vIIMz8vZ/load-vim-source-files-only-if-they-exist
"
function! SourceIfExists(file)
  if filereadable(expand(a:file))
    echom a:file . " is about to be sourced."
    exe 'source' a:file
  endif
endfunction
autocmd BufEnter * call SourceIfExists("command.vim")
" }}}

and then in the same directory that my python file is, I create a file named command.vim and paste the following inside that file:

noremap <leader><leader> :w <cr> :!python3 % &<cr>

Now this almost works perfectly except for the following issue. Suppose I want to run the following script, which I'll call file.py:

import numpy as np

x = np.linspace(0, 5, 6)
y = np.linspace(6, 10, 5)

print('{}\n{}'.format(x, y))

If I run this the standard way by using :! python3 file.py then the output is the following:

[0. 1. 2. 3. 4. 5.]
[ 6.  7.  8.  9. 10.]

Press ENTER or type command to continue

But, if I use the \\ method to run the same script, I get the following output:

Press ENTER or type command to continue[0. 1. 2. 3. 4. 5.]
                                                          [ 6.  7.  8.  9. 10.]

and you can see that the output of the script using \\ is not formatted nicely like it is when using the standard command :! python3 file.py.

Anyone know how to fix this?

New contributor
alpastor is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
8
  • nnoremap <buffer><leader><leader> :w<bar>!python3 %<cr>?
    – r_31415
    Sep 22 at 20:33
  • I don't get why you need to run command.vim . Just add your mappings in after/ftplugin/python.vim.
    – r_31415
    Sep 22 at 20:34
  • Thank you, that fixed the output formatting issue. But this causes another problem. If I now what to use matplotlib.pyplot and run plt.show(), then I can no longer edit the code until I close the plot that was created. Before when using the command.vim method, I did not need to close the plot to keep editing the code.
    – alpastor
    Sep 22 at 21:11
  • 1
    I would suggest :nnoremap <buffer><leader><leader>! :w! \| !python3 % & <cr> \| :redraw!<cr>. After running your script, the plot is shown and you will be able to go back to your text file, however, if you run your script again, a new plot will be created. In my opinion, a workflow based on :make is better as you have more control over which plot will be displayed and by "recompiling" your file, the initial plot will be updated. Having said that, this is not the usual iterative workflow that is common in other applications such as jupyter notebook.
    – r_31415
    Sep 22 at 22:16
  • 1
    That's fair - always good to run the script in a fresh instance to be sure although I guess sometimes it just depends on what the task at hand is.
    – mattb
    Sep 23 at 22:24

1 Answer 1

2

When you run this:

:! python3 file.py

Vim will run python3 file.py, display the output in the internal pager as the program outputs it, and asks you to press enter to continue when the program exits.

Your mapping is very similar, but not identical as it adds & at the end of the command:

noremap <leader><leader> :w <cr> :!python3 % &<cr>

The & instructs the shell to run the program in the "background", and immediately return control to the shell. With this you get the "Press ENTER or type command to continue" first because the program returns immediately, but it keeps running in the background and still outputs text whenever it's ready, which will interfere with Vim's UI drawing.

This is not a "Vim feature" but rather a "shell feature", for example:

% sleep 2; echo 'hello'
% (sleep 2; echo 'hello') &

In the first command, the shell will wait two seconds and then outputs hello; you can't really do anything in the meanwhile. In the second command it returns control to the shell and you can continue typing new commands, and it will echo hello after two seconds, which may be in the middle of the output of another command (the ( and ) in the second command just group the two commands together.)

You rarely want to use :!... & unless you have a specific reason; simply dropping the & should fix it:

noremap <leader><leader> :w <cr> :!python3 %<cr>
2
  • I'll accept this an the answer as it does fix what my original post was asking. I also removed the command.vim stuff and placed the new noremap command into a file titled ~/.vim/after/ftplugin/python.vim. However, a new problem that appeared from this. I can no longer do a plt.show() with matplotlib.pyplot and continue working on the code while the plot is appeared. This issue did not exist with my previous set up. Again this is a completely different issue but I thought I should mention the new problem for any future readers who are interested and may have the same issue.
    – alpastor
    Sep 23 at 17:28
  • I can no longer do a plt.show() with matplotlib.pyplot and continue working on the code while the plot is appeared I don't know what plt.show() does @alpastor, but I assume it's something that keeps running? Running stuff in the background is a bit harder, because you need to take care of all the output showing up nicely somewhere, like a new window. Sep 23 at 19:58

Your Answer

alpastor is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.