docs: add examples.org
This adds the basic framework of docs/examples.org, including the former contents of demo.org in :lang emacs-lisp. elisp-demo has also been reconfigured to search it instead. Keep in mind that examples.org references a few things in as-of-yet published documentation. This will be rectified soon.
This commit is contained in:
parent
e71daf5cc3
commit
94ea4aa7dc
3 changed files with 553 additions and 266 deletions
|
@ -1,49 +1,76 @@
|
||||||
#+title: API Demos
|
:PROPERTIES:
|
||||||
|
:ID: e103c1bc-be8e-4451-8e43-a93d9e35e692
|
||||||
|
:END:
|
||||||
|
#+title: Examples
|
||||||
|
#+subtitle: Samples of Emacs/Doom dotfiles, concepts, and sub-projects
|
||||||
#+property: header-args:elisp :results pp
|
#+property: header-args:elisp :results pp
|
||||||
|
|
||||||
This file contains demos of Doom's public API; its core library, macros, and
|
* Introduction
|
||||||
autodefs. It is used by the =elisp-demos= package to display examples of their
|
Examples speak louder than technical explanations, so this file exists to house
|
||||||
usage in the documentation displayed by either ~describe-function~ or
|
examples of Doom's (and Emacs') concepts, libraries, dotfiles, and more, for
|
||||||
~helpful-function~ (on [[kbd:][SPC h f]]).
|
your own reference. They are divided into Emacs-specific and Doom-specific
|
||||||
|
examples; where the former can also be useful to users who don't use Doom.
|
||||||
|
|
||||||
* Table of Contents :TOC_3:
|
Some of Doom's components will read this file to generate documentation for you,
|
||||||
- [[#doom-lib][doom-lib]]
|
for example:
|
||||||
- [[#add-hook][add-hook!]]
|
|
||||||
- [[#add-transient-hook][add-transient-hook!]]
|
|
||||||
- [[#after][after!]]
|
|
||||||
- [[#appendq][appendq!]]
|
|
||||||
- [[#custom-set-faces][custom-set-faces!]]
|
|
||||||
- [[#custom-theme-set-faces][custom-theme-set-faces!]]
|
|
||||||
- [[#defer-feature][defer-feature!]]
|
|
||||||
- [[#defer-until][defer-until!]]
|
|
||||||
- [[#disable-packages][disable-packages!]]
|
|
||||||
- [[#doom][doom!]]
|
|
||||||
- [[#file-exists-p][file-exists-p!]]
|
|
||||||
- [[#cmd][cmd!]]
|
|
||||||
- [[#cmd-1][cmd!!]]
|
|
||||||
- [[#cmds][cmds!]]
|
|
||||||
- [[#kbd][kbd!]]
|
|
||||||
- [[#lambda][lambda!]]
|
|
||||||
- [[#fn][fn!]]
|
|
||||||
- [[#letenv][letenv!]]
|
|
||||||
- [[#load][load!]]
|
|
||||||
- [[#map][map!]]
|
|
||||||
- [[#package][package!]]
|
|
||||||
- [[#pushnew][pushnew!]]
|
|
||||||
- [[#prependq][prependq!]]
|
|
||||||
- [[#quiet][quiet!]]
|
|
||||||
- [[#remove-hook][remove-hook!]]
|
|
||||||
- [[#setq][setq!]]
|
|
||||||
- [[#setq-hook][setq-hook!]]
|
|
||||||
- [[#unsetq-hook][unsetq-hook!]]
|
|
||||||
- [[#use-package][use-package!]]
|
|
||||||
|
|
||||||
* doom-lib
|
- Doom's [[doom-module:][:lang emacs-lisp]] module installs the [[doom-package:][elisp-demos]] package. This displays
|
||||||
** add-hook!
|
usage examples alongside documentation in [[doom-package:][help]] and [[doom-package:][helpful]] buffers (produced
|
||||||
|
by =describe-*= and =helpful-*= commands; e.g. [[kbd:][<help> h f]]). Doom has extended
|
||||||
|
this package to search this file as well.
|
||||||
|
- [[id:1b8b8fa9-6233-4ed8-95c7-f46f8e4e2592][Some Doom's CLI commands]] will emit documentation informed by Doom's org files,
|
||||||
|
including this file.
|
||||||
|
|
||||||
|
If you're interested in adding to this document, read [[id:9ac0c15c-29e7-43f8-8926-5f0edb1098f0][the documentation section]]
|
||||||
|
of our contributing guide first.
|
||||||
|
|
||||||
|
* TODO Emacs
|
||||||
|
This section is dedicated to examples of concepts and libraries that can benefit
|
||||||
|
all Emacs users, whether or not they use Doom.
|
||||||
|
|
||||||
|
** TODO Emacs Lisp :demos:
|
||||||
|
**** file-name-with-extension
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 28.1
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp
|
||||||
|
(file-name-with-extension "some/file.cpp" "h")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
: some/file.h
|
||||||
|
|
||||||
|
**** file-name-concat
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 28.1
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(file-name-concat user-emacs-directory "lisp" "file.el")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(file-name-concat "foo" "bar" "baz")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
: foo/bar/baz
|
||||||
|
|
||||||
|
** TODO Templates
|
||||||
|
*** TODO Emacs package
|
||||||
|
*** TODO Dynamic module
|
||||||
|
|
||||||
|
* TODO Doom Emacs
|
||||||
|
This section is dedicated to examples of concepts and libraries only relevant to
|
||||||
|
Doom and its users. These are intended to be demonstrations, not substitutes for
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
** TODO Emacs Lisp :demos:
|
||||||
|
*** doom-lib
|
||||||
|
**** add-hook!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
;; With only one hook and one function, this is identical to `add-hook'. In that
|
;; With only one hook and one function, this is identical to `add-hook'. In that
|
||||||
;; case, use that instead.
|
;; case, use that instead.
|
||||||
(add-hook! 'some-mode-hook #'enable-something)
|
(add-hook! 'some-mode-hook #'enable-something)
|
||||||
|
@ -70,13 +97,13 @@ usage in the documentation displayed by either ~describe-function~ or
|
||||||
...))
|
...))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** TODO add-transient-hook!
|
**** TODO add-transient-hook!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
** after!
|
**** after!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
;;; `after!' will take:
|
;;; `after!' will take:
|
||||||
|
@ -103,9 +130,9 @@ usage in the documentation displayed by either ~describe-function~ or
|
||||||
(after! rustic ...)
|
(after! rustic ...)
|
||||||
(after! python ...)
|
(after! python ...)
|
||||||
#+end_src
|
#+end_src
|
||||||
** appendq!
|
**** appendq!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(let ((x '(a b c)))
|
(let ((x '(a b c)))
|
||||||
|
@ -127,9 +154,9 @@ usage in the documentation displayed by either ~describe-function~ or
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
: (a b c c d e f g h)
|
: (a b c c d e f g h)
|
||||||
|
|
||||||
** custom-set-faces!
|
**** custom-set-faces!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
(custom-set-faces!
|
(custom-set-faces!
|
||||||
|
@ -162,9 +189,9 @@ usage in the documentation displayed by either ~describe-function~ or
|
||||||
`(outline-2 :background ,(doom-color 'blue)))
|
`(outline-2 :background ,(doom-color 'blue)))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** custom-theme-set-faces!
|
**** custom-theme-set-faces!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
(custom-theme-set-faces! 'doom-one
|
(custom-theme-set-faces! 'doom-one
|
||||||
|
@ -197,59 +224,26 @@ usage in the documentation displayed by either ~describe-function~ or
|
||||||
`(outline-2 :background ,(doom-color 'blue)))
|
`(outline-2 :background ,(doom-color 'blue)))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** TODO defer-feature!
|
**** TODO defer-feature!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
** TODO defer-until!
|
**** TODO defer-until!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
** disable-packages!
|
**** disable-packages!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
;; Disable packages enabled by DOOM
|
;; Disable packages enabled by DOOM
|
||||||
(disable-packages! some-package second-package)
|
(disable-packages! some-package second-package)
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** doom!
|
**** file-exists-p!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
|
||||||
#+begin_src emacs-lisp :eval no
|
|
||||||
(doom! :completion
|
|
||||||
company
|
|
||||||
ivy
|
|
||||||
;;helm
|
|
||||||
|
|
||||||
:tools
|
|
||||||
(:if IS-MAC macos)
|
|
||||||
docker
|
|
||||||
lsp
|
|
||||||
|
|
||||||
:lang
|
|
||||||
(cc +lsp)
|
|
||||||
(:cond ((string= system-name "work-pc")
|
|
||||||
python
|
|
||||||
rust
|
|
||||||
web)
|
|
||||||
((string= system-name "writing-pc")
|
|
||||||
(org +dragndrop)
|
|
||||||
ruby))
|
|
||||||
(:if IS-LINUX
|
|
||||||
(web +lsp)
|
|
||||||
web)
|
|
||||||
|
|
||||||
:config
|
|
||||||
literate
|
|
||||||
(default +bindings +smartparens))
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
** file-exists-p!
|
|
||||||
:PROPERTIES:
|
|
||||||
:added: pre-3.0.0
|
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(file-exists-p! "init.el" doom-emacs-dir)
|
(file-exists-p! "init.el" doom-emacs-dir)
|
||||||
|
@ -267,17 +261,17 @@ usage in the documentation displayed by either ~describe-function~ or
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
: /home/hlissner/.emacs.d/LICENSE
|
: /home/hlissner/.emacs.d/LICENSE
|
||||||
|
|
||||||
** cmd!
|
**** cmd!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
(map! "C-j" (cmd! (newline) (indent-according-to-mode)))
|
(map! "C-j" (cmd! (newline) (indent-according-to-mode)))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** cmd!!
|
**** cmd!!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
When ~newline~ is passed a numerical prefix argument (=C-u 5 M-x newline=), it
|
When ~newline~ is passed a numerical prefix argument (=C-u 5 M-x newline=), it
|
||||||
inserts N newlines. We can use ~cmd!!~ to easily create a keybinds that bakes in
|
inserts N newlines. We can use ~cmd!!~ to easily create a keybinds that bakes in
|
||||||
|
@ -297,9 +291,9 @@ Or to create aliases for functions that behave differently:
|
||||||
(fset 'org-reset-global-visibility (cmd!! #'org-global-cycle '(4))
|
(fset 'org-reset-global-visibility (cmd!! #'org-global-cycle '(4))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** cmds!
|
**** cmds!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
(map! :i [tab] (cmds! (and (modulep! :editor snippets)
|
(map! :i [tab] (cmds! (and (modulep! :editor snippets)
|
||||||
|
@ -320,16 +314,16 @@ Or to create aliases for functions that behave differently:
|
||||||
#'evil-jump-item))
|
#'evil-jump-item))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** kbd!
|
**** kbd!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
(map! "," (kbd! "SPC")
|
(map! "," (kbd! "SPC")
|
||||||
";" (kbd! ":"))
|
";" (kbd! ":"))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** lambda!
|
**** lambda!
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(mapcar (lambda! ((&key foo bar baz))
|
(mapcar (lambda! ((&key foo bar baz))
|
||||||
(list foo bar baz))
|
(list foo bar baz))
|
||||||
|
@ -338,49 +332,25 @@ Or to create aliases for functions that behave differently:
|
||||||
(:bar 42)))
|
(:bar 42)))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
#+RESULTS:
|
**** fn!
|
||||||
: ((10 25 nil) (nil nil hello) (nil 42 nil))
|
|
||||||
|
|
||||||
** fn!
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(mapcar (fn! (symbol-name %)) '(hello world))
|
(mapcar (fn! (symbol-name %)) '(hello world))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
#+RESULTS:
|
|
||||||
: ("hello" "world")
|
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(seq-sort (fn! (string-lessp (symbol-name %1)
|
(seq-sort (fn! (string-lessp (symbol-name %1)
|
||||||
(symbol-name %2)))
|
(symbol-name %2)))
|
||||||
'(bonzo foo bar buddy doomguy baz zombies))
|
'(bonzo foo bar buddy doomguy baz zombies))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
#+RESULTS:
|
|
||||||
: (bar baz bonzo buddy doomguy foo zombies)
|
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(format "You passed %d arguments to this function"
|
(format "You passed %d arguments to this function"
|
||||||
(funcall (fn! (length %*)) :foo :bar :baz "hello" 123 t))
|
(funcall (fn! (length %*)) :foo :bar :baz "hello" 123 t))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
#+RESULTS:
|
**** load!
|
||||||
: "You passed 6 arguments to this function"
|
|
||||||
|
|
||||||
** letenv!
|
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
|
||||||
#+begin_src emacs-lisp
|
|
||||||
(letenv! (("SHELL" "/bin/sh"))
|
|
||||||
(shell-command-to-string "echo $SHELL"))
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
#+RESULTS:
|
|
||||||
: "/bin/sh\n"
|
|
||||||
|
|
||||||
** load!
|
|
||||||
:PROPERTIES:
|
|
||||||
:added: pre-3.0.0
|
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
;;; Lets say we're in ~/.doom.d/config.el
|
;;; Lets say we're in ~/.doom.d/config.el
|
||||||
|
@ -392,9 +362,9 @@ Or to create aliases for functions that behave differently:
|
||||||
(load! "~/.maynotexist" nil t)
|
(load! "~/.maynotexist" nil t)
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** map!
|
**** map!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
(map! :map magit-mode-map
|
(map! :map magit-mode-map
|
||||||
|
@ -490,9 +460,188 @@ These are side-by-side comparisons, showing how to bind keys with and without
|
||||||
(:map go-lisp-mode :n "C-x x" #'do-something-else))
|
(:map go-lisp-mode :n "C-x x" #'do-something-else))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** package!
|
**** pushnew!
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:added: pre-3.0.0
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(let ((list '(a b c)))
|
||||||
|
(pushnew! list 'c 'd 'e)
|
||||||
|
list)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
: (e d a b c)
|
||||||
|
|
||||||
|
**** prependq!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(let ((x '(a b c)))
|
||||||
|
(prependq! x '(c d e))
|
||||||
|
x)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
: (c d e a b c)
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(let ((x '(a b c))
|
||||||
|
(y '(c d e))
|
||||||
|
(z '(f g)))
|
||||||
|
(prependq! x y z '(h))
|
||||||
|
x)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
: (c d e f g h a b c)
|
||||||
|
|
||||||
|
**** quiet!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp :eval no
|
||||||
|
;; Enters recentf-mode without extra output
|
||||||
|
(quiet! (recentf-mode +1))
|
||||||
|
#+end_src
|
||||||
|
**** remove-hook!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp :eval no
|
||||||
|
;; With only one hook and one function, this is identical to `remove-hook'. In
|
||||||
|
;; that case, use that instead.
|
||||||
|
(remove-hook! 'some-mode-hook #'enable-something)
|
||||||
|
|
||||||
|
;; Removing N functions from M hooks
|
||||||
|
(remove-hook! some-mode #'enable-something #'and-another)
|
||||||
|
(remove-hook! some-mode #'(enable-something and-another))
|
||||||
|
(remove-hook! '(one-mode-hook second-mode-hook) #'enable-something)
|
||||||
|
(remove-hook! (one-mode second-mode) #'enable-something)
|
||||||
|
|
||||||
|
;; Removing buffer-local hooks
|
||||||
|
(remove-hook! (one-mode second-mode) :local #'enable-something)
|
||||||
|
|
||||||
|
;; Removing arbitrary forms (must be exactly the same as the definition)
|
||||||
|
(remove-hook! (one-mode second-mode) (setq v 5) (setq a 2))
|
||||||
|
#+end_src
|
||||||
|
**** setq!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
;; Each of these have a setter associated with them, which must be triggered in
|
||||||
|
;; order for their new values to have an effect.
|
||||||
|
(setq! evil-want-Y-yank-to-eol nil
|
||||||
|
evil-want-C-u-scroll nil
|
||||||
|
evil-want-C-d-scroll nil)
|
||||||
|
#+end_src
|
||||||
|
**** setq-hook!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp :eval no
|
||||||
|
;; Set multiple variables after a hook
|
||||||
|
(setq-hook! 'markdown-mode-hook
|
||||||
|
line-spacing 2
|
||||||
|
fill-column 80)
|
||||||
|
|
||||||
|
;; Set variables after multiple hooks
|
||||||
|
(setq-hook! '(eshell-mode-hook term-mode-hook)
|
||||||
|
hscroll-margin 0)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
**** unsetq-hook!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp :eval no
|
||||||
|
(unsetq-hook! 'markdown-mode-hook line-spacing)
|
||||||
|
|
||||||
|
;; Removes the following variable hook
|
||||||
|
(setq-hook! 'markdown-mode-hook line-spacing 2)
|
||||||
|
|
||||||
|
;; Removing N variables from M hooks
|
||||||
|
(unsetq-hook! some-mode enable-something and-another)
|
||||||
|
(unsetq-hook! some-mode (enable-something and-another))
|
||||||
|
(unsetq-hook! '(one-mode-hook second-mode-hook) enable-something)
|
||||||
|
(unsetq-hook! (one-mode second-mode) enable-something)
|
||||||
|
#+end_src
|
||||||
|
**** versionp!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(versionp! "25.3" > "27.1")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
: nil
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(versionp! "28.0" <= emacs-version <= "28.1")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
: t
|
||||||
|
|
||||||
|
*** doom-modules
|
||||||
|
**** doom!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp :eval no
|
||||||
|
(doom! :completion
|
||||||
|
company
|
||||||
|
ivy
|
||||||
|
;;helm
|
||||||
|
|
||||||
|
:tools
|
||||||
|
(:if IS-MAC macos)
|
||||||
|
docker
|
||||||
|
lsp
|
||||||
|
|
||||||
|
:lang
|
||||||
|
(cc +lsp)
|
||||||
|
(:cond ((string= system-name "work-pc")
|
||||||
|
python
|
||||||
|
rust
|
||||||
|
web)
|
||||||
|
((string= system-name "writing-pc")
|
||||||
|
(org +dragndrop)
|
||||||
|
ruby))
|
||||||
|
(:if IS-LINUX
|
||||||
|
(web +lsp)
|
||||||
|
web)
|
||||||
|
|
||||||
|
:config
|
||||||
|
literate
|
||||||
|
(default +bindings +smartparens))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
**** use-package!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
|
:END:
|
||||||
|
#+begin_src emacs-lisp :eval no
|
||||||
|
;; Use after-call to load package before hook
|
||||||
|
(use-package! projectile
|
||||||
|
:after-call (pre-command-hook after-find-file dired-before-readin-hook))
|
||||||
|
|
||||||
|
;; defer recentf packages one by one
|
||||||
|
(use-package! recentf
|
||||||
|
:defer-incrementally easymenu tree-widget timer
|
||||||
|
:after-call after-find-file)
|
||||||
|
|
||||||
|
;; This is equivalent to :defer-incrementally (abc)
|
||||||
|
(use-package! abc
|
||||||
|
:defer-incrementally t)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
**** package!
|
||||||
|
:PROPERTIES:
|
||||||
|
:added: 3.0.0-pre
|
||||||
:END:
|
:END:
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
;; To install a package that can be found on ELPA or any of the sources
|
;; To install a package that can be found on ELPA or any of the sources
|
||||||
|
@ -525,130 +674,260 @@ These are side-by-side comparisons, showing how to bind keys with and without
|
||||||
(package! evil :ignore (not (equal system-name "my-desktop")))
|
(package! evil :ignore (not (equal system-name "my-desktop")))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** pushnew!
|
*** doom-cli
|
||||||
:PROPERTIES:
|
**** TODO defcli!
|
||||||
:added: pre-3.0.0
|
**** TODO defcli-alias!
|
||||||
:END:
|
**** TODO defcli-obsolete!
|
||||||
#+begin_src emacs-lisp
|
**** TODO defcli-stub!
|
||||||
(let ((list '(a b c)))
|
**** TODO defcli-autoload!
|
||||||
(pushnew! list 'c 'd 'e)
|
**** TODO defcli-group!
|
||||||
list)
|
**** TODO exit!
|
||||||
|
**** TODO call!
|
||||||
|
**** TODO run!
|
||||||
|
**** TODO sh!
|
||||||
|
**** TODO sh!!
|
||||||
|
**** TODO git!
|
||||||
|
**** TODO def-cli-context-get
|
||||||
|
**** TODO def-cli-context-put
|
||||||
|
**** TODO def-cli-context-find-option
|
||||||
|
**** TODO def-cli-call
|
||||||
|
**** TODO def-cli-exit
|
||||||
|
**** TODO def-cli-load
|
||||||
|
**** TODO def-cli-load-all
|
||||||
|
**** TODO doom-cli-find
|
||||||
|
**** TODO doom-cli-get
|
||||||
|
**** TODO doom-cli-prop
|
||||||
|
**** TODO doom-cli-subcommands
|
||||||
|
**** TODO doom-cli-aliases
|
||||||
|
*** TODO lib/files.el
|
||||||
|
**** TODO doom-path
|
||||||
|
**** TODO doom-glob
|
||||||
|
**** TODO doom-dir
|
||||||
|
**** TODO doom-files-in
|
||||||
|
**** TODO doom-file-cookie-p
|
||||||
|
**** TODO file-exists-p!
|
||||||
|
**** TODO doom-file-size
|
||||||
|
**** TODO doom-file-line-count
|
||||||
|
**** TODO doom-directory-size
|
||||||
|
**** TODO doom-file-read
|
||||||
|
**** TODO doom-file-write
|
||||||
|
**** TODO with-file-contents!
|
||||||
|
|
||||||
|
** TODO Configuration files
|
||||||
|
*** TODO doomprofiles.el
|
||||||
|
*** TODO =.doomrc=
|
||||||
|
*** TODO =.doomproject=
|
||||||
|
*** TODO =.doommodule=
|
||||||
|
*** TODO =.doomprofile=
|
||||||
|
** TODO Templates
|
||||||
|
*** TODO User configuration
|
||||||
|
*** TODO Module
|
||||||
|
*** TODO Project
|
||||||
|
*** TODO Theme
|
||||||
|
*** TODO Command-line interface
|
||||||
|
**** Unix utilities, rewritten as Doom scripts
|
||||||
|
To show off the syntax and capabilities of Doom's CLI framework, here are some
|
||||||
|
popular scripts ported to doomscripts for reference. They will all operate under
|
||||||
|
these assumptions:
|
||||||
|
|
||||||
|
1. The script lives somewhere in your =$PATH=,
|
||||||
|
2. =$EMACSDIR/bin/doomscript= lives in your =$PATH=.
|
||||||
|
3. The script is executable,
|
||||||
|
4. The script's filename matches the first argument of ~run!~ (by convention,
|
||||||
|
not a requirement),
|
||||||
|
|
||||||
|
***** ~mkdir~
|
||||||
|
#+begin_src emacs-lisp :eval no
|
||||||
|
#!/usr/bin/env doomscript
|
||||||
|
|
||||||
|
(defcli! mkdir
|
||||||
|
((mode ("-m" "--mode" mode))
|
||||||
|
(parents? ("-p" "--parents"))
|
||||||
|
(verbose? ("-v" "--verbose"))
|
||||||
|
&args directories)
|
||||||
|
"Create the DIRECTORIES, if do not already exist.
|
||||||
|
|
||||||
|
Mandatory arguments to long options are mandatory for short options too.
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
-m, --mode
|
||||||
|
set file mode (as in chmod), not a=rwx - umask.
|
||||||
|
-p, --parents
|
||||||
|
no error if existing, make parent directories as needed, with their file
|
||||||
|
modes unaffected by any `-m' option.
|
||||||
|
-v, --verbose
|
||||||
|
print a message for each created directory
|
||||||
|
|
||||||
|
AUTHOR:
|
||||||
|
Original program by David MacKenzie. Doomscript port by Henrik Lissner.
|
||||||
|
|
||||||
|
SEE ALSO:
|
||||||
|
`mkdir(2)`
|
||||||
|
|
||||||
|
Full documentation <https://www.gnu.org/software/coreutils/mkdir>
|
||||||
|
or available locally via: info '(coreutils) mkdir invocation'
|
||||||
|
|
||||||
|
Packaged by https://nixos.org
|
||||||
|
Copyright © 2022 Free Software Foundation, Inc.
|
||||||
|
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/li‐
|
||||||
|
censes/gpl.html>.
|
||||||
|
This is free software: you are free to change and redistribute it.
|
||||||
|
There is NO WARRANTY, to the extent permitted by law."
|
||||||
|
(dolist (dir directories)
|
||||||
|
(unless (file-directory-p dir)
|
||||||
|
(make-directory dir parents?)
|
||||||
|
(when mode
|
||||||
|
(set-file-modes dir mode))
|
||||||
|
(when verbose?
|
||||||
|
(print! "mkdir: created directory '%s'" dir)))))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
#+RESULTS:
|
****** Notes
|
||||||
: (e d a b c)
|
- Docstrings for Doom CLIs recognize indented sections with a capitalized
|
||||||
|
heading followed by a colon (like ~SEE ALSO:~, ~OPTIONS:~, etc). They will be
|
||||||
|
appended to the --help output for this command. ~OPTIONS~ and ~ARGUMENTS~ are
|
||||||
|
special, in that they decorate pre-existing documentation for referenced
|
||||||
|
options/arguments.
|
||||||
|
|
||||||
** prependq!
|
- The options were documented in the CLI's docstring, instead of inline like so:
|
||||||
:PROPERTIES:
|
|
||||||
:added: pre-3.0.0
|
|
||||||
:END:
|
|
||||||
#+begin_src emacs-lisp
|
|
||||||
(let ((x '(a b c)))
|
|
||||||
(prependq! x '(c d e))
|
|
||||||
x)
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
#+RESULTS:
|
|
||||||
: (c d e a b c)
|
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(let ((x '(a b c))
|
((mode ("-m" "--mode" mode) "set file modes (as in chmod), not a=rwx - umask.")
|
||||||
(y '(c d e))
|
(parents? ("-p" "--parents") "no error if existing, make parent directories as needed, with their file modes unaffected by any `-m' option.")
|
||||||
(z '(f g)))
|
(verbose? ("-v" "--verbose") "print a message for each created directory")
|
||||||
(prependq! x y z '(h))
|
&args directories)
|
||||||
x)
|
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
#+RESULTS:
|
Either is acceptable, but for long docs like this, it's better suited to the
|
||||||
: (c d e f g h a b c)
|
docstring. If both were present, Doom's help docs would have concatenated them
|
||||||
|
(separated by two newlines).
|
||||||
|
|
||||||
|
- The ~mode~ option takes one argument, a chmod mask. I indicate this with
|
||||||
|
~"`MODE'"~. This is a special syntax for highlighting arguments in the help
|
||||||
|
docs of this command. If I had used a symbol, instead (one of the predefined
|
||||||
|
types in [[var:][doom-cli-argument-value-types]]), I would've gotten free type-checking
|
||||||
|
and error handling, but there is no predefined type for chmod masks (yet), so
|
||||||
|
I'd have to do my own checks:
|
||||||
|
|
||||||
** quiet!
|
|
||||||
:PROPERTIES:
|
|
||||||
:added: pre-3.0.0
|
|
||||||
:END:
|
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
;; Enters recentf-mode without extra output
|
(defcli! mkdir
|
||||||
(quiet! (recentf-mode +1))
|
((mode ("-m" "--mode" "`MODE'"))
|
||||||
|
(parents? ("-p" "--parents"))
|
||||||
|
(verbose? ("-v" "--verbose"))
|
||||||
|
&args directories)
|
||||||
|
(unless (string-match-p "^[0-9]\\{3,4\\}$" mode)
|
||||||
|
(user-error "Invalid mode: %s" mode))
|
||||||
|
(setq mode (string-to-number mode 8))
|
||||||
|
(dolist (dir directories)
|
||||||
|
(unless (file-directory-p dir)
|
||||||
|
(make-directory dir parents?)
|
||||||
|
(when mode
|
||||||
|
(set-file-modes dir mode))
|
||||||
|
(when verbose?
|
||||||
|
(print! "mkdir: created directory '%s'" dir)))))
|
||||||
#+end_src
|
#+end_src
|
||||||
** remove-hook!
|
|
||||||
:PROPERTIES:
|
That said, set-file-modes will throw its own type error, but it likely won't
|
||||||
:added: pre-3.0.0
|
be as user friendly.
|
||||||
:END:
|
|
||||||
|
***** TODO ~say~
|
||||||
#+begin_src emacs-lisp :eval no
|
#+begin_src emacs-lisp :eval no
|
||||||
;; With only one hook and one function, this is identical to `remove-hook'. In
|
#!/usr/bin/env doomscript
|
||||||
;; that case, use that instead.
|
|
||||||
(remove-hook! 'some-mode-hook #'enable-something)
|
|
||||||
|
|
||||||
;; Removing N functions from M hooks
|
(defcli! say
|
||||||
(remove-hook! some-mode #'enable-something #'and-another)
|
((name ("--speaker" name) "Who is speaking?")
|
||||||
(remove-hook! some-mode #'(enable-something and-another))
|
&args args)
|
||||||
(remove-hook! '(one-mode-hook second-mode-hook) #'enable-something)
|
"This command repeats what you say to it.
|
||||||
(remove-hook! (one-mode second-mode) #'enable-something)
|
|
||||||
|
|
||||||
;; Removing buffer-local hooks
|
It serves as an example of the bare minimum you need to write a Doom-based CLI.
|
||||||
(remove-hook! (one-mode second-mode) :local #'enable-something)
|
Naturally, it could be more useful; it could process more complex options and
|
||||||
|
arguments, call other Doom CLIs, read/write data from files or over networks --
|
||||||
|
but that can wait for more complicated examples.
|
||||||
|
|
||||||
;; Removing arbitrary forms (must be exactly the same as the definition)
|
ARGUMENTS:
|
||||||
(remove-hook! (one-mode second-mode) (setq v 5) (setq a 2))
|
ARGS
|
||||||
|
The message to be repeated back at you.
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--speaker
|
||||||
|
If not specified, it is assumed that Emacs is speaking."
|
||||||
|
(print! "%s says: %S"
|
||||||
|
(or name "Emacs")
|
||||||
|
(string-join args " ")))
|
||||||
|
|
||||||
|
(run! "say" (cdr (member "--" argv)))
|
||||||
#+end_src
|
#+end_src
|
||||||
** setq!
|
|
||||||
:PROPERTIES:
|
#+begin_src bash :eval no
|
||||||
:added: pre-3.0.0
|
$ say hello world
|
||||||
:END:
|
Emacs says: "Hello world"
|
||||||
|
$ say --speaker Henrik "I've doomed us all"
|
||||||
|
Henrik says: "I've doomed us all"
|
||||||
|
$ say --help
|
||||||
|
TODO
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
***** emacs
|
||||||
|
This isn't useful, but it should hopefully demonstrate the full spectrum of
|
||||||
|
Doom's CLI, by reimplementing a subset of ~emacs~'s options and arguments (and
|
||||||
|
none of its documentation). It will simply forward them to the real program
|
||||||
|
afterwards.
|
||||||
|
|
||||||
|
Since I don't want to override the real ~emacs~ in the ~$PATH~, I'll just call
|
||||||
|
it ~demacs~:
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp :eval no
|
||||||
|
#!/usr/bin/env doomscript
|
||||||
|
|
||||||
|
(defcli! demacs
|
||||||
|
((cd ("--chdir" dir))
|
||||||
|
(quick? ("-Q" "--quick"))
|
||||||
|
(no-init? ("-q" "--no-init-file"))
|
||||||
|
(no-slisp? ("-nsl" "--no-site-lisp"))
|
||||||
|
(no-sfile? ("--no-site-file"))
|
||||||
|
(initdir ("--init-directory" dir))
|
||||||
|
(batch? ("--batch"))
|
||||||
|
(batch (("-l" "--load" (file) ...))
|
||||||
|
(("-e" "--eval" (form) ...))
|
||||||
|
(("-f" "--funcall" (fn) ...))
|
||||||
|
(("-L" "--directory" (dir) ...))
|
||||||
|
(("--kill")))
|
||||||
|
(script ("--script" (file)))
|
||||||
|
&args (args (file linecol)))
|
||||||
|
"Demacs is a thin wrapper around Emacs, made to demo of Doom's CLI Framework.
|
||||||
|
|
||||||
|
Since documentation isn't the focus of this example, this is all you'll get!"
|
||||||
|
(cond (script (load script))
|
||||||
|
(batch?
|
||||||
|
(dolist (do batch)
|
||||||
|
(pcase do
|
||||||
|
(`(,(or "-l" "--load") . ,file) (load file))
|
||||||
|
(`(,(or "-e" "--eval") . ,form) (eval (read form) t))
|
||||||
|
(`(,(or "-f" "--funcall") . ,fn) (funcall (read fn)))
|
||||||
|
(`("--kill" . t) (kill-emacs 0)))))
|
||||||
|
((exit! :then (cons "emacs"
|
||||||
|
(append (if quick '("-Q"))
|
||||||
|
(if no-init? '("-q"))
|
||||||
|
(if no-slisp? '("-nsl"))
|
||||||
|
(if no-sfile? '("--no-site-file"))
|
||||||
|
(if initdir `("--init-directory" ,initdir))
|
||||||
|
args))))))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
****** Notes
|
||||||
|
There's a lot of (intentional) redundancy here, for posterity. A *much* simpler
|
||||||
|
(and more reliable) version of this command would've looked like this:
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
;; Each of these have a setter associated with them, which must be triggered in
|
(defcli! demacs (&rest args)
|
||||||
;; order for their new values to have an effect.
|
(exit! :then (cons "emacs" args)))
|
||||||
(setq! evil-want-Y-yank-to-eol nil
|
|
||||||
evil-want-C-u-scroll nil
|
|
||||||
evil-want-C-d-scroll nil)
|
|
||||||
#+end_src
|
|
||||||
** setq-hook!
|
|
||||||
:PROPERTIES:
|
|
||||||
:added: pre-3.0.0
|
|
||||||
:END:
|
|
||||||
#+begin_src emacs-lisp :eval no
|
|
||||||
;; Set multiple variables after a hook
|
|
||||||
(setq-hook! 'markdown-mode-hook
|
|
||||||
line-spacing 2
|
|
||||||
fill-column 80)
|
|
||||||
|
|
||||||
;; Set variables after multiple hooks
|
|
||||||
(setq-hook! '(eshell-mode-hook term-mode-hook)
|
|
||||||
hscroll-margin 0)
|
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** unsetq-hook!
|
But that wouldn't demonstrate enough. Though, it wouldn't forward ~--version~ or
|
||||||
:PROPERTIES:
|
~--help~ either.
|
||||||
:added: pre-3.0.0
|
|
||||||
:END:
|
|
||||||
#+begin_src emacs-lisp :eval no
|
|
||||||
(unsetq-hook! 'markdown-mode-hook line-spacing)
|
|
||||||
|
|
||||||
;; Removes the following variable hook
|
** TODO Use cases
|
||||||
(setq-hook! 'markdown-mode-hook line-spacing 2)
|
*** TODO Note-taking
|
||||||
|
*** TODO Game development
|
||||||
;; Removing N variables from M hooks
|
*** TODO Web development
|
||||||
(unsetq-hook! some-mode enable-something and-another)
|
*** TODO Emacs as your terminal
|
||||||
(unsetq-hook! some-mode (enable-something and-another))
|
|
||||||
(unsetq-hook! '(one-mode-hook second-mode-hook) enable-something)
|
|
||||||
(unsetq-hook! (one-mode second-mode) enable-something)
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
** use-package!
|
|
||||||
:PROPERTIES:
|
|
||||||
:added: pre-3.0.0
|
|
||||||
:END:
|
|
||||||
#+begin_src emacs-lisp :eval no
|
|
||||||
;; Use after-call to load package before hook
|
|
||||||
(use-package! projectile
|
|
||||||
:after-call (pre-command-hook after-find-file dired-before-readin-hook))
|
|
||||||
|
|
||||||
;; defer recentf packages one by one
|
|
||||||
(use-package! recentf
|
|
||||||
:defer-incrementally easymenu tree-widget timer
|
|
||||||
:after-call after-find-file)
|
|
||||||
|
|
||||||
;; This is equivalent to :defer-incrementally (abc)
|
|
||||||
(use-package! abc
|
|
||||||
:defer-incrementally t)
|
|
||||||
#+end_src
|
|
|
@ -369,6 +369,31 @@ library/userland functions"
|
||||||
;;
|
;;
|
||||||
;;; Advice
|
;;; Advice
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun +emacs-lisp--add-doom-elisp-demos-a (fn symbol)
|
||||||
|
"Add Doom's own demos to `elisp-demos'.
|
||||||
|
|
||||||
|
Intended as :around advice for `elisp-demos--search'."
|
||||||
|
(let ((org-inhibit-startup t)
|
||||||
|
enable-dir-local-variables
|
||||||
|
org-mode-hook)
|
||||||
|
(or (funcall fn symbol)
|
||||||
|
(with-file-contents! (doom-path doom-docs-dir "examples.org")
|
||||||
|
(save-excursion
|
||||||
|
(when (re-search-backward
|
||||||
|
(format "^\\*+[ \t]+\\(?:TODO \\)?%s$"
|
||||||
|
(regexp-quote (symbol-name symbol)))
|
||||||
|
nil t)
|
||||||
|
(forward-line 1)
|
||||||
|
(let ((demos
|
||||||
|
(string-trim
|
||||||
|
(buffer-substring-no-properties
|
||||||
|
(point) (if (re-search-forward "^\\*+ " nil t)
|
||||||
|
(line-beginning-position)
|
||||||
|
(point-max))))))
|
||||||
|
(unless (string-blank-p demos)
|
||||||
|
demos))))))))
|
||||||
|
|
||||||
;;;###autoload (put 'map! 'indent-plists-as-data t)
|
;;;###autoload (put 'map! 'indent-plists-as-data t)
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun +emacs-lisp--calculate-lisp-indent-a (&optional parse-start)
|
(defun +emacs-lisp--calculate-lisp-indent-a (&optional parse-start)
|
||||||
|
|
|
@ -196,24 +196,7 @@ See `+emacs-lisp-non-package-mode' for details.")
|
||||||
(advice-add 'describe-function-1 :after #'elisp-demos-advice-describe-function-1)
|
(advice-add 'describe-function-1 :after #'elisp-demos-advice-describe-function-1)
|
||||||
(advice-add 'helpful-update :after #'elisp-demos-advice-helpful-update)
|
(advice-add 'helpful-update :after #'elisp-demos-advice-helpful-update)
|
||||||
:config
|
:config
|
||||||
(defadvice! +emacs-lisp--add-doom-elisp-demos-a (fn symbol)
|
(advice-add #'elisp-demos--search :around #'+emacs-lisp--add-doom-elisp-demos-a))
|
||||||
"Add Doom's own demos to help buffers."
|
|
||||||
:around #'elisp-demos--search
|
|
||||||
(or (funcall fn symbol)
|
|
||||||
(when-let (demos-file (doom-module-locate-path :lang 'emacs-lisp "demos.org"))
|
|
||||||
(with-temp-buffer
|
|
||||||
(insert-file-contents demos-file)
|
|
||||||
(goto-char (point-min))
|
|
||||||
(when (re-search-forward
|
|
||||||
(format "^\\*\\* %s$" (regexp-quote (symbol-name symbol)))
|
|
||||||
nil t)
|
|
||||||
(let (beg end)
|
|
||||||
(forward-line 1)
|
|
||||||
(setq beg (point))
|
|
||||||
(if (re-search-forward "^\\*" nil t)
|
|
||||||
(setq end (line-beginning-position))
|
|
||||||
(setq end (point-max)))
|
|
||||||
(string-trim (buffer-substring-no-properties beg end)))))))))
|
|
||||||
|
|
||||||
|
|
||||||
(use-package! buttercup
|
(use-package! buttercup
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue