Python raw_input() replacement that uses a configurable text editor
<p>I'm trying to implement a replacement for raw_input() that would use a configurable text editor like vim as the interface to to the user.</p>

<p>The ideal workflow would be like this:</p>

<ol>
<li>Your python script is running, and makes a call to my_raw_input().</li>
<li>Vim (or emacs, or gedit, or any other text editor) opens w/ a blank document</li>
<li>You type some text into the document, then save and exit</li>
<li>The python script resumes running, with the contents of the file as the return value of my_raw_input().</li>
</ol>

<p>If you're familiar with git, this is the experience when using <code>git commit</code>, where the editor is configured via <a href="http://git-scm.com/book/en/Customizing-Git-Git-Configuration" rel="nofollow">core.editor</a>. Other utilities like <code>crontab -e</code> also do this.</p>

<p>Ultimately, I would like this my_raw_input() function to also take an optional string w/ the default input contents, which the user could then edit.</p>

<h1>Research so far</h1>

<ul>
<li><a href="http://docs.python.org/2/library/os.html#os.execl" rel="nofollow">os.exec</a> replaces the current process with the editor command, but does not return. Ie, your python script exits when vim starts.</li>
<li><a href="http://docs.python.org/2/library/subprocess.html" rel="nofollow">popen</a> does not start the child process interactively, there is no user interface displayed.</li>
<li>vim has a <code>-</code> command-line parameter to read from stdin, but nothing to write to stdout with <code>:w</code>.</li>
<li>I took a look at the <a href="https://github.com/git/git/blob/master/run-command.c" rel="nofollow">code for git</a>, which I can't follow at all. </li>
</ul>

<p>Is this possible?</p>

<h1>Edit</h1>

<p>Good answers so far. I also found the <a href="http://selenic.com/repo/hg-stable/file/2770d03ae49f/mercurial/ui.py" rel="nofollow">mecurial code</a> that's doing the same thing. I also came up with an example that works from looking at the <a href="http://www.opensource.apple.com/source/cron/cron-35/crontab/crontab.c" rel="nofollow">crontab code</a>, but it looks like it's needlessly complicated compared to some of the responses.</p>

<pre><code>#!/usr/bin/python
import os
import tempfile


def raw_input_editor(default=None, editor=None):
    ''' like the built-in raw_input(), except that it uses a visual
    text editor for ease of editing. Unline raw_input() it can also
    take a default value. '''

    editor = editor or get_editor()

    with tempfile.NamedTemporaryFile(mode='r+') as tmpfile:

        if default:
            tmpfile.write(default)
            tmpfile.flush()

        child_pid = os.fork()
        is_child = child_pid == 0

        if is_child:
            os.execvp(editor, [editor, tmpfile.name])
        else:
            os.waitpid(child_pid, 0)
            tmpfile.seek(0)
            return tmpfile.read().strip()


def get_editor():
    return (os.environ.get('VISUAL')
        or os.environ.get('EDITOR')
        or 'vi')


if __name__ == "__main__":
    print raw_input_editor('this is a test')
</code></pre>
