Factor out a "Lisp font locking" section and tidy

This commit is contained in:
Gerard Vermeulen 2023-05-15 14:07:59 +02:00
parent c65b8834ba
commit 3bd627e095
1 changed files with 248 additions and 162 deletions

View File

@ -2124,11 +2124,9 @@ list detailing and motivating each listing:
"\\end{document}\n")))
(with-eval-after-load 'ob-lisp
;; (with-eval-after-load 'slime
;; (setopt org-babel-lisp-eval-fn #'slime-eval))
(with-eval-after-load 'sly
(setopt org-babel-lisp-eval-fn #'sly-eval))
)
;; Default to `sly-eval' whenever feasible:
(when (package-installed-p 'sly)
(setopt org-babel-lisp-eval-fn #'sly-eval)))
(with-eval-after-load 'emacs
(defun set-org-babel-language-activity (lang active)
@ -4005,22 +4003,16 @@ that do not visit a file.
:CUSTOM_ID: sec:common-lisp-programming
:END:
Listing [[lst:configure-sly]] configures the [[info:sly#Top][Sly (info)]] Common Lisp IDE for Emacs
for use with [[http://www.sbcl.org/][Steel Bank Common Lisp (sbcl)]]:
1. It configures =sly-default-lisp= and =sly-lisp-implementations= as in the
~sly~ documentation string instead of in the [[info:sly#Multiple Lisps][multiple lisps (info)]] manual.
2. It ensures the [[info:sly#Auto-SLY][automatic connection to the lisp server (info)]] when opening a
Common Lisp file.
3. It configures searching documentation in the [[http://www.lispworks.com/documentation/HyperSpec/Front/][Common Lisp HyperSpec]] according
to the [[info:sly#Basic customization][basic customization (info)]] manual.
Finally, listing [[lst:configure-sly]] uses a technique to [[info:sly#Loading Slynk faster][load Slynk faster (info)]]
by means of a custom core file in src_emacs-lisp{no-littering-var-directory}.
Listing [[lst:sbcl-core-for-sly]] tangles to a script to dump such a [[http://www.sbcl.org/][SBCL]] core.
*** [[https://slime.common-lisp.dev/doc/html/index.html][Slime]] :noexport:
:PROPERTIES:
:CUSTOM_ID: sec:slime
:header-args:emacs-lisp: :exports code :tangle no
:END:
#+caption[Configure =slime=]:
#+caption: Configure =slime=.
#+name: lst:configure-slime
#+begin_src emacs-lisp -n :results silent :tangle no
#+begin_src emacs-lisp -n :results silent
(when (ensure-package-installation 'slime)
(with-eval-after-load 'slime
(setq slime-default-lisp 'sbcl
@ -4048,6 +4040,24 @@ Listing [[lst:sbcl-core-for-sly]] tangles to a script to dump such a [[http://ww
(keymap-set slime-prefix-map "M-h" #'slime-documentation-lookup)))
#+end_src
*** [[https://joaotavora.github.io/sly/][Sly]]
:PROPERTIES:
:CUSTOM_ID: sec:sly
:END:
Listing [[lst:configure-sly]] configures the [[info:sly#Top][Sly (info)]] Common Lisp IDE for Emacs
for use with [[http://www.sbcl.org/][Steel Bank Common Lisp (sbcl)]]:
1. It configures =sly-default-lisp= and =sly-lisp-implementations= as in the
~sly~ documentation string instead of in the [[info:sly#Multiple Lisps][multiple lisps (info)]] manual.
2. It does not ensure the [[info:sly#Auto-SLY][automatic connection to the lisp server (info)]] when
opening a Common Lisp file because it does not play well with =ob-lisp=.
3. It configures searching documentation in the [[http://www.lispworks.com/documentation/HyperSpec/Front/][Common Lisp HyperSpec]] according
to the [[info:sly#Basic customization][basic customization (info)]] manual.
Listing [[lst:slink-sel]] allows to set or get the Sly string elision length.
Finally, listing [[lst:configure-sly]] uses a technique to [[info:sly#Loading Slynk faster][load Slynk faster (info)]]
by means of a custom core file in src_emacs-lisp{no-littering-var-directory}.
Listing [[lst:sbcl-core-for-sly]] tangles to a script to dump such a [[http://www.sbcl.org/][SBCL]] core.
#+caption[Configure =sly=]:
#+caption: Configure =sly=.
#+name: lst:configure-sly
@ -4086,6 +4096,51 @@ Listing [[lst:sbcl-core-for-sly]] tangles to a script to dump such a [[http://ww
(keymap-set sly-prefix-map "M-h" #'sly-documentation-lookup)))
#+end_src
#+caption[Get/set Sly ~slynk:*string-elision-length*~ functionality]:
#+caption: Get/set Sly ~slynk:*string-elision-length*~ functionality.
#+name: lst:slink-sel
#+begin_src emacs-lisp -n :results silent
(with-eval-after-load 'sly
(defconst slynk-command-get-sel
"(cdr (assoc 'slynk:*string-elision-length* slynk:*slynk-pprint-bindings*))"
"Slynk \"string elision length\" getter command.")
(defun slynk-command-set-sel (sel)
"Slynk SEL \"string elision length\" setter command.
SEL values must be positive integers to enable or `nil' to disable elision."
(format "(setf %s %s)" slynk-command-get-sel sel))
(defun slynk-get-sel ()
"Get the Slynk \"string-elision-length\"."
(cadr (sly-eval `(slynk:eval-and-grab-output ,slynk-command-get-sel))))
(defun slynk-set-sel (sel)
"Set the Slynk \"string-elision-length\" SEL.
SEL values must be positive integers to enable or `nil' to disable elision."
(cadr (sly-eval `(slynk:eval-and-grab-output ,(slynk-command-set-sel sel)))))
(defun slynk-eval-sel-command (string)
"Evaluate the Slynk \"string-elision-length\" command STRING."
(unless (sly-connected-p)
(user-error "Slynk connection is not open: \"M-x sly\"?"))
(message "Slynk string elision length is %S"
(read (cadr (sly-eval `(slynk:eval-and-grab-output ,string))))))
(defun slynk-get-string-elision-length ()
"Get the Slynk \"string-elision-length\"."
(interactive)
(slynk-eval-sel-command slynk-command-get-sel))
(defun slynk-set-string-elision-length (&optional sel)
"Set the Slynk \"string-elision-length\" by evaluting SEL.
Valid SEL values are positive integers to enable or `nil' to disable elision."
(interactive "XSlynk string-elision-length (nil or sel > 0): ")
(unless (or (null sel) (and (integerp sel) (> sel 0)))
(user-error
"Slynk `sel' must evaluate to `nil' or a positive integer (got `%S')" sel))
(slynk-eval-sel-command (slynk-command-set-sel sel))))
#+end_src
#+caption[Script to dump a SBCL core for the Sly Common Lisp IDE]:
#+caption: Script to dump a SBCL core for the Sly Common Lisp IDE.
#+header: :tangle-mode (identity #o755)
@ -4105,9 +4160,152 @@ EOF
# End:
#+end_src
*** [[https://www.n16f.net/blog/custom-font-lock-configuration-in-emacs/][Common Lisp custom font locking]]
*** [[https://courses.cs.northwestern.edu/325/][CS 325 AI Programming]]
:PROPERTIES:
:CUSTOM_ID: sec:cl-custom-font-locking
:CUSTOM_ID: sec:cs-325-ai-programming
:END:
The [[https://courses.cs.northwestern.edu/325/][CS 325 AI Programming]] course allows to learn Common Lisp by self-study and
the page [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php][CS 325: Setting up Lisp]] gives instructions how to:
1. [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php#lisp][Download and install common lisp]].
2. [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php#quicklisp][Install Quicklisp]].
3. [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php#install-325][Install the CS325 library]].
*** [[https://www.quicklisp.org/][Quicklisp]]
:PROPERTIES:
:CUSTOM_ID: sec:quicklisp
:END:
[[https://www.quicklisp.org/][Quicklisp]] is a library manager for Common Lisp. Listing
[[lst:download+verify-quicklisp]] downloads the [[https://www.quicklisp.org/][Quicklisp]] installation file and
verifies its signature to prevent tampering. Listing [[lst:bootstrap-quicklisp]]
tangles to a shell script allowing to bootstrap [[https://www.quicklisp.org/][Quicklisp]] with [[http://www.sbcl.org/][SBCL]]. Listing
[[lst:quicklisp-sbclrc-file]] tangles to the a [[http://www.sbcl.org/][SBCL]] resource file with [[https://www.quicklisp.org/][Quicklisp]]
support. Listing [[lst:clone-local-projects]] shows how to make local projects out
of unpackaged projects and listing [[lst:register-load-local-projects]] shows how to
register local projects in order to load those unpackaged projects in the same
way as packaged projects.
#+caption[Download and verify =quicklisp=]:
#+caption: Download and verify =quicklisp=.
#+name: lst:download+verify-quicklisp
#+begin_src shell -n :dir ~ :results none :tangle no
curl -sS -O https://beta.quicklisp.org/quicklisp.lisp
curl -sS -O https://beta.quicklisp.org/quicklisp.lisp.asc
curl -sS -O https://beta.quicklisp.org/release-key.txt
gpg --import release-key.txt
gpg --verify quicklisp.lisp.asc quicklisp.lisp
#+end_src
#+caption[Bootstrap =quicklisp=]:
#+caption: Bootstrap =quicklisp=.
#+header: :tangle-mode (identity #o755)
#+name: lst:bootstrap-quicklisp
#+begin_src shell -n :noeval :tangle ~/bin/quicklisp-sbcl-bootstrap
#!/bin/sh
sbcl --load ~/quicklisp.lisp <<EOF
(quicklisp-quickstart:install)
(quit)
EOF
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# sh-basic-offset: 2
# End:
#+end_src
#+caption[Clone local =quicklisp= projects]:
#+caption: Clone local =quicklisp= projects.
#+name: lst:clone-local-projects
#+begin_src shell -n :dir ~/quicklisp/local-projects :results none :tangle no
git clone https://gitlab.com/criesbeck/cs325.git
git clone git@github.com:ageldama/cl-state-machine.git
#+end_src
#+caption[Register and load local =quicklisp= projects with dependencies]:
#+caption: Register and load local =quicklisp= projects with dependencies.
#+name: lst:register-load-local-projects
#+begin_src lisp -n :eval never-export :results none :tangle no
;; SBCL on Darwin fails to run cl-cffi-gtk:
;; https://lisp-journey.gitlab.io/blog/gui-programming-in-common-lisp-part-3-of-5-gtk3/
;; https://www.crategus.com/books/cl-cffi-gtk/
;; https://www.crategus.com/books/cl-gtk/gtk-tutorial.html
(defun probe--local-project-directory (name)
(some #'identity (mapcar (lambda (x)
(let ((*default-pathname-defaults* x))
(probe-file name)))
ql:*local-project-directories*)))
(when (probe--local-project-directory "cs325")
(ql:register-local-projects)
(ql:quickload "cs325")
(ql:quickload "meta")
(ql:quickload '("named-readtables" "try")) ;; testing requires "try".
#-:clozure
(ql:quickload "nodgui") ;; requires https://www.tcl.tk/software/tklib/
(ql:quickload '("rutils" "rutilsx"))
(ql:quickload "ucons"))
(when (probe--local-project-directory "cl-state-machine")
(ql:quickload '("cl-state-machine" "cl-state-machine-examples"
"cl-state-machine-graphing" "cl-state-machine-test")))
#+end_src
#+caption: A =quicklisp= sbclrc file.
#+name: lst:quicklisp-sbclrc-file
#+begin_src lisp -n :eval never :tangle ~/.sbclrc
;;; Hey Emacs, this is my -*- lisp -*- .sbclrc file.
;;; The following lines added by ql:add-to-init-file:
#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
(user-homedir-pathname))))
(when (probe-file quicklisp-init)
(load quicklisp-init)))
;;; Load cs325.lisp to create the cs325 package.
;; (eval-when (:compile-toplevel :load-toplevel :execute)
;; (ql:quickload "cs325")
;; (setq *package* (find-package :cs325-user)))
#+end_src
*** [[https://github.com/hellerve/sbcli][Better REPL for SBCL]]
:PROPERTIES:
:CUSTOM_ID: sec:sbcli
:END:
#+caption[Install =sbcli=]:
#+caption: Install =sbcli=.
#+name: lst:install-sbcli
#+begin_src emacs-lisp -n :eval never-export :lexical t :tangle no
(let ((url "https://raw.githubusercontent.com/hellerve/sbcli/master/repl.lisp")
(file "~/bin/sbcli"))
(url-copy-file url file 'ok-if-already-exists)
(set-file-modes file #o700))
#+end_src
#+caption[Tangle a =sbcli= resource file]:
#+caption: Tangle a =sbcli= resource file.
#+name: lst:write-sbslirc
#+begin_src lisp -n :eval never :tangle ~/.sbclirc
(setf *repl-name* "Gerard's custom REPL for SBCLI")
;; The style option fails:
;; (setf *pygmentize* (merge-pathnames ".pyenv/shims/pygmentize"
;; (user-homedir-pathname)))
;; (defvar *pygmentize-options* (list "-s" "-l" "lisp" "-O" "style=zenburn"))
#+end_src
** [[https://www.n16f.net/blog/custom-font-lock-configuration-in-emacs/][Lisp mode custom font locking for Common Lisp]]
:PROPERTIES:
:CUSTOM_ID: sec:lisp-custom-font-locking
:END:
*** [[https://www.n16f.net/blog/custom-font-lock-configuration-in-emacs/][Initialize Common Lisp custom font locking]]
:PROPERTIES:
:CUSTOM_ID: sec:cl-custom-font-locking-start
:END:
#+caption[Define faces for =Common Lisp= custom font locking]:
@ -4130,15 +4328,6 @@ EOF
"The face used to highlight standard Common Lisp value symbols.")
#+end_src
#+caption[Setup =SLY= printing]:
#+caption: Setup =SLY= printing.
#+name: lst:setup-sly-printing
#+begin_src lisp -n :eval never-export :results silent :tangle no
;; Works in case of sly, but fails in case of slime.
(rplacd (assoc 'slynk:*string-elision-length* slynk:*slynk-pprint-bindings*)
(ash 1 14))
#+end_src
#+caption[Define a =Common Lisp= function to find standard symbol names]:
#+caption: Define a =Common Lisp= function to find standard symbol names.
#+name: lst:standard-symbol-names
@ -4151,6 +4340,28 @@ EOF
(sort symbols #'string<)))
#+end_src
#+caption[Set Sly ~slynk:*string-elision-length*~]:
#+caption: Set Sly ~slynk:*string-elision-length*~.
#+name: lst:set-sly-sel
#+header: :wrap "src text -n"
#+begin_src emacs-lisp -n :eval never-export :exports both :tangle no
(when (and (fboundp 'sly-connected-p) (sly-connected-p))
(and (fboundp 'slynk-set-sel) (slynk-set-sel (ash 1 14))))
#+end_src
#+caption[Set Sly ~slynk:*string-elision-length*~ result]:
#+caption: Set Sly ~slynk:*string-elision-length*~ result.
#+name: lst:set-sly-sel-result
#+RESULTS: lst:set-sly-sel
#+begin_src text -n
16384 (15 bits, #x4000)
#+end_src
*** [[https://www.n16f.net/blog/custom-font-lock-configuration-in-emacs/][Collect standard symbol function names]]
:PROPERTIES:
:CUSTOM_ID: sec:cl-function-names
:END:
#+caption[Define the =cl-function-names= variable in an =Emacs Lisp= block]:
#+caption: Use =Common Lisp= to define the =cl-function-names= variable in
#+caption: an =Emacs Lisp= source block for tangling into =user-init-file=.
@ -4317,7 +4528,10 @@ EOF
"yes-or-no-p" "zerop"))
#+end_src
\newpage
*** [[https://www.n16f.net/blog/custom-font-lock-configuration-in-emacs/][Collect standard symbol value names]]
:PROPERTIES:
:CUSTOM_ID: sec:cl-value-names
:END:
#+caption[Define the =cl-variable-names= variable in an =Emacs Lisp= block]:
#+caption: Use =Common Lisp= to define the =cl-variable-names= variable in
@ -4373,6 +4587,11 @@ EOF
"single-float-negative-epsilon" "t"))
#+end_src
*** [[https://www.n16f.net/blog/custom-font-lock-configuration-in-emacs/][Finalize Common Lisp custom font locking]]
:PROPERTIES:
:CUSTOM_ID: sec:cl-custom-font-locking-final
:END:
#+caption[Finalize =Common Lisp= custom font locking]:
#+caption: Finalize =Common Lisp= custom font locking.
#+name: lst:finalize-cl-custom-font-locking
@ -4402,139 +4621,6 @@ EOF
(add-hook 'lisp-mode-hook 'cl-init-lisp-font-lock)
#+end_src
*** [[https://courses.cs.northwestern.edu/325/][CS 325 AI Programming]]
:PROPERTIES:
:CUSTOM_ID: sec:cs-325-ai-programming
:END:
The [[https://courses.cs.northwestern.edu/325/][CS 325 AI Programming]] course allows to learn Common Lisp by self-study and
the page [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php][CS 325: Setting up Lisp]] gives instructions how to:
1. [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php#lisp][Download and install common lisp]].
2. [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php#quicklisp][Install Quicklisp]].
3. [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php#install-325][Install the CS325 library]].
*** [[https://www.quicklisp.org/][Quicklisp]]
:PROPERTIES:
:CUSTOM_ID: sec:quicklisp
:END:
[[https://www.quicklisp.org/][Quicklisp]] is a library manager for Common Lisp. Listing
[[lst:download+verify-quicklisp]] downloads the [[https://www.quicklisp.org/][Quicklisp]] installation file and
verifies its signature to prevent tampering. Listing [[lst:bootstrap-quicklisp]]
tangles to a shell script allowing to bootstrap [[https://www.quicklisp.org/][Quicklisp]] with [[http://www.sbcl.org/][SBCL]]. Listing
[[lst:quicklisp-sbclrc-file]] tangles to the a [[http://www.sbcl.org/][SBCL]] resource file with [[https://www.quicklisp.org/][Quicklisp]]
support. Listing [[lst:clone-local-projects]] shows how to make local projects out
of unpackaged projects and listing [[lst:register-load-local-projects]] shows how to
register local projects in order to load those unpackaged projects in the same
way as packaged projects.
#+caption[Download and verify =quicklisp=]:
#+caption: Download and verify =quicklisp=.
#+name: lst:download+verify-quicklisp
#+begin_src shell -n :dir ~ :results none :tangle no
curl -sS -O https://beta.quicklisp.org/quicklisp.lisp
curl -sS -O https://beta.quicklisp.org/quicklisp.lisp.asc
curl -sS -O https://beta.quicklisp.org/release-key.txt
gpg --import release-key.txt
gpg --verify quicklisp.lisp.asc quicklisp.lisp
#+end_src
#+caption[Bootstrap =quicklisp=]:
#+caption: Bootstrap =quicklisp=.
#+header: :tangle-mode (identity #o755)
#+name: lst:bootstrap-quicklisp
#+begin_src shell -n :noeval :tangle ~/bin/quicklisp-sbcl-bootstrap
#!/bin/sh
sbcl --load ~/quicklisp.lisp <<EOF
(quicklisp-quickstart:install)
(quit)
EOF
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# sh-basic-offset: 2
# End:
#+end_src
#+caption[Clone local =quicklisp= projects]:
#+caption: Clone local =quicklisp= projects.
#+name: lst:clone-local-projects
#+begin_src shell -n :dir ~/quicklisp/local-projects :results none :tangle no
git clone https://gitlab.com/criesbeck/cs325.git
git clone git@github.com:ageldama/cl-state-machine.git
#+end_src
#+caption[Register and load local =quicklisp= projects with dependencies]:
#+caption: Register and load local =quicklisp= projects with dependencies.
#+name: lst:register-load-local-projects
#+begin_src lisp -n :eval never-export :results none :tangle no
;; SBCL on Darwin fails to run cl-cffi-gtk:
;; https://lisp-journey.gitlab.io/blog/gui-programming-in-common-lisp-part-3-of-5-gtk3/
;; https://www.crategus.com/books/cl-cffi-gtk/
;; https://www.crategus.com/books/cl-gtk/gtk-tutorial.html
(defun probe--local-project-directory (name)
(some #'identity (mapcar (lambda (x)
(let ((*default-pathname-defaults* x))
(probe-file name)))
ql:*local-project-directories*)))
(when (probe--local-project-directory "cs325")
(ql:register-local-projects)
(ql:quickload "cs325")
(ql:quickload "meta")
(ql:quickload '("named-readtables" "try")) ;; testing requires "try".
#-:clozure
(ql:quickload "nodgui") ;; requires https://www.tcl.tk/software/tklib/
(ql:quickload '("rutils" "rutilsx"))
(ql:quickload "ucons"))
(when (probe--local-project-directory "cl-state-machine")
(ql:quickload '("cl-state-machine" "cl-state-machine-examples"
"cl-state-machine-graphing" "cl-state-machine-test")))
#+end_src
#+caption: A =quicklisp= sbclrc file.
#+name: lst:quicklisp-sbclrc-file
#+begin_src lisp -n :eval never :tangle ~/.sbclrc
;;; Hey Emacs, this is my -*- lisp -*- .sbclrc file.
;;; The following lines added by ql:add-to-init-file:
#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
(user-homedir-pathname))))
(when (probe-file quicklisp-init)
(load quicklisp-init)))
;;; Load cs325.lisp to create the cs325 package.
;; (eval-when (:compile-toplevel :load-toplevel :execute)
;; (ql:quickload "cs325")
;; (setq *package* (find-package :cs325-user)))
#+end_src
#+caption[Install =sbcli=]:
#+caption: Install =sbcli=.
#+name: lst:install-sbcli
#+begin_src emacs-lisp -n :eval never-export :lexical t :tangle no
(let ((url "https://raw.githubusercontent.com/hellerve/sbcli/master/repl.lisp")
(file "~/bin/sbcli"))
(url-copy-file url file 'ok-if-already-exists)
(set-file-modes file #o700))
#+end_src
#+caption[Tangle a =sbcli= resource file]:
#+caption: Tangle a =sbcli= resource file.
#+name: lst:write-sbslirc
#+begin_src lisp -n :eval never :tangle ~/.sbclirc
(setf *repl-name* "Gerard's custom REPL for SBCLI")
;; The style option fails:
;; (setf *pygmentize* (merge-pathnames ".pyenv/shims/pygmentize"
;; (user-homedir-pathname)))
;; (defvar *pygmentize-options* (list "-s" "-l" "lisp" "-O" "style=zenburn"))
#+end_src
** [[info:eintr#Top][Emacs Lisp Programming (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:emacs-lisp-programming