Fellow Lispers:
I had some marketing letters to prepare, and wasn't real
happy with the lack of openness of the Windows and PC-based
mail merge facilities (plus the fact that I only have a
Solaris box and a Linux box!). I pretty much want to keep
my contacts in a simple SQL database or flat files, and
I want the highest degree of flexibility for creating form
letters and so forth out of them.
I also have other varied needs to generate finely controlled printed
outputs.
HTML is great for web publishing and web applications, but
it is still not really to the point of supporting finely
controlled printed output (and maybe never will be, since
that was never its original intent).
So, I decided to go ahead and develop a set of Lisp macros
and functions for generating LaTeX output, in the spirit of
the nice CL-HTTP macros for HTML output.
To make things additionally comfortable for myself, I also
decided to go ahead and develop a macro for declarative specification of
CLOS objects and methods, which looks
very similar to the Defpart macro I am used to using in
ICAD. I want my office-automation tools to work in both
an ICAD and non-ICAD Lisp, so I put together a very small
subset of a defpart-compatible macro, since I am so used
to working in that declarative mode.
Attached is an example of a standard-form-letter
``defpart'' for your preliminary perusal.
The complete source for the LaTeX synthesis (beginning
with just a very small set limited to the ``letter''
documentclass), and other supporting utilities will soon
be GPL'ed and available via anonymous ftp from www.genworks.org, if any
interest manifests itself.
(It's not there now, and documenting and packaging will
probably not happen until after the Lisp conference next week, unless I
get some specific requests for it sooner
than that).
I just wanted to ask this group a few questions:
1) Has something like this already been done? Am I wasting
my time?
2) Would anyone be so kind as to look through the code I have
so far and comment on it? Does it look like the
beginnings of anything remotely useful?
4) Any other specific or general comments welcome.
Thanks!
-djc
============================================
(in-package :drl-user)
(defpart standard-form-letter
(base-web-inspectable-object)
:optional-inputs
(
:body-filename
"~/office/marketing/autofact-body-1.txt"
:data-filename
"~/office/marketing/autofact-leads.lisp"
:name "David J. Cooper Jr."
:signature
'("David J. Cooper Jr."
"President, Genworks International")
:address '("Genworks International"
"5777 West Maple, Suite 130"
"West Bloomfield, MI 48125")
:point-size 11
:paper-size :usletter
:make-labels? t)
:attributes
(
:recipient-data
(with-open-file (instream (the :data-filename))
(read instream))
:body-string
(with-open-file (instream (the :body-filename))
(read-multi-line-string-from-stream instream)))
:parts
((:letters :type 'standard-letter
:quantify (:series
(length
(rest (the :recipient-data))))
:data (rest (the :recipient-data))
:body-string (the :body-string)))
:methods
((:print-to-stream
(&key (stream t))
(latex2e:document-class
:letter
:point-size (the :point-size)
:paper-size (the :paper-size)
:name (the :name)
:address (the :address)
:signature (the :signature)
:make-labels? (the :make-labels?)
:stream stream)
(latex2e:with-document (:stream stream)
(dotimes (n (array-dimension (the :letters) 0))
(the (:letters n)
(:print-to-stream :stream stream)))))))
(defpart standard-letter (base-web-inspectable-object)
:inputs
(:data
:body-string)
:attributes
(:my-data
(nth (the :index) (the :data)))
:uncached-attributes
(
:last-name
(first (the :my-data))
:first-name (second (the :my-data))
:title (third (the :my-data))
:company-name (fourth (the :my-data))
:address (fifth (the :my-data))
:city (sixth (the :my-data))
:state (seventh (the :my-data))
:zip (eighth (the :my-data))
:phone (ninth (the :my-data))
:fax (tenth (the :my-data))
:salutation (nth 11 (the :my-data))
:opening (format nil "Dear ~a ~a:"
(the :salutation)
(the :last-name))
:recipient-field (list (concatenate 'string
(the :first-name)
" "
(the :last-name))
(the :title)
(the :company-name)
(the :address)
(concatenate 'string
(the :city) ", "
(the :state) " "
(the :zip))))
:methods
((:print-to-stream
(&key (stream t))
(latex2e:print-letter :recipient (the :recipient-field)
:opening (the :opening)
:closing "Yours Truly,"
:body (the :body-string)
:stream stream))))
===================================================
Sample of Generated LaTeX:
==============================
\documentclass[letterpaper,10pt]{letter}
\name{David J. Cooper Jr.}
\address{Genworks International\\
5777 West Maple, Suite 130\\
West Bloomfield, MI 48125}
\signature{David J. Cooper Jr.\\
President, Genworks International}
\makelabels
\begin{document}
\begin{letter}{Jane Doe\\
Big Shot\\
Acme Industries, Inc.\\
P.O. Box 55555\\
Springfield, PA 55555-5555}
\opening{Dear Ms. Doe:}
Recently, you visited our booth at Autofact in Detroit,
or otherwise expressed an interest about a generic
manufacturing process planning system we have developed
using the ICAD System and Common Lisp.
We at Genworks continue to increase our commitment to
Dynamic Objects and Common Lisp, and remain convinced
that this concentrated vision will allow us to accelerate
the technology gap between the more ``mundane'' approaches
and our own.
Hopefully you have had a chance to review our white paper,
``Understanding Multi-state Generative Process Planning.''
Also, we have recently installed a new web server, powered
by the Common Lisp Hypermedia Server, at
\emph{http://www.genworks.com/}, which will soon be
host to live running examples of process planning and
related systems.
Please feel free to contact us to arrange for further correspondence and
perhaps an on-site visit, to discuss
any further questions you may have or your specific
potential needs for such a system.
Thank you.
\closing{Yours Truly,}
\end{letter}
\begin{letter}
...
...
...
--
-----
"Microsoft is not the answer. Microsoft is a question,
and the answer is `No.'"