Web Application Programming in PicoLisp: Introducing the GUI framework

Web Application Programming in PicoLisp: Introducing the GUI framework


5 min read

Now that we have covered the basics of object-oriented programming in PicoLisp, we can finally start with the PicoLisp GUI framework!

What is the PicoLisp GUI framework?

The PicoLisp GUI framework is a set of objects and classes that allow a very efficient and simplified way to define user interactive forms.

They are organized within the form function and sent to the server via POST. The POST is always redirected back to the current page and is triggered by a button press. As we will see, a button's action code can do almost anything: Read and modify the contents of input fields, communicate with the database, display alerts and dialogs, or even fake the POST request to a GET, with the effect of showing a completely different document.

Checking out the source code

The PicoLisp GUI framework is defined in the library form.l. You can find it in the lib-Folder of your PicoLisp installation (or type $ locate "lib/form.l" in your terminal). The framework is organized in classes: Each GUI element has its own class, and we can modify and extend its behaviour by using Prefix-Classes.

The library also has its own documentation, available at software-lab.de/doc/form/form.html.

Before we dive into the theory, let's take a look at an example - our previously defined first Name, last Name-example.

(setq *Css '("@lib.css" "bootstrap.css"))


   (html 0 "Simple Session" *Css NIL
      (form NIL
         (gui 'a '(+TextField) 30 "First Name")                    
         (gui 'b '(+TextField) 30 "Last Name")                         
         (gui '(+Button) "Send" ) ) ) )

This is the output we get:


By typing Ctrl-U in the browser (Firefox), we can also view the source code.


As you can see, we have two <input type="text"> fields with name *Gui:1 and *Gui:, with id2-1 and id2-2, and an <input type="submit" with name *Gui:-3 and an id i2--3.

The input fields are surrounded by a <form>-tag with method=post and an action=<some auto-generated link>. If we fill in the form and click on "Send", we see that the URL changes to http://localhost:<new-port>/<action-link>.

So far so good, but how does it work? Let's review again the source code and check what functions we have: action, html, form and gui.

      (form NIL
         (gui 'a '(+TextField) 30 "First Name")                    
           ... ) ) )

We will go through it step by step with help fo the form library reference.

The action function

The top function is action. From the documentation, we learn that it's "only" a wrapper function:

(action Prg)

Top level wrapper function for the form event handling. Typically contains one or several calls to form.

The form function

Then we get to the form function, which is the wrapper function for the form elements.

The gui function

Inside form, we can find many calls to a function called gui. gui is only defined inside a form function and takes the following parameters:

  • an alias name for the component (optional)
  • a list of classes that define the GUI-element, for example +TextField
  • additional arguments as needed by the constructors of these classes.

All gui-classes are subclasses of the abstract class +gui. We can list them all by viewing the dependency tree of +gui with (+dep 'gui):

: (dep '+gui)
-> +gui

Let's take a closer look at +TextField and +Button.

The +TextFieldclass

The +TextField class can be defined by several arguments:

  • (gui '(+TextField)): Plain HTML text is created.
  • (gui '(+TextField) 10): A text field of length 10 is created.
  • (gui '(+TextField) 10 4): A text field of length 10 and 4 lines is created.
  • (gui '(+TextField) '("Value 1" "Value 2" "Value 3")): a drop-down selection.
  • (gui '(+TextField) '("Value1" "Value2" "Value3") "Please choose: ") Strings are used as labels.

In rendered form, it looks like this:


The +Button class

A +Button takes several arguments as well:

  • A label, which may be either a string or the name of an image file,
  • An optional, alternative label which is shown when the button is disabled,
  • An optional executable expression.

The button works as submit-element that sends the form data via POST and causes the reloading of the page with updated data.

Accessing the data

Now we come to an important point: where can we find the data that we have collected?

If you remember the Object-Oriented programming introduction, you might remember that we can get specific properties of an object with the : function. All GUI-elements have a property called home which contains the current form, a function val>that returns the current value and a function set> that sets the current value.

Let's take again our textfield example from the beginning:

(form NIL
   (gui 'a '(+TextField) 30 "First Name")      
   ... )

We can find its content by getting the home property from our current form, and then return its property a (which is our +TextField-object):

(: home a)

To get its value:

(val> (: home a))

Now let's modify our button so that it prints the content of a when we press it. Printing to standard error is possible using the msg function.

(gui '(+Button) "Print" '(msg (val> (: home a)))

If we now enter our text into the textfield and press the button, we see a line in the terminal where the server is running:

: "hello!"

Instead of referencing by alias names, we can also use the relative position of the GUI element, which can be more convenient. For example, in order to access the text of the previous element, we can use (field -1).

(gui '(+Style +TextField) "mb-2" 30 "Enter your text: ")   
(gui '(+Button) "Print" '(msg (val> (field -1)))


The example showed how to create HTML forms using the PicoLisp GUI framework.

By calling a form function within action, the content is created by pre-defined classes. At submission, the form content is automatically re-directed to the current page using POST. We can access the values in each field by relative position or by alias names.

It might seem a little confusing at the moment, but it will become clearer the more examples we see. In the next post, we will see how to use Prefix-Classes to further style and define those elements.