Vim Tips Wiki
m (Execute python from within current file moved to Execute Python from within current file: Page moved by JohnBot to improve title)
(Change to TipImported template + severe manual clean)
Line 1: Line 1:
 
{{review}}
 
{{review}}
  +
{{TipImported
{{Tip
 
 
|id=609
 
|id=609
  +
|previous=608
|title=Execute python from within current file
 
  +
|next=610
|created=November 28, 2003 15:22
+
|created=November 28, 2003
 
|complexity=intermediate
 
|complexity=intermediate
 
|author=Steve Halpin
 
|author=Steve Halpin
 
|version=6.0
 
|version=6.0
 
|rating=14/8
 
|rating=14/8
 
}}
|text=
 
Inspired by [[VimTip608]].
+
Inspired by [[VimTip608]].
   
To execute python from a range within the current text file and write the output to that file (replacing the python), add the snippet below to .vimrc (or other suitable *rc file).
+
To execute Python from a range within the current text file and write the output to that file (replacing the Python), add the snippet below to .vimrc (or other suitable *rc file).
   
Requires a 'proper' python setup so that the imported modules can be found.
+
Requires a 'proper' Python setup so that the imported modules can be found.
   
I find it a handy intermediate step between using the python interpreter on command line and running a complete script. Can be used for easy buffer manipulation, filtering input, preprocessing text and templating-like tasks.
+
I find it a handy intermediate step between using the Python interpreter on command line and running a complete script. Can be used for easy buffer manipulation, filtering input, preprocessing text and templating-like tasks.
   
 
<pre>
 
<pre>
 
python &lt;&lt; EOL
def PyExecReplace(line1,line2):
 
 
import vim, StringIO,sys
r = vim.current.buffer.range(int(line1),int(line2))
 
 
def PyExecReplace(line1,line2):
redirected = cStringIO.StringIO()
 
 
r = vim.current.buffer.range(int(line1),int(line2))
sys.stdout = redirected
 
 
redirected = StringIO.StringIO()
exec('\n'.join(r[:]) + '\n')
 
sys.stdout = sys.__stdout__
+
sys.stdout = redirected
 
exec('\n'.join(r[:]) + '\n')
output = redirected.getvalue().split('\n')
 
 
sys.stdout = sys.__stdout__
r[:] = output[:-1] &#35; the -1 is to remove the final blank line
 
redirected.close()
+
output = redirected.getvalue().split('\n')
 
r[:] = output[:-1] # the -1 is to remove the final blank line
EOL
 
 
redirected.close()
command -range Pyer python PyExecReplace(&lt;f-line1&gt;,&lt;f-line2&gt;)
 
 
EOL
 
command -range Pyer python PyExecReplace(&lt;f-line1&gt;,&lt;f-line2&gt;)
 
</pre>
 
</pre>
   
==Some examples of use:==
+
==Some examples of use==
   
 
===Simple===
 
===Simple===
  +
<pre>
print 2 + 2
+
print 2 + 2
  +
</pre>
   
  +
<pre>
:Pyer
+
:Pyer
  +
</pre>
   
If cursor is on the 'print' line, replaces line with 4
+
With the cursor on the 'print' line, that line is replaced with 4.
   
===Filter ===
+
===Filter===
 
<pre>
 
<pre>
for line in vim.current.buffer:
+
for line in vim.current.buffer:
if line[0] != '\t':
+
if line[0] != '\t':
print line
+
print line
 
</pre>
 
</pre>
:%Pyer
 
   
Filters out lines beginning with a tab in the current buffer
 
 
===Inserting time ===
 
 
<pre>
 
<pre>
 
:%Pyer
import time
 
print time.ctime()
 
 
</pre>
 
</pre>
:%Pyer
 
   
 
Filters out lines beginning with a tab in the current buffer.
Replaces line with date/time
 
   
 
===Inserting time===
===Getting web content without tags ===
 
 
<pre>
 
<pre>
import urllib2,htmllib,formatter
+
import time
 
print time.ctime()
h = htmllib.HTMLParser(formatter.AbstractFormatter(formatter.DumbWriter()))
 
h.feed(urllib2.urlopen('http://www.somesite.com').read())
 
 
</pre>
 
</pre>
:%Pyer
 
   
  +
<pre>
Inserts the web page text, but not the html tags, for a given site
 
 
:%Pyer
  +
</pre>
   
 
Replaces line with date/time.
   
 
===Getting web content without tags===
  +
<pre>
  +
import urllib2,htmllib,formatter
 
h = htmllib.HTMLParser(formatter.AbstractFormatter(formatter.DumbWriter()))
 
h.feed(urllib2.urlopen('http://www.somesite.com').read())
  +
</pre>
   
I also use a slightly modified version that appends the output, leaving the python intact.
 
}}
 
 
== Comments ==
 
The Tipp is cool, but it does not wor the way you posted it. On my fedora core 1 I had to change it into:
 
 
<pre>
 
<pre>
 
:%Pyer
python &lt;&lt; EOL
 
import vim, StringIO,sys
 
def PyExecReplace(line1,line2):
 
r = vim.current.buffer.range(int(line1),int(line2))
 
redirected = StringIO.StringIO()
 
sys.stdout = redirected
 
exec('\n'.join(r[:]) + '\n')
 
sys.stdout = sys.__stdout__
 
output = redirected.getvalue().split('\n')
 
r[:] = output[:-1] &#35; the -1 is to remove the final blank line
 
redirected.close()
 
EOL
 
command -range Pyer python PyExecReplace(&lt;f-line1&gt;,&lt;f-line2&gt;)
 
 
</pre>
 
</pre>
André
 
   
 
Inserts the web page text, but not the html tags, for a given site.
fs111--AT--linuxmail.org
 
, December 1, 2003 5:23
 
----
 
My apologies - cut &amp; paste error, thanks for the correction.
 
   
 
==Comments==
Now what was that vim command that takes what you actually copied to the clipboard and replaces it with what you meant to copy .... :)
 
 
I use the following:
 
Steve Halpin
 
, December 10, 2003 10:06
 
----
 
Hello
 
 
can somebody tell how to change the scrip so that it:
 
# writes the python output to a new window and not replaceing the source
 
# evaluates the hole buffer and not a selection
 
 
thank you
 
 
Michael
 
 
MIBSchmidt--AT--gmx.de
 
, December 12, 2003 5:00
 
----
 
<blockquote>&gt;can somebody tell how to change the scrip so that it: <br/>
 
&gt;1. writes the python output to a new window and not replaceing the source </blockquote>
 
::You can just enter 'u' in command mode to 'undo' the output and get your source back. However, as you suggest sending the output to (for instance, the Preview window) would probably be better.
 
 
<blockquote>&gt; 2. evaluates the hole buffer and not a selection </blockquote>
 
::':%Pyer' does this. '%' represents the whole buffer in vim.
 
 
 
'''Anonymous'''
 
, February 10, 2004 19:17
 
----
 
I use the following:
 
   
 
<pre>
 
<pre>
"in ~/.vimrc:
+
"in ~/.vimrc:
"python extensions
+
"python extensions
py from vim import buffers, windows, command, current, error
+
py from vim import buffers, windows, command, current, error
py import vim, sys
+
py import vim, sys
py from vimpy import *
+
py from vimpy import *
   
command! PyExecBuffer py exec('\n'.join(current.buffer))
+
command! PyExecBuffer py exec('\n'.join(current.buffer))
   
map &lt;F5&gt; :PyExecBuffer&lt;CR&gt;
+
map &lt;F5&gt; :PyExecBuffer&lt;CR&gt;
imap &lt;F5&gt; &lt;Esc&gt;&lt;F5&gt;&lt;CR&gt;a
+
imap &lt;F5&gt; &lt;Esc&gt;&lt;F5&gt;&lt;CR&gt;a
 
</pre>
 
</pre>
   
 
vimpy.py
 
vimpy.py
 
<pre>
 
<pre>
import sys, vim
+
import sys, vim
class Buffer:
+
class Buffer:
def __init__(self,buf):
+
def __init__(self,buf):
self.buf=buf
+
self.buf=buf
def write(self,s):
+
def write(self,s):
ll=s.split('\n')
+
ll=s.split('\n')
self.buf[-1]+=ll[0]
+
self.buf[-1]+=ll[0]
for l in ll[1:]:
+
for l in ll[1:]:
self.buf.append(l)
+
self.buf.append(l)
def clear(self):
+
def clear(self):
del self.buf[:]
+
del self.buf[:]
   
def redirect(buf=None):
+
def redirect(buf=None):
buf = buf or vim.current.window.buffer
+
buf = buf or vim.current.window.buffer
try:
+
try:
sys._stdout
+
sys._stdout
except:
+
except:
sys._stdout=sys.stdout
+
sys._stdout=sys.stdout
sys.stdout = Buffer(buf)
+
sys.stdout = Buffer(buf)
 
</pre>
 
</pre>
   
Then i start Vim, create new window (&lt;C-W&gt; N), and do
+
Then I start Vim, create new window (&lt;C-W&gt; N), and do
:py redirect(current.window.buffer)
+
:py redirect(current.window.buffer)
on a window i want to receive all printed data.
+
on a window I want to receive all printed data.
   
Then &lt;F5&gt; in any buffer exec's the buffer contents in python, output goes to the window selected.
+
Then &lt;F5&gt; in any buffer executes the buffer contents in Python, output goes to the window selected.
   
To redirect output back just do sys.stdout = sys._stdout
+
To redirect output back just do <tt>sys.stdout = sys._stdout</tt>
   
 
tws5--AT--mail.ru
 
, April 29, 2004 5:01
 
 
----
 
----
can any one tell me how can I use a python bot online.
 
 
asadhasan--AT--pakistani.com
 
, May 29, 2004 12:03
 
----
 
<!-- parsed by vimtips.py in 0.556592 seconds-->
 
 
 
[[Category:Python]]
 
[[Category:Python]]

Revision as of 09:40, 9 November 2007

Tip 609 Printable Monobook Previous Next

created November 28, 2003 · complexity intermediate · author Steve Halpin · version 6.0


Inspired by VimTip608.

To execute Python from a range within the current text file and write the output to that file (replacing the Python), add the snippet below to .vimrc (or other suitable *rc file).

Requires a 'proper' Python setup so that the imported modules can be found.

I find it a handy intermediate step between using the Python interpreter on command line and running a complete script. Can be used for easy buffer manipulation, filtering input, preprocessing text and templating-like tasks.

python << EOL
import vim, StringIO,sys
def PyExecReplace(line1,line2):
  r = vim.current.buffer.range(int(line1),int(line2))
  redirected = StringIO.StringIO()
  sys.stdout = redirected
  exec('\n'.join(r[:]) + '\n')
  sys.stdout = sys.__stdout__
  output = redirected.getvalue().split('\n')
  r[:] = output[:-1] # the -1 is to remove the final blank line
  redirected.close()
EOL
command -range Pyer python PyExecReplace(<f-line1>,<f-line2>)

Some examples of use

Simple

print 2 + 2
:Pyer

With the cursor on the 'print' line, that line is replaced with 4.

Filter

for line in vim.current.buffer:
 if line[0] != '\t':
  print line
:%Pyer

Filters out lines beginning with a tab in the current buffer.

Inserting time

import time
print time.ctime()
:%Pyer

Replaces line with date/time.

Getting web content without tags

import urllib2,htmllib,formatter
h = htmllib.HTMLParser(formatter.AbstractFormatter(formatter.DumbWriter()))
h.feed(urllib2.urlopen('http://www.somesite.com').read())
:%Pyer

Inserts the web page text, but not the html tags, for a given site.

Comments

I use the following:

"in ~/.vimrc:
"python extensions
py from vim import buffers, windows, command, current, error
py import vim, sys
py from vimpy import *

command! PyExecBuffer py exec('\n'.join(current.buffer))

map <F5> :PyExecBuffer<CR>
imap <F5> <Esc><F5><CR>a

vimpy.py

import sys, vim
class Buffer:
    def __init__(self,buf):
        self.buf=buf
    def write(self,s):
        ll=s.split('\n')
        self.buf[-1]+=ll[0]
        for l in ll[1:]:
            self.buf.append(l)
    def clear(self):
        del self.buf[:]

def redirect(buf=None):
    buf = buf or vim.current.window.buffer
    try:
        sys._stdout
    except:
        sys._stdout=sys.stdout
    sys.stdout = Buffer(buf)

Then I start Vim, create new window (<C-W> N), and do

:py redirect(current.window.buffer)

on a window I want to receive all printed data.

Then <F5> in any buffer executes the buffer contents in Python, output goes to the window selected.

To redirect output back just do sys.stdout = sys._stdout