rabbibotton / clog Goto Github PK
View Code? Open in Web Editor NEWCLOG - The Common Lisp Omnificent GUI
License: Other
CLOG - The Common Lisp Omnificent GUI
License: Other
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?
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
I am looking for suggestions on ways to make CLOG "feel" lispy - let me know!
Can CLOG be used without Clack? The reason is that Clack is LLGPL, which many companies don't have on their white list.
Hello RabbiBotton,
I do have the following issue as the situation is al follows:
But if firefox is already open, a new tab will open and the content will be displayed properly:
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
Thoughts?
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}>
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
Output
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 :)
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
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.
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]
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
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.
currently says:
The clog-repl URL is http://127.0.0.1/repl body will always refer to the
last access of that URL.
should be:
The clog-repl URL is http://127.0.0.1:8080/repl body will always refer to the
last access of that URL.
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.
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".
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.
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.
Line 255 in 5de7cad
$ 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.
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"))
Line 62 in 74e38ba
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.
(create-form-element form :select) does not work. As all kind of form elements can be used with (create-form-element ...) it would be logical to also have :select as an option.
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.
Whilst quickloading clog:
[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: 3763
in the clog-helpers.lisp file
Running on Windows, portacle SBCL
Hi!,
I was following the tutorial at https://docs.google.com/document/d/1z8w95aB2hES7LYXWfHMB3GNSYNwayCiHczJOo5TinOU/edit#
But trying to save the template the application does not take input, I cannot select the output folder where to save the system nor does entering a name produces any result.
clog is stuck in this screen
Hello,
I was thinking of creating maps with d3/d3-geo. Any tips on how to implement such foreign lib FFI with clog?
Instructions followed on this page: https://github.com/rabbibotton/clog
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.
CL-USER> (ql:quickload :clog)
CL-USER> (clog:run-tutorial 1)
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]
I am curious to learn how to start debugging these kinds of issues.
Since CLOG is interactive and live it is an amazing platform to teach Common Lisp. I am looking for someone interested in writing a CLOG program to teach Common Lisp! If interested please let me know, I am willing to help!
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.
I created a page for CLOG on http://cliki.net/CLOG but it's very rudimentary.
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! :)
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.
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'>×</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'>×</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'>×</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'>×</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'>×</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'>×</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.
Greetings from Hacker News!
Out of curiosity, why are you using Google Docs for the tutorial posts? It's surprising, a bit distracting, and the mobile view of code might be lacking.
I'd include them in the repo: save the docs as docx files, then use pandoc to turn those into Markdown files. Let me know if you could use help!
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).
https://stackoverflow.com/a/54303184/546404
How difficult would it be to add touch events as a fallback for mouse-less interaction?
Safari doesn't implement the DragEvent interface. It adds a dataTransfer property to MouseEvent instead. See WebKit bug #103423.
https://caniuse.com/dragndrop under known issues.
https://developer.mozilla.org/en-US/docs/Web/API/Touch_events
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.
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).
The repo description says Omnificent, and the text of README.md has both Omnificent and Omnificient. Which one is correct?
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.
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?
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.
(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)
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.
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.
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.
This line:
;; Open a browser to http://12.0.0.1:8080 - the default for CLOG apps
Should read:
;; Open a browser to http://127.0.0.1:8080 - the default for CLOG apps
From the description of CLOG, it feels that it is close in spirit to Weblocks.
Probably it can be useful to create a CLOG powered widget for Weblocks to allow custom drawing and event handling.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.