Giter Site home page Giter Site logo

rabbibotton / clog Goto Github PK

View Code? Open in Web Editor NEW
1.4K 42.0 95.0 16.34 MB

CLOG - The Common Lisp Omnificent GUI

License: Other

Common Lisp 100.00%
common-lisp html-bindings gui webframework html-over-the-wire lisp websocket-server javascript-over-the-wire

clog's Introduction

CLOG - The Common Lisp Omnificent GUI

David Botton [email protected]

License BSD 3-Clause License


Image of CLOG

The Common Lisp Omnificent GUI, CLOG for short, uses web technology to produce graphical user interfaces for applications locally or remotely. CLOG can take the place, or work alongside, most cross-platform GUI frameworks and website frameworks. The CLOG package starts up the connectivity to the browser or other websocket client (often a browser embedded in a native application.)

STATUS: CLOG and CLOG Builder 2.0 released.

CLOG is actually based on GNOGA, a framework I wrote for Ada in 2013 and used in commercial production code for the last 10+ years. CLOG itself is already used in commerical products, corporate websites, and other opensource projects.

CLOG is being actively extended, however the core API is stable and proven, the CLOG Builder is rich in features. Check the github discussion boards for the latest on the project.

Consider sponsoring work on CLOG at https://github.com/sponsors/rabbibotton

Some potential applications for CLOG:

  • Cross-platform GUIs and Reports
  • Secure websites and complex interactive web applications
  • Desktop buisiness software (CLOG Runs native on Windows, Mac and Linux)
  • Mobile software (CLOG Runs native on Android and iOS)
  • Massive multiplayer online games
  • Monitoring software for embedded systems
  • A fun way to teach programming and advanced multi-tasking parallel programming techniques. (CLOG is a parallel GUI)
  • And the list goes on

The key to CLOG is the relationship it forms with a browser window or browser control compiled to native code. CLOG uses websockets for communications and the browser to render a GUI that maintains an active soft realtime connection. For most CLOG applications all programming logic, events and decisions are done on the server which can be local, or remote over the web.

CLOG is developed with ECL, CCL and SBCL, it is tested fairly regulary on Linux, Windows, Android, Rasperry Pi, and Mac. It is also know to work with the commercial Common Lisps as well.

To install CLOG - install Common Lisp:

For Windows users there is an easy install for full CL and CLOG - https://github.com/rabbibotton/clog-win64-ez/releases/tag/v1.0a Unzip, double click setup.bat and then drag the resulting builder.exe to your application bar or double click. Update regularly by running update.bat If you change directories you need to run make.bat or update.bat

CLOG is in QuickLisp (ql:quickload :clog), however one should add the UltraLisp distribution as QuickLisp is updated very infrequenty (see below).

To add UltraLisp to QuickLisp:

(ql-dist:install-dist "http://dist.ultralisp.org/"
                      :prompt nil)

You still need to often update the UltraLisp and QuickLisp distros with:

(ql:update-all-dists)

To get started load CLOG and then can load and run the builder:

(ql:quickload :clog)
(ql:quickload :clog/tools)
(clog-tools:clog-builder)

To use the git versions CLOG, place git clone into ~/common-lisp or a findable source directory, i.e. [ (push #P"path/to/dir/of/projects" ql:*local-project-directories*) ]

For git (you also need the clog builder plugins clog-ace and clog-terminal for the builder):

cd ~/common-lisp
git clone https://github.com/rabbibotton/clog.git
git clone https://github.com/rabbibotton/clog-ace.git
git clone https://github.com/rabbibotton/clog-terminal.git

Update git clones with:

git pull
  1. Start emacs then M-x slime (or just run sbcl at the command line or use the CLOG Buider REPL Tools -> CLOG Builder Repl)
  2. In the REPL, run:
CL-USER> (ql:quickload :clog) ; if not already loaded
CL-USER> (clog:run-tutorial 1)

Tip for Windows WSL linux user. Install "sudo apt install xdg-utils" to install xdg-open so that run-tutorial uses the windows browser.

To see where the source, tutorial and demo files are:

CL-USER> (clog:clog-install-dir)

You can the run the demos with:

CL-USER> (clog:run-demo 1)

The CLOG Builder tool can be run with:

CL-USER> (ql:quickload :clog/tools)
CL-USER> (clog-tools:clog-builder)

You can also open a "clog-repl" browser window to play from the common-lisp repl:

CL-USER> (in-package clog-user)
CLOG-USER> (clog-repl)
CLOG-USER> (setf (background-color *body*) "beige")
CLOG-USER> (create-div *body* :content "Hello World!")

The clog-repl URL is http://127.0.0.1:8080/repl *body* will always refer to the last access of that URL.

To open a browser with the CLOG manual (or in the builder it is under Help):

CL-USER> (clog:open-manual)

Work your way through the tutorials. You will see how quick and easy it is to be a CLOGer.

Image of clog-builder Image of clog-builder-web Image of demo1 Image of demo2 Image of demo3 Image of clog-db-admin Image of clog-web-containers

Here is a very simple sample CLOG app (from Tutorial 1):

(defpackage #:clog-user               ; Setup a package for our work to exist in
  (:use #:cl #:clog)                  ; Use the Common Lisp language and CLOG
  (:export start-tutorial))           ; Export as public the start-tutorial function

(in-package :clog-user)               ; Tell the "reader" we are in the clog-user package


;; Define our CLOG application
(defun on-new-window (body)           ; Define the function called on-new-window
  "On-new-window handler."            ; Optional docstring to describe function

  (let ((hello-element                ; hello-element is a local variable that
                                      ; will be bound to our new CLOG-Element

      ;; This application simply creates a CLOG-Element as a child to the
      ;; CLOG-body object in the browser window.

      ;; A CLOG-Element represents a block of HTML (we will later see ways to
      ;; directly create buttons and all sorts of HTML elements in more
      ;; lisp-like ways with no knowledge of HTML or JavaScript.
      (create-child body "<h1>Hello World! (click me!)</h1>")))

    (set-on-click hello-element      ; Now we set a function to handle clicks
          (lambda (obj)              ; In this case we use an anonymous function
            (setf (color hello-element) "green"))))))

;; To see all the events one can set and the many properties and styles that
;; exist, refer to the CLOG manual or the file clog-element.lisp


(defun start-tutorial ()   ; Define the function called start-tutorial
  "Start tutorial."        ; Optional docstring to describe function

  ;; Initialize the CLOG system
  (initialize #'on-new-window)
  ;; Set the function on-new-window to execute
  ;; every time a browser connection to our app.
  ;; #' tells Common Lisp to pass the function
  ;; to intialize and not to execute it.


  ;; Open a browser to http://12.0.0.1:8080 - the default for CLOG apps
  (open-browser))

Other samples of CLOG on the web:

Get started learning CLOG and the CLOG Builder with

Tool Summary

  • clog-builder - Rapid visual interactive development for Web and GUIs
  • clog-db-admin - SQLite3 admin tool

High Order Extensions to CLOG

  • clog-gui - Desktop over the web

    • Menus
    • Windowing system
    • Modal windows, Keep-on-top windows
    • File Load / Save dialogs
    • Alert, Input and Confirmation dialogs
    • Form dialogs
  • clog-web - Webpage creation

    • Auto column layouts
    • 12 Point Grid System layouts
    • Content containers
    • Panels
    • Sidebar menus
    • Compositor containers
    • Menus
    • Alerts
  • clog-web-site - Instant themed websites with plugins:

    • clog-web-page - create a theme based page
    • clog-web-dbi - database driven websites (uses clog-auth)
    • clog-web-forms - Instant web forms
    • clog-web-themes - basic themes for clog based websites
    • clog-web-content - database driven content,tags, comments (in progress)
    • clog-web-blog - instant blogs (in progress)
    • clog-web-cart - instant shopping carts (future)
  • clog-panels - Quick application layouts

  • clog-presentations - bi-directional linking of Lisp Objects and CLOG Objects

  • clog-jquery - DOM queries

  • clog-data - Move data to and from groups of controls

    • SQL writer helpers for basic SQL
    • CLOG-Database - Database control for CLOG Builder
    • CLOG-One-Row - One row at a time table access auto binds to controls in CLOG Builder
    • CLOG-Lookup - Version of the select control (dropdown and listbox) that are database connected
    • CLOG-DB-Table - Version of html table that are database connected
  • clog-auth - Authentication and authorization framework

  • clog-plugin - Custom Control Plug-in template for Builder and CLOG

clog's People

Contributors

apr3vau avatar aykaramba avatar b-tach avatar cgore avatar cmstrickland avatar davidquan111 avatar ebrasca avatar em7 avatar fbmnds avatar fskolodny avatar hxzrx avatar imadhui avatar jingtaozf avatar jpe90 avatar justjoheinz avatar kaeland avatar mcsh avatar mmontone avatar ormf avatar orsenthil avatar pankajgodbole avatar rabbibotton avatar reflektoin avatar sabracrolleton avatar shakatoday avatar ska80 avatar smvamse avatar svetlyak40wt avatar tomrake avatar veer66 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clog's Issues

Trouble deploying to Heroku

I've tried to deploy the second tutorial to Heroku using two different build packs (one based on roswell https://gitlab.com/bendersteed/heroku-buildpack-common-lisp and then the other not https://github.com/hackeryarn/heroku-buildpack-cl). Both seem to end up with the same error, post build, when trying to start the application:

2021-03-13T18:16:51.233423+00:00 app[web.1]: Listening on port 38633
2021-03-13T18:16:51.240923+00:00 app[web.1]: Unhandled SIMPLE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING
2021-03-13T18:16:51.240925+00:00 app[web.1]:                                     {10030D8103}>:
2021-03-13T18:16:51.241101+00:00 app[web.1]:   :HUNCHENTOOT is unknown handler.
2021-03-13T18:16:51.241102+00:00 app[web.1]: 
2021-03-13T18:16:51.241194+00:00 app[web.1]: Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {10030D8103}>
2021-03-13T18:16:51.241534+00:00 app[web.1]: 0: (SB-DEBUG::DEBUGGER-DISABLED-HOOK #<SIMPLE-ERROR "~S is unknown handler." {10030F13A3}> #<unused argument> :QUIT T)
2021-03-13T18:16:51.241731+00:00 app[web.1]: 1: (SB-DEBUG::RUN-HOOK *INVOKE-DEBUGGER-HOOK* #<SIMPLE-ERROR "~S is unknown handler." {10030F13A3}>)
2021-03-13T18:16:51.241820+00:00 app[web.1]: 2: (INVOKE-DEBUGGER #<SIMPLE-ERROR "~S is unknown handler." {10030F13A3}>)
2021-03-13T18:16:51.241934+00:00 app[web.1]: 3: (ERROR "~S is unknown handler." :HUNCHENTOOT)
2021-03-13T18:16:51.242069+00:00 app[web.1]: 4: (CLACK.UTIL:FIND-HANDLER :HUNCHENTOOT)
2021-03-13T18:16:51.242545+00:00 app[web.1]: 5: (CLACK:CLACKUP #<FUNCTION (LAMBDA (CLOG-CONNECTION::ENV) :IN CLOG-CONNECTION:INITIALIZE) {10030EEA2B}> :ADDRESS "0.0.0.0" :PORT 38633)
2021-03-13T18:16:51.242741+00:00 app[web.1]: 6: (CLOG-CONNECTION:INITIALIZE #<FUNCTION CLOG::ON-CONNECT> :HOST "0.0.0.0" :PORT 38633 :BOOT-FILE "/boot.html" :STATIC-ROOT #P"/tmp/codon/tmp/cache/quicklisp/dists/quicklisp/software/clog-20210228-git/./static-files/")
2021-03-13T18:16:51.242935+00:00 app[web.1]: 7: (HEROKU-TOPLEVEL)
2021-03-13T18:16:51.243046+00:00 app[web.1]: 8: ((FLET SB-UNIX::BODY :IN SB-IMPL::START-LISP))
2021-03-13T18:16:51.243144+00:00 app[web.1]: 9: ((FLET "WITHOUT-INTERRUPTS-BODY-1" :IN SB-IMPL::START-LISP))
2021-03-13T18:16:51.243207+00:00 app[web.1]: 10: (SB-IMPL::START-LISP)
2021-03-13T18:16:51.243239+00:00 app[web.1]: 
2021-03-13T18:16:51.243240+00:00 app[web.1]: unhandled condition in --disable-debugger mode, quitting

Here is the application repo: https://github.com/hackeryarn/chat

I would really appreciate any help.

I am also happy to write this up as part of clog's documentation once I have things working.

Working time tracking tool using CLOG (programming noob)

Hej,

I recently wrote on reddit, asking for a way to find out the screen resolution.

Trying to give a bit more context, maybe it will be easier to understand what I am trying to achieve, as I still struggle to formulate in proper terms what I require for my program.

I am currently trying to design and program a user interface which gives users (my coworkers and me) the possibility to input working time data, especially regarding the spread of working time over two types of categories: (1) pedagogical work/preparation of that work/administration (2) a specification of what was chosen for (1). Using this, I want to gather data in order to pressure my superiors into either accepting that we have way more administrative chores then they see, or changing something about this problem. Because it is a problem when we are supposed to have 20% of our working time in administration and I find myself since more than one year having around 40%.

The user interface mainly revolves around two sections which could be dubbed "Input" and "Output".

Input

  • In the Input section, the users are supposed to enter their data: date, working time span (e.g. 10-18:00), the place where you work (I work in two different places) and the distribution of working time ( (1) from above). This data is written to an array slot and stored locally.
  • I want to offer two options for Input: one that is quick and requires said data for an entire day, and one which is exhaustive and requires the data for each time span within the working day (e.g. 10:00-11:00, pedagogical work, homework support). This is supposed to help with another administrative chore where we have to evaluate, at the end of the year, how we expended our working time.
  • On the GUI side, I consider this a bit special: while the "quick" method requires only few text fields (they ideally should have labels above them), the "exhaustive" method should feature a "+" sign at the end of each new row to create a new row right below (I normally have something between 4 and 8 slots per day, but the users' mileage may vary).

Output

  • In the Output section, I want to show the aggregated data to the user. The program reads the array and aggregates matching entries (I already wrote a working prototype, will probably have to adapt to gui). On the one hand, I want the show the user, for the current {month,quarter,year}, how much working time has been expended in which category. I'm not set on the details of this, as depending on whether the user customarily chooses "quick" or "exhaustive" Input, the Output could get very big and messy (I always use "exhaustive" and employ around 20 different specification categories).
  • On the other hand, I want to allow for PDF export which can be much more verbose and show the distribution for each month or quarter, and for the entire year. As you might have guessed by now, I hope to use this as a tool to put pressure on my superiors to do something about the amount of administration that is part of my (and my colleagues') everyday life as pedagogical professionals. Because every minute that is spent on administration is a minute that cannot be expended working with children (our job), and currently it feels like it's pretty much the other way around.

So, I guess this should do as an explanation for a start. The code already present is public and can be found over at gitlab: https://gitlab.com/hapster/azvdoc . The repo is a bit messy because I am still learning how to use it and how to manage a repo. Most of the work happens in the files "construct-transform", "date", "day", "time" and "save-restore". I am also in the process of experimenting how to structure my program, since it is the first "real" program I write (excercise programs don't count in my opinion).

I hope I am not taking too much of your time with this issue where I'm basically asking for spoonfeeding and already want to thank you for the offer to discuss (here or over on reddit doesn't make a difference for me). Have a good day and thanks for your contribution to the community with clog, the resources you offer (tutorials etc) and your willingness to help people.

Have a good day :)

There is no applicable method for the generic function

Hello i'm newbie in cl and this error
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION ASDF/SESSION:SESSION-CACHE (1)>
when called with arguments
(NIL).
[Condition of type SB-PCL::NO-APPLICABLE-METHOD-ERROR]
See also:
Common Lisp Hyperspec, 7.6.6 [:section]

Opening Emacs in clog directory, still page "not found"

Hello there,
I'm trying to take a look at CLOG.
I've started Emacs on clog directory under ~/common-lisp/ just like the tutorial asks.
Starting the tutorial still shows "Not Found" though.

SBCL 2.0.1.debian.
GNU Emacs 27.1
Slime 2.26
quicklisp 2020-10-16

Screenshot from 2021-01-22 21-51-00

Screenshot from 2021-01-22 21-51-10

Screenshot from 2021-01-22 21-51-13

Compile error on (ql:quickload :clog) in Portacle for Windows

First time running and many years since I last programmed, I saw your clog tutorials and was inspired. I remember how much I enjoyed lisp the few times I used it. Thanks for your offerings. Please let me know if this is the sort of issue you are happy to hear about or if it's a bit much, I can see the beauty of your creation and don't want to impinge on a developer doing good.

the situation is I've got Portacle on windows, I've installed the SQL binaries to the /win/lib subdirectory of portacle, updated quicklisp client (ql:update-dist "quicklisp") and updated the client (ql:update-client) and also installed clog from git where portacle expects quicklisp systems in its /projects directory

running (ql:quickload :clog) after sometime downloading and compiling various packages spits out...

COMPILE-FILE-ERROR while
compiling #<CL-SOURCE-FILE "clog" "clog-gui">
   [Condition of type UIOP/LISP-BUILD:COMPILE-FILE-ERROR]

looking down at the back trace (skipping the first few lines)

0: (UIOP/LISP-BUILD:CHECK-LISP-COMPILE-RESULTS NIL T T "~/asdf-action::format-action/" ((#<ASDF/LISP-ACTION:COMPILE-OP > . #<ASDF/LISP-ACTION:CL-SOURCE-FILE "clog" "clog-gui">)))
 1: ((SB-PCL::EMF ASDF/ACTION:PERFORM) #<unused argument> #<unused argument> #<ASDF/LISP-ACTION:COMPILE-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "clog" "clog-gui">)
 2: ((LAMBDA NIL :IN ASDF/ACTION:CALL-WHILE-VISITING-ACTION))
 3: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS (ASDF/LISP-ACTION:LOAD-OP ASDF/LISP-ACTION:CL-SOURCE-FILE)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "clog" "clog-gui">) [fast-method]
 4: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS :AROUND (T T)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "clog" "clog-gui">) [fast-method]
 5: ((:METHOD ASDF/PLAN:PERFORM-PLAN (T)) #<ASDF/PLAN:SEQUENTIAL-PLAN {10046A56D3}>) [fast-method]
 6: ((FLET SB-C::WITH-IT :IN SB-C::%WITH-COMPILATION-UNIT))
 7: ((:METHOD ASDF/PLAN:PERFORM-PLAN :AROUND (T)) #<ASDF/PLAN:SEQUENTIAL-PLAN {10046A56D3}>) [fast-method]
 8: ((:METHOD ASDF/OPERATE:OPERATE (ASDF/OPERATION:OPERATION ASDF/COMPONENT:COMPONENT)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/SYSTEM:SYSTEM "clog"> :PLAN-CLASS NIL :PLAN-OPTIONS NIL) [fast-method]
 9: ((SB-PCL::EMF ASDF/OPERATE:OPERATE) #<unused argument> #<unused argument> #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/SYSTEM:SYSTEM "clog"> :VERBOSE NIL)
10: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
11: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/SYSTEM:SYSTEM "clog"> :VERBOSE NIL) [fast-method]
12: ((SB-PCL::EMF ASDF/OPERATE:OPERATE) #<unused argument> #<unused argument> ASDF/LISP-ACTION:LOAD-OP "clog" :VERBOSE NIL)
13: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
14: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) ASDF/LISP-ACTION:LOAD-OP "clog" :VERBOSE NIL) [fast-method]
15: (ASDF/SESSION:CALL-WITH-ASDF-SESSION #<CLOSURE (LAMBDA NIL :IN ASDF/OPERATE:OPERATE) {100469A33B}> :OVERRIDE T :KEY NIL :OVERRIDE-CACHE T :OVERRIDE-FORCING NIL)
16: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
17: (ASDF/SESSION:CALL-WITH-ASDF-SESSION #<CLOSURE (LAMBDA NIL :IN ASDF/OPERATE:OPERATE) {100468230B}> :OVERRIDE NIL :KEY NIL :OVERRIDE-CACHE NIL :OVERRIDE-FORCING NIL)
18: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) ASDF/LISP-ACTION:LOAD-OP "clog" :VERBOSE NIL) [fast-method]
19: (ASDF/OPERATE:LOAD-SYSTEM "clog" :VERBOSE NIL)
20: (QUICKLISP-CLIENT::CALL-WITH-MACROEXPAND-PROGRESS #<CLOSURE (LAMBDA NIL :IN QUICKLISP-CLIENT::APPLY-LOAD-STRATEGY) {100468211B}>)
21: (QUICKLISP-CLIENT::AUTOLOAD-SYSTEM-AND-DEPENDENCIES "clog" :PROMPT NIL)
22: ((:METHOD QL-IMPL-UTIL::%CALL-WITH-QUIET-COMPILATION (T T)) #<unused argument> #<CLOSURE (FLET QUICKLISP-CLIENT::QL :IN QUICKLISP-CLIENT:QUICKLOAD) {100466AD4B}>) [fast-method]
23: ((:METHOD QL-IMPL-UTIL::%CALL-WITH-QUIET-COMPILATION :AROUND (QL-IMPL:SBCL T)) #<QL-IMPL:SBCL {1002F2F8C3}> #<CLOSURE (FLET QUICKLISP-CLIENT::QL :IN QUICKLISP-CLIENT:QUICKLOAD) {100466AD4B}>) [fast-me..
24: ((:METHOD QUICKLISP-CLIENT:QUICKLOAD (T)) :CLOG :PROMPT NIL :SILENT NIL :VERBOSE NIL) [fast-method]
25: (QL-DIST::CALL-WITH-CONSISTENT-DISTS #<CLOSURE (LAMBDA NIL :IN QUICKLISP-CLIENT:QUICKLOAD) {100466102B}>)
26: (SB-INT:SIMPLE-EVAL-IN-LEXENV (QUICKLISP-CLIENT:QUICKLOAD :CLOG) #<NULL-LEXENV>)
27: (EVAL (QUICKLISP-CLIENT:QUICKLOAD :CLOG))
28: ((LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL))
29: (SWANK::CALL-WITH-RETRY-RESTART "Retry SLIME interactive evaluation request." #<CLOSURE (LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL) {100466079B}>)
30: (SWANK::CALL-WITH-BUFFER-SYNTAX NIL #<CLOSURE (LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL) {100466077B}>)
31: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK:INTERACTIVE-EVAL "(ql:quickload :clog)") #<NULL-LEXENV>)
32: (EVAL (SWANK:INTERACTIVE-EVAL "(ql:quickload :clog)"))
33: (SWANK:EVAL-FOR-EMACS (SWANK:INTERACTIVE-EVAL "(ql:quickload :clog)") "COMMON-LISP-USER" 5)
34: ((LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD))
35: (SWANK/SBCL::CALL-WITH-BREAK-HOOK #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<FUNCTION (LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD) {10028F988B}>)
36: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGER-HOOK :IN "c:/Users/Administrator/portacle/all/emacsd/elpa/slime-20191224.2328/swank/sbcl.lisp") #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<FUNCTION (LAMBDA NIL :IN..
37: (SWANK::CALL-WITH-BINDINGS ((*STANDARD-INPUT* . #1=#<SWANK/GRAY::SLIME-INPUT-STREAM {1008EDFA53}>) (*STANDARD-OUTPUT* . #2=#<SWANK/GRAY::SLIME-OUTPUT-STREAM {1008EDFB03}>) (*TRACE-OUTPUT* . #2#) (*ERR..
38: ((LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD))
39: ((FLET SB-UNIX::BODY :IN SB-THREAD::NEW-LISP-THREAD-TRAMPOLINE))
40: ((FLET "WITHOUT-INTERRUPTS-BODY-4" :IN SB-THREAD::NEW-LISP-THREAD-TRAMPOLINE))
41: ((FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::NEW-LISP-THREAD-TRAMPOLINE))
42: ((FLET "WITHOUT-INTERRUPTS-BODY-1" :IN SB-THREAD::CALL-WITH-MUTEX))
43: (SB-THREAD::CALL-WITH-MUTEX #<CLOSURE (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::NEW-LISP-THREAD-TRAMPOLINE) {575FBEB}> #<SB-THREAD:MUTEX "thread result lock" owner: #<SB-THREAD:THREAD "worker" ..
44: (SB-THREAD::NEW-LISP-THREAD-TRAMPOLINE #<SB-THREAD:THREAD "worker" RUNNING {10046505E3}> NIL #<CLOSURE (LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD) {100465056B}> NIL)
45: ("foreign function: #x438ADB")
46: ("foreign function: #x404D31")

when it returns to the repl

[package clog-gui]................................
[package clog-gui].

; file: g:/portable windows lisp environment/portacle/portacle/projects/clog/source/clog-gui.lisp
; in: DEFMETHOD CREATE-GUI-MENU-ICON (CLOG-GUI-MENU-BAR)
;     (FORMAT NIL "<button class='~A'>~

;                                   <img height=22 src='~A'></button>"
;             CLASS CLOG-GUI::IMAGE-URL)
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<button class='~A'>~

;                                   <img height=22 src='~A'></button>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <button class='~A'>~

;                                   <img height=22 src='~A'></button>
;                         ^
....
; in: DEFUN ALERT-TOAST
;     (FORMAT NIL
;             "  <div class='w3-panel ~A w3-animate-right w3-display-container'>~

;      <span id=~A-close class='w3-button w3-large w3-display-topright'>&times;</span>~

;      <h3>~A</h3>~

;      <p>~A</p>~

;   </div>"
;             CLOG-GUI::COLOR-CLASS CLOG:HTML-ID CLOG:TITLE CLOG-GUI::CONTENT)
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "  <div class='w3-panel ~A w3-animate-right w3-display-container'>~

;      <span id=~A-close class='w3-button w3-large w3-display-topright'>&times;</span>~

;      <h3>~A</h3>~

;      <p>~A</p>~

;   </div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;       <div class='w3-panel ~A w3-animate-right w3-display-container'>~

;      <span id=~A-close class='w3-button w3-large w3-display-topright'>&times;</span>~

;      <h3>~A</h3>~

;      <p>~A</p>~

;   </div>
;                                                                       ^
.
; in: DEFUN FORM-DIALOG
;     (FORMAT NIL "<div><label class='w3-text-black'><b>~A</b></label>~

;   			       <select class='w3-select w3-border' name='~A-~A'>~A</select></div>"
;             (FIRST CLOG-GUI::L) CLOG:HTML-ID (SECOND CLOG-GUI::L)
;             (FORMAT NIL "~{~A~}"
;                     (MAPCAR
;                      (LAMBDA (CLOG-GUI::S)
;                        (FORMAT NIL "<option value='~A' ~A>~A</option>" # # #))
;                      (FOURTH CLOG-GUI::L))))
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<div><label class='w3-text-black'><b>~A</b></label>~

;   			       <select class='w3-select w3-border' name='~A-~A'>~A</select></div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <div><label class='w3-text-black'><b>~A</b></label>~

;   			       <select class='w3-select w3-border' name='~A-~A'>~A</select></div>
;                                                         ^

;     (FORMAT NIL "<div><input type=radio class='w3-radio' name='~A-~A'~

;                                         id='~A-~A-~A' value='~A' ~A> ~

;                                        <label for='~A-~A-~A'>~A</label></div>"
;             CLOG:HTML-ID (SECOND CLOG-GUI::L) CLOG:HTML-ID (SECOND CLOG-GUI::L)
;             (SECOND CLOG-GUI::S) (SECOND CLOG-GUI::S)
;             (IF (THIRD CLOG-GUI::S)
;                 (THIRD CLOG-GUI::S)
;                 "")
;             CLOG:HTML-ID (SECOND CLOG-GUI::L) ...)
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<div><input type=radio class='w3-radio' name='~A-~A'~

;                                         id='~A-~A-~A' value='~A' ~A> ~

;                                        <label for='~A-~A-~A'>~A</label></div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <div><input type=radio class='w3-radio' name='~A-~A'~

;                                         id='~A-~A-~A' value='~A' ~A> ~

;                                        <label for='~A-~A-~A'>~A</label></div>
;                                                          ^

;     (FORMAT NIL
;             #<(SIMPLE-ARRAY CHARACTER
;                (343)) <div><input class='w3-check' type='checkbox' ~

;                                                     name='~A-~A' id='~A-~A' ~A> ~

;                                                     <label class='w3-text... {100A3B3DFF}>
;             CLOG:HTML-ID (SECOND CLOG-GUI::L) CLOG:HTML-ID (SECOND CLOG-GUI::L)
;             (IF (FOURTH CLOG-GUI::L)
;                 "checked"
;                 "")
;             CLOG:HTML-ID (SECOND CLOG-GUI::L) (FIRST CLOG-GUI::L))
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<div><input class='w3-check' type='checkbox' ~

;                                                     name='~A-~A' id='~A-~A' ~A> ~

;                                                     <label class='w3-text-black' for='~A-~A'>~

;                                                     <b>~A</b></label>~

;                                               </div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <div><input class='w3-check' type='checkbox' ~

;                                                     name='~A-~A' id='~A-~A' ~A> ~

;                                                     <label class='w3-text-black' for='~A-~A'>~

;                                                     <b>~A</b></label>~

;                                               </div>
;                                                   ^

;     (FORMAT NIL
;             #<(SIMPLE-ARRAY CHARACTER
;                (240)) <div><label class='w3-text-black'><b>~A</b></label>~

;                                                    <input class='w3-input w3-border' type='~A'~

;                                                     n... {100A3B49CF}>
;             (FIRST CLOG-GUI::L) (THIRD CLOG-GUI::L) CLOG:HTML-ID
;             (SECOND CLOG-GUI::L) CLOG:HTML-ID (SECOND CLOG-GUI::L)
;             (IF (FOURTH CLOG-GUI::L)
;                 (FOURTH CLOG-GUI::L)
;                 ""))
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<div><label class='w3-text-black'><b>~A</b></label>~

;                                                    <input class='w3-input w3-border' type='~A'~

;                                                     name='~A-~A' id='~A-~A' value='~A'></div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <div><label class='w3-text-black'><b>~A</b></label>~

;                                                    <input class='w3-input w3-border' type='~A'~

;                                                     name='~A-~A' id='~A-~A' value='~A'></div>
;                                                         ^

;     (FORMAT NIL "<div><label class='w3-text-black'><b>~A</b></label>~

;                                  <input class='w3-input w3-border' type='text' name='~A-~A' id='~A-~A'></div>"
;             (FIRST CLOG-GUI::L) CLOG:HTML-ID (SECOND CLOG-GUI::L) CLOG:HTML-ID
;             (SECOND CLOG-GUI::L))
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<div><label class='w3-text-black'><b>~A</b></label>~

;                                  <input class='w3-input w3-border' type='text' name='~A-~A' id='~A-~A'></div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <div><label class='w3-text-black'><b>~A</b></label>~

;                                  <input class='w3-input w3-border' type='text' name='~A-~A' id='~A-~A'></div>
;                                                         ^
..........................
[package clog-gui]................................
[package clog-gui]..

; file: g:/portable windows lisp environment/portacle/portacle/projects/clog/source/clog-gui.lisp
; in: DEFMETHOD CREATE-GUI-MENU-ICON (CLOG-GUI-MENU-BAR)
;     (FORMAT NIL "<button class='~A'>~

;                                   <img height=22 src='~A'></button>"
;             CLASS CLOG-GUI::IMAGE-URL)
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<button class='~A'>~

;                                   <img height=22 src='~A'></button>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <button class='~A'>~

;                                   <img height=22 src='~A'></button>
;                         ^
....
; in: DEFUN ALERT-TOAST
;     (FORMAT NIL
;             "  <div class='w3-panel ~A w3-animate-right w3-display-container'>~

;      <span id=~A-close class='w3-button w3-large w3-display-topright'>&times;</span>~

;      <h3>~A</h3>~

;      <p>~A</p>~

;   </div>"
;             CLOG-GUI::COLOR-CLASS CLOG:HTML-ID CLOG:TITLE CLOG-GUI::CONTENT)
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "  <div class='w3-panel ~A w3-animate-right w3-display-container'>~

;      <span id=~A-close class='w3-button w3-large w3-display-topright'>&times;</span>~

;      <h3>~A</h3>~

;      <p>~A</p>~

;   </div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;       <div class='w3-panel ~A w3-animate-right w3-display-container'>~

;      <span id=~A-close class='w3-button w3-large w3-display-topright'>&times;</span>~

;      <h3>~A</h3>~

;      <p>~A</p>~

;   </div>
;                                                                       ^
.
; in: DEFUN FORM-DIALOG
;     (FORMAT NIL "<div><label class='w3-text-black'><b>~A</b></label>~

;   			       <select class='w3-select w3-border' name='~A-~A'>~A</select></div>"
;             (FIRST CLOG-GUI::L) CLOG:HTML-ID (SECOND CLOG-GUI::L)
;             (FORMAT NIL "~{~A~}"
;                     (MAPCAR
;                      (LAMBDA (CLOG-GUI::S)
;                        (FORMAT NIL "<option value='~A' ~A>~A</option>" # # #))
;                      (FOURTH CLOG-GUI::L))))
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<div><label class='w3-text-black'><b>~A</b></label>~

;   			       <select class='w3-select w3-border' name='~A-~A'>~A</select></div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <div><label class='w3-text-black'><b>~A</b></label>~

;   			       <select class='w3-select w3-border' name='~A-~A'>~A</select></div>
;                                                         ^

;     (FORMAT NIL "<div><input type=radio class='w3-radio' name='~A-~A'~

;                                         id='~A-~A-~A' value='~A' ~A> ~

;                                        <label for='~A-~A-~A'>~A</label></div>"
;             CLOG:HTML-ID (SECOND CLOG-GUI::L) CLOG:HTML-ID (SECOND CLOG-GUI::L)
;             (SECOND CLOG-GUI::S) (SECOND CLOG-GUI::S)
;             (IF (THIRD CLOG-GUI::S)
;                 (THIRD CLOG-GUI::S)
;                 "")
;             CLOG:HTML-ID (SECOND CLOG-GUI::L) ...)
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<div><input type=radio class='w3-radio' name='~A-~A'~

;                                         id='~A-~A-~A' value='~A' ~A> ~

;                                        <label for='~A-~A-~A'>~A</label></div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <div><input type=radio class='w3-radio' name='~A-~A'~

;                                         id='~A-~A-~A' value='~A' ~A> ~

;                                        <label for='~A-~A-~A'>~A</label></div>
;                                                          ^

;     (FORMAT NIL
;             #<(SIMPLE-ARRAY CHARACTER
;                (343)) <div><input class='w3-check' type='checkbox' ~

;                                                     name='~A-~A' id='~A-~A' ~A> ~

;                                                     <label class='w3-text... {100CD7B1BF}>
;             CLOG:HTML-ID (SECOND CLOG-GUI::L) CLOG:HTML-ID (SECOND CLOG-GUI::L)
;             (IF (FOURTH CLOG-GUI::L)
;                 "checked"
;                 "")
;             CLOG:HTML-ID (SECOND CLOG-GUI::L) (FIRST CLOG-GUI::L))
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<div><input class='w3-check' type='checkbox' ~

;                                                     name='~A-~A' id='~A-~A' ~A> ~

;                                                     <label class='w3-text-black' for='~A-~A'>~

;                                                     <b>~A</b></label>~

;                                               </div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <div><input class='w3-check' type='checkbox' ~

;                                                     name='~A-~A' id='~A-~A' ~A> ~

;                                                     <label class='w3-text-black' for='~A-~A'>~

;                                                     <b>~A</b></label>~

;                                               </div>
;                                                   ^

;     (FORMAT NIL
;             #<(SIMPLE-ARRAY CHARACTER
;                (240)) <div><label class='w3-text-black'><b>~A</b></label>~

;                                                    <input class='w3-input w3-border' type='~A'~

;                                                     n... {100CD7B75F}>
;             (FIRST CLOG-GUI::L) (THIRD CLOG-GUI::L) CLOG:HTML-ID
;             (SECOND CLOG-GUI::L) CLOG:HTML-ID (SECOND CLOG-GUI::L)
;             (IF (FOURTH CLOG-GUI::L)
;                 (FOURTH CLOG-GUI::L)
;                 ""))
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<div><label class='w3-text-black'><b>~A</b></label>~

;                                                    <input class='w3-input w3-border' type='~A'~

;                                                     name='~A-~A' id='~A-~A' value='~A'></div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <div><label class='w3-text-black'><b>~A</b></label>~

;                                                    <input class='w3-input w3-border' type='~A'~

;                                                     name='~A-~A' id='~A-~A' value='~A'></div>
;                                                         ^

;     (FORMAT NIL "<div><label class='w3-text-black'><b>~A</b></label>~

;                                  <input class='w3-input w3-border' type='text' name='~A-~A' id='~A-~A'></div>"
;             (FIRST CLOG-GUI::L) CLOG:HTML-ID (SECOND CLOG-GUI::L) CLOG:HTML-ID
;             (SECOND CLOG-GUI::L))
; 
; caught ERROR:
;   during macroexpansion of
;   (FORMATTER "<div><label class='w3-text-black'><b>~A</b></label>~

;                                  <input class='w3-input w3-border' type='text' name='~A-~A' id='~A-~A'></div>").
;   Use *BREAK-ON-SIGNALS* to intercept.
;   
;    error in FORMAT: Unknown directive (character: Return)
;     <div><label class='w3-text-black'><b>~A</b></label>~

;                                  <input class='w3-input w3-border' type='text' name='~A-~A' id='~A-~A'></div>
;                                                         ^
.
; 
; compilation unit aborted
;   caught 1 fatal ERROR condition
;   caught 14 ERROR conditions

CL-USER>

Apologies for the verbosity, as I'm just rekindling the fire and love for programming again and haven't yet developed the required eyes to analyse the stack traces Common lisp gives.

Many thanks for your sage guidance and attentions :)

Thank you for your offerings of software I can see from the demos this is potentially quite empowering to newbs and a human way of working.

I'm sure I could get it going just by installing on debian at this stage to follow the demos. Maybe it's something to do with portacle for windows in which case I could give a go at a patch for them if I had any indication what the problem could be. By the way it dumped on a foreign function interface, my guessing is something changed in whatever library that called on the system side.

substantive typo in Common Lisp - "The Tutorial" Part 2

In CL tutorial part 2, you say:

"In emacs execute C-x C-f and type a file name say like hello.lisp.
The .lisp extension is most often used.
We can not enter our program in to our file:
(print "hello")
Save the file C-x C-s"

Clearly, you meant to say: "We can now enter our program into our file"

This could be very confusing for beginners.

Not able to compile

Could not get this to work.
commit: b79a343
OS: Ubuntu 20.04.1
SBCL: 2.0.1.debian

[package clog-user]
;
; caught ERROR:
; READ error during COMPILE-FILE:
;
; Symbol "UPDATE-ASDF-SYSTEM-HTML-DOCS" not found in the MGL-PAX package.
;
; Line: 130, Column: 39, File-Position: 3658
;
; Stream: #<SB-INT:FORM-TRACKING-STREAM for "file ...../clog/clog-helpers.lisp" {1005EC2CB3}>

Opening gui_builder - browser content is mangled

Hello RabbiBotton,

I do have the following issue as the situation is al follows:

  • Ubuntu 20.10
  • Firefox Webbrowser as default
  • The Browser is closed
  • running (clog-tools:clog-builder)
  • Firefox will open, but the content/text is mangled (look at atatched image).
    clog_mangled

But if firefox is already open, a new tab will open and the content will be displayed properly:
clog_correct

The Firefox version is as followin
firefox_ubuntu
:

[Question] Progressive Web Apps with CLOG

I was curious about whether one can make a PWA (Progressive Web App) with CLOG. In particular, to make a web app with CLOG which can be opened in a browser as usual, but which can also

  1. be 'installed', so assets don't need to be fetched again (decreasing subsequent load times) and users can have a desktop/homescreen shortcut to it (it still opens in a browser)
  2. work offline, possibly storing server side data locally, and/or saving database changes locally and synchronizing with the server when online.
  3. use OS sharing protocols (via Web Share API and Web Share Target API)

Thoughts?

Tutorial 7 - Value 800 is not of type STRING

Tutorial 7 fails to run (on SBCL 2.1.1) returning
The value 800 is not of type STRING when binding STRING

width and height are returning integers
changing:

(flet ((set-bounds ()
   	   (setf bounds-x (parse-integer (width (window body)) :junk-allowed t))
   	   (setf bounds-y (parse-integer (height (window body)) :junk-allowed t))))

to:

(flet ((set-bounds ()
		   (setf bounds-x (width (window body)))
		   (setf bounds-y (height (window body)))))

runs as expected

Add a default page name

In Safari on macOS, the text box is nearly invisible, so I'd like to suggest adding a default title for new pages.

(let ((new-page (create-form-element (main app) :text :value "New Page"))

(let ((new-page (create-form-element (main app) :text))

Wait for script to load to run code

Hello,

I'm having a problem integrating some JS I'm loading dynamically. I'm using add-script.
Problem is, I need to find a way of hooking to the script's 'load' event somehow, before being able to run some initialization code, cause that init code requires the library to be already loaded.

I have something like this:

(defun init-dashboard (body)
  (load-script (html-document body) "https://gridstackjs.com/node_modules/gridstack/dist/gridstack-h5.js")
  (load-css (html-document body) "https://gridstackjs.com/node_modules/gridstack/dist/gridstack.min.css"))

(defvar *dashboard*)

(defun create-dashboard (clog-obj)
  (setf *dashboard*
        (create-div clog-obj :class "grid-stack"))
  (clog:js-execute clog-obj "window.dashboard = GridStack.init()"))

But I cannot simply call create-dashboard after init-dashboard when my program starts, as the script may not have been loaded yet, and I get JS errors.

Do you know how I can achieve this?

I thought of perhaps adding an extra on-load callback argument to add-script, but don't know how to implement, as CLOG only works with set-event, and I'm not sure I can do set-event with a script element on a load event.

Please let me know if you have any ideas.

Installation: which SBCL version?

Hi,

During the installation step, I got an error with the Ironclad-VM library in quicklisp (please find the error details below).

I guess this might be an Ironclad-related issue but I want to try to see if using your specific SBCL version may work around this.

Could you tell me the SBCL version you used for this project?

My error details are below:

CL-USER> (ql:quickload :clog)
...
[package ironclad]................................
[package ironclad-vm]
; 
; caught ERROR:
;   READ error during COMPILE-FILE:
;   
;     Lock on package SB-VM violated when interning MAKE-EA while in package
;     IRONCLAD-VM.
;   See also:
;     The SBCL Manual, Node "Package Locks"
;   
;     (in form starting at line: 34, column: 0, position: 1344)

and the Slime debugger window shows:

COMPILE-FILE-ERROR while compiling
   #<IRONCLAD-SOURCE-FILE "ironclad" "src" "opt" "sbcl" "x86oid-vm">
   [Condition of type UIOP/LISP-BUILD:COMPILE-FILE-ERROR]

Restarts:
 0: [RETRY] Retry compiling #<IRONCLAD-SOURCE-FILE "ironclad" "src" "opt" "sbcl" "x86oid-vm">.
 1: [ACCEPT] Continue, treating compiling #<IRONCLAD-SOURCE-FILE "ironclad" "src" "opt" "sbcl" "x86oid-vm"> as having been successful.
 2: [RETRY] Retry ASDF operation.
 3: [CLEAR-CONFIGURATION-AND-RETRY] Retry ASDF operation after resetting the configuration.
 4: [RETRY] Retry ASDF operation.
 5: [CLEAR-CONFIGURATION-AND-RETRY] Retry ASDF operation after resetting the configuration.
 --more--

Thank you for your support.

Wrong reaction on :html-id 0

Hello! I have discovered a new problem of my favorite clog😂
When I ordered a clog-element as :html-id 0, all operation on it will certainly redirect to <body>... It's difficult to say but it can be easily produced by add :html-id 0 to the 70 line of 08-tutorial, change it to (let* ((div1 (create-div body :html-id 0)).
It is a little problem, but I hope it will do some help. :D
image

Suggestions

I am looking for suggestions on ways to make CLOG "feel" lispy - let me know!

[Question] How does clog work conceptually? And which kinds of apps would/wouldn't be a good fit for clog?

I'm new to Common Lisp and just found Clog recently. It's really interesting and impressive, but conceptually I don't really understand it.

I get the idea of treating a browser window like a screen, but if I left it at that clog couldn't be anything be used for anything more than pet projects, intranet applications or streaming applications, but not for serving thousands of users from a single instance. I expect most people aren't trying to build the next Netflix on the web, but would like more powerful GUI abstractions.

If clog is meant as a pure GUI (client/server) framework then that should be mentioned somewhere.
From the docs it's really difficult to tell if it would be appropriate for most web apps; i.e. small infrequent exchanges of data to over an unreliable connection.

I don't want to give up all of the things that web pages give us. Ideally, I want the best of both worlds, rich dynamic interactions, local caching of data, and robustness against network connectivity issues. The other impression it gives me is one of tight client/server relationship (almost like an ssh session). In that case it seems like it would severely limit the number of clients it can service at a single time.

So far documentation has been my biggest gripe with the lisp community. Clog is far better than most libraries I've seen. You have a fair bit of documentation, but it is not written for beginners or people coming from more common ways of writing web code.

From the README

The key to CLOG is the relationship it forms with a Browser window or Browser control compiled to native code. CLOG uses websockets for communications and the browser to render a GUI that maintains an active soft realtime connection. For most CLOG applications all programming logic, events and decisions are done on the server which can be local, or remote over the web.

From the user manual

The Common Lisp Omnificent GUI, CLOG for short, uses web technology to produce graphical user interfaces for applications locally or remotely. CLOG can take the place, or work alongside, most cross-platform GUI frameworks and website frameworks. The CLOG package starts up the connectivity to the browser or other websocket client (often a browser embedded in a native template application.)

These explanations are a great to get people excited about it, but are insufficient once you want to jump in with an idea or project.

I.e. So, you go to the URL and get some HTML, CSS, jquery, and boot.js, which connect a websocket back to the server. Ok, then what? If I have a drag-gable window; am I streaming mouse positions to the server for it to determine what to do next? How is it doing that? Via events it seems, but those events call JS functions I presume...

Also, if I change content is it doing incremental updates with DOM mutations or is it conceptually closer to a get or post? And so on.

Can you provide some conceptual explanations in the docs for some of the ways you can use clog (especially as it relates to other web applications)?
Descriptions I've seen online have been calling this an isomorphic web framework, but that doesn't really sound right either. My impression of those is that pages can be rendered server-side, but that's only done as part of bootstrapping after which they run (almost) entirely on in-browser code.

I would love to give this a try for a project I'm working, but it's like an e-reader, so it's much closer to a standard webpage than a desktop application which means the first problem I'm faced with is persistence. If someone drives through a tunnel or they live on a farm with poor cell service and they lose their connection and need to start over, how would I go about solving that? How much of it can be handled by clog or other components and how much would I need to write myself?

Cannot run tutorial 1

  1. Instructions followed on this page: https://github.com/rabbibotton/clog

  2. I tried the following on a laptop, desktop and vm:

a) All environments are running the latest debian 10.8
b) All environments had their quicklisp installations deleted, sbcl reinstalled, quicklisp reinstalled and only clog package installed.

  1. I ran the following on all 3 environment:

CL-USER> (ql:quickload :clog)
CL-USER> (clog:run-tutorial 1)

  1. After do run-tutorial 1 I get the following information:

Symbol "RUN-TUTORIAL" not found in the CLOG package.

Line: 1, Column: 17, File-Position: 17

Stream: #<SB-IMPL::STRING-INPUT-STREAM {1001EB12A3}>
[Condition of type SB-INT:SIMPLE-READER-PACKAGE-ERROR]

  1. Can I get comments on why this might be hapening? Unlike dpkg, I have had these kinds of issues with various packages and I suspect it might be quicklisp even if it was on 3 different clean environments.

I am curious to learn how to start debugging these kinds of issues.

Last commit was a breaking change.

After the last commit I now have an extra line ') ') ') at the top of a gui body and it broke various bits of things in my app under development. Rolling clog back to 13a09b2 fixed it. Have to get to sleep but will try to figure out what might have happened tomorrow.

Windows WSL information in README.md may be incomplete/may need improvement

In the README.md file it says: "Tip for Windows WSL linux user. Create a symbolic link from wslview to xdg-open in /usr/local/bin so that run-tutorial uses the windows browser."

I don't know about WSL1 but in WSL2 (using Ubuntu) you do not need to create a symbolic link. What you do need to do in that case, though, is to install the "xdg-utils" package with sudo apt install xdg-utils, so xdg-open is available, as xdg-open is not installed by default. After that Microsoft Edge (my default) pops up when I run (clog:run-tutorial 1) . I think eliminating the symbolic link part may make it easier to understand how to run clog for beginners than having to deal with symbolic links (as easy as it is).

Some systems failed to build for Quicklisp dist

Building with SBCL 2.0.5 / ASDF 3.3.1 for quicklisp dist creation.

Trying to build commit id a884327

clog fails to build with the following error:

; caught WARNING:
;   Literal string as destination in FORMAT:
;     (FORMAT "~(~a~)Storage.length" STORAGE-TYPE)
...
Unhandled UIOP/LISP-BUILD:COMPILE-FILE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING {1000A10083}>: COMPILE-FILE-ERROR while compiling #<CL-SOURCE-FILE "clog" "clog-window">

clog/tools fails to build because of a failure in clog.

hello-clog fails to build because of a failure in clog.

Full log here

Omnificient

The repo description says Omnificent, and the text of README.md has both Omnificent and Omnificient. Which one is correct?

CLOG learning center app

Hi.

As part of my self-teaching of CLOG I decided to build a small app. I'm building a dashboard with many of the CLOG resources I could find and I'm putting there in windows, like manual, readmes, etc. The coolest feature, though, is the ability to browse the CLOG tutorials right from there; inspect their source and run.

If you want to try, just load and start: https://gist.github.com/mmontone/3a5a8a57675750e99ffb7fa64f40bc39#file-clog-learn-lisp

I've just started, so it is still incomplete, but I'm planing to develop further.

Hope you like it.

clog-learn screenshot

Tutorial 06 doesn't (fully) take into account browser closing connection

I was reading through tut. 06 and it occurred to me: "but after the loop exits because of connection loss, this will surely try to access invalid obj". And sure as hell, when you close the connection while the event handler is still looping, it crashes.

Furthermore, the sleeps give user enough time to close the connection while the thread is asleep and thinks the connection is valid.

EDIT: Now that I looked at it again, probably only the access after the first sleep needs to be guarded.

I'd think about adding a condition for "invalid object access", so handlers could deal with it better (later there could be even macros to make it sweeter).

Tutorial 6

Hello, Thank you so much for creating this very interesting piece of technology. I was running tutorial 6 and when I clicked the second time to stop it the console printed the start message once followed by two stop messages. I am running on Ubuntu 20 with an Intel processor and using the firefox browser. I am wondering if there is any minimum requirements I am not meeting that could be causing the double printing or if it is running as designed.

Upload file with form

Discussed in #91

Originally posted by 3vau December 5, 2021
Hello!
I'm a noob of clog. I really love its simple and powerful, but when I tried to use clog to upload file to my server through form, I got some trouble.
I tried to use post method, just like the way in tutorial 17, and with encoding of "multipart/form-data". but after I submit the form, the form-post-data is still (("undefined") . nil) . I also tried to use post-parameter in hunchentoot, but it tell me hunchentoot:*request* is unbound and it is difficult for me to deal with it.
If anyone can give me a direction? Thanks! :)

How to query DOM?

Say, I created a bunch of form elements with create-form-element but didn't keep references. How can I get references to those elements? In jQuery I may do something like $('form').find('input'). Is it possible with CLOG? Thanks.

Manual out of sync

First of all: thank you for this system!

Near the beginning of the manual, I noticed that its text doesn't match the current code.

It says

CL-USER> (load "path to clog/demos/01-snake.lisp")
CL-USER> (clog-user:start-demo)

while I had to run

(load "path to clog/demos/01-demo.lisp")
(clog-demo-1:start-demo)

I assume that at least for the file name what the manual says should be correct because it is more telling, but for start-demo, I'm not sure because one could load more than one demo. Maybe something like (clog-user:start-demo N) would make sense if more than one is loaded?

Compile error

I got this message when I tried to load CLOG:

; 
; caught ERROR:
;   READ error during COMPILE-FILE:
;   
;     Symbol "UPDATE-ASDF-SYSTEM-HTML-DOCS" not found in the MGL-PAX package.
;   
;       Line: 151, Column: 39, File-Position: 4380
;   
;       Stream: #<SB-INT:FORM-TRACKING-STREAM for "file /tmp/clog/source/clog-helpers.lisp" {1006D42433}>

That error falls in this function:

(defun make-html ()
  (load-world)
  (mgl-pax:update-asdf-system-html-docs clog:@CLOG-MANUAL :clog))

I tried replacing it with this:

(defun make-html ()
  (load-world)
  (error "Not implemented"))

Then it compiled and worked with no problems. All dependencies were whatever versions Quicklisp is serving right now.

Declarative GUI syntax

Just for fun, I wrote this macro:

(defmacro with-gui (obj spec &body body)
  (let ((let-bindings ())
	(used-bindings ()))
    (labels ((create-from-spec (spec parent-binding)
	       (destructuring-bind (gui-func-name args &body children)
		   spec
		 (let* ((gui-func-args (alexandria:remove-from-plist args :bind))
			(bind (getf args :bind))
			(binding (or bind (gensym)))
			(create-func-name (intern (concatenate 'string "CREATE-" (symbol-name gui-func-name)))))
		   (push `(,binding (,create-func-name ,parent-binding ,@gui-func-args)) let-bindings)
		   (when (or bind children)
		     (push binding used-bindings))
		   (dolist (child-spec children)
		     (create-from-spec child-spec binding))))))
      (create-from-spec spec obj)
      `(let* ,(reverse let-bindings)
	 (declare (ignore ,@(set-difference (mapcar #'first let-bindings) used-bindings)))
	 ,@body))))

Spec syntax is basically, (creation-func args &body children).
And for binding some widget to a variable for later use, add :bind binding-name as part of the args.

As an example, this example from tutorial 24:

(defun on-new-window (body)
  (setf (title (html-document body)) "Tutorial 22")  
  ;; For web oriented apps consider using the :client-movement option.
  ;; See clog-gui-initialize documentation.
  (clog-gui-initialize body)
  (add-class body "w3-cyan")  
  (let* ((menu  (create-gui-menu-bar body))
	 (tmp   (create-gui-menu-icon menu :on-click 'on-help-about))
	 (file  (create-gui-menu-drop-down menu :content "File"))
	 (tmp   (create-gui-menu-item file :content "Count" :on-click 'on-file-count))
	 (tmp   (create-gui-menu-item file :content "Browse" :on-click 'on-file-browse))
	 (tmp   (create-gui-menu-item file :content "Drawing" :on-click 'on-file-drawing))
	 (tmp   (create-gui-menu-item file :content "Movie" :on-click 'on-file-movies))
	 (tmp   (create-gui-menu-item file :content "Pinned" :on-click 'on-file-pinned))
	 (tmp   (create-gui-menu-item file :content "Tutorials" :on-click 'open-tutorials-window))
	 (win   (create-gui-menu-drop-down menu :content "Window"))
	 (tmp   (create-gui-menu-item win :content "Maximize All" :on-click 'maximize-all-windows))
	 (tmp   (create-gui-menu-item win :content "Normalize All" :on-click 'normalize-all-windows))
	 (tmp   (create-gui-menu-window-select win))
	 (dlg   (create-gui-menu-drop-down menu :content "Dialogs"))
	 (tmp   (create-gui-menu-item dlg :content "Alert Dialog Box" :on-click 'on-dlg-alert))	 
	 (tmp   (create-gui-menu-item dlg :content "Input Dialog Box" :on-click 'on-dlg-input))
	 (tmp   (create-gui-menu-item dlg :content "Confirm Dialog Box" :on-click 'on-dlg-confirm))
	 (tmp   (create-gui-menu-item dlg :content "Form Dialog Box" :on-click 'on-dlg-form))
	 (tmp   (create-gui-menu-item dlg :content "Server File Dialog Box" :on-click 'on-dlg-file))
	 (tst   (create-gui-menu-drop-down menu :content "Toasts"))
	 (tmp   (create-gui-menu-item tst :content "Alert Toast" :on-click 'on-toast-alert))
	 (tmp   (create-gui-menu-item tst :content "Warning Toast" :on-click 'on-toast-warn))
	 (tmp   (create-gui-menu-item tst :content "Success Toast" :on-click 'on-toast-success))
	 (help  (create-gui-menu-drop-down menu :content "Help"))
	 (tmp   (create-gui-menu-item help :content "About" :on-click 'on-help-about))
	 (tmp   (create-gui-menu-full-screen menu)))
    (declare (ignore tmp)))
  (set-on-before-unload (window body) (lambda(obj)
					(declare (ignore obj))
					;; return empty string to prevent nav off page
					"")))

Can be rewritten as:

(defun on-new-window-decl (body)
  (setf (title (html-document body)) "Tutorial 22")  
  ;; For web oriented apps consider using the :client-movement option.
  ;; See clog-gui-initialize documentation.
  (clog-gui-initialize body)
  (add-class body "w3-cyan")
  (with-gui body
    (gui-menu-bar ()
      (gui-menu-icon (:on-click 'on-help-about))
      (gui-menu-drop-down (:content "File")
        (gui-menu-item (:content "Count" :on-click 'on-file-count))
	(gui-menu-item (:content "Browse" :on-click 'on-file-browse))
	(gui-menu-item (:content "Drawing" :on-click 'on-file-drawing)))   
      (gui-menu-drop-down (:content "Window")
	(gui-menu-item (:content "Maximize All" :on-click 'maximize-all-windows))
	(gui-menu-item (:content "Normalize All" :on-click 'normalize-all-windows))
	(gui-menu-window-select ()))
      (gui-menu-drop-down (:content "Dialogs")
	(gui-menu-item (:content "Alert Dialog Box" :on-click 'on-dlg-alert))	 
	(gui-menu-item (:content "Input Dialog Box" :on-click 'on-dlg-input))
	(gui-menu-item (:content "Confirm Dialog Box" :on-click 'on-dlg-confirm))
	(gui-menu-item (:content "Form Dialog Box" :on-click 'on-dlg-form))
	(gui-menu-item (:content "Server File Dialog Box" :on-click 'on-dlg-file)))
      (gui-menu-drop-down (:content "Toasts")
	 (gui-menu-item (:content "Alert Toast" :on-click 'on-toast-alert))
	 (gui-menu-item (:content "Warning Toast" :on-click 'on-toast-warn))
	 (gui-menu-item (:content "Success Toast" :on-click 'on-toast-success)))
      (gui-menu-drop-down (:content "Help")
         (gui-menu-item (:content "About" :on-click 'on-help-about)))
      (gui-menu-full-screen ())))
  (set-on-before-unload (window body) (lambda(obj)
					(declare (ignore obj))
					;; return empty string to prevent nav off page
					"")))

The macroexpansion also takes care of the let bindings to ignore:

(LET* ((#:G1066 (CREATE-GUI-MENU-BAR BODY))
       (#:G1067 (CREATE-GUI-MENU-ICON #:G1066 :ON-CLICK 'ON-HELP-ABOUT))
       (#:G1068 (CREATE-GUI-MENU-DROP-DOWN #:G1066 :CONTENT "File"))
       (#:G1069
        (CREATE-GUI-MENU-ITEM #:G1068 :CONTENT "Count" :ON-CLICK
                              'ON-FILE-COUNT))
       (#:G1070
        (CREATE-GUI-MENU-ITEM #:G1068 :CONTENT "Browse" :ON-CLICK
                              'ON-FILE-BROWSE))
       (#:G1071
        (CREATE-GUI-MENU-ITEM #:G1068 :CONTENT "Drawing" :ON-CLICK
                              'ON-FILE-DRAWING))
       (#:G1072 (CREATE-GUI-MENU-DROP-DOWN #:G1066 :CONTENT "Window"))
       (#:G1073
        (CREATE-GUI-MENU-ITEM #:G1072 :CONTENT "Maximize All" :ON-CLICK
                              'MAXIMIZE-ALL-WINDOWS))
       (#:G1074
        (CREATE-GUI-MENU-ITEM #:G1072 :CONTENT "Normalize All" :ON-CLICK
                              'NORMALIZE-ALL-WINDOWS))
       (#:G1075 (CREATE-GUI-MENU-WINDOW-SELECT #:G1072))
       (#:G1076 (CREATE-GUI-MENU-DROP-DOWN #:G1066 :CONTENT "Dialogs"))
       (#:G1077
        (CREATE-GUI-MENU-ITEM #:G1076 :CONTENT "Alert Dialog Box" :ON-CLICK
                              'ON-DLG-ALERT))
       (#:G1078
        (CREATE-GUI-MENU-ITEM #:G1076 :CONTENT "Input Dialog Box" :ON-CLICK
                              'ON-DLG-INPUT))
       (#:G1079
        (CREATE-GUI-MENU-ITEM #:G1076 :CONTENT "Confirm Dialog Box" :ON-CLICK
                              'ON-DLG-CONFIRM))
       (#:G1080
        (CREATE-GUI-MENU-ITEM #:G1076 :CONTENT "Form Dialog Box" :ON-CLICK
                              'ON-DLG-FORM))
       (#:G1081
        (CREATE-GUI-MENU-ITEM #:G1076 :CONTENT "Server File Dialog Box"
                              :ON-CLICK 'ON-DLG-FILE))
       (#:G1082 (CREATE-GUI-MENU-DROP-DOWN #:G1066 :CONTENT "Toasts"))
       (#:G1083
        (CREATE-GUI-MENU-ITEM #:G1082 :CONTENT "Alert Toast" :ON-CLICK
                              'ON-TOAST-ALERT))
       (#:G1084
        (CREATE-GUI-MENU-ITEM #:G1082 :CONTENT "Warning Toast" :ON-CLICK
                              'ON-TOAST-WARN))
       (#:G1085
        (CREATE-GUI-MENU-ITEM #:G1082 :CONTENT "Success Toast" :ON-CLICK
                              'ON-TOAST-SUCCESS))
       (#:G1086 (CREATE-GUI-MENU-DROP-DOWN #:G1082 :CONTENT "Help"))
       (#:G1087
        (CREATE-GUI-MENU-ITEM #:G1082 :CONTENT "About" :ON-CLICK
                              'ON-HELP-ABOUT))
       (#:G1088 (CREATE-GUI-MENU-FULL-SCREEN #:G1066)))
  (DECLARE
   (IGNORE #:G1067 #:G1069 #:G1070 #:G1071 #:G1073 #:G1074 #:G1075 #:G1077
    #:G1078 #:G1079 #:G1080 #:G1081 #:G1083 #:G1084 #:G1085 #:G1086 #:G1087
    #:G1088)))

Posting here in case somebody likes it and wants to use.

Unable to install with Quicklisp on Windows 10, SBCL 2.0

I saw in the manual that Clog is periodically tested on Windows.
I currently have SBCL 2.0, the only official binary for Windows, used with Emacs 27.2 native for Windows and Slime, on Windows 10.
I followed the instructions to install with Quicklisp, but ran into the following error.

[package cl+ssl]
;
; compilation unit aborted
; caught 1 fatal ERROR condition
; Evaluation aborted on #<CFFI:LOAD-FOREIGN-LIBRARY-ERROR "Unable to load any of the alternatives:~% ~S" {100427AA73}>.

My plan now, rather than trying to compile a more up-to-date SBCL for Windows, is to use Docker, and pick up a standard Docker image for SBCL, and use it locally with Docker Desktop, but eventually deploy on a VPS with the same Docker image.
Still curious though if there is a quick fix that would allow me to play with this using Windows SBCL.

clog-multimedia; media-duration causes parse error

(media-duration ((obj clog-multimedia)) is throwing an error;
it is fetching the property "loop" instead of "duration", then failing to parse as an integer

definition should change to:

(defmethod media-duration ((obj clog-multimedia))
  (property obj "duration"))

This returns a string-of-float, parse-integer will continue throwing parse error
consider using parse-float or just returning the string

Note that
(media-position ...)
is currently returning a string (these should be consistent)

demo 1 fail, demo 2 ok with warnings, manual ok

$ git clone https://github.com/rabbibotton/clog.git
⋮
(ql:update-all-dists)
(ql:quickload "clog")
(clog-user:run-demo 1)	; error no such external symbol
(clog-user::run-demo 1)
⋮
;   In START-GAME: Unused lexical variable BR
⋮
New connection id - 1 - #<SERVER #x3020B18785BD>
[2021-02-01 13:09:15 [ERROR]] Error while processing connection: The condition on #<BASIC-TCP-STREAM ISO-8859-1 (SOCKET/31) #x3020B143B96D> : 
Broken pipe (error #32) during write occurred with errno: 0.
⋮
The value NIL, derived from the initform NIL, can not be used to set the value of the slot CLOG-USER::SNAKE in #<CLOG-USER::APP-DATA #x3020B1A1D1BD>, because it is not of type CONS.
   [Condition of type CCL::BAD-SLOT-TYPE-FROM-INITFORM]
  0: (CCL::%SHARED-INITIALIZE #<CLOG-USER::APP-DATA #x3020B1A1D1BD> T NIL)
      Locals:
        INSTANCE = #<CLOG-USER::APP-DATA #x3020B1A1D1BD>
        SLOT-NAMES = T
        INITARGS = NIL
        WRAPPER = #<CCL::CLASS-WRAPPER CLOG-USER::APP-DATA #x3020B0679E1D>
        CLASS = #<STANDARD-CLASS CLOG-USER::APP-DATA>
        #:G135927 = (#<STANDARD-EFFECTIVE-SLOT-DEFINITION for instance slot CLOG-USER::SNAKE #x3020B0679FAD>)
        SLOTD = #<STANDARD-EFFECTIVE-SLOT-DEFINITION for instance slot CLOG-USER::SNAKE #x3020B0679FAD>
        PREDICATE = CONSP
        IGNORE = NIL
        NEW-VALUE = NIL
        FOUNDP = NIL
        INITFUNCTION = #<Compiled-function FALSE #x300000085B4F>
        NEWVAL = NIL

(clog-user::run-demo 2) ; chat works despite minor warnings.
; In an anonymous lambda form inside SEND-MESSAGE: Unused lexical variable KEY
; In an anonymous lambda form inside ON-NEW-WINDOW: Unused lexical variable OBJ
; In ON-NEW-WINDOW: Unused lexical variable TMP (4 references)
; In ON-NEW-WINDOW: Unused lexical variable CAPTION

(clog:open-manual) ; manual browser works with no warnings.

installing clog using portacle on Linux is failing

Hello,

I'm not able to install clog using portacle on Linux:

CL-USER> (ql:quickload :clog)
; Evaluation aborted on #<QUICKLISP-CLIENT:SYSTEM-NOT-FOUND {100A461433}>.

are there any hints to solve this issue?

Beside of this quicklisp is working properly, e.g. (ql:quickload "mcclim") is working properly.

Best

Create a single Tutorials ASDF system

It would be cool to run:

(ql:quickload :clog-tutorials)
(clog-tutorials:start)

It should open the web page with the list of all tutorials where I can click and view them all without having to load separate lisp files manually.

looping for a dynamic table

I have this pseudo-code:

(loop for (id name some-field) in results-sql
  do (let ((row (create-row table)))
    (create-table-column :content id)
    (set-on-click row (lambda (obj) (my-on-click obj id))))

(defun my-on-click (obj id)
  (create-gui-window obj :title (format nil "Id: ~a" id)))

results-sql is a list of lists, returned by running an SQL statement.

However, it seems that whatever row I click on clog, I get the last id value in the results-sql list (looking at the window title). I analyzed in detail the clog-db-admin.lisp and I can't see any difference between my code. Would you have an idea why is this? I need the loop macro because I want to destructure the row.

Non escaped parameters in clog-db-admin::edit-record

When trying to update a record from clog-db-admin, if the row has characters like ', the thread
fails with the following error:

Could not prepare an sqlite statement.
Code ERROR: near "Cultural": syntax error.

This occurs because the sql creation in clog-db-admin::edit-record does not properly escape the
parameters. I will provide a PR fixing this.

Tutorial 12, missing "No dice!"

The default router never gets to say "No Dice!". On tutorial 12, when going to a route that is not /tutorial/tut-11.html nor any of the other handled paths like /page1, it instead says "Not Found".

Can CLOG be run without Clack?

Can CLOG be used without Clack? The reason is that Clack is LLGPL, which many companies don't have on their white list.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.