Fixing my presentation/demo configuration

This commit is contained in:
Howard Abrams 2024-12-16 17:02:23 -08:00
parent c11ab5d0ef
commit 3f84fcd436
3 changed files with 502 additions and 166 deletions

View file

@ -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. Im 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: Ive 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 doesnt 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 doesnt 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,66 +121,320 @@ 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
Ive 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
(use-package dslide
:straight (dslide :type git :host github :repo "positron-solutions/dslide")
:custom
(dslide-start-from 'point)
;; Let's keep our presentations simple:
(dslide-slide-in-effect nil)
(dslide-header nil)
(dslide-header-date nil)
(dslide-header-author nil)
(dslide-header-email nil)
(dslide-breadcrumb-separator nil)
:general
(:states 'normal :no-autoload t :keymaps 'dslide-mode-map
"q" '("quit presentation" . dslide-deck-stop)
"<left>" '("previous slide" . dslide-deck-backward)
"<right>" '("next slide" . dslide-deck-forward)
"C" '("show cursor" . ha-demo-show-cursor)
"c" '("hide cursor" . ha-demo-hide-cursor)
"<up>" '("previous slide" . previous-line)
"<down>" '("next slide" . next-line))
:bind
("C-<f5>" . dslide-deck-start)
(: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
Lets 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
*** 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 Im 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 #+BEGIN_SRC emacs-lisp
(use-package org-tree-slide (use-package dslide
:config :hook (dslide-narrow . 'ha-slide-notes-update))
(setq org-tree-slide-heading-emphasis nil #+END_SRC
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 ()
"Configure the presentation display.
See `ha-org-tree-slide-stop' that undoes this."
(setq org-hide-emphasis-markers t) #+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-blocks-hide-headers)
(ha-demo-hide-cursor) (ha-org-hide-stars)
(font-lock-update)
(ha-demo-hide-mode-line) (ha-demo-hide-mode-line)
(ha-demo-presentation-frame) (ha-demo-hide-cursor)
;; (demo-it--presentation-display-set) (ha-demo-presentation-frame frame-name)
(text-scale-set 4) (text-scale-set 4)
(git-gutter-mode -1) (git-gutter-mode -1)
(flycheck-mode -1) (flycheck-mode -1)
(jinx-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)
(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-org-blocks-show-headers)
(ha-demo-show-cursor) (font-lock-update)
(ha-demo-show-mode-line) (ha-demo-show-mode-line)
(ha-demo-show-cursor)
(ha-demo-normalize-frame) (ha-demo-normalize-frame)
;; (demo-it--presentation-display-restore) ; Restore previous changes
(text-scale-set 0) (text-scale-set 0)
(git-gutter-mode) (git-gutter-mode)
(flycheck-mode) (flycheck-mode)
(jinx-mode)) (jinx-mode))
#+END_SRC
:bind The =dslide= seems to reset /everything/ on each slide display, so:
(: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 #+BEGIN_SRC emacs-lisp
(:states 'normal :keymaps 'org-tree-slide-mode-map (defun ha-slide-reset ()
"C" #'ha-demo-toggle-cursor "Reset the current slide."
"n" #'org-tree-slide-move-next-tree (interactive)
"N" #'org-tree-slide-move-previous-tree (ha-org-blocks-hide-headers)
"Q" (lambda () (interactive) (org-tree-slide-mode -1))) (font-lock-update))
:hook
((org-tree-slide-play . ha-org-tree-slide-start)
(org-tree-slide-stop . ha-org-tree-slide-stop)))
#+END_SRC #+END_SRC
* New Demonstration * New Demonstration
@ -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 @@ Lets 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= doesnt 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= doesnt 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)
@ -425,8 +694,9 @@ Like the work Im doing to the mode-line, can we make the frame cleaner for a
#+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.
@ -461,7 +731,7 @@ All options? Should I use Common Lisps =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,9 +740,13 @@ All options? Should I use Common Lisps =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."
(let ((orig-buf (current-buffer)))
(unless position (unless position
(setq position :right)) (setq position :right))
@ -501,28 +775,14 @@ All options? Should I use Common Lisps =cl-defun= for the keyword parameters?
(when size (when size
(text-scale-set size)) (text-scale-set size))
(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:
(if shift
(when (integerp shift)
(recenter-top-bottom shift))
(recenter-top-bottom 0))
(unless modeline (unless modeline
(setq-local mode-line-format nil)) (setq-local mode-line-format nil))
(when commands (funcall commands))) (ha-demo-highlight-buffer :line line :heading heading :shift shift
:commands commands)
(when (and focus (eq focus 'presentation))
(pop-to-buffer orig-buf))))
#+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:

View 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

View file

@ -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
Ive struggled with hiding the initial asterisks that denote a headline in Org. Ive struggled with hiding the initial asterisks that denote a headline in Org. The following code doesnt 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 arent 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 arent 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: