Docs and clean up.

This commit is contained in:
David Botton 2020-12-14 13:28:09 -05:00
parent fc7c764d2d
commit 252f2bd922
4 changed files with 74 additions and 28 deletions

View file

@ -1,5 +1,4 @@
# CLOG - The Common Lisp Omnificent GUI # CLOG - The Common Lisp Omnificent GUI
## David Botton <david@botton.com> ## David Botton <david@botton.com>
@ -9,5 +8,40 @@
#### ####
The Common Lisp Omnificient GUI, CLOG for short, uses web technology The Common Lisp Omnificient GUI, CLOG for short, uses web technology
to produce graphical user interfaces for applications locally or to produce graphical user interfaces for applications locally or
remotely. remotely, ie as web applications.
Status:
- Connection methods
- Websockets - Done
- AJAX/HTML - to do (In 2021 are there browsers supporting Websockets?)
- Long Poll - to do (Needed for websites for webcrawlers and firewalls)
- Direct API access to native browser components - to do
- HTML bindings and Browser - to do
- Base (Not per se a binding of Node in DOM but takes its place)
- Base Elements (HTML Elements)
- Canvas - HTML 5 Canvas bindings
- SVG - HTML SVG vector graphics
- Multimedia - HTML 5 Audio and Video
- Styles - CSS Style blocks
- Window, Navigator, Screen, Location, Document
- CLOG higher level containers and GUI widgets - to do
- Database bindings and server side APIs - to do
- Current CL packages
- Direct bidings to widgets ete.
- CLOG Devtools - to do
- Generate application scaffolding
- GUI Builder
- Grid style
- Page style
- Electron for native GUIs
- Plugins - to do
- General CL systems
- Widgets
- Documentation

View file

@ -54,7 +54,7 @@
(defun query (connection-id script) (defun query (connection-id script)
"Execute SCRIPT on CONNECTION-ID, return value." "Execute SCRIPT on CONNECTION-ID, return value."
(let ((uid (clog::generate-connection-id))) (let ((uid (clog::generate-connection-id)))
(clog::store-query uid nil) (clog::prep-query uid nil)
(execute connection-id (execute connection-id
(format nil "ws.send (\"~A:\"+eval(\"~A\"));" uid script)) (format nil "ws.send (\"~A:\"+eval(\"~A\"));" uid script))
(clog::wait-for-answer uid))) (clog::wait-for-answer uid)))

View file

@ -58,8 +58,12 @@ application."
(defvar *connection-lock* (bordeaux-threads:make-lock) (defvar *connection-lock* (bordeaux-threads:make-lock)
"Protect the connection hash tables") "Protect the connection hash tables")
(defvar *queries-lock* (bordeaux-threads:make-lock)
"Protect query hash tables")
(defvar *queries* (make-hash-table) "Waiting queries") (defvar *queries* (make-hash-table) "Query ID to Answers")
(defvar *queries-sems* (make-hash-table) "Query ID to semiphores")
(defvar *query-time-out* 3 "Number of seconds to timeout waiting for a query")
;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; generate-connection-id ;; ;; generate-connection-id ;;
@ -77,6 +81,31 @@ application."
"Return the connection associated with CONNECITION-ID. (Private)" "Return the connection associated with CONNECITION-ID. (Private)"
(gethash connection-id *connection-ids*)) (gethash connection-id *connection-ids*))
;;;;;;;;;;;;;;;;
;; prep-query ;;
;;;;;;;;;;;;;;;;
(defun prep-query (id default-answer)
"Setup up a query to be received from a script identified by ID an returning
with DEFAULT-ANSWER in case of a time out. (Private)"
(bordeaux-threads:with-lock-held (*queries-lock*)
(setf (gethash id *queries-sems*) (bordeaux-threads:make-semaphore))
(setf (gethash id *queries*) default-answer)))
;;;;;;;;;;;;;;;;;;;;;
;; wait-for-answer ;;
;;;;;;;;;;;;;;;;;;;;;
(defun wait-for-answer (id &key (timeout *query-time-out*))
"Block after prep-query and sending the query script with ID and TIMEOUT with
the default answer. (Private)"
(bordeaux-threads:wait-on-semaphore (gethash id *queries-sems*) :timeout timeout)
(let ((answer (gethash id *queries*)))
(bordeaux-threads:with-lock-held (*queries-lock*)
(remhash id *queries*)
(remhash id *queries-sems*))
answer))
;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; handle-new-connection ;; ;; handle-new-connection ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -105,22 +134,6 @@ application."
;; handle-message ;; ;; handle-message ;;
;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;
(defvar *queries-lock* (bordeaux-threads:make-lock))
(defvar *queries-sems* (make-hash-table))
(defun store-query (id answer)
(bordeaux-threads:with-lock-held (*queries-lock*)
(setf (gethash id *queries-sems*) (bordeaux-threads:make-semaphore))
(setf (gethash id *queries*) answer)))
(defun wait-for-answer (id)
(bordeaux-threads:wait-on-semaphore (gethash id *queries-sems*) :timeout 3)
(let ((answer (gethash id *queries*)))
(bordeaux-threads:with-lock-held (*queries-lock*)
(remhash id *queries*)
(remhash id *queries-sems*))
answer))
(defun handle-message (connection message) (defun handle-message (connection message)
(let ((id (gethash connection *connections*)) (let ((id (gethash connection *connections*))
(ml (ppcre:split ":" message :limit 2))) (ml (ppcre:split ":" message :limit 2)))

View file

@ -1,31 +1,30 @@
(defpackage #:test-clog (defpackage #:test-clog
(:use #:cl) (:use #:cl)
(:export test-connect on-connect1 on-connect2)) (:export test-connect on-connect))
(in-package :test-clog) (in-package :test-clog)
(defun on-connect1 (id) (defun on-connect (id)
(format t "Connection ~A is valid? ~A~%" id (clog-connection:validp id)) (format t "Connection ~A is valid? ~A~%" id (clog-connection:validp id))
;; (clog:execute-script id "alert('test1');")
(dotimes (n 10) (dotimes (n 10)
(clog-connection:cwrite id "<b>connection-write</b>") (clog-connection:cwrite id "<b>connection-write</b>")
(clog-connection:cwriteln id "<i>connection-writeln</i>") (clog-connection:cwriteln id "<i>connection-writeln</i>")
(sleep .2)) (sleep .2))
(clog-connection:cwrite id "<br><b>Query Result : </b>")
(clog-connection:cwrite id (clog-connection:query id "navigator.appVersion"))
(clog-connection:cwrite id "<hr>simulate network interupt") (clog-connection:cwrite id "<hr>simulate network interupt")
(clog-connection:cclose id) (clog-connection:cclose id)
(sleep .2) (sleep .2)
(clog-connection:cwrite id "<br><b>reconnected</b>") (clog-connection:cwrite id "<br><b>reconnected</b>")
(sleep .2) (sleep .2)
(clog-connection:cwrite id "<br><b>shutting down connection</b>") (clog-connection:cwrite id "<br><b>shutting down connection</b>")
(sleep .2)
;; It is generally uneccessary to shutdown the connection
(clog-connection:shutdown id)) (clog-connection:shutdown id))
(defun on-connect2 (id)
(clog-connection:cwrite id "<b>Query Result : </b>")
(clog-connection:cwrite id (clog-connection:query id "navigator.appVersion")))
(defun test-connect () (defun test-connect ()
(print "Init connection") (print "Init connection")
(clog:initialize #'on-connect2 :boot-file "/debug.html") (clog:initialize #'on-connect :boot-file "/debug.html")
(print "Open browser") (print "Open browser")
(clog:open-browser) (clog:open-browser)
) )