Skip to content

Instantly share code, notes, and snippets.

@kamykaze
Last active December 30, 2015 10:29
Show Gist options
  • Save kamykaze/7816160 to your computer and use it in GitHub Desktop.
Save kamykaze/7816160 to your computer and use it in GitHub Desktop.
Text Filter server for TextAid. To use it, put these files into a directory, then run python ~/some/path/to/pytextfilter/pytextfilter.py
#!/usr/bin/env python
# vim:ft=python
config = {
"server": {
# The port that the edit server listens at
"port": 8888
},
"environment": {
# An array stores the parameters that needed to launch your text editor.
# "%s" will be replaced by the filename to be edited.
#"editor": [ "vim", "%s"],
"editor": [ "mvim", "-f", "%s"],
# Base directory to store the temporary files.
"tmpdir": "/tmp"
}
}
#!/usr/bin/env python
# vim:ft=python
def GetFilename(params):
if params.has_key("file"):
return params["file"]
if params.has_key("id"):
id = params["id"]
if params.has_key("url"):
url = params["url"]
if url.find("mail") != -1:
return "content.eml"
if url.find("template") != -1:
return "file.html"
if url.find("importrequest") != -1 and id.find('_log') != -1:
return "file.py"
if url.find("sitestyle") != -1 and id.find('stylesheet') != -1:
return "file.css"
if url.find("sitestyle") != -1 and id.find('script') != -1:
return "file.js"
if params.has_key("ext"):
return "file." + params["ext"]
return "file.html"
#!/bin/sh
#
# This shell script passes all its arguments to the binary inside the
# MacVim.app application bundle. If you make links to this script as view,
# gvim, etc., then it will peek at the name used to call it and set options
# appropriately.
#
# Based on a script by Wout Mertens and suggestions from Laurent Bihanic. This
# version is the fault of Benji Fisher, 16 May 2005 (with modifications by Nico
# Weber and Bjorn Winckler, Aug 13 2007).
# First, check "All the Usual Suspects" for the location of the Vim.app bundle.
# You can short-circuit this by setting the VIM_APP_DIR environment variable
# or by un-commenting and editing the following line:
# VIM_APP_DIR=/Applications
if [ -z "$VIM_APP_DIR" ]
then
myDir="`dirname "$0"`"
myAppDir="$myDir/../Applications"
for i in ~/Applications ~/Applications/vim $myDir $myDir/vim $myAppDir $myAppDir/vim /Applications /Applications/vim /Applications/Utilities /Applications/Utilities/vim; do
if [ -x "$i/MacVim.app" ]; then
VIM_APP_DIR="$i"
break
fi
done
fi
if [ -z "$VIM_APP_DIR" ]
then
echo "Sorry, cannot find MacVim.app. Try setting the VIM_APP_DIR environment variable to the directory containing MacVim.app."
exit 1
fi
binary="$VIM_APP_DIR/MacVim.app/Contents/MacOS/Vim"
# Next, peek at the name used to invoke this script, and set options
# accordingly.
name="`basename "$0"`"
gui=
opts=
# GUI mode, implies forking
case "$name" in m*|g*|rm*|rg*) gui=true ;; esac
# Restricted mode
case "$name" in r*) opts="$opts -Z";; esac
# vimdiff, view, and ex mode
case "$name" in
*vimdiff)
opts="$opts -dO"
;;
*view)
opts="$opts -R"
;;
*ex)
opts="$opts -e"
;;
esac
# Last step: fire up vim.
# The program should fork by default when started in GUI mode, but it does
# not; we work around this when this script is invoked as "gvim" or "rgview"
# etc., but not when it is invoked as "vim -g".
if [ "$gui" ]; then
# Note: this isn't perfect, because any error output goes to the
# terminal instead of the console log.
# But if you use open instead, you will need to fully qualify the
# path names for any filenames you specify, which is hard.
exec "$binary" -g $opts ${1:+"$@"}
else
exec "$binary" $opts ${1:+"$@"}
fi
#!/usr/bin/env python
#
# Copyright 2010 Edward Leap Fox (edyfox@gmail.com).
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import BaseHTTPServer
import SocketServer
import cgi
import os
import shutil
import subprocess
import tempfile
import filename_filter
from config import config
class EditServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""An HTTP server that handles text filter requests"""
def do_GET(self):
try:
if self.path.endswith("/favicon.ico"):
self.send_response(404)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write("File not found.")
else:
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(
"Server is up and running. " +
"To use it, issue a POST request with the file to edit " +
"as the content body.")
except:
# Swallow the exceptions.
pass
def __cleanup(self, tempdir):
try:
shutil.rmtree(tempdir)
except:
pass
def __error(self):
try:
content = "Invalid request"
self.send_response(500)
self.send_header("Content-length", len(content))
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(content)
except:
pass
def do_POST(self):
# Create the temp directory.
try:
tempdir = tempfile.mkdtemp(
prefix = "edit-server-",
dir = config["environment"]["tmpdir"])
except:
self.__error()
return
params = {}
# Check x-id and x-url to keep compatible with emacs_chrome.
id = self.headers.getheader("x-id")
if id != None:
params["id"] = id
url = self.headers.getheader("x-url")
if url != None:
params["url"] = url
# Extract the parameters from the query string.
query = self.path.split("?", 1)
if len(query) > 1:
qs = cgi.parse_qs(query[1])
for i in qs:
params[i] = qs[i][-1]
print "Filtering filename: ", params
# Get the temp filename.
filename = filename_filter.GetFilename(params)
filename = filename.replace("/", "").replace("\\", "").replace(os.sep, "")
tempname = tempdir + os.sep + filename
# Write the temp file.
try:
temp = file(tempname, "w")
temp.write(
self.rfile.read(int(self.headers.getheader("content-length"))))
temp.close()
except:
temp.close()
self.__cleanup(tempdir)
self.__error()
return
# Launch the text editor.
params = []
for i in config["environment"]["editor"]:
if i == "%s":
params.append(tempname)
else:
params.append(i)
try:
print "calling ", params
subprocess.call(params)
except:
self.__cleanup(tempdir)
self.__error()
return
# Read the edited file.
try:
temp = file(tempname, "r")
content = temp.read()
temp.close()
except:
self.__cleanup(tempdir)
self.__error()
return
# Write the response.
try:
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.send_header("Content-length", len(content))
self.end_headers()
self.wfile.write(content)
except :
self.__cleanup(tempdir)
self.__error()
return
self.__cleanup(tempdir)
class ThreadedHTTPServer(
SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
"""Handle requests in a separate thread."""
def main():
try:
server = ThreadedHTTPServer(
("127.0.0.1", config["server"]["port"]),
EditServerHandler)
print "Text filter server started..."
server.serve_forever()
except KeyboardInterrupt:
print "Shutting down text filter server..."
server.socket.close()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment