#+TITLE: 021 / #100daystooffload clim presentations, re/drawing rectangles by command #+author: screwtape M-x org-execute-buffer Note I have McCLIM and dependencies inside =~/common-lisp/ already, slime and inferior-lisp set. * Executing this buffer. Well, M-x org-babel-execute-buffer works for *me* but I have slime installed and the slime common-lisp repo and all the other McCLIM dependencies in my ~/common-lisp/. good luck. * Do what :remind_me_of_the_babe: ** TODO Remember who tooted about org-roam In the fediverse, someone told me they saved my gopher phost as an org-roam note. I had that experience maybe we all have, where I hear the name of an emacs mode that I've maybe heard before but I'm not familiar with. org-roam sounded tramp-like: Though in fact it's basically the third generation successor to the defunct org-mind-map as a wikiwiki knowledge graph builder + several tie-ins such as graphviz (derived from the org major mode). * Cow launched :PROPERTIES: :session: clim :END: Remembering that we are going to use clim, so I'm duplicating this block from 015 here: ** Starting swank in eshell #+name: eshell-swank #+begin_src elisp :var my-slime-path="common-lisp/slime-v2.27/" :results none (eshell) (dolist (cmd `("cd" ,(format "cd %s" my-slime-path) "sbcl --load start-swank.lisp")) (insert cmd) (eshell-send-input)) (previous-buffer) #+end_src swank is a wire protocol. ** Connecting slime to that swank #+name: start-slime #+begin_src elisp :results none (slime-connect "localhost" "4005") #+end_src ** Doing some clim *** Require McCLIM #+name: require-clim #+begin_src lisp :results none (Require :mcclim) #+end_src *** test application #+name: define-test-frame #+begin_src lisp (clim:define-application-frame myframe () () (:pane :application)) #+end_src #+RESULTS: define-test-frame : DEFINE-MYFRAME-COMMAND *** Make one of those #+name: test-make-frame #+begin_src lisp (defparameter *my-test-frame* (clim:make-application-frame 'myframe)) #+end_src #+RESULTS: test-make-frame : *MY-TEST-FRAME* *** Run that top level #+name: test-toplevel #+begin_src lisp :results none (clim:run-frame-top-level *my-test-frame*) #+end_src ** Some class *** A notion of tiles with a textual view I wonder if I can have a tile class, tiles having slots ($\hat{x}\;\hat{y}$). Then I can have a textual view of the tile which will be called like =(format t "~?" "tile-control" ())=. **** Tile class #+name: defclass-tile #+begin_src lisp (defclass controlled.text () ((control :initarg :of-control :accessor control-of) (text :initarg :of-text :accessor text-of) (controlled-slots :initarg :of-controlled-slots :accessor controlled-slots-of)) (:default-initargs :of-control "~a" :of-text "a" :of-controlled-slots '(text-of))) #+end_src #+RESULTS: defclass-tile : # **** presentation-type thereof #+name:presentation-controlled.text #+begin_src lisp (clim:define-presentation-type controlled.text ()) #+end_src #+RESULTS: presentation-controlled.text : # ***** Text view thereof #+name:textual-view-controlled.text #+begin_src lisp (clim:define-presentation-method clim:present (controlled.text (type controlled.text) stream (view clim:textual-view) &key) (apply #'format stream (control-of controlled.text) (loop for field in (controlled-slots-of controlled.text) collecting (funcall field controlled.text)))) #+end_src #+RESULTS: textual-view-controlled.text : # ***** Try it out #+name: test-obj-present #+begin_src lisp results output (with-output-to-string (*standard-output*) (clim:present (make-instance 'controlled.text))) #+end_src #+RESULTS: test-obj-present : a Basically toplevel is somewhere else, hence needing to shadow it with org-babel's toplevel here. **** collectiony #+name: collected-formatted #+begin_src lisp (let ((sequence (loop repeat 3 collect (make-instance 'controlled.text)))) (with-output-to-string (*standard-output*) (clim:present sequence `((sequence ,(clim:presentation-type-of (car sequence))) :separator #\|)))) #+end_src #+RESULTS: collected-formatted : a|a|a I'm happy with this, but I would like to know why the optional type-specifier argument to the sequence is the presentation-type t (which is probably #) rather than the most specific available presentation-type in the collection. I think somewhere it's mentioned that it would like to be told this type information at compile-time. Anyway, I have this option to say "this is an implicitly non-empty sequence of the presentation-type of whatever its first element is". So I have not been forced to hardcode the member type(s). I guess I was forced to say that this was a sequence anyway. Probably there's a good way such that a list is implicitly understood to be nil or a sequence of the type member of the types present in the list. Maybe I must say that that sort of thing is what I'm expecting at compile time. On the other hand, all we covered today is sequence types. I guess the next big topic is going to be collections of commands. So we might define a command that draws a square accepting two coordinate parameters, and then maybe cells of a grid could have PRESENTATION-TYPEs for both my CONTROLLED-TEXT and a SQUARE-GRID we could work on now. ***** SQUARE-COMMAND ****** In this case I think we need an application frame. #+name: define-an-application-frame #+begin_src lisp (defgeneric squares-of (obj)) (defun paint-squares (frame stream) (declare (ignorable keys)) (let ((squares (squares-of frame))) (when squares (apply #'clim:draw-rectangle* stream squares)))) (clim:define-application-frame to.be.a.grid () ((squares :initform '(120 30 145 135) :type list :accessor squares-of)) (:panes (disp :application :width 512 :height 512 :scroll-bars nil :display-function #'paint-squares) (int :interactor)) (:layouts (default (clim:horizontally () disp int)))) (defparameter *frame* (clim:make-application-frame 'to.be.a.grid)) #+end_src #+RESULTS: define-an-application-frame : *FRAME* ****** Define a command that moves a square #+name: add-a-command #+begin_src lisp (define-to.be.a.grid-command (com-square :name t) ((x '(clim:integer 0 200)) (y '(clim:integer 0 200)) (w '(clim:integer 1 200))) (let ((new-square (list x y (+ x w) (+ y w)))) (setf (squares-of clim:*application-frame*) new-square))) #+end_src #+RESULTS: add-a-command : COM-SQUARE ****** We should be able to just run this right. Running a frame does not have a return. #+name: try-running #+begin_src lisp :results none (clim:run-frame-top-level *frame*) #+end_src Try typing #+BEGIN_QUOTE s 1 2 200 #+END_QUOTE for example. You could also press enter after s. h c might be interesting too. q will complete to quit as well as the X. * retrospective I don't think my :session clim property worked. * Talk together - #phloggersgarage on libera.chat - the gopher gopher://i-logout.cz/1/bongusta - sdf commode chat https://sdf.org - The Lispy Gopher Climate w/screwtape at 000UTC every Wednesday! - The mastodon https://mastodon.sdf.org/@screwtape - @prahou@merveilles.town 's lemmy https://lemmy.sdf.org/c/unix_surrealism