Compare commits

...

4 commits

Author SHA1 Message Date
Howard Abrams
e40c57ff18 More fixes to the theme. 2024-12-16 17:05:09 -08:00
Howard Abrams
3adc01620a Not crazy about how winner mode doesn't work with persp mode 2024-12-16 17:04:32 -08:00
Howard Abrams
3f84fcd436 Fixing my presentation/demo configuration 2024-12-16 17:03:28 -08:00
Howard Abrams
c11ab5d0ef Make C-g close mini-buffer
This has annoyed me for a while, and I'm stealing Prot's solution.
2024-12-09 09:23:51 -08:00
6 changed files with 548 additions and 179 deletions

View file

@ -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-appearance . dark)))
#+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
After reading [[https://irreal.org/blog/?p=12139][Jon Sanders essay]] as well as [[https://mbork.pl/2024-04-27_Emacs_everywhere][Marcin Borkowski's essay]], I decided to try out Tecosaurs [[https://github.com/tecosaur/emacs-everywhere][Emacs Everywhere]] approach:

View file

@ -2,7 +2,8 @@
#+author: Howard X. Abrams
#+date: 2024-10-18
#+filetags: emacs hamacs
#+lastmod: [2024-11-09 Sat]
#+lastmod: [2024-12-16 Mon]
#+STARTUP: showstars
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/.
* 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.
** 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:
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.
** Org Tree Slide
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
(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))))))
#+BEGIN_SRC emacs-lisp :tangle no
(use-package org-tree-slide
:config
(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-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))
: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
(: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
** 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
(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
"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
(:map org-present-mode-keymap
("<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)
:hook
(org-present-mode . ha-org-present-start)
(org-present-mode-quit . ha-org-present-end))
(org-present-mode . ha-slide-setup)
(org-present-mode-quit . ha-slide-teardown))
#+end_src
** Org Tree Slide
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.
** DSlide
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
(use-package org-tree-slide
:config
(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)
(use-package dslide
:hook (dslide-narrow . 'ha-slide-notes-update))
#+END_SRC
(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-demo-hide-cursor)
(ha-org-hide-stars)
(font-lock-update)
(ha-demo-hide-mode-line)
(ha-demo-presentation-frame)
;; (demo-it--presentation-display-set)
(ha-demo-hide-cursor)
(ha-demo-presentation-frame frame-name)
(text-scale-set 4)
(git-gutter-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-demo-show-cursor)
(font-lock-update)
(ha-demo-show-mode-line)
(ha-demo-show-cursor)
(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
(: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-org-tree-slide-start)
(org-tree-slide-stop . ha-org-tree-slide-stop)))
#+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
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
(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
matched during previous calls. We do this by keeping track
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
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
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
(defvar ha-demo-cursor nil
"List of cursor states stored during `ha-demo-hide-cursor' and
restored with `ha-demo-show-cursor'.")
"List of cursor states stored during `ha-demo-hide-cursor'.
Used to restore with `ha-demo-show-cursor'.")
(defun ha-demo-hide-cursor ()
"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)))
(defun ha-demo-toggle-cursor ()
"Toggles the display of the cursor."
"Toggle cursor display from shown or hidden."
(interactive)
(if ha-demo-cursor
(ha-demo-show-cursor)
@ -418,15 +687,16 @@ For Org file displayed as presentations as well as images, we probably dont w
(interactive)
(if ha-demo-mode-line
(setq mode-line-format ha-demo-mode-line)))
#+END_SRC
#+END_SRC
** Presentation Frame Properties
Like the work Im doing to the mode-line, can we make the frame cleaner for a presentation?
#+BEGIN_SRC emacs-lisp
(defvar ha-demo-frame-state nil
"Store frame properties during `ha-demo-presentation-frame' before
altering them, and then restore them with `ha-demo-normalize-frame'.")
"Store frame properties during `ha-demo-presentation-frame'.
Stored before alteration, as to restore them with
`ha-demo-normalize-frame'.")
(defun ha-demo-presentation-frame (&optional name)
"Remove the fringe and other frame settings.
@ -446,7 +716,7 @@ Like the work Im doing to the mode-line, can we make the frame cleaner for a
(interactive)
(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)))
#+END_SRC
#+END_SRC
** Display File
Displaying a File with:
@ -461,7 +731,7 @@ All options? Should I use Common Lisps =cl-defun= for the keyword parameters?
#+BEGIN_SRC emacs-lisp
(cl-defun ha-demo-show-file (filename &key position size modeline
line heading shift cursor
commands)
commands focus)
"Show a file, FILENAME, in a buffer based on keyed parameters.
POSITION can be 'full 'right or 'below and positions the window.
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.
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 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
instructions to happen to the buffer display."
(let ((orig-buf (current-buffer)))
(unless position
(setq position :right))
@ -501,28 +775,14 @@ All options? Should I use Common Lisps =cl-defun= for the keyword parameters?
(when 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
(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
Let try it all together:
@ -539,6 +799,75 @@ Or:
:commands (lambda () (jinx-mode -1)))
#+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:
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")
:config
(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)
:hook (text-mode . mixed-pitch-mode))
#+end_src

View file

@ -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
:config
(defhydra hydra-window-resize (:color blue :hint nil) "
_w_: select _m_: move/swap _u_: undo _^_: taller (t) _+_: text larger
_j_: go up _d_: delete _U_: undo+ _v_: shorter (T) _-_: text smaller
_k_: down _e_: balance _r_: redo _>_: wider _F_: font larger
_h_: left _n_: v-split _R_: redo+ _<_: narrower _f_: font smaller
_w_: select _m_: move/swap _^_: taller (t) _+_: text larger
_j_: go up _d_: delete _v_: shorter (T) _-_: text smaller
_k_: down _e_: balance _>_: wider _F_: font larger
_h_: left _n_: v-split _<_: narrower _f_: font smaller
_l_: right _s_: split _o_: only this window _c_: choose (also 1-9)"
("w" ace-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)
("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)
("K" evil-window-up :color pink)

View file

@ -82,23 +82,29 @@ The following adds frame borders and window dividers to give space between windo
#+end_src
** 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 ()
(font-lock-add-keywords
nil
'(("^\\*+ "
(0 (put-text-property (match-beginning 0) (match-end 0) 'face
(list :foreground
(face-attribute 'default :background))))))))
`(( ,(rx line-start (one-or-more "*") space)
(0 (put-text-property (match-beginning 0) (match-end 0)
'invisible t))))))
#+end_src
And hook this function to Org:
#+begin_src emacs-lisp
#+begin_src emacs-lisp :tangle no
(use-package org
:hook (org-mode . org-mode-hide-stars))
#+end_src
The list of things to try:
#+BEGIN_SRC emacs-lisp
(setq org-hide-leading-stars nil) ; or t
#+END_SRC
** 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:

View file

@ -2,7 +2,7 @@
#+author: Howard Abrams
#+date: 2024-06-18
#+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.
@ -158,6 +158,8 @@ And encapsulate them in a named list:
("yellow-lt" . "#d8bb77")
("green" . "#899d03")
("green-lt" . "#b3bf8e")
("dk-green" . "#55702c")
("dk-green-lt" . "#979e6e")
("blue" . "#6f8b93")
("blue-lt" . "#91b5bf")
("purple" . "#893161")
@ -348,7 +350,7 @@ Lets make a /theme/:
`(link ((t (:foreground ,link-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-string-face ((t (:foreground ,gray-75))))
`(font-lock-type-face ((t (:foreground ,green-lt))))
@ -378,8 +380,8 @@ Lets make a /theme/:
`(org-document-info-keyword ((t (:foreground ,gray-70))))
`(org-meta-line ((t (:foreground ,gray-55))))
`(org-drawer ((t (:foreground ,purple-dk :height ,smallest))))
`(org-special-keyword ((t (:foreground ,purple :height ,smaller))))
`(org-property-value ((t (:foreground ,purple-lt :height ,smaller))))
`(org-special-keyword ((t (:foreground ,purple2 :height ,small))))
`(org-property-value ((t (:foreground ,purple2-lt :height ,small))))
`(org-table ((t (:foreground ,purple-lt))))
`(org-quote ((t (:inherit variable-pitch :slant italic :height 0.9))))
@ -422,6 +424,9 @@ Lets make a /theme/:
`(ahs-face ((t (:foreground ,orange-lt :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