From: drewc Date: Sat, 18 Jun 2005 00:07:22 +0000 (-0700) Subject: documentation enhancements (create doc directory, commited txt version) X-Git-Url: https://git.hcoop.net/clinton/lisp-on-lines.git/commitdiff_plain/e37ba21c0da40f4a6920cca150df9c8966c9cfea documentation enhancements (create doc directory, commited txt version) darcs-hash:20050618000722-39164-9531bdb0a737e736b137affa9f3532ce5ff524b4.gz --- diff --git a/lisp-on-lines.lyx b/doc/lisp-on-lines.lyx similarity index 65% rename from lisp-on-lines.lyx rename to doc/lisp-on-lines.lyx index dcbe7b4..5bf6161 100644 --- a/lisp-on-lines.lyx +++ b/doc/lisp-on-lines.lyx @@ -31,7 +31,7 @@ LISP-ON-LINES \noun on -Drew Crapmsie +Drew Crampsie \noun default , \noun on @@ -72,7 +72,7 @@ Lisp-On-Lines was founded and developed and continues to be developed and mantained by \noun on -Drew Crapmsie +Drew Crampsie \noun default . \layout Subsection @@ -83,7 +83,7 @@ Conventions The conventions used in this manual are: \layout Itemize -Dode is shown as a monospace font. +Code is shown in a monospace font. When it is expected that the user is working in an interactive environment what the user should type appears as bold, while the computer result appears non-bold, for example: @@ -101,7 +101,7 @@ Dode is shown as a monospace font. Names of people or products are show as small caps, like \noun on -Drew Crapmsie +Drew Crampsie \noun default or \noun on @@ -451,16 +451,17 @@ CSS \noun default \begin_inset Foot -collapsed true +collapsed false \layout Standard \noun on -Drew Crapmsie +Drew Crampsie \noun default discovered this, rather than invent or design it, so there are some rough edges, but its a good start. + Exploration baby yeah! \end_inset . @@ -683,7 +684,7 @@ UnCommon Web \series bold - (call 'products-presentation)) + (call 'lol-example)) \layout Standard As you'll see, nothing is exported from the LISP-ON-LINES package. @@ -691,25 +692,27 @@ As you'll see, nothing is exported from the LISP-ON-LINES package. you simply need to use the MEWA and META-MODEL packages. \layout Standard -SET-ATTRIBUTE can be used in place of (setf (find-attribute)) when you want - to "inherit" the properties of an existing attribute definition : -\layout Standard +SET-ATTRIBUTE can be used in place of (setf (find-attribute ...)) when you + want to "inherit" the properties of an existing attribute definition : +\layout LyX-Code -LISP-ON-LINES> (set-attribute 'user 'password '(string :label "password: - (must be at leat 8 chars)")) -\layout Standard +LISP-ON-LINES> +\series bold +(set-attribute 'user 'password '(string :label "password: (must be at least + 8 chars)")) +\layout LyX-Code (PASSWORD STRING -\layout Standard +\layout LyX-Code :LABEL -\layout Standard +\layout LyX-Code "password: (must be at leat 8 chars)" -\layout Standard +\layout LyX-Code :SLOT-NAME -\layout Standard +\layout LyX-Code PASSWORD) \layout Standard @@ -717,58 +720,81 @@ PASSWORD) Now we want to create a presentation with which to edit the username. we will use the existing attributes on a subclass of mewa-object-presetation : -\layout Standard +\layout LyX-Code -LISP-ON-LINES> (defcomponent user-editor (mewa-object-presentation) -\layout Standard +> +\series bold +(defcomponent user-editor (mewa-object-presentation) +\layout LyX-Code -() -\layout Standard -(:default-initargs -\layout Standard +\series bold + () +\layout LyX-Code -:attributes '((username :label "Enter your New Username") password) -\layout Standard -:global-properties '(:editablep t))) -\layout Standard +\series bold + (:default-initargs +\layout LyX-Code -USER-EDITOR -\layout Standard -LISP-ON-LINES> (setf (find-attribute 'user :editor) '(user-editor)) -\layout Standard +\series bold + :attributes '((username :label "Enter your New Username") password) +\layout LyX-Code -(:EDITOR USER-EDITOR) -\layout Standard + +\series bold + :global-properties '(:editablep t))) +\layout LyX-Code + +USER-EDITOR +\layout LyX-Code LISP-ON-LINES> +\series bold +(setf (find-attribute 'user :editor) '(user-editor)) +\layout LyX-Code + +(:EDITOR USER-EDITOR) \layout Standard which we then can display below our earlier example : -\layout Standard +\layout LyX-Code + +\series bold (defmethod render-on ((res response) (e presentations-index)) -\layout Standard +\layout LyX-Code + +\series bold " -\layout Standard +\layout LyX-Code + +\series bold As you'll see, nothing is exported from the LISP-ON-LINES package. -\layout Standard +\layout LyX-Code + +\series bold if you wish to use LOL in your own package (or in UCW-USER or whatever), -\layout Standard +\layout LyX-Code + +\series bold you simply need to use the MEWA and META-MODEL packages" -\layout Standard +\layout LyX-Code + +\series bold (adjuster-id) '(ucw::has-very-many + :label "Claims as Adjuster" :slot-name claim->adjuster-id ) ) +\layout LyX-Code + +\layout LyX-Code + +(set-attribute 'person 'policy->agent-id '(ucw::has-very-many :label "Policies + as Agent")) +\layout LyX-Code + +\layout LyX-Code + +(defcomponent new-person (person-display) +\layout LyX-Code + + () +\layout LyX-Code + + (:default-initargs +\layout LyX-Code + + :attributes '(first-name last-name company-name))) +\layout LyX-Code + +\layout LyX-Code + +(defcomponent person-chooser (mewa::mewa-list-presentation) +\layout LyX-Code + + () +\layout LyX-Code + + (:default-initargs +\layout LyX-Code + + :attributes '(first-name +\layout LyX-Code + + last-name +\layout LyX-Code + + company-name +\layout LyX-Code + + address +\layout LyX-Code + + city +\layout LyX-Code + + person-type-code) +\layout LyX-Code + + :global-properties '(:editablep nil) +\layout LyX-Code + + :editablep nil +\layout LyX-Code + + :deleteablep nil)) +\layout LyX-Code + +\layout LyX-Code + +(defmethod render-on :wrapping ((res response) (self person-chooser)) +\layout LyX-Code + + (<:p (<:as-html "Similar contact(s) in database. + You can :") +\layout LyX-Code + + (<:ul +\layout LyX-Code + + (<:li (<:as-html "Select one of the contacts below")) +\layout LyX-Code + + (<:li ( (+ 5 10) + + 15 + +* Names of people or products are show as small caps, + like Drew Crampsie or Lisp-On-Lines. + +* Sections marked with ToDo require further revision. + +ToDo: Add more conventions as they are needed, possible +classes of text: names of concepts, name of programming +entities, like variables, functions, etc (which are +embedded in text, should they be shown monospaced ?). + +2 Components + + Meta Model Protocol A Protocol for introspection on + relational objects. + + Mewa Presentations A Mewa-likehttp://www.adrian-lienhard.ch/files/mewa.pdf layer for UncommonWebhttp://common-lisp.net/project/ucw/ + Presentations. + +3 Example + +First we start with the data model. The Meta Model +Protocol (MMP) is used to provide information on the +data objects and how they relate to one another. Its is +currently implemented as a layer over CLSQLhttp://clsql.b9.com/, although +support is planned for other backends (CLOS, +Elephant[4], whatever). + +The MMP shares its definition syntax with CLSQL's +Object Oriented Data Definition Language (OODDL)http://clsql.b9.com/manual/ref-ooddl.html. The +macro to define view-classes is named +DEF-VIEW-CLASS/META, and takes the same arguments as +DEF-VIEW-CLASS from CLSQL. For the purposes of this +simple example, we will only need two functions from +the MMP beyond what CLSQL provides : LIST-SLOTS and +LIST-SLOT-TYPES[5]. + +We'll define a simple class to hold a user. + +> (def-view-class/meta user () + + ((userid :initarg :userid :accessor userid :type +integer :db-kind :key) + + (username :initarg :username :accessor username +:type string :db-kind :base) + + (password :initarg :password :accessor password +:type string :db-kind :base))) + +and now we create a user: + +> (defparameter user (make-instance 'user :userid 1 + + :username "drewc" + + :password "p@ssw0rd")) + +We can see the slots of users running: + +> (lisp-on-lines::list-slots user) + +(USERID USERNAME PASSWORD) + +or the types with: + +> (lisp-on-lines::list-slot-types user) + +((USERID INTEGER) (USERNAME STRING) (PASSWORD STRING)) + +To see the default attributes of a classIs this correct ? Drew, please, check. we run. + +> (lisp-on-lines::default-attributes user) + +((USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) + + (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) + + (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD)) + +To set the attributes of a class to the default values +we use: + +> (lisp-on-lines::set-default-attributes user) + +((USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) + + (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) + + (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD)) + +which takes an object of the class we are working with. +This is going to be change so we can do this action +directly on the class. It is on the TODO file. + +Class attributes? + +> (lisp-on-lines::find-class-attributes user) + +(USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) + + (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) + + (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) + + NIL) + +note that the mewa functions (find-attribute, +set-attribute etc) can take either an instance, or a +class-name as a symbol: + +> (lisp-on-lines::find-class-attributes 'user) + +(USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) + + (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) + + (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) + + NIL) + +> (lisp-on-lines::find-class-attributes (make-instance 'user)) + +(USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) + + (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) + + (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) + + NIL) + +Using that information, we have enough to create an +interface to the object. UnCommon Web includes a +powerful presentation systemTo see this system in action, we strongly recomend to +study the presentations example which comes with +UnCommon Web. Reading components/presentations.lisp can +help understand a lot about how presentations are built. +, but it is not dynamic enough for some of the most +advanced applications. Mewa defines an approach to +presentations that solves that problem, but the paper +is written from a Smalltalk point of view. A mixture of +the two , Mewa Presentations(MP), is described here. + +MP introduces to UnCommon Web the concept of +attributes. An attribute is essentially a named version +of the DEFPRESENTATION slot-like arguments, for example +in : + +> (defpresentation person-editor (object-presentation) + + ((string :label "First Name" :slot-name 'first-name +:max-length 30))) + +the (string :label "First Name" ...) form is an +attribute definiton. Attributes are accessed through +FIND-ATTIRIBUTES, and are composed at run time (where +the UnCommon Web's presentation system is done at +compile time) to display the object. This allows a very +flexible system of displaying objects which is +reminiscent of CSSDrew Crapmsie discovered this, rather than invent or +design it, so there are some rough edges, but its a +good start. +. + +Its much easier to show this than to tell. Lets present +our user class. Currently in UnCommon Web, you'd define +a presentation as such : + +> (defpresentation user-presentation (object-presentation) + +((INTEGER :LABEL "USERID" :SLOT-NAME USERID) + + (STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) + + (STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD))) + +which could be presented using PRESENT-OBJECT : + +> (present-object user :using 'user-presentation) + +The equivalent approach using mewa presentations is +actually longer and more verbose(!) but it serves to +demonstrate how the MP system works. + +Mewa Presentations adds a set of attributes to a class, +keyed off the class name. Attributes are inherited, so +if you define an attribute on T, you can use it with +any class. + +MP stores named attributes keyed on a class name. To +achieve the same functionality as the above using mp +would look like this : + +> (setf (lisp-on-lines::find-attribute 'user :viewer)Isn't this too imperative (in contrast to functional, lispy). + + '(lisp-on-lines::mewa-object-presentation + + :attributes (userid username password) + + :global-properties (:editablep nil))) + +(:VIEWER MEWA-OBJECT-PRESENTATION + + :ATTRIBUTES + + (USERID USERNAME PASSWORD) + + :GLOBAL-PROPERTIES + + (:EDITABLEP NIL)) + +> (setf (lisp-on-lines::find-attribute 'user 'userid)Are this setfs to 'userid, 'username and 'password +needed ? I (Pupeno) inspected they contents at of this +moment and they seem to already contain what they are +being set to. + + '(integer :label "userid" :slot-name userid)) + +(USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) + +> (setf (lisp-on-lines::find-attribute 'user 'username) + + '(STRING :LABEL "USERNAME" :SLOT-NAME USERNAME)) + +(USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) + +> (setf (lisp-on-lines::find-attribute 'user 'password) + + '(STRING :LABEL "USERNAME" :SLOT-NAME PASSWORD)) + +(PASSWORD STRING :LABEL "USERNAME" :SLOT-NAME PASSWORD) + +> (lisp-on-lines::find-class-attributes 'user) + +(USER + + (:VIEWER MEWA-OBJECT-PRESENTATION + + :ATTRIBUTES + + (USERID USERNAME PASSWORD) + + :GLOBAL-PROPERTIES + + (:EDITABLEP NIL)) + + (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) + + (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) + + (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) + + NIL) + +this is all turned into a UnCommon Web presentation at +runtime using MAKE-PRESENTATION, for example, the +following code should be enough to show what's built so +far attached to the examples application: + +> (defcomponent lol-example (window-component) + + ()) + +> (defmethod render-on ((res response) (lol-example lol-example)) + + (<:h1 "User") + + ( (defentry-point "lol.ucw" (:application +*example-application*) () + + (call 'lol-example)) + +As you'll see, nothing is exported from the +LISP-ON-LINES package. If you wish to use LOL in your +own package (or in UCW-USER or whatever), you simply +need to use the MEWA and META-MODEL packages. + +SET-ATTRIBUTE can be used in place of (setf +(find-attribute ...)) when you want to "inherit" the +properties of an existing attribute definition : + +LISP-ON-LINES> (set-attribute 'user 'password '(string +:label "password: (must be at least 8 chars)")) + +(PASSWORD STRING + +:LABEL + +"password: (must be at leat 8 chars)" + +:SLOT-NAME + +PASSWORD) + +Now we want to create a presentation with which to edit +the username. we will use the existing attributes on a +subclass of mewa-object-presetation : + +> (defcomponent user-editor (mewa-object-presentation) + + () + + (:default-initargs + + :attributes '((username :label "Enter your New +Username") password) + + :global-properties '(:editablep t))) + +USER-EDITOR + +LISP-ON-LINES> (setf (find-attribute 'user :editor) +'(user-editor)) + +(:EDITOR USER-EDITOR) + +which we then can display below our earlier example : + +(defmethod render-on ((res response) (e presentations-index)) + +" + +As you'll see, nothing is exported from the +LISP-ON-LINES package. + +if you wish to use LOL in your own package (or in +UCW-USER or whatever), + +you simply need to use the MEWA and META-MODEL +packages" + +( (clsql:connect '("localhost" "geo" "geo" "geogeo")) + +which connect us to the server on localhost, to the +database geo as user "geo" with password "geogeo" (this is +not a smart way to generate password, don't do this). +To have a nice SQL environment, we also want: + +> (clsql:locally-enable-sql-reader-syntax) + +> (setf clsql:*default-caching* nil) + +Actually, it is more than a nice environmnet, without +those lines the rest of the code won't work. + +On the geo database, there's a table called product +which has the following structure: + +CREATE TABLE product ( + + id serial NOT NULL, + + name text NOT NULL, + + details text, + + description text, + + cost double precision, + + CONSTRAINT product_cost_check CHECK ((cost > +(0)::double precision)) + +); + +ALTER TABLE ONLY product ADD CONSTRAINT +product_name_key UNIQUE (name); + +ALTER TABLE ONLY product ADD CONSTRAINT product_pkey +PRIMARY KEY (id); + +ToDo: express the table structure in a better way. + +Now we'll create the class that represents a product, +mirroring the database structure: + +> (lisp-on-lines::def-view-class/table "product") + +and then we generate the default attributes (from +product's slots) and assign it to product: + +> (lisp-on-lines::set-default-attributes (make-instance +'product))set-default-attributes is marked to be renamed to +set-generated-attributes. + +As you can see, we instantiate product to pass it to +set-default-attributes, because it expects an object +instead of a class. We don't need the object anymore, +so we don't save any reference to it. In the future we +might have a set-default-attributes that can use a +class directly. Now we set a the attribute :viewer to +contain the mewa-object-presentation exposing the +attributes we like the user to work with: + +> (setf (lisp-on-lines::find-attribute (make-instance +'product) :viewer) + + '(lisp-on-lines::mewa-object-presentation + + :attributes (name details description cost) + + :global-properties (:editablep nil))) + +The last parameter is a list of properties that will be +applied to each attribute. + +5 Yet Another Example . + +Drew Crampsie Posted the following to comp.lang.lisp .. +it just might help until he writes some real +documentation. + +I've written a system that generates presentations for +database objects based on the type and relation +information in the system catalog. Its based on MewaMewa : Meta-level Architecture for Generic +Web-Application Construction + + + + + + + + + + + + + + + + +http://map1.squeakfoundation.org/sm/package/32c5401f-fa30-4a2b-80c8-1006dd462859 + clsql + postgres and the UCW presentation components. + +This is the code to add a new contact to the system. +(screenshot pr0n follows). + +In the RENDER-ON method of my front-page i have : + + + +(let ((p (make-instance 'person :person-type-code nil))) + + (<:as-html "Add Person :") + + (adjuster-id) +'(ucw::has-very-many :label "Claims as Adjuster" +:slot-name claim->adjuster-id ) ) + + + +(set-attribute 'person 'policy->agent-id +'(ucw::has-very-many :label "Policies as Agent")) + + + +(defcomponent new-person (person-display) + + () + + (:default-initargs + + :attributes '(first-name last-name company-name))) + + + +(defcomponent person-chooser (mewa::mewa-list-presentation) + + () + + (:default-initargs + + :attributes '(first-name + + last-name + + company-name + + address + + city + + person-type-code) + + :global-properties '(:editablep nil) + + :editablep nil + + :deleteablep nil)) + + + +(defmethod render-on :wrapping ((res response) (self +person-chooser)) + + (<:p (<:as-html "Similar contact(s) in database. You +can :") + + (<:ul + + (<:li (<:as-html "Select one of the contacts below")) + + (<:li ( (def-view-class/meta user () - ((userid :initarg :userid :accessor userid :type integer :db-kind :key) - (username :initarg :username :accessor username :type string :db-kind :base) - (password :initarg :password :accessor password :type string :db-kind :base))) -STYLE-WARNING: redefining META-MODEL.METADATA (USER) in DEFMETHOD -# -LISP-ON-LINES> (defparameter user (make-instance 'user :userid 1 :username "drewc" :password "p@ssw0rd")) -USER -LISP-ON-LINES> (list-slots user) -(USERID USERNAME PASSWORD) -LISP-ON-LINES> (list-slot-types user) -((USERID INTEGER) (USERNAME STRING) (PASSWORD STRING)) -; compiling file "/tmp/fileQQsHyN" (written 03 JUN 2005 03:20:06 PM): - -; /tmp/fileQQsHyN.fasl written -; compilation finished in 0:00:00 -LISP-ON-LINES> (default-attributes user) -((USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) - (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) - (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD)) -LISP-ON-LINES> (set-default-attributes user) -((USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) - (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) - (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD)) -LISP-ON-LINES> (find-class-attributes user) -(USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) - (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) - (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) - COMMON-LISP:NIL) -LISP-ON-LINES> ;;;; note that the mewa functions (find-attribute, set-attribute etc) can take either an instance, or a class-name as a symbol , ie : -; No value -LISP-ON-LINES> (find-class-attributes 'user) -(USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) - (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) - (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) - COMMON-LISP:NIL) -LISP-ON-LINES> (find-class-attributes (make-instance 'user)) -(USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) - (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) - (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) - COMMON-LISP:NIL) -LISP-ON-LINES> - -Using that information, we have enough to create an interface to the object. UncommonWeb includes a powerful presentation system, but it is not quite dynamic enough for our needs. Mewa defines an approach to presentations that suits our purposes, but the paper is written from a smalltalk point of view. A mixture of the two , Mewa Presentations(MP), is described here. - -MP introduces to UCW the concept of attributes. an attribute is essentially a named version of the defpresentation slot-like arguments. for example in : - -(defpresentation person-editor (object-presentation) - ((string :label "First Name" :slot-name 'first-name :max-length 30))) - - the (string :label "First Name" ...) form is an attribute definiton. Attributes are accessed through FIND-ATTIRIBUTES, and are composed at run time (where the current system is done at compile time) to display the object. This allows a very flexible system of displaying objects which is reminiscent of CSS. I discovered this, rather than invent or design it, so there are some rough edges, but its a good start. - -Its much easier to show this then to tell. Lets present our user class. Currently in UCW, you'd define a presentation as such : - -(defpresentation user-presentation (object-presentation) -((INTEGER :LABEL "USERID" :SLOT-NAME USERID) - (STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) - (STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD))) - -which could be presented using PRESENT-OBJECT : - -(present-object user :using 'user-presentation) - -The equiv approach using mewa presentations is actually longer and more verbose(!) but it serves to demonstrate how the MP system works. - -Mewa Presentations adds a set of attributes to a class, keyed off the class name. Attributes are inherited, so if you define an attribute on T, you can use it with any class. - -MP stores named attributes keyed on a class name. to achieve the same functionality as the above using mp would look like this : - -LISP-ON-LINES> (setf (find-attribute 'user :viewer) '(mewa-object-presentation :attributes (userid username password) :global-properties (:editablep nil))) -(:VIEWER MEWA-OBJECT-PRESENTATION - :ATTRIBUTES - (USERID USERNAME PASSWORD) - :GLOBAL-PROPERTIES - (:EDITABLEP NIL)) -LISP-ON-LINES> (setf (find-attribute 'user 'userid) '(INTEGER :LABEL "USERID" :SLOT-NAME USERID)) -(USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) -LISP-ON-LINES> (setf (find-attribute 'user 'username) '(STRING :LABEL "USERNAME" :SLOT-NAME USERNAME)) -(USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) -LISP-ON-LINES> (setf (find-attribute 'user 'password) '(STRING :LABEL "USERNAME" :SLOT-NAME PASSWORD)) -(PASSWORD STRING :LABEL "USERNAME" :SLOT-NAME PASSWORD) - -LISP-ON-LINES> (find-class-attributes 'user) -(USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) - (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) - (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) - (:VIEWER MEWA-OBJECT-PRESENTATION - :ATTRIBUTES - (USERID USERNAME PASSWORD) - :GLOBAL-PROPERTIES - (:EDITABLEP NIL)) - COMMON-LISP:NIL) - - -this is all turned into a UCW presentation at runtime using MAKE-PRESENTATION : - -(defmethod render-on ((res response) (e presentations-index)) - " -As you'll see, nothing is exported from the LISP-ON-LINES package. -if you wish to use LOL in your own package (or in UCW-USER or whatever), -you simply need to use the MEWA and META-MODEL packages" - ( (set-attribute 'user 'password '(string :label "password: (must be at leat 8 chars)")) -(PASSWORD STRING - :LABEL - "password: (must be at leat 8 chars)" - :SLOT-NAME - PASSWORD) - - -Now we want to create a presentation with which to edit the username. we will use the existing attributes on a subclass of mewa-object-presetation : - -LISP-ON-LINES> (defcomponent user-editor (mewa-object-presentation) - () - (:default-initargs - :attributes '((username :label "Enter your New Username") password) - :global-properties '(:editablep t))) -USER-EDITOR -LISP-ON-LINES> (setf (find-attribute 'user :editor) '(user-editor)) -(:EDITOR USER-EDITOR) -LISP-ON-LINES> - - -which we then can display below our earlier example : - -(defmethod render-on ((res response) (e presentations-index)) - " -As you'll see, nothing is exported from the LISP-ON-LINES package. -if you wish to use LOL in your own package (or in UCW-USER or whatever), -you simply need to use the MEWA and META-MODEL packages" - (