読者です 読者をやめる 読者になる 読者になる

reST記法をおぼえるためにreSTプレビュー用webサーバーを作ってみた

ぼくはreST記法をおぼえていません。だからSphinxもあまり使えません。挑戦はしましたが、毎回、コンパイルを通さないと見れないようです。こんなのC言語を知らずにC++でしかもSTLガンガンなコードを書くようなもんです。でもSphinxは使いたいと思っています。

そこでrstファイルをhtmlに変換するrst2htmlというコマンドライン・ツールを使って、おぼえることにしました。これでhtmlとrstの関係が付きます。しかし、毎回htmlをテキストレベルで見るのは辛いものがあります。それで結局webブラウザでチェックします。疲れます。

このままでは「rstファイルを書く->エラーメッセージのある無しを見る(->htmlソースを見る)?(->(F5キーを押して)webブラウザでhtmlを見る)?」という作業を繰り返すことになります。おかしなhtmlが出てもブラウザが補完してしまうという問題はありますが、とりあえず「rstファイルを書く->(F5キーを押して)webブラウザで確認する」という作業に短縮できれば、rstファイルを頻繁に書き直す気力が湧いてきそうです。

それで、webサーバーを書いてみました。do_GETでrstファイルをhtmlに変換して、出力してくれるようにします。やっつけ仕事なので、python2.6.5のSimpleHTTPServer.pyをコピペしてserver.pyを作ります。diffは次のようになります。

--- SimpleHTTPServer.py	2011-07-18 02:42:53.213544902 +0900
+++ server.py	2011-07-18 02:44:12.309540962 +0900
@@ -1,3 +1,5 @@
+from doc import rst2html
+open = rst2html
 """Simple HTTP Server.
 
 This module builds on BaseHTTPServer by implementing the standard GET
@@ -89,9 +91,8 @@
             return None
         self.send_response(200)
         self.send_header("Content-type", ctype)
-        fs = os.fstat(f.fileno())
-        self.send_header("Content-Length", str(fs[6]))
-        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
+        self.send_header("Content-Length", str(len(f.getvalue())))
+        self.send_header("Last-Modified", self.date_time_string(None))
         self.end_headers()
         return f
 
@@ -206,6 +207,7 @@
         '.py': 'text/plain',
         '.c': 'text/plain',
         '.h': 'text/plain',
+        '.rst': 'text/html',
         })

インポートしているdoc.pyで定義されているrst2htmlは拡張子rstのときだけhtmlに変換し、ファイルオブジェクトもどきを生成する__builtin__.openのような関数です。

#!/usr/bin/env python2.6
from docutils.core import Publisher, publish_file, default_description
from docutils.io import NullOutput
from cStringIO import StringIO
import __builtin__
import posixpath
def rst2html(file_path, mode=None):
  base, ext = posixpath.splitext(file_path) 
  if(ext == '.rst'):
    pub = Publisher(destination_class=NullOutput)
    pub.set_components('standalone', 'restructuredtext', 'html')
    pub.process_programmatic_settings(None, None, None)
    pub.set_source(None, file_path)
    pub.publish()    
    return StringIO(unicode(pub.writer.output).encode('utf-8'))
  else:
    f = __builtin__.open(file_path, mode)
    return StringIO(f.read()) 
if __name__ == '__main__':
  f = rst2html('./doc.rst')
  print f.read()

使い方はSimpleHTTPServerと同じです。


python server.py port

[port]はポート番号で、デフォルトでは8000になっています。

[追記]
日本語が使えないことの気づいたので、utf-8にencodeすることにしました。