Compare commits
9 Commits
84cd8a677c
...
825b7e21c4
Author | SHA1 | Date |
---|---|---|
Gerard Vermeulen | 825b7e21c4 | |
Gerard Vermeulen | d5a67d01bb | |
Gerard Vermeulen | 7e0bb2b96f | |
Gerard Vermeulen | 865e4a6c7e | |
Gerard Vermeulen | bcfa2eba72 | |
Gerard Vermeulen | d25d366530 | |
Gerard Vermeulen | 9560eadb5d | |
Gerard Vermeulen | ae396be077 | |
Gerard Vermeulen | 48e6673b0e |
264
README.org
264
README.org
|
@ -152,6 +152,9 @@ Here follows a list of links on how to use Emacs and Elisp:
|
|||
the best approach to learn Emacs and Elisp.
|
||||
5. [[https://www.masteringemacs.org/][Mastering Emacs]] is a link to a blog with many interesting posts that promotes
|
||||
a book on how to become a proficient Emacs user.
|
||||
6. [[https://www2.lib.uchicago.edu/keith/emacs/][Use GNU Emacs: The Plain Text Computing Environment]] explains the fundamentals
|
||||
of the Emacs abstractions before showing how to exploit those abstractions
|
||||
interactively. It targets a similar audience as the [[https://www.masteringemacs.org/][Mastering Emacs]] book.
|
||||
|
||||
* [[info:emacs#Early Init File][Early Init File (info)]]
|
||||
:PROPERTIES:
|
||||
|
@ -2054,6 +2057,7 @@ list detailing and motivating each listing:
|
|||
(gnuplot . ,(fboundp 'gnuplot-mode))
|
||||
(js . t)
|
||||
(latex . t)
|
||||
(lilypond . ,(fboundp 'lilypond-mode))
|
||||
(lisp . t)
|
||||
(lua . ,(fboundp 'lua-mode))
|
||||
(maxima . ,(fboundp 'maxima-mode))
|
||||
|
@ -2074,18 +2078,7 @@ list detailing and motivating each listing:
|
|||
ol-info
|
||||
org-id
|
||||
org-protocol
|
||||
org-tempo)
|
||||
org-structure-template-alist '(("a" . "export ascii")
|
||||
("c" . "center")
|
||||
("C" . "comment")
|
||||
("e" . "example")
|
||||
("E" . "export")
|
||||
("h" . "export html")
|
||||
("l" . "export latex")
|
||||
("q" . "quote")
|
||||
("s" . "src")
|
||||
("p" . "src python -n -i :session")
|
||||
("v" . "verse"))))
|
||||
org-tempo)))
|
||||
#+end_src
|
||||
|
||||
#+caption[Setup =org-babel=]:
|
||||
|
@ -2417,7 +2410,7 @@ else:
|
|||
#+caption: Find valid entries for =org-babel-load-languages=.
|
||||
#+name: lst:valid-org-babel-load-languages-entries
|
||||
#+header: :wrap "src emacs-lisp :results silent :tangle no"
|
||||
#+begin_src emacs-lisp :exports both :results value pp :exports both
|
||||
#+begin_src emacs-lisp :exports both :results value pp
|
||||
(defun all-org-babel-execute-fns ()
|
||||
"Find `ob-LANGUAGE' files in Org defining `org-babel-execute:LANGUAGE'.
|
||||
|
||||
|
@ -4532,6 +4525,96 @@ src_emacs-lisp{(describe-function 'inferior-emacs-lisp-mode)}.
|
|||
(setopt ielm-dynamic-return nil))
|
||||
#+end_src
|
||||
|
||||
*** [[https://emacs.stackexchange.com/questions/2129/why-is-let-faster-with-lexical-scope][Disassemble dynamical and lexical scope]]
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: sec:disassemble-dynamical-lexical-scope
|
||||
:header-args:emacs-lisp: :exports code :tangle no
|
||||
:END:
|
||||
|
||||
Listing [[lst:disassemble-lexical-scope][lexical scope disassembly]] and [[lst:disassemble-dynamical-scope][dynamical scope disassembly]] disassemble
|
||||
identical code in case of respectively lexical and dynamical scope. Listing
|
||||
[[lst:disassemble-lexical-scope-results][lexical scope disassembly results]] and [[lst:disassemble-dynamical-scope-results][dynamical scope disassembly results]] show
|
||||
the respective results.
|
||||
|
||||
The link [[https://emacs.stackexchange.com/questions/61754/how-can-i-enable-lexical-binding-for-elisp-code-in-org-mode][how to enable lexical scope for Emacs Lisp in org-mode source blocks]]
|
||||
explains all possibilities of disabling or enabling lexical scope.
|
||||
|
||||
#+caption[Disassemble lexical scope]:
|
||||
#+caption: Disassemble lexical scope.
|
||||
#+name: lst:disassemble-lexical-scope
|
||||
#+header: :wrap "src text -n"
|
||||
#+begin_src emacs-lisp -n :exports both :lexical t :results value
|
||||
(with-temp-buffer
|
||||
(disassemble (lambda (n)
|
||||
"Demonstrate lexical scope."
|
||||
(let* ((lower most-negative-fixnum)
|
||||
(upper most-positive-fixnum)
|
||||
(sum (+ lower upper)))
|
||||
(expt sum n)))
|
||||
(current-buffer))
|
||||
(buffer-substring-no-properties (point-min) (point-max)))
|
||||
#+end_src
|
||||
|
||||
#+caption[Disassemble lexical scope results]:
|
||||
#+caption: Disassemble lexical scope results.
|
||||
#+name: lst:disassemble-lexical-scope-results
|
||||
#+RESULTS: lst:disassemble-lexical-scope
|
||||
#+begin_src text -n
|
||||
byte code:
|
||||
doc: Demonstrate lexical scope. ...
|
||||
args: (arg1)
|
||||
0 varref most-negative-fixnum
|
||||
1 varref most-positive-fixnum
|
||||
2 stack-ref 1
|
||||
3 stack-ref 1
|
||||
4 plus
|
||||
5 constant expt
|
||||
6 stack-ref 1
|
||||
7 stack-ref 5
|
||||
8 call 2
|
||||
9 return
|
||||
#+end_src
|
||||
|
||||
#+caption[Disassemble dynamical scope]:
|
||||
#+caption: Disassemble dynamical scope.
|
||||
#+name: lst:disassemble-dynamical-scope
|
||||
#+header: :wrap "src text -n"
|
||||
#+begin_src emacs-lisp -n :exports both :results value
|
||||
(with-temp-buffer
|
||||
(disassemble (lambda (n)
|
||||
"Demonstrate lexical scope."
|
||||
(let* ((lower most-negative-fixnum)
|
||||
(upper most-positive-fixnum)
|
||||
(sum (+ lower upper)))
|
||||
(expt sum n)))
|
||||
(current-buffer))
|
||||
(buffer-substring-no-properties (point-min) (point-max)))
|
||||
#+end_src
|
||||
|
||||
#+caption[Disassemble dynamical scope results]:
|
||||
#+caption: Disassemble dynamical scope results.
|
||||
#+name: lst:disassemble-dynamical-scope-results
|
||||
#+RESULTS: lst:disassemble-dynamical-scope
|
||||
#+begin_src text -n
|
||||
byte code:
|
||||
doc: Demonstrate lexical scope.
|
||||
args: (n)
|
||||
0 varref most-negative-fixnum
|
||||
1 varbind lower
|
||||
2 varref most-positive-fixnum
|
||||
3 varbind upper
|
||||
4 varref lower
|
||||
5 varref upper
|
||||
6 plus
|
||||
7 varbind sum
|
||||
8 constant expt
|
||||
9 varref sum
|
||||
10 varref n
|
||||
11 call 2
|
||||
12 unbind 3
|
||||
13 return
|
||||
#+end_src
|
||||
|
||||
** [[https://fennel-lang.org/][Fennel Programming]]
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: sec:fennel-programming
|
||||
|
@ -4977,9 +5060,14 @@ ruff "$@" | cat
|
|||
:header-args: :eval never-export
|
||||
:END:
|
||||
|
||||
Listing [[lst:shell-pip-list-outdated]] and [[lst:shell-pip-index-versions]] are two
|
||||
examples of invoking [[https://pip.pypa.io/en/stable/][pip]] in =org-mode= =shell= source blocks with the respective
|
||||
results in listing [[lst:shell-pip-list-outdated-results]] and
|
||||
[[lst:shell-pip-index-versions-results]].
|
||||
|
||||
#+caption[Show how to use =pip list --outdated=]:
|
||||
#+caption: Show how to use =pip list --outdated=.
|
||||
#+header: :wrap src text
|
||||
#+header: :wrap "src text -n"
|
||||
#+name: lst:shell-pip-list-outdated
|
||||
#+begin_src shell :exports both :results verbatim
|
||||
# WARNING: "pip index" is currently an experimental command.
|
||||
|
@ -4988,12 +5076,13 @@ pip list --outdated
|
|||
|
||||
#+caption[The result of =pip list --outdated=]:
|
||||
#+caption: The result of =pip list --outdated=.
|
||||
#+name: lst:shell-pip-list-outdated-results
|
||||
#+RESULTS: lst:shell-pip-list-outdated
|
||||
#+begin_src text
|
||||
#+begin_src text -n
|
||||
Package Version Latest Type
|
||||
------------------- ------- ------ -----
|
||||
aiofiles 22.1.0 23.1.0 wheel
|
||||
jupyter_server_ydoc 0.6.1 0.7.0 wheel
|
||||
jupyter_server_ydoc 0.6.1 0.8.0 wheel
|
||||
jupyter-ydoc 0.2.2 0.3.4 wheel
|
||||
y-py 0.5.9 0.6.0 wheel
|
||||
ypy-websocket 0.8.2 0.8.4 wheel
|
||||
|
@ -5001,7 +5090,7 @@ ypy-websocket 0.8.2 0.8.4 wheel
|
|||
|
||||
#+caption[Show how to use =pip index versions=]:
|
||||
#+caption: Show how to use =pip index versions=.
|
||||
#+header: :wrap src text
|
||||
#+header: :wrap "src text -n"
|
||||
#+name: lst:shell-pip-index-versions
|
||||
#+begin_src shell :exports both :results verbatim
|
||||
# WARNING: "pip index" is currently an experimental command.
|
||||
|
@ -5010,8 +5099,9 @@ pip index versions circular-buffer --no-color
|
|||
|
||||
#+caption[The result of =pip index versions=]:
|
||||
#+caption: The result of =pip index versions=.
|
||||
#+name: lst:shell-pip-index-versions-results
|
||||
#+RESULTS: lst:shell-pip-index-versions
|
||||
#+begin_src text
|
||||
#+begin_src text -n
|
||||
circular-buffer (0.2.0)
|
||||
Available versions: 0.2.0, 0.1.1, 0.1.0
|
||||
#+end_src
|
||||
|
@ -5037,6 +5127,7 @@ Available versions: 0.2.0, 0.1.1, 0.1.0
|
|||
(string-replace "_" "-" (alist-get 'name (car alists))))
|
||||
(setq alists (cdr alists))))
|
||||
(kill-buffer)
|
||||
(describe-variable 'pip-outdated-packages)
|
||||
(message "Calling `%S' succeeded" #'pip-list-outdated))))
|
||||
|
||||
(defun pip-list-outdated ()
|
||||
|
@ -5057,14 +5148,22 @@ This invokes an asynchonous process and finishes with a message."
|
|||
#+caption: Emacs interface to upgrade outdated unfrozen Python packages.
|
||||
#+name: lst:pip-upgrade-maybe
|
||||
#+begin_src emacs-lisp -n :results silent
|
||||
(defcustom pip-frozen-packages '("aiofiles"
|
||||
"jupyter-server-ydoc"
|
||||
"jupyter-ydoc"
|
||||
"y-py"
|
||||
"ypy-websocket")
|
||||
"Frozen Python packages (until jupyterlab-4.0.0)"
|
||||
(defgroup pip nil
|
||||
"Client for accessing the \"Package Installer for Python\" and \"PyPI\"."
|
||||
:group 'applications)
|
||||
|
||||
(defcustom pip-frozen-packages nil
|
||||
"Frozen Python packages."
|
||||
:group 'pip
|
||||
:type '(repeat string))
|
||||
|
||||
;; Frozen until the release of jupyterlab-4.0.0.
|
||||
(setopt pip-frozen-packages '("aiofiles"
|
||||
"jupyter-server-ydoc"
|
||||
"jupyter-ydoc"
|
||||
"y-py"
|
||||
"ypy-websocket"))
|
||||
|
||||
(defun pip--upgrade-maybe-sentinel (process event)
|
||||
(when (and (eq (process-status process) 'exit)
|
||||
(buffer-live-p (process-buffer process)))
|
||||
|
@ -5096,16 +5195,72 @@ buffer to check whether upgrading has made the dependencies incompatible."
|
|||
|
||||
#+caption[Emacs interface to the =PyPI= simple =JSON= =API=]:
|
||||
#+caption: Emacs interface to the =PyPI= simple =JSON= =API=.
|
||||
#+name: lst:pip-pypi-simple-json-apip
|
||||
#+begin_src emacs-lisp -n :results silent
|
||||
(defun pip-simple-json-project-details (name)
|
||||
(let ((url (format "https://pypi.org/simple/%s" name))
|
||||
(url-request-method "GET")
|
||||
(url-mime-accept-string "application/vnd.pypi.simple.latest+json"))
|
||||
(url-retrieve url
|
||||
(lambda (status) (switch-to-buffer (current-buffer))))))
|
||||
#+name: lst:pip-pypi-simple-json-api
|
||||
#+begin_src emacs-lisp -n :lexical t :results silent
|
||||
;; https://emacs.stackexchange.com/questions/61754/
|
||||
;; "How can I enable lexical binding for elisp code in Org mode?"
|
||||
|
||||
(defun pip-simple-json-project-list ()
|
||||
(defvar pip--simple-details-cache (make-hash-table :test 'equal)
|
||||
"Cache for PyPI project details")
|
||||
|
||||
(defun pip-simple-get-json ()
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(and (re-search-forward "^HTTP/.+ 200 OK$" nil (line-end-position))
|
||||
(search-forward "\n\n" nil t)
|
||||
(json-parse-buffer :array-type 'list))))
|
||||
|
||||
(defun pip-simple-details-retrieve (name callback &optional cbargs)
|
||||
(pip--simple-details-prune-cache)
|
||||
(if-let ((cached (gethash name pip--simple-details-cache)))
|
||||
(apply callback (cdr cached) cbargs)
|
||||
(let ((url (format "https://pypi.org/simple/%s" name))
|
||||
(url-request-method "GET")
|
||||
(url-mime-accept-string "application/vnd.pypi.simple.latest+json"))
|
||||
(url-retrieve
|
||||
url
|
||||
(lambda (status)
|
||||
(let ((details (and (not (plist-get status :error))
|
||||
(pip-simple-get-json))))
|
||||
(when details
|
||||
(setf (gethash name pip--simple-details-cache)
|
||||
(cons (time-convert nil 'integer) details)))
|
||||
(prog1
|
||||
(apply callback (or details 'error) cbargs)
|
||||
(kill-buffer))))
|
||||
nil t))))
|
||||
|
||||
(defun pip--simple-details-prune-cache ()
|
||||
(let ((expired nil)
|
||||
(time (- (time-convert nil 'integer)
|
||||
;; Ten minutes
|
||||
(* 10 60))))
|
||||
(maphash (lambda (key val)
|
||||
(when (< (car val) time)
|
||||
(push key expired)))
|
||||
pip--simple-details-cache)
|
||||
(dolist (key expired)
|
||||
(remhash key pip--simple-details-cache))))
|
||||
#+end_src
|
||||
|
||||
#+caption[Using the Emacs interface to the =PyPI= simple =JSON= =API=]:
|
||||
#+caption: Using the Emacs interface to the =PyPI= simple =JSON= =API=.
|
||||
#+name: lst:using-pip-pypi-simple-json-api
|
||||
#+begin_src emacs-lisp -n :lexical t :results silent
|
||||
;; https://emacs.stackexchange.com/questions/61754/
|
||||
;; "How can I enable lexical binding for elisp code in Org mode?"
|
||||
|
||||
(defun pip-simple-project-versions (name)
|
||||
"Return the versions of Python package NAME."
|
||||
(interactive "sPython package name: ")
|
||||
(pip-simple-details-retrieve
|
||||
name
|
||||
(lambda (details)
|
||||
(when-let ((versions (reverse (cdr (gethash "versions" details)))))
|
||||
(message "`%s' versions: %S" name versions)))))
|
||||
|
||||
(defun pip-simple-project-list ()
|
||||
"Get the Python package project list (PEP-691 and PEP-700)."
|
||||
(interactive)
|
||||
(let ((url-request-method "GET")
|
||||
(url-mime-accept-string "application/vnd.pypi.simple.latest+json"))
|
||||
|
@ -5501,9 +5656,9 @@ contrary to for instance [[https://github.com/Fanael/rainbow-delimiters#readme][
|
|||
:CUSTOM_ID: sec:electric-operators
|
||||
:END:
|
||||
|
||||
Listing [[lst:configure-electric-operator]] configures =electric-operator-mode=
|
||||
to add spaces around operators for compatibility with for instance the [[https://black.readthedocs.io/en/stable/][Black
|
||||
code formatter for Python]].
|
||||
Listing [[lst:configure-electric-operator]] configures =electric-operator-mode= to
|
||||
add spaces around operators for compatibility with for instance the [[https://black.readthedocs.io/en/stable/][Black code
|
||||
formatter for Python]].
|
||||
|
||||
#+caption[Configure =electric-operator=]:
|
||||
#+caption: Configure =electric-operator=.
|
||||
|
@ -5555,7 +5710,7 @@ Listing [[lst:configure-tempo-latex-completing-read]] shows how to combine =temp
|
|||
#+caption: Configure =tempo= user-interface.
|
||||
#+name: lst:configure-tempo-ui
|
||||
#+begin_src emacs-lisp -n :results silent
|
||||
(with-eval-after-load 'tempo
|
||||
(when (require 'tempo nil 'noerror)
|
||||
(setopt tempo-interactive t)
|
||||
|
||||
(with-eval-after-load 'marginalia
|
||||
|
@ -5589,31 +5744,30 @@ Allows `tempo' expansion by typing <SPC> after a complete `tempo' tag."
|
|||
(unless (abbrev-symbol (car tag) abbrev-table)
|
||||
(define-abbrev abbrev-table
|
||||
(car tag) 1 'abbrev-tempo-expand-if-complete)))))
|
||||
|
||||
(with-eval-after-load 'org
|
||||
(add-hook 'org-mode-hook 'setup-local-tempo-key-bindings))
|
||||
#+end_src
|
||||
|
||||
*** Tempo for =AUCTeX='s =LaTeX-mode=
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: sec:tempo-latex
|
||||
:END:
|
||||
|
||||
#+caption[Configure =tempo= for =latex= with =completing-read=]:
|
||||
#+caption: Configure =tempo= for =latex= with =completing-read=.
|
||||
#+name: lst:configure-tempo-latex-completing-read
|
||||
#+begin_src emacs-lisp -n :results silent
|
||||
(with-eval-after-load 'latex
|
||||
(unless (featurep 'tempo)
|
||||
(require 'tempo))
|
||||
(require 'tempo nil 'noerror)
|
||||
|
||||
(defun tempo-latex-environment-handler (element)
|
||||
(when-let ((ok (eq element 'latex-environment))
|
||||
(environment
|
||||
(completing-read "LaTeX environment: "
|
||||
(LaTeX-environment-list)
|
||||
#'always 'require-match)))
|
||||
`(l "\\begin{" ,environment "}" > n > r n "\\end{" ,environment "}" >)))
|
||||
(when (eq element 'latex-environment)
|
||||
(let ((environment (completing-read "LaTeX environment: "
|
||||
(LaTeX-environment-list)
|
||||
#'always 'require-match)))
|
||||
`(l "\\begin{" ,environment "}" > n > r n "\\end{" ,environment "}" >))))
|
||||
|
||||
(cl-pushnew 'tempo-latex-environment-handler tempo-user-elements)
|
||||
|
||||
(defun setup-tempo-latex ()
|
||||
(setup-local-tempo-key-bindings)
|
||||
(defvar latex-tempo-tags nil)
|
||||
|
||||
(tempo-define-template
|
||||
|
@ -5624,18 +5778,24 @@ Allows `tempo' expansion by typing <SPC> after a complete `tempo' tag."
|
|||
'latex-tempo-tags)
|
||||
|
||||
(tempo-use-tag-list 'latex-tempo-tags)
|
||||
(add-tempo-tags-to-abbrev-table latex-tempo-tags latex-mode-abbrev-table))
|
||||
(add-tempo-tags-to-abbrev-table latex-tempo-tags latex-mode-abbrev-table)
|
||||
(setup-local-tempo-key-bindings))
|
||||
|
||||
(add-hook 'LaTeX-mode-hook 'setup-tempo-latex))
|
||||
#+end_src
|
||||
|
||||
|
||||
*** Tempo for =python-mode=
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: sec:tempo-python
|
||||
:END:
|
||||
|
||||
#+caption[Configure =tempo= for =python-mode=]:
|
||||
#+caption: Configure =tempo= for =python-mode=.
|
||||
#+name: lst:setup-python-tempo
|
||||
#+begin_src emacs-lisp -n :results silent
|
||||
(with-eval-after-load 'python
|
||||
(unless (featurep 'tempo)
|
||||
(require 'tempo))
|
||||
(require 'tempo nil 'noerror)
|
||||
|
||||
(defun setup-tempo-python ()
|
||||
(defvar python-tempo-tags nil)
|
||||
|
|
Loading…
Reference in New Issue