# Call a text-editor from within a Python script to get user input

## Motivation

I'd like to know how integrate the use of text editors (e.g. emacs, vim, etc.) into command-line Python programs.

## Features

I'd like to be able to do the following:

• Call a text editor from within a program in order to edit a file or buffer

• Regain control after the text editor exits

• Use temporary files, i.e. don't leave anything lying around after the program exits

• Prepopulate the file or buffer with data

• Get the edited text back for use in the program

## Implementation

I wrote a small module named callvim.py (betraying my preferred choice of text editor) which creates a temporary file, populates it with some text, opens it with a text editor (defaults to vim), and prints the modified text:

#!/usr/bin/env python
# -*- encoding: ascii -*-
"""callvim.py

Demonstrates calling a text-editor (e.g. Vim) from within a Python script,
including passing input to the editor and reading output from the editor.
"""

import tempfile
import os
from subprocess import call

# Get the text editor from the shell, otherwise default to Vim
EDITOR = os.environ.get('EDITOR','vim')

# Set initial input with which to populate the buffer
initial_message = "Hello world!"

# Open a temporary file to communicate through (tempfile should avoid any filename conflicts)
#
# NOTE: Don't autodelete the file on close!
#       We want to reopen the file incase the editor uses a swap-file.
#
with tempfile.NamedTemporaryFile(suffix=".tmp", delete=False) as tf:

# Write the initial content to the file I/O buffer
tf.write(initial_message)

# Flush the I/O buffer to make sure the data is written to the file
tf.flush()

# Open the file with the text editor
call([EDITOR, tf.name])

# Reopen the file to read the edited data
with open(tf.name, 'r') as tf:

# Read the file data into a variable

# Output the data
print(edited_message)


If I read it correctly, your edited_message would also contain your initial_message, is this expected?

I think this could be fixed by wrapping your input message this way in the file :

<Input message>

Input above this line will be ignored
###########################

<end of file>


You could then do :

edited_message = tf.read()
start_input_index = edited_message.find("###########################")

# Use the +2 to account for the \n
edited_message = edited_message[start_input_index + 2 :]


Maybe this exact code wouldn't work, I didn't test it, but the main idea is there, it would make more sense to your code.