Compare commits
4 commits
994c36c5a5
...
e40c57ff18
Author | SHA1 | Date | |
---|---|---|---|
|
e40c57ff18 | ||
|
3adc01620a | ||
|
3f84fcd436 | ||
|
c11ab5d0ef |
6 changed files with 548 additions and 179 deletions
|
@ -98,6 +98,39 @@ And some Mac-specific settings:
|
||||||
(add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
|
(add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
|
||||||
(add-to-list 'default-frame-alist '(ns-appearance . dark)))
|
(add-to-list 'default-frame-alist '(ns-appearance . dark)))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
** Make C-g a little more useful
|
||||||
|
|
||||||
|
Protesilaos has a simple fix for [[https://protesilaos.com/codelog/2024-11-28-basic-emacs-configuration/#h:1e468b2a-9bee-4571-8454-e3f5462d9321][closing minibuffer with C-g]]. His explanation:
|
||||||
|
|
||||||
|
#+begin_quote
|
||||||
|
Do-What-I-Mean behaviour for a general keyboard-quit. The generic keyboard-quit does not do the expected thing when the minibuffer is open. Whereas we want it to close the minibuffer, even without explicitly focusing it. The DWIM behaviour of this command is as follows:
|
||||||
|
|
||||||
|
- When the region is active, disable it.
|
||||||
|
- When a minibuffer is open, but not focused, close the minibuffer.
|
||||||
|
- When the Completions buffer is selected, close it.
|
||||||
|
- In every other case use the regular keyboard-quit.
|
||||||
|
#+end_quote
|
||||||
|
|
||||||
|
And my copy of his code:
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(defun keyboard-quit-dwim ()
|
||||||
|
"Cancel everything, even in the mini-buffer."
|
||||||
|
(interactive)
|
||||||
|
(cond
|
||||||
|
((region-active-p)
|
||||||
|
(keyboard-quit))
|
||||||
|
((derived-mode-p 'completion-list-mode)
|
||||||
|
(delete-completion-window))
|
||||||
|
((> (minibuffer-depth) 0)
|
||||||
|
(abort-recursive-edit))
|
||||||
|
(t
|
||||||
|
(keyboard-quit))))
|
||||||
|
|
||||||
|
(define-key global-map (kbd "C-g") #'keyboard-quit-dwim)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
** Emacs Everywhere
|
** Emacs Everywhere
|
||||||
After reading [[https://irreal.org/blog/?p=12139][Jon Sander’s essay]] as well as [[https://mbork.pl/2024-04-27_Emacs_everywhere][Marcin Borkowski's essay]], I decided to try out Tecosaur’s [[https://github.com/tecosaur/emacs-everywhere][Emacs Everywhere]] approach:
|
After reading [[https://irreal.org/blog/?p=12139][Jon Sander’s essay]] as well as [[https://mbork.pl/2024-04-27_Emacs_everywhere][Marcin Borkowski's essay]], I decided to try out Tecosaur’s [[https://github.com/tecosaur/emacs-everywhere][Emacs Everywhere]] approach:
|
||||||
|
|
||||||
|
|
647
ha-demos.org
647
ha-demos.org
|
@ -2,7 +2,8 @@
|
||||||
#+author: Howard X. Abrams
|
#+author: Howard X. Abrams
|
||||||
#+date: 2024-10-18
|
#+date: 2024-10-18
|
||||||
#+filetags: emacs hamacs
|
#+filetags: emacs hamacs
|
||||||
#+lastmod: [2024-11-09 Sat]
|
#+lastmod: [2024-12-16 Mon]
|
||||||
|
#+STARTUP: showstars
|
||||||
|
|
||||||
A literate programming file for creating and running demonstrations
|
A literate programming file for creating and running demonstrations
|
||||||
|
|
||||||
|
@ -57,32 +58,39 @@ But I feel I should replace it, and this project encapsulates the following goal
|
||||||
- Most importantly, a more flexible demonstration where trigger events based on the current /state/.
|
- Most importantly, a more flexible demonstration where trigger events based on the current /state/.
|
||||||
|
|
||||||
* Presentations with Org
|
* Presentations with Org
|
||||||
A demonstration begins with an Org file where the screen shows a /single heading/ with a larger font. Not much more. I have two projects that I like to use.
|
A demonstration begins with an Org file where the screen shows a /single heading/ with a larger font. Not much more. I’m playing around with /all/ the projects available, including writing my own.
|
||||||
** Hiding Blocks
|
** Org Tree Slide
|
||||||
When showing a presentation, I never want the =#+business= to lines to completely disappear. First attempt turned the foreground color to the background color, but that still leaves a blank, but occupied line. Using the invisible overlays removes them completely:
|
I’ve used [[https://github.com/takaxp/org-tree-slide][org-tree-slide]] for years for showing org files as presentations. I like the /simple/ presentation and it seems to shows all the images.
|
||||||
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp :tangle no
|
||||||
(defun ha-org-blocks-hide-headers ()
|
(use-package org-tree-slide
|
||||||
"Make the headers and other block metadata invisible.
|
:config
|
||||||
See `ha-org-blocks-show-headers' to return their appearance."
|
(setq org-tree-slide-heading-emphasis nil
|
||||||
(let ((pattern (rx bol (zero-or-more space)
|
org-tree-slide-activate-message "† This demonstration is running in Emacs"
|
||||||
(or ":" "#")
|
org-tree-slide-indicator '(:next nil :previous nil :content nil)
|
||||||
(zero-or-more any) eol)))
|
org-tree-slide-cursor-init nil)
|
||||||
(save-excursion
|
(org-tree-slide-simple-profile)
|
||||||
(goto-char (point-min))
|
|
||||||
(while (re-search-forward pattern nil t)
|
|
||||||
(let* ((start (match-beginning 0)) (end (1+ (match-end 0)))
|
|
||||||
(ovlay (make-overlay start end)))
|
|
||||||
(overlay-put ovlay 'invisible t))))))
|
|
||||||
|
|
||||||
(defun ha-org-blocks-show-headers ()
|
:bind
|
||||||
"Un-invisibilize the headers and other block metadata invisible.
|
(:map org-tree-slide-mode-map
|
||||||
In other words, this undoes what `ha-org-blocks-hide-headers' did."
|
("<f5>" . org-tree-slide-move-next-tree)
|
||||||
(delete-all-overlays))
|
("S-<f5>" . org-tree-slide-move-previous-tree)
|
||||||
|
("M-<f5>" . org-tree-slide-content)
|
||||||
|
("C-<f5>" . (lambda () (interactive) (org-tree-slide-mode -1))))
|
||||||
|
|
||||||
|
:general
|
||||||
|
(:states 'normal :keymaps 'org-tree-slide-mode-map
|
||||||
|
"C" #'ha-demo-toggle-cursor
|
||||||
|
"n" #'org-tree-slide-move-next-tree
|
||||||
|
"N" #'org-tree-slide-move-previous-tree
|
||||||
|
"Q" (lambda () (interactive) (org-tree-slide-mode -1)))
|
||||||
|
|
||||||
|
:hook
|
||||||
|
((org-tree-slide-play . ha-slide-setup)
|
||||||
|
(org-tree-slide-stop . ha-slide-teardown)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
** Org Present
|
** Org Present
|
||||||
Converted to use [[https://github.com/rlister/org-present][org-present]]. I love the /hooks/ as that makes it easier to handle. My problem with =org-present= is that it doesn’t always display images.
|
Converted to use [[https://github.com/rlister/org-present][org-present]]. I love the /hooks/ as that makes it easier to handle. My problem with =org-present= is that it doesn’t always display images based on how it handles overlays.
|
||||||
|
|
||||||
#+begin_src emacs-lisp :tangle no
|
#+begin_src emacs-lisp :tangle no
|
||||||
(use-package org-present
|
(use-package org-present
|
||||||
|
@ -90,37 +98,6 @@ Converted to use [[https://github.com/rlister/org-present][org-present]]. I love
|
||||||
(defvar ha-org-present-mode-line mode-line-format
|
(defvar ha-org-present-mode-line mode-line-format
|
||||||
"Cache previous mode-line format state")
|
"Cache previous mode-line format state")
|
||||||
|
|
||||||
(defun ha-org-present-start ()
|
|
||||||
"Hook to run when starting a presentation.
|
|
||||||
This happens _after_ `org-present' has started."
|
|
||||||
(unless ha-org-present-mode-line
|
|
||||||
(setq ha-org-present-mode-line mode-line-format))
|
|
||||||
(goto-char (point-min)) (re-search-forward (rx bol "*"))
|
|
||||||
(ha-org-blocks-hide-headers)
|
|
||||||
(org-present-big)
|
|
||||||
(org-display-inline-images)
|
|
||||||
(org-present-read-only)
|
|
||||||
(jinx-mode -1) ; Turn off spell checking
|
|
||||||
(evil-normal-state)
|
|
||||||
(setq org-image-actual-width nil)
|
|
||||||
|
|
||||||
;; Clear the demonstration state cache:
|
|
||||||
(clrhash ha-demo-prev-state)
|
|
||||||
|
|
||||||
(setq mode-line-format nil)
|
|
||||||
(org-present-hide-cursor))
|
|
||||||
|
|
||||||
(defun ha-org-present-end ()
|
|
||||||
"Hook to run when ending a presentation.
|
|
||||||
This happens _after_ `org-present-quit' has occurred,
|
|
||||||
and attempts to _undo_ effects of `ha-org-present-start'."
|
|
||||||
(org-present-small)
|
|
||||||
(org-present-read-write)
|
|
||||||
(ha-org-blocks-show-headers)
|
|
||||||
(setq mode-line-format ha-org-present-mode-line)
|
|
||||||
(jinx-mode) ; Turn on spell checking
|
|
||||||
(org-present-show-cursor))
|
|
||||||
|
|
||||||
:bind
|
:bind
|
||||||
(:map org-present-mode-keymap
|
(:map org-present-mode-keymap
|
||||||
("<f5>" . org-present-next)
|
("<f5>" . org-present-next)
|
||||||
|
@ -144,68 +121,322 @@ Converted to use [[https://github.com/rlister/org-present][org-present]]. I love
|
||||||
"Q" #'org-present-quit)
|
"Q" #'org-present-quit)
|
||||||
|
|
||||||
:hook
|
:hook
|
||||||
(org-present-mode . ha-org-present-start)
|
(org-present-mode . ha-slide-setup)
|
||||||
(org-present-mode-quit . ha-org-present-end))
|
(org-present-mode-quit . ha-slide-teardown))
|
||||||
#+end_src
|
#+end_src
|
||||||
** Org Tree Slide
|
** DSlide
|
||||||
I’ve used [[https://github.com/takaxp/org-tree-slide][org-tree-slide]] for years for showing org files as presentations. I like the /simple/ presentation and it seems to shows all the images.
|
The [[https://github.com/positron-solutions/dslide][dslide project]] is flexible, interesting, and can run code.
|
||||||
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(use-package org-tree-slide
|
(use-package dslide
|
||||||
:config
|
:straight (dslide :type git :host github :repo "positron-solutions/dslide")
|
||||||
(setq org-tree-slide-heading-emphasis nil
|
|
||||||
org-tree-slide-activate-message "† This demonstration is running in Emacs"
|
|
||||||
org-tree-slide-indicator '(:next nil :previous nil :content nil)
|
|
||||||
org-tree-slide-cursor-init nil)
|
|
||||||
(org-tree-slide-simple-profile)
|
|
||||||
|
|
||||||
(defun ha-org-tree-slide-start ()
|
:custom
|
||||||
"Configure the presentation display.
|
(dslide-start-from 'point)
|
||||||
See `ha-org-tree-slide-stop' that undoes this."
|
;; Let's keep our presentations simple:
|
||||||
(setq org-hide-emphasis-markers t)
|
(dslide-slide-in-effect nil)
|
||||||
(ha-org-blocks-hide-headers)
|
(dslide-header nil)
|
||||||
(ha-demo-hide-cursor)
|
(dslide-header-date nil)
|
||||||
(ha-demo-hide-mode-line)
|
(dslide-header-author nil)
|
||||||
(ha-demo-presentation-frame)
|
(dslide-header-email nil)
|
||||||
;; (demo-it--presentation-display-set)
|
(dslide-breadcrumb-separator nil)
|
||||||
(text-scale-set 4)
|
|
||||||
(git-gutter-mode -1)
|
|
||||||
(flycheck-mode -1)
|
|
||||||
(jinx-mode -1))
|
|
||||||
|
|
||||||
(defun ha-org-tree-slide-stop ()
|
|
||||||
"Reset the display after a presentation.
|
|
||||||
See `ha-org-tree-slide-start' for what's set."
|
|
||||||
(setq org-hide-emphasis-markers t)
|
|
||||||
(ha-org-blocks-show-headers)
|
|
||||||
(ha-demo-show-cursor)
|
|
||||||
(ha-demo-show-mode-line)
|
|
||||||
(ha-demo-normalize-frame)
|
|
||||||
;; (demo-it--presentation-display-restore) ; Restore previous changes
|
|
||||||
(text-scale-set 0)
|
|
||||||
(git-gutter-mode)
|
|
||||||
(flycheck-mode)
|
|
||||||
(jinx-mode))
|
|
||||||
|
|
||||||
:bind
|
|
||||||
(:map org-tree-slide-mode-map
|
|
||||||
("<f5>" . org-tree-slide-move-next-tree)
|
|
||||||
("S-<f5>" . org-tree-slide-move-previous-tree)
|
|
||||||
("M-<f5>" . org-tree-slide-content)
|
|
||||||
("C-<f5>" . (lambda () (interactive) (org-tree-slide-mode -1))))
|
|
||||||
|
|
||||||
:general
|
:general
|
||||||
(:states 'normal :keymaps 'org-tree-slide-mode-map
|
(:states 'normal :no-autoload t :keymaps 'dslide-mode-map
|
||||||
"C" #'ha-demo-toggle-cursor
|
"q" '("quit presentation" . dslide-deck-stop)
|
||||||
"n" #'org-tree-slide-move-next-tree
|
"<left>" '("previous slide" . dslide-deck-backward)
|
||||||
"N" #'org-tree-slide-move-previous-tree
|
"<right>" '("next slide" . dslide-deck-forward)
|
||||||
"Q" (lambda () (interactive) (org-tree-slide-mode -1)))
|
"C" '("show cursor" . ha-demo-show-cursor)
|
||||||
|
"c" '("hide cursor" . ha-demo-hide-cursor)
|
||||||
|
"<up>" '("previous slide" . previous-line)
|
||||||
|
"<down>" '("next slide" . next-line))
|
||||||
|
|
||||||
:hook
|
:bind
|
||||||
((org-tree-slide-play . ha-org-tree-slide-start)
|
("C-<f5>" . dslide-deck-start)
|
||||||
(org-tree-slide-stop . ha-org-tree-slide-stop)))
|
(:map dslide-mode-map
|
||||||
|
("<f5>" . dslide-deck-forward)
|
||||||
|
("S-<f5>" . dslide-deck-backward)
|
||||||
|
("C-<f5>" . dslide-deck-stop))
|
||||||
|
|
||||||
|
:hook ((dslide-start . ha-slide-setup)
|
||||||
|
(dslide-stop . ha-slide-teardown)
|
||||||
|
(dslide-narrow . ha-slide-reset)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Let’s try it out by loading this example.[[file:~/.emacs.d/straight/repos/dslide/test/demo.org][ demo.org]]
|
||||||
|
|
||||||
|
What features do I like and want to take advantage of?
|
||||||
|
- Inline Children show: =:DSLIDE_SLIDE_ACTION: dslide-slide-action-inline=
|
||||||
|
- Flat Slide (shows children section immediately): =:DSLIDE_SLIDE_ACTION: dslide-slide-action-flat=
|
||||||
|
- Show images only? I guess we could use my own thing, but it is nice and easy: =:DSLIDE_ACTIONS: dslide-action-image :slide-display nil=
|
||||||
|
- No header slides: =:DSLIDE_SLIDE_ACTION: dslide-slide-action-child :header nil=
|
||||||
|
- Re-execute Babel blocks: =:DSLIDE_SLIDE_ACTION: dslide-slide-babel=
|
||||||
|
- Hiding Blocks
|
||||||
|
- Results Only
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp :tangle no
|
||||||
|
(use-package dslide
|
||||||
|
:config
|
||||||
|
;; The dslide-highlight inherits from 'highlight'
|
||||||
|
;; (set-face-attribute dslide-highlight :foreground "red")
|
||||||
|
;; This too inherits from 'highlight'
|
||||||
|
;; (set-face-attribute dslide-babel-success-highlight :foreground "red")
|
||||||
|
;; This inherits from `error'
|
||||||
|
;; (set-face-attribute dslide-babel-error-highlight :foreground "red")
|
||||||
|
(set-face-attribute 'highlight nil :background 'unspecified :foreground "lightblue"))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Master of Ceremonies
|
||||||
|
The [[https://github.com/positron-solutions/moc][Master of Ceremonies]] package (moc) is to help when recording Emacs screens. Early in development, but it looks to have some potential. Not sure how to use it yet.
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp :tangle no
|
||||||
|
(use-package default-text-scale)
|
||||||
|
|
||||||
|
(use-package moc
|
||||||
|
:straight (:type git :host github
|
||||||
|
:repo "positron-solutions/moc"))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Select text, and call =moc-focus= (call =moc-focus-quit= to stop). Highlight more text, and call =moc-focus-highlight= to brighten it, or =moc-focus-obscure= to hide it.
|
||||||
|
|
||||||
|
The =moc-screenshot= seems to only work on Linux.
|
||||||
|
|
||||||
|
An interesting approach for making presentations, that I’m not sure I will need.
|
||||||
|
|
||||||
|
*** Showing Something associated with a Headline
|
||||||
|
:PROPERTIES:
|
||||||
|
:DSLIDE_ACTIONS: dslide-action-babel
|
||||||
|
:END:
|
||||||
|
|
||||||
|
When I give a /demonstration/ (uising my [[New Demonstration]] project), I could, instead, use a custom =dslide= action.
|
||||||
|
|
||||||
|
But how would I get it to close? Maybe we use a combination of actions and my “demo” code for everything else?
|
||||||
|
|
||||||
|
*Note:* Code blocks with =exports= set to =none= are not displayed.
|
||||||
|
|
||||||
|
#+begin_src elisp :tangle no :exports none :results none
|
||||||
|
(ha-demo-show-file "ha-org.org" :position 'right
|
||||||
|
:focus 'presentation :heading "Meetings"
|
||||||
|
:shift 0)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp :tangle no :exports none :results none
|
||||||
|
(ha-demo-highlight-buffer :buffer "ha-org.org"
|
||||||
|
:hi-lines "268-274")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+begin_src elisp :tangle no :exports none :results none
|
||||||
|
(delete-other-windows)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
*** Bullet/Paragraph Highlighting
|
||||||
|
I would like to highlight a bullet point or a paragraph while talking.
|
||||||
|
To do this, add =:DSLIDE_ACTIONS: dslide-action-highlight-paragraphs= to the properties of a section.
|
||||||
|
|
||||||
|
#+begin_src elisp emacs-lisp
|
||||||
|
(defclass dslide-action-highlight-paragraphs (dslide-action)
|
||||||
|
((overlays :initform nil))
|
||||||
|
"Paint the paragraphs with the highlight color, one by one.")
|
||||||
|
|
||||||
|
;; Default no-op `dslide-begin' is sufficient
|
||||||
|
|
||||||
|
;; Default implementation of `dslide-end', which just plays forward to the end,
|
||||||
|
;; is well-behaved with this class.
|
||||||
|
|
||||||
|
;; Remove any remaining overlays when calling final.
|
||||||
|
(cl-defmethod dslide-final :after ((obj dslide-action-highlight-paragraphs))
|
||||||
|
(mapc #'delete-overlay (oref obj overlays)))
|
||||||
|
|
||||||
|
;; Find the next paragraph and add an overlay if it exists
|
||||||
|
(cl-defmethod dslide-forward ((obj dslide-action-highlight-paragraphs))
|
||||||
|
;; This line removes all overlays allowing us to highlight a new one.
|
||||||
|
;; Remove this if you want the paragraphs to _linger_.
|
||||||
|
(mapc #'delete-overlay (oref obj overlays))
|
||||||
|
(when-let ((paragraph (dslide-section-next obj 'paragraph)))
|
||||||
|
(let* ((beg (org-element-property :begin paragraph))
|
||||||
|
(end (org-element-property :end paragraph))
|
||||||
|
(new-overlay (make-overlay beg end)))
|
||||||
|
(overlay-put new-overlay 'face 'highlight)
|
||||||
|
(push new-overlay (oref obj overlays))
|
||||||
|
;; Return non-nil to indicate progress was made. This also informs the
|
||||||
|
;; highlight when following the slides in the base buffer.
|
||||||
|
beg)))
|
||||||
|
|
||||||
|
(cl-defmethod dslide-backward ((obj dslide-action-highlight-paragraphs))
|
||||||
|
(when-let* ((overlay (pop (oref obj overlays))))
|
||||||
|
(delete-overlay overlay)
|
||||||
|
;; If there is a preceding overlay, move to its beginning else move to the
|
||||||
|
;; beginning of the heading.
|
||||||
|
(if-let ((overlay (car (oref obj overlays))))
|
||||||
|
(dslide-marker obj (overlay-start overlay))
|
||||||
|
(dslide-marker obj (org-element-property :begin (dslide-heading obj))))))
|
||||||
|
#+end_src
|
||||||
|
*** Custom Action Demo
|
||||||
|
:PROPERTIES:
|
||||||
|
:DSLIDE_ACTIONS: dslide-action-highlight-paragraphs
|
||||||
|
:END:
|
||||||
|
Massachusetts, in particular, has always been one of the laboratories of democracy. It's where people try things before they're popular. It's where we experiment.
|
||||||
|
|
||||||
|
- Red
|
||||||
|
- Orange
|
||||||
|
- Yellow
|
||||||
|
|
||||||
|
Democracy depends on an informed citizenry and the social cohesion that those citizens can show even when they disagree.
|
||||||
|
|
||||||
|
The essence of democracy is the resolve of individuals working together to shape our institutions and our society in ways that allow all of us to flourish.
|
||||||
|
** My Slides
|
||||||
|
A /full/ presentation requires my /notes/ on one frame, and the presentation on the other.
|
||||||
|
|
||||||
|
To use this, following:
|
||||||
|
1. Select the Org mode presentation
|
||||||
|
2. Run the function, =ha-slide-make-notes-frame=
|
||||||
|
3. Reference the notes file that would be associated with the presentation
|
||||||
|
|
||||||
|
The end result is two frames, where updating the presentation, updates the location of the other frame to match the same headline.
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(defvar ha-slide-notes-frame-name "Demonstration Notes"
|
||||||
|
"The name of the frame that displays the presentation notes.")
|
||||||
|
|
||||||
|
(defvar ha-slide-notes-frame nil
|
||||||
|
"Frame containing the presentation notes.")
|
||||||
|
|
||||||
|
(defvar ha-slide-notes-window nil
|
||||||
|
"Window containing the presentation notes.")
|
||||||
|
|
||||||
|
(defun ha-slide-make-notes-frame (filename &optional heading)
|
||||||
|
"Display the notes, FILENAME, in a new frame.
|
||||||
|
If HEADING is given, jump to that `org-mode' headline."
|
||||||
|
(interactive "fNotes File: ")
|
||||||
|
(let ((f (selected-frame)))
|
||||||
|
(setq ha-slide-notes-frame
|
||||||
|
(make-frame `((name . ,ha-slide-notes-frame-name))))
|
||||||
|
(set-frame-position ha-slide-notes-frame 1310 0)
|
||||||
|
(set-frame-size ha-slide-notes-frame 920 1420 t)
|
||||||
|
|
||||||
|
;; While I could call `find-file-other-frame', I want to make
|
||||||
|
;; sure I get the file loaded in the correct frame:
|
||||||
|
(x-focus-frame ha-slide-notes-frame)
|
||||||
|
(find-file filename)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(when heading
|
||||||
|
(re-search-forward (rx bol (one-or-more "*") (one-or-more space) (literal heading)))
|
||||||
|
(recenter-top-bottom 0))
|
||||||
|
|
||||||
|
(setq ha-slide-notes-window (selected-window))
|
||||||
|
(delete-other-windows)
|
||||||
|
|
||||||
|
;; Highlight the original window containing the presentation:
|
||||||
|
(x-focus-frame f)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
These interactive functions scroll the “notes” in the other window in another frame:
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(defun ha-slide-notes-scroll-up ()
|
||||||
|
"Scroll the frame/window containing the notes, up."
|
||||||
|
(interactive)
|
||||||
|
(when ha-slide-notes-window
|
||||||
|
(with-selected-window ha-slide-notes-window
|
||||||
|
(scroll-up -10))))
|
||||||
|
|
||||||
|
(defun ha-slide-notes-scroll-down ()
|
||||||
|
"Scroll the frame/window containing the notes, down."
|
||||||
|
(interactive)
|
||||||
|
(when ha-slide-notes-window
|
||||||
|
(with-selected-window ha-slide-notes-window
|
||||||
|
(scroll-up 10))))
|
||||||
|
|
||||||
|
(defun ha-slide-notes-update ()
|
||||||
|
"Function to move the notes headline to current buffers.
|
||||||
|
Assuming the buffer is showing an org-file, and previously
|
||||||
|
called `ha-slide-make-notes-frame', this function moves
|
||||||
|
the point in that buffer to the same headline."
|
||||||
|
(interactive)
|
||||||
|
(when ha-slide-notes-window
|
||||||
|
(let ((heading (thread-first
|
||||||
|
(org-get-heading t t t t)
|
||||||
|
(substring-no-properties))))
|
||||||
|
(with-selected-window ha-slide-notes-window
|
||||||
|
(goto-char (point-min))
|
||||||
|
(re-search-forward (rx (literal heading)) nil t)
|
||||||
|
(recenter-top-bottom 0)))))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Call the =ha-slide-notes-update= function automatically after updating a slide. With =dslide=, we add a hook:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(use-package dslide
|
||||||
|
:hook (dslide-narrow . 'ha-slide-notes-update))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** My Presentation View
|
||||||
|
Regardless of the presentation package I use, I make them all look similar with the following code. Much of this is getting rid of Emacs visual elements, like the cursor and the mode-line, as well as stopping minor modes that add visual changes, like spellchecking and the gutter. I can call this function from any presentation software used.
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defun ha-slide-setup (&optional frame-name)
|
||||||
|
"Configure the look I want for presentations.
|
||||||
|
The frame associated with FRAME-NAME is tidied
|
||||||
|
by removing the gutters and other informative
|
||||||
|
widgets not needed for a presentation."
|
||||||
|
(org-indent-mode -1)
|
||||||
|
;; (org-modern-mode -1)
|
||||||
|
|
||||||
|
(setq org-image-actual-width nil)
|
||||||
|
(org-display-inline-images)
|
||||||
|
(ha-org-blocks-hide-headers)
|
||||||
|
(ha-org-hide-stars)
|
||||||
|
(font-lock-update)
|
||||||
|
(ha-demo-hide-mode-line)
|
||||||
|
(ha-demo-hide-cursor)
|
||||||
|
(ha-demo-presentation-frame frame-name)
|
||||||
|
|
||||||
|
(text-scale-set 4)
|
||||||
|
(git-gutter-mode -1)
|
||||||
|
(flycheck-mode -1)
|
||||||
|
(jinx-mode -1)
|
||||||
|
|
||||||
|
;; Clear the demonstration state cache:
|
||||||
|
(clrhash ha-demo-prev-state)
|
||||||
|
|
||||||
|
(evil-normal-state))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
And after a presentation finishes, this function cleans up by restoring minor modes, etc:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defun ha-slide-teardown ()
|
||||||
|
"Reset the Org after a presentation."
|
||||||
|
(org-indent-mode 1)
|
||||||
|
;; (org-modern-mode 1)
|
||||||
|
|
||||||
|
(ha-org-blocks-show-headers)
|
||||||
|
(font-lock-update)
|
||||||
|
(ha-demo-show-mode-line)
|
||||||
|
(ha-demo-show-cursor)
|
||||||
|
(ha-demo-normalize-frame)
|
||||||
|
|
||||||
|
(text-scale-set 0)
|
||||||
|
(git-gutter-mode)
|
||||||
|
(flycheck-mode)
|
||||||
|
(jinx-mode))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
The =dslide= seems to reset /everything/ on each slide display, so:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defun ha-slide-reset ()
|
||||||
|
"Reset the current slide."
|
||||||
|
(interactive)
|
||||||
|
(ha-org-blocks-hide-headers)
|
||||||
|
(font-lock-update))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
* New Demonstration
|
* New Demonstration
|
||||||
Instead of executing a sequence of demonstration steps, demonstrations key on “state”, that is, the active buffer or major-mode, or the heading of an Org file, etc. I described the [[https://howardism.org/Technical/Emacs/demonstrations-part-two.html][guts of writing this code]], but we bind a key to calling =ha-demo-step= with a list of /state matchers/ to functions to call when matched. For instance:
|
Instead of executing a sequence of demonstration steps, demonstrations key on “state”, that is, the active buffer or major-mode, or the heading of an Org file, etc. I described the [[https://howardism.org/Technical/Emacs/demonstrations-part-two.html][guts of writing this code]], but we bind a key to calling =ha-demo-step= with a list of /state matchers/ to functions to call when matched. For instance:
|
||||||
|
|
||||||
|
@ -264,7 +495,7 @@ The matching function, =ha-demo-state-match= looks in a cache, the =demo-prev-st
|
||||||
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun ha-demo-state-match (triggers state)
|
(defun ha-demo-state-match (triggers state)
|
||||||
"Return non-nil if STATE contains all TRIGGERS.
|
"Return non-nil if STATE has all TRIGGERS.
|
||||||
The state also includes the number of times the triggers
|
The state also includes the number of times the triggers
|
||||||
matched during previous calls. We do this by keeping track
|
matched during previous calls. We do this by keeping track
|
||||||
of the number of successful calls, and incrementing
|
of the number of successful calls, and incrementing
|
||||||
|
@ -338,13 +569,51 @@ Let’s create a function that could accept a list of /triggering keys/, and the
|
||||||
* Demonstration Support
|
* Demonstration Support
|
||||||
What sort of functions will I often be doing?
|
What sort of functions will I often be doing?
|
||||||
|
|
||||||
|
** Hiding Blocks
|
||||||
|
When showing a presentation, I never want the =#+business= to lines to completely disappear. First attempt turned the foreground color to the background color, but that still leaves a blank, but occupied line. Using the invisible overlays removes them completely:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defun ha-org-blocks-hide-headers ()
|
||||||
|
"Make the headers and other block metadata invisible.
|
||||||
|
See `ha-org-blocks-show-headers' to return their appearance."
|
||||||
|
(let ((pattern (rx bol (zero-or-more space)
|
||||||
|
(or ":" "#")
|
||||||
|
(zero-or-more any) eol)))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(while (re-search-forward pattern nil t)
|
||||||
|
(let* ((start (match-beginning 0)) (end (1+ (match-end 0)))
|
||||||
|
(ovlay (make-overlay start end)))
|
||||||
|
(overlay-put ovlay 'invisible t))))))
|
||||||
|
|
||||||
|
(defun ha-org-blocks-show-headers ()
|
||||||
|
"Un-invisibilize the headers and other block metadata invisible.
|
||||||
|
In other words, this undoes what `ha-org-blocks-hide-headers' did."
|
||||||
|
(delete-all-overlays))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
What about deleting the initial bullets in =org-indent-mode=:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defun ha-org-hide-stars ()
|
||||||
|
"Create overlay to hide all initial astericks in Org headlines."
|
||||||
|
(let ((pattern (rx bol (one-or-more "*") (one-or-more space))))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(while (re-search-forward pattern nil t)
|
||||||
|
(let* ((start (match-beginning 0))
|
||||||
|
(end (1+ (match-end 0)))
|
||||||
|
(ovlay (make-overlay start end)))
|
||||||
|
(overlay-put ovlay 'invisible t))))))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
** Hide and Show the Cursor
|
** Hide and Show the Cursor
|
||||||
The typical presentation software has an issue for hiding the cursor when working with Evil mode, and since setting =cursor-type= to =nil= doesn’t work in a graphical display (where we typically run a presentation), the following functions turn on/off the displayed cursor.
|
The typical presentation software has an issue for hiding the cursor when working with Evil mode, and since setting =cursor-type= to =nil= doesn’t work in a graphical display (where we typically run a presentation), the following functions turn on/off the displayed cursor.
|
||||||
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defvar ha-demo-cursor nil
|
(defvar ha-demo-cursor nil
|
||||||
"List of cursor states stored during `ha-demo-hide-cursor' and
|
"List of cursor states stored during `ha-demo-hide-cursor'.
|
||||||
restored with `ha-demo-show-cursor'.")
|
Used to restore with `ha-demo-show-cursor'.")
|
||||||
|
|
||||||
(defun ha-demo-hide-cursor ()
|
(defun ha-demo-hide-cursor ()
|
||||||
"Hide the cursor for the current frame."
|
"Hide the cursor for the current frame."
|
||||||
|
@ -392,7 +661,7 @@ The typical presentation software has an issue for hiding the cursor when workin
|
||||||
(setq ha-demo-cursor nil)))
|
(setq ha-demo-cursor nil)))
|
||||||
|
|
||||||
(defun ha-demo-toggle-cursor ()
|
(defun ha-demo-toggle-cursor ()
|
||||||
"Toggles the display of the cursor."
|
"Toggle cursor display from shown or hidden."
|
||||||
(interactive)
|
(interactive)
|
||||||
(if ha-demo-cursor
|
(if ha-demo-cursor
|
||||||
(ha-demo-show-cursor)
|
(ha-demo-show-cursor)
|
||||||
|
@ -418,15 +687,16 @@ For Org file displayed as presentations as well as images, we probably don’t w
|
||||||
(interactive)
|
(interactive)
|
||||||
(if ha-demo-mode-line
|
(if ha-demo-mode-line
|
||||||
(setq mode-line-format ha-demo-mode-line)))
|
(setq mode-line-format ha-demo-mode-line)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
** Presentation Frame Properties
|
** Presentation Frame Properties
|
||||||
Like the work I’m doing to the mode-line, can we make the frame cleaner for a presentation?
|
Like the work I’m doing to the mode-line, can we make the frame cleaner for a presentation?
|
||||||
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defvar ha-demo-frame-state nil
|
(defvar ha-demo-frame-state nil
|
||||||
"Store frame properties during `ha-demo-presentation-frame' before
|
"Store frame properties during `ha-demo-presentation-frame'.
|
||||||
altering them, and then restore them with `ha-demo-normalize-frame'.")
|
Stored before alteration, as to restore them with
|
||||||
|
`ha-demo-normalize-frame'.")
|
||||||
|
|
||||||
(defun ha-demo-presentation-frame (&optional name)
|
(defun ha-demo-presentation-frame (&optional name)
|
||||||
"Remove the fringe and other frame settings.
|
"Remove the fringe and other frame settings.
|
||||||
|
@ -446,7 +716,7 @@ Like the work I’m doing to the mode-line, can we make the frame cleaner for a
|
||||||
(interactive)
|
(interactive)
|
||||||
(set-frame-parameter (selected-frame) 'left-fringe (nth 0 ha-demo-frame-state))
|
(set-frame-parameter (selected-frame) 'left-fringe (nth 0 ha-demo-frame-state))
|
||||||
(set-frame-parameter (selected-frame) 'right-fringe (nth 1 ha-demo-frame-state)))
|
(set-frame-parameter (selected-frame) 'right-fringe (nth 1 ha-demo-frame-state)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
** Display File
|
** Display File
|
||||||
Displaying a File with:
|
Displaying a File with:
|
||||||
|
@ -461,7 +731,7 @@ All options? Should I use Common Lisp’s =cl-defun= for the keyword parameters?
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(cl-defun ha-demo-show-file (filename &key position size modeline
|
(cl-defun ha-demo-show-file (filename &key position size modeline
|
||||||
line heading shift cursor
|
line heading shift cursor
|
||||||
commands)
|
commands focus)
|
||||||
"Show a file, FILENAME, in a buffer based on keyed parameters.
|
"Show a file, FILENAME, in a buffer based on keyed parameters.
|
||||||
POSITION can be 'full 'right or 'below and positions the window.
|
POSITION can be 'full 'right or 'below and positions the window.
|
||||||
SIZE is an integer for the font size based on the default size.
|
SIZE is an integer for the font size based on the default size.
|
||||||
|
@ -470,59 +740,49 @@ All options? Should I use Common Lisp’s =cl-defun= for the keyword parameters?
|
||||||
HEADING is a headline from the currently display Org file.
|
HEADING is a headline from the currently display Org file.
|
||||||
SHIFT is the number of lines above the point to show, in case
|
SHIFT is the number of lines above the point to show, in case
|
||||||
the LINE shouldn't be at the top of the window.
|
the LINE shouldn't be at the top of the window.
|
||||||
|
The CURSOR can be 'show / 'yes or 'hide / 'no.
|
||||||
|
The FOCUS can be 'presentation to return the cursor to the
|
||||||
|
calling buffer.
|
||||||
|
|
||||||
COMMANDS is a lambda expression that can contain any other
|
COMMANDS is a lambda expression that can contain any other
|
||||||
instructions to happen to the buffer display."
|
instructions to happen to the buffer display."
|
||||||
(unless position
|
(let ((orig-buf (current-buffer)))
|
||||||
(setq position :right))
|
(unless position
|
||||||
|
(setq position :right))
|
||||||
|
|
||||||
;; Step 1: Create a window
|
;; Step 1: Create a window
|
||||||
(pcase position
|
(pcase position
|
||||||
('above (progn (split-window-vertically)))
|
('above (progn (split-window-vertically)))
|
||||||
('up (progn (split-window-vertically)))
|
('up (progn (split-window-vertically)))
|
||||||
('left (progn (split-window-horizontally)))
|
('left (progn (split-window-horizontally)))
|
||||||
('right (progn (split-window-horizontally) (other-window 1)))
|
('right (progn (split-window-horizontally) (other-window 1)))
|
||||||
('above (progn (split-window-vertically) (other-window 1)))
|
('above (progn (split-window-vertically) (other-window 1)))
|
||||||
('below (progn (split-window-vertically) (other-window 1))))
|
('below (progn (split-window-vertically) (other-window 1))))
|
||||||
|
|
||||||
;; Step 2: Load the file or switch to the buffer:
|
;; Step 2: Load the file or switch to the buffer:
|
||||||
(if (file-exists-p filename)
|
(if (file-exists-p filename)
|
||||||
(find-file filename)
|
(find-file filename)
|
||||||
(switch-to-buffer filename))
|
(switch-to-buffer filename))
|
||||||
|
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
|
|
||||||
(when cursor
|
(when cursor
|
||||||
(if (or (eq cursor 'yes) (eq cursor 'show))
|
(if (or (eq cursor 'yes) (eq cursor 'show))
|
||||||
(ha-demo-show-cursor)
|
(ha-demo-show-cursor)
|
||||||
(ha-demo-hide-cursor)))
|
(ha-demo-hide-cursor)))
|
||||||
|
|
||||||
;; Step 3: Increase the font size
|
;; Step 3: Increase the font size
|
||||||
(when size
|
(when size
|
||||||
(text-scale-set size))
|
(text-scale-set size))
|
||||||
|
|
||||||
(when line
|
(unless modeline
|
||||||
(if (integerp line)
|
(setq-local mode-line-format nil))
|
||||||
(forward-line line)
|
|
||||||
(re-search-forward line nil t)))
|
|
||||||
|
|
||||||
(when heading
|
(ha-demo-highlight-buffer :line line :heading heading :shift shift
|
||||||
(re-search-forward (rx bol (one-or-more "*") (one-or-more space)
|
:commands commands)
|
||||||
(literal heading))
|
|
||||||
nil t))
|
|
||||||
|
|
||||||
;; If SHIFT is positive integer, left that many line above point,
|
(when (and focus (eq focus 'presentation))
|
||||||
;; otherwise don't do anything to leave it in the middle.
|
(pop-to-buffer orig-buf))))
|
||||||
;; If SHIFT is null, move it to the top of the buffer window:
|
|
||||||
(if shift
|
|
||||||
(when (integerp shift)
|
|
||||||
(recenter-top-bottom shift))
|
|
||||||
(recenter-top-bottom 0))
|
|
||||||
|
|
||||||
(unless modeline
|
|
||||||
(setq-local mode-line-format nil))
|
|
||||||
|
|
||||||
(when commands (funcall commands)))
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
Let try it all together:
|
Let try it all together:
|
||||||
|
@ -539,6 +799,75 @@ Or:
|
||||||
:commands (lambda () (jinx-mode -1)))
|
:commands (lambda () (jinx-mode -1)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
** Highlight Text in Buffer
|
||||||
|
Perhaps when we call =ha-demo-show-file=, we want to highlight different parts of the file?
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defface ha-demo-highlight-1 '((t :weight ultra-heavy))
|
||||||
|
"Face used for highlighting alternate buffers.")
|
||||||
|
|
||||||
|
(defface ha-demo-highlight-2 '((t :slant italic))
|
||||||
|
"Face used for highlighting alternate buffers.")
|
||||||
|
|
||||||
|
(defface ha-demo-highlight-3 '((t :background "#0000a0" :extend t))
|
||||||
|
"Face used for highlighting alternate buffers.")
|
||||||
|
|
||||||
|
(cl-defun ha-demo-highlight-buffer (&key buffer line heading shift
|
||||||
|
hi-lines hi-face commands)
|
||||||
|
"Move to a section of a buffer, and possibly highlight text.
|
||||||
|
If BUFFER is given, call `pop-to-buffer' on that.
|
||||||
|
If LINE, HEADING, or SHIFT is given, move to that section.
|
||||||
|
If HI-LINES is given, create an overlay for those lines
|
||||||
|
based on the face, HI-FACE (if that isn't given, bold those lines).
|
||||||
|
Finally execute COMMANDS, if given."
|
||||||
|
(when buffer
|
||||||
|
(pop-to-buffer buffer))
|
||||||
|
|
||||||
|
(when line
|
||||||
|
(if (integerp line)
|
||||||
|
(forward-line line)
|
||||||
|
(re-search-forward line nil t)))
|
||||||
|
|
||||||
|
(when heading
|
||||||
|
(re-search-forward (rx bol (one-or-more "*") (one-or-more space)
|
||||||
|
(literal heading))
|
||||||
|
nil t))
|
||||||
|
|
||||||
|
;; If SHIFT is positive integer, left that many line above point,
|
||||||
|
;; otherwise don't do anything to leave it in the middle.
|
||||||
|
;; If SHIFT is null, move it to the top of the buffer window:
|
||||||
|
(when shift
|
||||||
|
(if (integerp shift)
|
||||||
|
(recenter-top-bottom shift))
|
||||||
|
(recenter-top-bottom 0))
|
||||||
|
|
||||||
|
(when hi-lines
|
||||||
|
(remove-overlays)
|
||||||
|
(seq-let (first-line last-line) (string-split hi-lines (rx (or ":" "-")))
|
||||||
|
(save-excursion
|
||||||
|
(let* ((beg (goto-line (string-to-number first-line)))
|
||||||
|
(end (progn
|
||||||
|
(goto-line (string-to-number last-line))
|
||||||
|
(line-end-position)))
|
||||||
|
(new-overlay (make-overlay beg end)))
|
||||||
|
|
||||||
|
(if hi-face
|
||||||
|
(overlay-put new-overlay 'face hi-face)
|
||||||
|
(overlay-put new-overlay 'face ha-demo-highlight-2))
|
||||||
|
|
||||||
|
;; (push new-overlay (oref obj overlays))
|
||||||
|
))))
|
||||||
|
|
||||||
|
(when commands (funcall commands)))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp :tangle no
|
||||||
|
(ha-demo-highlight-buffer :hi-lines "874-881" :hi-face 'ha-demo-highlight-3)
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
|
||||||
* Technical Artifacts :noexport:
|
* Technical Artifacts :noexport:
|
||||||
Let's =provide= a name so we can =require= this file:
|
Let's =provide= a name so we can =require= this file:
|
||||||
|
|
||||||
|
|
|
@ -320,6 +320,7 @@ Which font to choose?
|
||||||
:straight (:host github :repo "jabranham/mixed-pitch")
|
:straight (:host github :repo "jabranham/mixed-pitch")
|
||||||
:config
|
:config
|
||||||
(add-to-list 'mixed-pitch-fixed-pitch-faces 'org-property-value)
|
(add-to-list 'mixed-pitch-fixed-pitch-faces 'org-property-value)
|
||||||
|
(add-to-list 'mixed-pitch-fixed-pitch-faces 'org-special-keyword)
|
||||||
(add-to-list 'mixed-pitch-fixed-pitch-faces 'font-lock-comment-face)
|
(add-to-list 'mixed-pitch-fixed-pitch-faces 'font-lock-comment-face)
|
||||||
:hook (text-mode . mixed-pitch-mode))
|
:hook (text-mode . mixed-pitch-mode))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
|
@ -625,10 +625,10 @@ Let's try this out with a Hydra since some I can /repeat/ some commands (e.g. en
|
||||||
(use-package hydra
|
(use-package hydra
|
||||||
:config
|
:config
|
||||||
(defhydra hydra-window-resize (:color blue :hint nil) "
|
(defhydra hydra-window-resize (:color blue :hint nil) "
|
||||||
_w_: select _m_: move/swap _u_: undo _^_: taller (t) _+_: text larger
|
_w_: select _m_: move/swap _^_: taller (t) _+_: text larger
|
||||||
_j_: go up _d_: delete _U_: undo+ _v_: shorter (T) _-_: text smaller
|
_j_: go up _d_: delete _v_: shorter (T) _-_: text smaller
|
||||||
_k_: down _e_: balance _r_: redo _>_: wider _F_: font larger
|
_k_: down _e_: balance _>_: wider _F_: font larger
|
||||||
_h_: left _n_: v-split _R_: redo+ _<_: narrower _f_: font smaller
|
_h_: left _n_: v-split _<_: narrower _f_: font smaller
|
||||||
_l_: right _s_: split _o_: only this window _c_: choose (also 1-9)"
|
_l_: right _s_: split _o_: only this window _c_: choose (also 1-9)"
|
||||||
("w" ace-window)
|
("w" ace-window)
|
||||||
("c" other-window :color pink) ; change window
|
("c" other-window :color pink) ; change window
|
||||||
|
@ -640,11 +640,6 @@ Let's try this out with a Hydra since some I can /repeat/ some commands (e.g. en
|
||||||
("D" ace-delete-window)
|
("D" ace-delete-window)
|
||||||
("O" ace-delete-other-windows)
|
("O" ace-delete-other-windows)
|
||||||
|
|
||||||
("u" winner-undo)
|
|
||||||
("U" winner-undo :color pink)
|
|
||||||
("C-r" winner-redo)
|
|
||||||
("r" winner-redo)
|
|
||||||
("R" winner-redo :color pink)
|
|
||||||
|
|
||||||
("J" evil-window-down :color pink)
|
("J" evil-window-down :color pink)
|
||||||
("K" evil-window-up :color pink)
|
("K" evil-window-up :color pink)
|
||||||
|
|
|
@ -82,23 +82,29 @@ The following adds frame borders and window dividers to give space between windo
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** Hide Heading Stars
|
** Hide Heading Stars
|
||||||
I’ve struggled with hiding the initial asterisks that denote a headline in Org.
|
I’ve struggled with hiding the initial asterisks that denote a headline in Org. The following code doesn’t work with how the built-in [[https://orgmode.org/manual/Org-Indent-Mode.html][org-indent-mode]] works.
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp :tangle no
|
||||||
(defun org-mode-hide-stars ()
|
(defun org-mode-hide-stars ()
|
||||||
(font-lock-add-keywords
|
(font-lock-add-keywords
|
||||||
nil
|
nil
|
||||||
'(("^\\*+ "
|
`(( ,(rx line-start (one-or-more "*") space)
|
||||||
(0 (put-text-property (match-beginning 0) (match-end 0) 'face
|
(0 (put-text-property (match-beginning 0) (match-end 0)
|
||||||
(list :foreground
|
'invisible t))))))
|
||||||
(face-attribute 'default :background))))))))
|
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
And hook this function to Org:
|
And hook this function to Org:
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp :tangle no
|
||||||
(use-package org
|
(use-package org
|
||||||
:hook (org-mode . org-mode-hide-stars))
|
:hook (org-mode . org-mode-hide-stars))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
The list of things to try:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(setq org-hide-leading-stars nil) ; or t
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
** Markup View
|
** Markup View
|
||||||
The variable, =org-hide-emphasis-markers=, is key to pretending that Emacs can be a word processor, however, since the org markup controls aren’t viewable, I find it challenging at times, to change that. The [[https://github.com/awth13/org-appear][org-appear project]] seeks to fix this by showing the markup when the point is nearby:
|
The variable, =org-hide-emphasis-markers=, is key to pretending that Emacs can be a word processor, however, since the org markup controls aren’t viewable, I find it challenging at times, to change that. The [[https://github.com/awth13/org-appear][org-appear project]] seeks to fix this by showing the markup when the point is nearby:
|
||||||
|
|
||||||
|
|
13
ha-theme.org
13
ha-theme.org
|
@ -2,7 +2,7 @@
|
||||||
#+author: Howard Abrams
|
#+author: Howard Abrams
|
||||||
#+date: 2024-06-18
|
#+date: 2024-06-18
|
||||||
#+filetags: emacs hamacs
|
#+filetags: emacs hamacs
|
||||||
#+lastmod: [2024-11-26 Tue]
|
#+lastmod: [2024-12-10 Tue]
|
||||||
|
|
||||||
A literate programming file for defining a warm, autumn, but subtle color theme for Emacs.
|
A literate programming file for defining a warm, autumn, but subtle color theme for Emacs.
|
||||||
|
|
||||||
|
@ -158,6 +158,8 @@ And encapsulate them in a named list:
|
||||||
("yellow-lt" . "#d8bb77")
|
("yellow-lt" . "#d8bb77")
|
||||||
("green" . "#899d03")
|
("green" . "#899d03")
|
||||||
("green-lt" . "#b3bf8e")
|
("green-lt" . "#b3bf8e")
|
||||||
|
("dk-green" . "#55702c")
|
||||||
|
("dk-green-lt" . "#979e6e")
|
||||||
("blue" . "#6f8b93")
|
("blue" . "#6f8b93")
|
||||||
("blue-lt" . "#91b5bf")
|
("blue-lt" . "#91b5bf")
|
||||||
("purple" . "#893161")
|
("purple" . "#893161")
|
||||||
|
@ -348,7 +350,7 @@ Let’s make a /theme/:
|
||||||
`(link ((t (:foreground ,link-color))))
|
`(link ((t (:foreground ,link-color))))
|
||||||
`(link-visited ((t (:foreground ,visited-color))))
|
`(link-visited ((t (:foreground ,visited-color))))
|
||||||
|
|
||||||
`(font-lock-comment-face ((t (:foreground ,gray-65))))
|
`(font-lock-comment-face ((t (:foreground ,gray-60))))
|
||||||
`(font-lock-comment-delimiter-face ((t (:foreground ,gray-50))))
|
`(font-lock-comment-delimiter-face ((t (:foreground ,gray-50))))
|
||||||
`(font-lock-string-face ((t (:foreground ,gray-75))))
|
`(font-lock-string-face ((t (:foreground ,gray-75))))
|
||||||
`(font-lock-type-face ((t (:foreground ,green-lt))))
|
`(font-lock-type-face ((t (:foreground ,green-lt))))
|
||||||
|
@ -378,8 +380,8 @@ Let’s make a /theme/:
|
||||||
`(org-document-info-keyword ((t (:foreground ,gray-70))))
|
`(org-document-info-keyword ((t (:foreground ,gray-70))))
|
||||||
`(org-meta-line ((t (:foreground ,gray-55))))
|
`(org-meta-line ((t (:foreground ,gray-55))))
|
||||||
`(org-drawer ((t (:foreground ,purple-dk :height ,smallest))))
|
`(org-drawer ((t (:foreground ,purple-dk :height ,smallest))))
|
||||||
`(org-special-keyword ((t (:foreground ,purple :height ,smaller))))
|
`(org-special-keyword ((t (:foreground ,purple2 :height ,small))))
|
||||||
`(org-property-value ((t (:foreground ,purple-lt :height ,smaller))))
|
`(org-property-value ((t (:foreground ,purple2-lt :height ,small))))
|
||||||
`(org-table ((t (:foreground ,purple-lt))))
|
`(org-table ((t (:foreground ,purple-lt))))
|
||||||
`(org-quote ((t (:inherit variable-pitch :slant italic :height 0.9))))
|
`(org-quote ((t (:inherit variable-pitch :slant italic :height 0.9))))
|
||||||
|
|
||||||
|
@ -422,6 +424,9 @@ Let’s make a /theme/:
|
||||||
|
|
||||||
`(ahs-face ((t (:foreground ,orange-lt :background unspecified))))
|
`(ahs-face ((t (:foreground ,orange-lt :background unspecified))))
|
||||||
`(ahs-plugin-default-face ((t (:foreground unspecified :background unspecified))))
|
`(ahs-plugin-default-face ((t (:foreground unspecified :background unspecified))))
|
||||||
|
|
||||||
|
`(mastodon-display-name-face ((t (:foreground ,orange-lt))))
|
||||||
|
`(mastodon-boosted-face ((t (:foreground ,green-lt))))
|
||||||
))
|
))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue