From akamaus at gmail.com Mon Nov 23 16:37:04 2009 From: akamaus at gmail.com (Dmitry V'yal) Date: Mon, 23 Nov 2009 19:37:04 +0300 Subject: [cl-who-devel] Generating html tree with dynamic structure Message-ID: <4B0ABA30.3000206@gmail.com> Hello anyone, I have a simple problem, but I can't find an elegant solution. Basically I have a message and two flags, the first one signals message should be rendered in tag and the second - in . So there are four possibilities. Here is the actual code: (defmethod p-render-html ((s-tree tree) (p text-piece) s) (with-html-output (s nil :prologue nil) (let ((style (style-of p)) (txt (text-of p))) (if style (if (tree-find-prop s-tree style #'bold) (htm (:strong (if (tree-find-prop s-tree style #'italic) (htm (:italic (str txt))) (str txt)))) (if (tree-find-prop s-tree style #'italic) (htm (:italic (str txt))) (str txt))) (str txt))))) I had to test for each case and it resulted in code duplication. Can it be avoided? What if I had 5 flags or so? From kengruven at gmail.com Mon Nov 23 18:49:01 2009 From: kengruven at gmail.com (Ken Harris) Date: Mon, 23 Nov 2009 10:49:01 -0800 Subject: [cl-who-devel] Generating html tree with dynamic structure In-Reply-To: <4B0ABA30.3000206@gmail.com> References: <4B0ABA30.3000206@gmail.com> Message-ID: Hi Dmitry, I had the same problem about a year ago. After looking at cl-who, my conclusion was that it's really designed for efficiently writing fixed structure with variable content, not variable structure. My first attempt was simply string concatenation on the result of multiple with-html-output-to-string calls. It worked fine, but with bigger inputs it became unusably slow due to all the consing. A second option I considered was to slap a big ol' EVAL (or MACROEXPAND? I can't remember, offhand) in there. This is a little weird, since cl-who transforms the input sexp into code to efficiently write it, but then I'm only using it once. Also, due to the weird call structure (to-macro-and-back), I recall it being somewhat hard to debug. The thing I finally settled on was writing my own function that took as input something that looked like cl-who's input, and wrote it out to a stream. It was surprisingly simple to write (I think it was 10-15 lines, but I don't have it in front of me right now), though it obviously doesn't handle every case cl-who does. It wouldn't handle htm/str/txt or prologues or inline code or whatever -- I just pass in a complete sexp, and it walks the tree and writes to a stream. In your case, you'd just need to generate a value like (:strong (:italic "text")) to pass in -- and Lisp tends to be pretty good at letting you build lists. :-) (I hooked it up to write to my web server's response stream directly, and it screamed. Well, at least compared to the old "cons a few gigabytes every request" method.) I can dig up that function tonight if it sounds useful to you. - Ken From amalawi at gmail.com Mon Nov 23 19:26:06 2009 From: amalawi at gmail.com (Ala'a (cmo-0)) Date: Mon, 23 Nov 2009 23:26:06 +0400 Subject: [cl-who-devel] Generating html tree with dynamic structure In-Reply-To: <4B0ABA30.3000206@gmail.com> References: <4B0ABA30.3000206@gmail.com> Message-ID: this is a my first shot. I do not know what is an s-tree, thus the implementation of 'text-style' (defmethod p-render-html ((s-tree tree) (p text-piece) stream) (with-html-output (stream nil :prologue nil) (let ((text (text-of p))) (if (styled-p text-piece) (styled-str text ) (str text))))) (defun styled-p (text-piece) (if (style-of text-piece) t nil)) (defun styled-str (text) (dolist (style (text-styles text)) (setf text (apply-style style text))) text) ;; or you can use recursive style ;; this is only for light testing (defun text-styles (text) (list 'italic 'bold)) ;; you may change the internals to a macro (aka defstyle ) based for example on a hastable of lambdas ;; rather than using and maintaining/updating ecase form manually (defun apply-style (style text) (with-output-to-string (out) (with-html-output (out nil :prologue nil) (ecase style ('italic (htm (:italic (str text)))) ('bold (htm (:strong (str text)))))))) Regards, Ala'a (cmo-0) On Mon, Nov 23, 2009 at 8:37 PM, Dmitry V'yal wrote: > Hello anyone, > > I have a simple problem, but I can't find an elegant solution. > > Basically I have a message and two flags, the first one signals message > should be rendered in tag and the second - in . So > there are four possibilities. > > Here is the actual code: > > (defmethod p-render-html ((s-tree tree) (p text-piece) s) > ? (with-html-output (s nil :prologue nil) > ? ? (let ((style (style-of p)) > ? ? ? ? ? (txt (text-of p))) > ? ? ? (if style > ? ? ? ? ? (if (tree-find-prop s-tree style #'bold) > ? ? ? ? ? ? ? (htm (:strong (if (tree-find-prop s-tree style #'italic) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (htm (:italic (str txt))) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (str txt)))) > ? ? ? ? ? ? ? (if (tree-find-prop s-tree style #'italic) > ? ? ? ? ? ? ? ? ? (htm (:italic (str txt))) > ? ? ? ? ? ? ? ? ? (str txt))) > ? ? ? ? ? (str txt))))) > > I had to test for each case and it resulted in code duplication. Can it > be avoided? What if I had 5 flags or so? > > _______________________________________________ > cl-who-devel site list > cl-who-devel at common-lisp.net > http://common-lisp.net/mailman/listinfo/cl-who-devel > -- It does not matter how fast your code is, if it does not work! From akamaus at gmail.com Tue Nov 24 08:47:22 2009 From: akamaus at gmail.com (Dmitry V'yal) Date: Tue, 24 Nov 2009 11:47:22 +0300 Subject: [cl-who-devel] Generating html tree with dynamic structure In-Reply-To: References: <4B0ABA30.3000206@gmail.com> Message-ID: <4B0B9D9A.9090209@gmail.com> Ken Harris wrote: > Hi Dmitry, > > I had the same problem about a year ago. After looking at cl-who, my > conclusion was that it's really designed for efficiently writing fixed > structure with variable content, not variable structure. I have the same feeling now > > My first attempt was simply string concatenation on the result of > multiple with-html-output-to-string calls. It worked fine, but with > bigger inputs it became unusably slow due to all the consing. > A second option I considered was to slap a big ol' EVAL (or > MACROEXPAND? I can't remember, offhand) in there. This is a little > weird, since cl-who transforms the input sexp into code to efficiently > write it, but then I'm only using it once. Also, due to the weird > call structure (to-macro-and-back), I recall it being somewhat hard to > debug. > > The thing I finally settled on was writing my own function that took > as input something that looked like cl-who's input, and wrote it out > to a stream. It was surprisingly simple to write (I think it was > 10-15 lines, but I don't have it in front of me right now), though it > obviously doesn't handle every case cl-who does. It wouldn't handle > htm/str/txt or prologues or inline code or whatever -- I just pass in > a complete sexp, and it walks the tree and writes to a stream. > > In your case, you'd just need to generate a value like (:strong > (:italic "text")) to pass in -- and Lisp tends to be pretty good at > letting you build lists. :-) > > (I hooked it up to write to my web server's response stream directly, > and it screamed. Well, at least compared to the old "cons a few > gigabytes every request" method.) > > I can dig up that function tonight if it sounds useful to you. Yes, please, share it. I thought about such approach and was sure someone already faced that problem and has a solution. P.S. After some search I found htmlgen library. It seems to have built in functions for generate html from s-expressions. Probably it better suited for my use case.