Let's write β

プログラミング中にできたことか、思ったこととか

Lispでテケトーにhtmlのレイアウトシステムなど

railsのレイアウトってうらやましいなぁとおもっていたので、もうちょっと親の指定に関数をつかえるようにするなどの強化はしたいですが
とちゅう経過ということでここはひとつ

(defclass layout ()
  ((parent-layout :initform nil
		  :initarg :parent
		  :accessor parent)
   (layout-func   :initform (error "You must specitic layout function")
		  :initarg  :layout
		  :accessor layout)))

(defmacro render (contents)
  `(markup:raw ,contents))
(defmacro deflayout (name parent place-holders &body body)
  `(setf ,name
	 (make-instance 'layout
			:parent ,parent
			:layout (lambda ,place-holders
				  ,(if (null parent)
				       `(markup:markup ,@body)
				       `(with-layout ,parent
					  (markup:markup ,@body)))))))
(defmacro with-layout (layout-name &rest args)
  `(funcall (layout ,layout-name) ,@args))

ええっと使いがってはこんなものです

(deflayout app-main nil (main-contents)
  (:html
   (:header
    (:title "App-main"))
   (:body
    (render main-contents)
    (:hr)
    "Footer")))

(with-layout app-main "Hoge")
=>

"<html><header><title>App-main</title></header><body>Hoge<hr />Footer</body></html>"

(deflayout in-header app-main (str)
  (:h1 str))

(with-layout in-header "Fuga")
=>
"<html><header><title>App-main</title></header><body><h1>Fuga</h1><hr />Footer</body></html>"

とまぁちゃんと親のやつも読んでから表示されている事がわかります。