diff --git a/tools/clog-builder.lisp b/tools/clog-builder.lisp index 47be360..02cf072 100644 --- a/tools/clog-builder.lisp +++ b/tools/clog-builder.lisp @@ -121,6 +121,19 @@ "Increment next id and store it in CONTENT" (setf-next-id content (1+ (next-id content)))) +;; Lisp code evaluation utilities + +(defun capture-eval (form &key (eval-in-package "clog-user")) + "Capture lisp evaluaton of FORM" + (let ((result (make-array '(0) :element-type 'base-char + :fill-pointer 0 :adjustable t)) + (eval-result)) + (with-output-to-string (stream result) + (let* ((*standard-output* stream) + (*error-output* stream) + (*package* (find-package (string-upcase eval-in-package)))) + (setf eval-result (eval (read-from-string (format nil "(progn ~A)" form)))))) + (format nil "~A~%=>~A~%" result eval-result))) ;; Local file utilities @@ -139,19 +152,90 @@ (with-open-file (outstream outfile :direction :output :if-exists action-if-exists) (write-sequence string outstream))) -;; Lisp code evaluation utilities +(defun save-panel (fname content panel-id hide-loc) + "Save panel to FNAME" + (let ((app (connection-data-item content "builder-app-data"))) + (maphash + (lambda (html-id control) + (declare (ignore html-id)) + (place-inside-bottom-of hide-loc + (get-placer control))) + (get-control-list app panel-id)) + (let ((data + (create-child content "" + :html-id (format nil "I~A" (get-universal-time))))) + (place-inside-top-of content data) + (setf (attribute data "data-in-package") + (attribute content "data-in-package")) + (setf (attribute data "data-custom-slots") + (attribute content "data-custom-slots")) + (setf (attribute data "data-clog-next-id") + (attribute content "data-clog-next-id")) + (setf (attribute data "data-clog-title") + (attribute content "data-clog-name")) + (write-file (js-query content + (format nil + "var z=~a.clone();~ + z.find('*').each(function(){if($(this).attr('id') !== undefined && ~ + $(this).attr('id').substring(0,5)=='CLOGB'){$(this).removeAttr('id')}});~ + z.html()" + (clog::jquery content))) + fname) + (destroy data)) + (maphash + (lambda (html-id control) + (declare (ignore html-id)) + (place-after control (get-placer control))) + (get-control-list app panel-id)))) -(defun capture-eval (form &key (eval-in-package "clog-user")) - "Capture lisp evaluaton of FORM" - (let ((result (make-array '(0) :element-type 'base-char - :fill-pointer 0 :adjustable t)) - (eval-result)) - (with-output-to-string (stream result) - (let* ((*standard-output* stream) - (*error-output* stream) - (*package* (find-package (string-upcase eval-in-package)))) - (setf eval-result (eval (read-from-string (format nil "(progn ~A)" form)))))) - (format nil "~A~%=>~A~%" result eval-result))) +;; Template Utilities + +(defun walk-files-and-directories (path process) + "Walk PATH and apply PROCESS on each (path and file)" + (let* ((flist (uiop:directory-files path)) + (dlist (uiop:subdirectories path))) + (dolist (f flist) + (funcall process path (file-namestring f))) + (dolist (d dlist) + (walk-files-and-directories d process)))) + +(defun template-copy (sys-name start-dir filename &key panel) + "Copy START-DIR to FILENAME processing .lt files as cl-template files, +if PANEL each copy produces a source to destination added as +create-div's" + (walk-files-and-directories + start-dir + (lambda (path file) + (let* ((tmpl-ext "lt") + (src-file (format nil "~A~A" + path file)) + (out-dir (format nil "~A/~A/~A" + filename + sys-name + (subseq (format nil "~A" path) + (length start-dir)))) + (out-file (format nil "~A~A" + out-dir + file))) + (ensure-directories-exist out-dir) + (cond ((equalp (pathname-type file) tmpl-ext) + (let* ((nfile (pathname-name file)) + (afile (if (equalp (pathname-name nfile) "tmpl") + (format nil "~A~A.~A" out-dir sys-name (pathname-type nfile)) + (format nil "~A~A" out-dir nfile)))) + (write-file (funcall (cl-template:compile-template (read-file src-file)) + (list :sys-name sys-name)) + afile) + (when panel + (create-div panel + :content (format nil "~A -> ~A" + src-file afile))))) + (t + (uiop:copy-file src-file out-file) + (when panel + (create-div panel + :content (format nil "~A -> ~A" + src-file out-file))))))))) ;; Control utilities @@ -433,6 +517,80 @@ not a temporary attached one when using select-control." (setf control (next-sibling control)))))) (add-siblings (first-child parent))))) +;; Code rendering utlities + +(defun render-clog-code (content win hide-loc) + "Render panel to clog code and add tp CW window" + (let* ((app (connection-data-item content "builder-app-data")) + (panel-id (html-id content)) + (package (attribute content "data-in-package")) + (slots (attribute content "data-custom-slots")) + (cname (attribute content "data-clog-name")) + cmembers vars events) + (unless (or (equal slots "") + (equal slots "undefined")) + (push slots cmembers)) + (maphash (lambda (html-id control) + (place-inside-bottom-of hide-loc + (get-placer control)) + (let ((vname (attribute control "data-clog-name"))) + (unless (and (>= (length vname) 5) + (equalp (subseq vname 0 5) "none-")) + (push (format nil + " \(~A :reader ~A\)~%" + vname + vname) + cmembers) + (push (format nil + " \(setf (slot-value panel '~A\) ~ + \(attach-as-child clog-obj \"~A\" :clog-type \'~A\ :new-id t)\)~%" + vname + html-id + (format nil "CLOG:~A" (type-of control))) + vars) + (let ((info (control-info (attribute control "data-clog-type")))) + (dolist (event (getf info :events)) + (let ((handler (attribute control (format nil "data-~A" (getf event :name))))) + (unless (or (equalp handler "undefined") + (equal handler "")) + (push (format nil + " \(set-~A \(~A panel\) \(lambda \(~A\) \(declare \(ignorable ~A\)\) ~A\)\)~%" + (getf event :name) + vname + (getf event :parameters) + (getf event :parameters) + handler) + events)))))))) + (get-control-list app panel-id)) + (let ((result (format nil + "\(in-package \"~A\"\) +\(defclass ~A \(clog:clog-div\) + \(~{~A~}\)\) +\(defun create-~A \(clog-obj &key \(hidden nil\) \(class nil\) \(html-id nil\) \(auto-place t\)\) + \(let \(\(panel \(change-class \(clog:create-div clog-obj :content \"~A\" + :hidden hidden :class class :html-id html-id :auto-place auto-place\) \'~A\)\)\) +~{~A~}~{~A~} panel\)\)~%" + (string-upcase package) + cname ;;defclass + cmembers + cname ;;defun + (ppcre:regex-replace-all "\"" + (js-query content + (format nil + "var z=~a.clone();~ + z.find('*').each(function(){for(n in $(this).get(0).dataset){delete $(this).get(0).dataset[n]}});~ + z.html()" + (clog::jquery content))) + "\\\"") + cname + vars + events))) + (maphash (lambda (html-id control) + (declare (ignore html-id)) + (place-after control (get-placer control))) + (get-control-list app panel-id)) + result))) + ;; Population of utility windows (defun on-populate-control-events-win (obj) @@ -762,114 +920,6 @@ of controls and double click to select control." place static~% child to selected")) (set-on-window-close win (lambda (obj) (setf (control-list-win app) nil))))))) -(defun render-clog-code (content win hide-loc) - "Render panel to clog code and add tp CW window" - (let* ((app (connection-data-item content "builder-app-data")) - (panel-id (html-id content)) - (package (attribute content "data-in-package")) - (slots (attribute content "data-custom-slots")) - (cname (attribute content "data-clog-name")) - cmembers vars events) - (unless (or (equal slots "") - (equal slots "undefined")) - (push slots cmembers)) - (maphash (lambda (html-id control) - (place-inside-bottom-of hide-loc - (get-placer control)) - (let ((vname (attribute control "data-clog-name"))) - (unless (and (>= (length vname) 5) - (equalp (subseq vname 0 5) "none-")) - (push (format nil - " \(~A :reader ~A\)~%" - vname - vname) - cmembers) - (push (format nil - " \(setf (slot-value panel '~A\) ~ - \(attach-as-child clog-obj \"~A\" :clog-type \'~A\ :new-id t)\)~%" - vname - html-id - (format nil "CLOG:~A" (type-of control))) - vars) - (let ((info (control-info (attribute control "data-clog-type")))) - (dolist (event (getf info :events)) - (let ((handler (attribute control (format nil "data-~A" (getf event :name))))) - (unless (or (equalp handler "undefined") - (equal handler "")) - (push (format nil - " \(set-~A \(~A panel\) \(lambda \(~A\) \(declare \(ignorable ~A\)\) ~A\)\)~%" - (getf event :name) - vname - (getf event :parameters) - (getf event :parameters) - handler) - events)))))))) - (get-control-list app panel-id)) - (let ((result (format nil - "\(in-package \"~A\"\) -\(defclass ~A \(clog:clog-div\) - \(~{~A~}\)\) -\(defun create-~A \(clog-obj &key \(hidden nil\) \(class nil\) \(html-id nil\) \(auto-place t\)\) - \(let \(\(panel \(change-class \(clog:create-div clog-obj :content \"~A\" - :hidden hidden :class class :html-id html-id :auto-place auto-place\) \'~A\)\)\) -~{~A~}~{~A~} panel\)\)~%" - (string-upcase package) - cname ;;defclass - cmembers - cname ;;defun - (ppcre:regex-replace-all "\"" - (js-query content - (format nil - "var z=~a.clone();~ - z.find('*').each(function(){for(n in $(this).get(0).dataset){delete $(this).get(0).dataset[n]}});~ - z.html()" - (clog::jquery content))) - "\\\"") - cname - vars - events))) - (maphash (lambda (html-id control) - (declare (ignore html-id)) - (place-after control (get-placer control))) - (get-control-list app panel-id)) - result))) - -(defun save-panel (fname content panel-id hide-loc) - "Save panel to FNAME" - (let ((app (connection-data-item content "builder-app-data"))) - (maphash - (lambda (html-id control) - (declare (ignore html-id)) - (place-inside-bottom-of hide-loc - (get-placer control))) - (get-control-list app panel-id)) - (let ((data - (create-child content "" - :html-id (format nil "I~A" (get-universal-time))))) - (place-inside-top-of content data) - (setf (attribute data "data-in-package") - (attribute content "data-in-package")) - (setf (attribute data "data-custom-slots") - (attribute content "data-custom-slots")) - (setf (attribute data "data-clog-next-id") - (attribute content "data-clog-next-id")) - (setf (attribute data "data-clog-title") - (attribute content "data-clog-name")) - (write-file (js-query content - (format nil - "var z=~a.clone();~ - z.find('*').each(function(){if($(this).attr('id') !== undefined && ~ - $(this).attr('id').substring(0,5)=='CLOGB'){$(this).removeAttr('id')}});~ - z.html()" - (clog::jquery content))) - fname) - (destroy data)) - (maphash - (lambda (html-id control) - (declare (ignore html-id)) - (place-after control (get-placer control))) - (get-control-list app panel-id)))) - (defun on-new-builder-panel (obj) "Open new panel" (let* ((app (connection-data-item obj "builder-app-data")) @@ -1338,53 +1388,6 @@ of controls and double click to select control." (dolist (tmpl *supported-templates*) (add-select-option (template-box ct) (getf tmpl :code) (getf tmpl :name))))) -(defun walk-files-and-directories (path process) - "Walk PATH and apply PROCESS on each (path and file)" - (let* ((flist (uiop:directory-files path)) - (dlist (uiop:subdirectories path))) - (dolist (f flist) - (funcall process path (file-namestring f))) - (dolist (d dlist) - (walk-files-and-directories d process)))) - -(defun template-copy (sys-name start-dir filename &key panel) - "Copy START-DIR to FILENAME processing .lt files as cl-template files, -if PANEL each copy produces a source to destination added as -create-div's" - (walk-files-and-directories - start-dir - (lambda (path file) - (let* ((tmpl-ext "lt") - (src-file (format nil "~A~A" - path file)) - (out-dir (format nil "~A/~A/~A" - filename - sys-name - (subseq (format nil "~A" path) - (length start-dir)))) - (out-file (format nil "~A~A" - out-dir - file))) - (ensure-directories-exist out-dir) - (cond ((equalp (pathname-type file) tmpl-ext) - (let* ((nfile (pathname-name file)) - (afile (if (equalp (pathname-name nfile) "tmpl") - (format nil "~A~A.~A" out-dir sys-name (pathname-type nfile)) - (format nil "~A~A" out-dir nfile)))) - (write-file (funcall (cl-template:compile-template (read-file src-file)) - (list :sys-name sys-name)) - afile) - (when panel - (create-div panel - :content (format nil "~A -> ~A" - src-file afile))))) - (t - (uiop:copy-file src-file out-file) - (when panel - (create-div panel - :content (format nil "~A -> ~A" - src-file out-file))))))))) - (defun fill-button-clicked (panel) "Template fill botton clicked" (let* ((tmpl-rec (find-if (lambda (x)