テンプレートエンジンの仕様

まだ変わるかもしれませんが、今のところこんな仕様です。

  • テンプレートは基本的にただのHTMLファイル
  • {HOGE}のような{}で囲まれた独自タグを使用する。これはレンダリング時に別の文字列に置換される。
  • のような最後に_のついた独自タグを使用する。これはレンダリング時にイテレータとして機能し、複数回ループされレンダリングされる。
  • の中の置換タグは{HOGE}を使用するが、外のタグとの混同を防ぐために{HOGE_}という記述方法を推奨する。
  • 今のところ条件分岐の記述はできない。条件分岐はPHP上で行なう。
  • 今のところテンプレート内にPHPは記述できない(HTMLとして解釈される?未検証)。

このテンプレートエンジンの実装はPHPで数十行なんですが、汎用的に使うには条件分岐がないのがネックになるかもしれません。現在ブログエンジンを作っている限りでは今のところ支障はないようです。

ブログエンジン作ってます

アウトラインプロセッサ「AOISO」は、この半年ぜんぜん進んでいません。

何も書かないのもあれなので、ちょっと話題がそれますが、仕事で作っているブログエンジンのことでも書きます。

ブログエンジンはもういくらでもありますね。MTとWPだけでもお腹いっぱいだし。しかし自分で作る意義というのもあるのです。きっと。

僕が作ってるブログエンジンはこんな感じです。

想定しているのはブログというよりは、HTMLで書かれたサイトにフォームから更新できるような仕組みを埋め込むためのCMSのサブセットのようなものです。企業サイトなんかではよくMTで組まれていますがあれをMTなしで実現するためのものです。

MTを使ってもいいんですが、あれはライセンスの問題がある(OSS版は中途半端)だし、小規模サイトにはちょっと大袈裟すぎます。WPは複数ブログに対応していないので1サイトに複数インストールしないといけなくて不便です。そういうわけで軽量でシンプルなブログエンジンを自作することにしたのです。

言語はPython・・・にしたいところなんですが、日本のレンタルサーバの実情を考えてPHPにしました。ぶっちゃけPHPはよく知らないので試行錯誤しながらやっています。「軽量」というコンセプトなのでPearなどの外部ライブラリは使用しない方針です。PDOすら使っていません(これはMySQL対応の時には使うことになるかもしれません)。テンプレートエンジンも自作しています。

完成したら会社のサイトでオープンソースで公開しようかなと思っています。

Qtがすごいことに

で、ちょっと話がずれますが、最近Qtのことを完全無視していたので久し振りにチェックしてみたら、Qt Creatorというのが現れてすごいことになってますね。C++限定ですがRADと言ってもいいくらいのGUIビルダー連動のIDEです。Qtそのものも3までしか知らないのでその進化っぷりにも驚きました。Webkit対応とか。まああれは元々KDE由来なんで逆輸入みたいなもんですが。

そういうわけでQtもやってみたくなりました。とは言え、AOISOに関してはGTKからwxに変えた経緯もあるしそれでまたまたQtに変えてたらいつまでたっても完成しないのでwxのままいきますが。

Qt Creator、Pythonサポートしないかなぁ。

今日もDDLを

テーブル構造をちょっと弄って、サンプルのINSERT文も更新(rev.54)。行数としては数行だけど、頭の中の整理ができてきたので気持的にはだいぶ進みました。

以前からアウトラインプロセッサにありがちな「ノード=タイトル+本文」という構造はおかしいのではないかと思っていたのですが、じゃあ具体的にどうするのかというあたりのアイデアが漠然としていました。この辺にちょこっと書いてますが、ノードよりも小さい単位が必要じゃないかということで内部的にチップと呼んでる最小単位があって、それをグループ化したものがノード、という感じを目指してます。DDLはそれで進めているんですが、クラスは「ノード=タイトル+本文」のままなのでこれからここを変えていくことになるでしょう。

空のDBかどうかの判定

久しぶりに更新。

pysqliteで動的にDBを作成したりする場合、新規につくられたものか既存のものかをどうやって判定しようかと考えて、以前は以下のコードにしていました。

self.con = sqlite.connect(path)
cur = self.con.cursor()
cur.execute("SELECT count(*) FROM SQLITE_MASTER")
cnt = cur.fetchone()[0]
if cnt==0:
    self.__initTables()

以前はこれで通ってたと思うのですが、今日やってみたらセグメンテーション違反で落ちる。pythonの問題ではなく、sqliteコマンドでやっても同様に落ちる。何も落ちなくてもとは思うが、DDLが全く定義されていないDBで"SELECT count(*) FROM SQLITE_MASTER"は(仕様かバクかはともかく)NGということなのだろう。しかし"SELECT * FROM SQLITE_MASTER"なら通るので以下のようにしてみました。

self.con = sqlite.connect(path)
cur = self.con.cursor()
cur.execute("SELECT * FROM SQLITE_MASTER")
try:
   cnt = cur.fetchone()[0]
except:
   self.__initTables()

これでうまくいきました。こういうのってほんとは定石があるのかな?

ほか、ちょこちょこと弄ってコミット(rev.52、53)。

wxPythonとXRCとAUIの関係

ドッカブルウインドウってwxでできるんだろうか? と調べていて、wxAUIほにゃららというやつを使えばできることを知りました。早速wxPythonでやってみる。

test1.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import wx
import wx.aui

class MyFrame(wx.Frame):
    def __init__(self, title, pos, size):
        wx.Frame.__init__(self, None, -1, title, pos, size)
        self.auimgr = wx.aui.AuiManager(self)
        txtctrl1 = wx.TextCtrl(self, -1, "Hello",wx.DefaultPosition, wx.Size(200,200),wx.TE_MULTILINE)
        txtctrl2 = wx.TextCtrl(self, -1, "World",wx.DefaultPosition, wx.Size(200,200),wx.TE_MULTILINE)
        self.auimgr.AddPane(txtctrl1,wx.LEFT, "hello")
        self.auimgr.AddPane(txtctrl2,wx.BOTTOM, "world")
        self.auimgr.Update()

    def OnQuit(self, event):
        self.Cose()

if __name__ == '__main__':
    app = wx.App()
    frame = MyFrame("test",wx.DefaultPosition,wx.Size(300,300))
    frame.Show()
    app.MainLoop()

案外簡単。

ところが、aoisoではGUI編集をXRCedでやってますので、上記のようなGUI直書きではありません。調べてみるとXRCedにはAUI関係のコントロールは用意されていない様子。ということはカスタムウィジェットのようにunknownを使ってやるのか・・・と思いきや、unknownはコンテナには使えないらしい。じゃぁどうするんだ、ということでいろいろ試してみたら何のことはない。以下のようにできました。

test2.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import wx
import wx.xrc as xrc
import wx.aui

class MyApp(wx.App):
    def OnInit(self):
        self.res = xrc.XmlResource("test2.xrc")
        self.frame = MyFrame(self)
        self.frame.Show()
        return True

class MyFrame(wx.Frame):
    def __init__(self, app):
        pre = wx.PreFrame()
        app.res.LoadOnFrame(pre, None, "ID_FRAME_1")
        self.PostCreate(pre)
        self.auimgr = wx.aui.AuiManager(self)
        self.text1 = xrc.XRCCTRL(self,"ID_TEXT_1")
        self.text2 = xrc.XRCCTRL(self,"ID_TEXT_2")
        self.auimgr.AddPane(self.text1,wx.LEFT,"hello")
        self.auimgr.AddPane(self.text2,wx.BOTTOM,"world")
        self.auimgr.Update()

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()

test2.xrc

<?xml version="1.0" ?>
<resource>
  <object class="wxFrame" name="ID_FRAME_1">
    <object class="wxTextCtrl" name="ID_TEXT_1">
      <style>wxTE_MULTILINE</style>
    </object>
    <object class="wxTextCtrl" name="ID_TEXT_2">
      <style>wxTE_MULTILINE</style>
    </object>
  </object>
</resource>

要するに、XRC上はFrameに直置きして、実行時にaddPaneすれば良い、と。

これからの予定

半年ぶりの更新になります。

・・・うーんと、何やってたんだっけ? と、自分のブログを読み返しながら思い出しました。

Gtkからwxに変更したのは覚えてる。で、wxで行けそうってことになったので脱線してバックエンドをSQLにするテストをやってる最中に、突然WebアプリにしたくなってPylonsをイジってたんだな。Pylonsチュートリアルやってる途中か。

Webアプリはしばらくお休みします。仕事でDjangoを使い始めたので復活するならDjangoかもしれません。

wxの方をちょっと進めたいな。SQL書いたところで止まってるので、GUIから操作できるようにしたい。