Compare commits
14 commits
71168110e0
...
4629cbf1a0
Author | SHA1 | Date | |
---|---|---|---|
|
4629cbf1a0 | ||
|
de7770280a | ||
|
f1ddcec3ab | ||
|
db4c460453 | ||
|
bc06c77df5 | ||
|
06643aa146 | ||
|
3c2c266009 | ||
|
b067964930 | ||
|
6d92980311 | ||
|
2bd14a876a | ||
|
990cc577dc | ||
|
3b1427a8db | ||
|
809a542e6d | ||
|
ffe662ced0 |
41 changed files with 656 additions and 385 deletions
|
@ -19,7 +19,7 @@ A literate programming file for bootstraping my Emacs Configuration.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/bootstrap.org
|
||||
;; ~/src/hamacs/bootstrap.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
;;; ha-focus.el --- Emacs lisp code to focus my thoughts. -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (C) 2021 Howard X. Abrams
|
||||
;; Copyright © 2021,2024 Howard X. Abrams
|
||||
;;
|
||||
;; Author: Howard X. Abrams <http://gitlab.com/howardabrams>
|
||||
;; Maintainer: Howard X. Abrams <howard.abrams@workday.com>
|
||||
;; Maintainer: Howard X. Abrams <howard.abrams@gmail.com>
|
||||
;; Created: May 28, 2021
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Find details of this code on my website at:
|
||||
;; https://www.howardism.org/Technical/Emacs/focused-work.html
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/website/Technical/Emacs/focused-work.org
|
||||
;; And tangle the file to recreate this one.
|
||||
|
@ -18,7 +23,7 @@
|
|||
|
||||
(defun ha-focus-countdown-timer (minutes fun)
|
||||
(let ((the-future (* minutes 60)))
|
||||
(run-at-time the-future nil fun)))
|
||||
(setq ha-focus-timer (run-at-time the-future nil fun))))
|
||||
|
||||
(defun ha-focus-begin ()
|
||||
"Start a concerted, focused effort, ala Pomodoro Technique.
|
||||
|
@ -31,44 +36,57 @@ Call `ha-focus-break' when finished."
|
|||
(ha-focus--command "tell application \"Spotify\" to play")
|
||||
(if (eq major-mode 'org-mode)
|
||||
(org-clock-in)
|
||||
(org-clock-in-last)))
|
||||
(org-clock-in-last))
|
||||
(message "🍅 Started clocked %s"
|
||||
(substring-no-properties
|
||||
(org-clock-get-clock-string))))
|
||||
|
||||
(defun ha-focus-break ()
|
||||
"Stop the focused time by stopping the music.
|
||||
This also starts another break timer, that calls
|
||||
`ha-focus-break-over' when finished."
|
||||
(interactive)
|
||||
(run-with-idle-timer 5 nil 'ha-focus-capture)
|
||||
(run-with-idle-timer 30 nil 'ha-focus-capture)
|
||||
(ha-focus--command "tell application \"Spotify\" to pause")
|
||||
(message "Time to take a break."))
|
||||
(ha-focus-countdown-timer 5 'ha-focus-break-over)
|
||||
(message "🍅 Time to take a break."))
|
||||
|
||||
(defun ha-focus-capture ()
|
||||
"Spin up a capture window."
|
||||
(ignore-errors
|
||||
(org-capture nil "cc")
|
||||
(sit-for 1)
|
||||
(org-clock-out))
|
||||
(ha-focus-countdown-timer 5 'ha-focus-break-over)
|
||||
(message "Taking a much needed break..."))
|
||||
(org-clock-out)))
|
||||
|
||||
(defun ha-focus-break-over ()
|
||||
"Message me to know that the break time is over. Notice that
|
||||
this doesn't start anything automatically, as I may have simply
|
||||
this doesn't start anything automatically, as I may have
|
||||
wandered off."
|
||||
(ha-focus--command "set v to output volume of (get volume settings)
|
||||
set volume output volume 1
|
||||
say \"Break time over. Back on your head.\"
|
||||
set volume output volume v"))
|
||||
set volume output volume v")
|
||||
(message "🍅 Type <f12> to restart the timer."))
|
||||
|
||||
(defun ha-focus-interrupt ()
|
||||
"Interrupt the current focused timer, if set."
|
||||
(interactive)
|
||||
(when (timerp ha-focus-timer)
|
||||
(cancel-timer ha-focus-timer)
|
||||
(ignore-errors
|
||||
(org-clock-out))))
|
||||
|
||||
(require 'async)
|
||||
|
||||
(defun ha-focus--command (osascript)
|
||||
"Runs OSASCRIPT by passing to the `osascript' command asynchronously."
|
||||
(async-start-process "focus-os" "osascript" 'ha-focus--command-callback "-e" osascript))
|
||||
(async-start-process "focus-os" "osascript"
|
||||
'ha-focus--command-callback "-e" osascript))
|
||||
|
||||
(defun ha-focus--command-callback (proc)
|
||||
"Asynchronously called when the `osascript' process finishes."
|
||||
(message "Finished calling osascript."))
|
||||
|
||||
(global-set-key (kbd "<f7>") 'ha-focus-begin)
|
||||
(global-set-key (kbd "S-<f7>") 'ha-focus-break)
|
||||
;; ...
|
||||
)
|
||||
|
||||
(provide 'ha-focus)
|
||||
;;; ha-focus.el ends here
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming configuration for fancy agenda and todo lists.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-agendas.org
|
||||
;; ~/src/hamacs/ha-agendas.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file configuring critical applications.
|
|||
;; While obvious, GNU Emacs does not include this file
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard/other/hamacs/ha-applications.org
|
||||
;; ~/src/hamacs/ha-applications.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -815,15 +815,6 @@ When having your point on a key entry, you can copy fields to kill-ring using:
|
|||
- ~b~ :: user name
|
||||
- ~c~ :: password
|
||||
|
||||
* Demo It
|
||||
Making demonstrations /within/ Emacs with my [[https://github.com/howardabrams/demo-it][demo-it]] project. While on MELPA, I want to use my own cloned version to make sure I can keep debugging it.
|
||||
#+begin_src emacs-lisp
|
||||
(use-package demo-it
|
||||
:straight (:local-repo "~/other/demo-it")
|
||||
;; :straight (:host github :repo "howardabrams/demo-it")
|
||||
:commands (demo-it-create demo-it-start))
|
||||
#+end_src
|
||||
|
||||
* PDF Viewing
|
||||
Why not [[https://github.com/politza/pdf-tools][view PDF files]] better? If you have standard build tools installed on your system, run [[help:pdf-tools-install][pdf-tools-install]], as this command will an =epdfinfo= program to PDF displays.
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for helper apps in Emacs.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-aux-apps.org
|
||||
;; ~/src/hamacs/ha-aux-apps.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -33,7 +33,7 @@ Glad to see the 2FA feature is working on the [[https://codeberg.org/martianh/ma
|
|||
(use-package mastodon
|
||||
:straight (:host codeberg :repo "martianh/mastodon.el")
|
||||
:init
|
||||
(setq mastodon-instance-url "https://emacs.ch"
|
||||
(setq mastodon-instance-url "https://pdx.sh"
|
||||
mastodon-active-user "howard"))
|
||||
#+end_src
|
||||
|
||||
|
@ -175,23 +175,23 @@ In the Telega chat’s, let’s turn on non-fixed-width fonts:
|
|||
* RPG DM
|
||||
Been working on my [[https://gitlab.com/howardabrams/emacs-rpgdm][RPG DM project]] for getting Emacs helping as a /Dungeon Master's Assistant/. The idea is to be able to roll dice and whatnot. What I find most useful is the [[https://gitlab.com/howardabrams/emacs-rpgdm/-/blob/main/rpgdm-tables.el][random tables]].
|
||||
#+begin_src emacs-lisp
|
||||
(when (f-directory? "~/other/emacs-rpgdm")
|
||||
(when (f-directory? "~/src/emacs-rpgdm")
|
||||
(use-package rpgdm
|
||||
:straight (:local-repo "~/other/emacs-rpgdm")
|
||||
:straight (:local-repo "~/src/emacs-rpgdm")
|
||||
:commands (rpgdm-mode rpgdm-tables-load)
|
||||
:init (setq rpgdm-base (expand-file-name "~/other/emacs-rpgdm"))
|
||||
:init (setq rpgdm-base (expand-file-name "~/src/emacs-rpgdm"))
|
||||
:config (ha-leader "t D" '("rpg dm" . rpgdm-mode))))
|
||||
#+end_src
|
||||
|
||||
Working on my new replacement of my DM code:
|
||||
#+begin_src emacs-lisp
|
||||
(when (f-directory? "~/other/emacs-rpgtk")
|
||||
(when (f-directory? "~/src/emacs-rpgtk")
|
||||
(use-package rpgtk
|
||||
:straight (:local-repo "~/other/emacs-rpgtk")
|
||||
:straight (:local-repo "~/src/emacs-rpgtk")
|
||||
:after hydra
|
||||
;; :commands (rpgtk-mode rpgtk-tables-load rpgtk-dice rpgtk-message)
|
||||
:custom
|
||||
(rpgtk-tables-directory (expand-file-name "~/other/emacs-rpgtk/tables"))
|
||||
(rpgtk-tables-directory (expand-file-name "~/src/emacs-rpgtk/tables"))
|
||||
|
||||
:config
|
||||
(ha-leader
|
||||
|
@ -202,12 +202,12 @@ Working on my new replacement of my DM code:
|
|||
|
||||
And my [[https://gitlab.com/howardabrams/emacs-ironsworn][new Ironsworn project]] expands on it, giving me both the Oracles and the Moves. With an Org file, I can easily play Solo:
|
||||
#+begin_src emacs-lisp
|
||||
(when (f-directory? "~/other/emacs-ironsworn")
|
||||
(when (f-directory? "~/src/emacs-ironsworn")
|
||||
(use-package rpgdm-ironsworn
|
||||
:after rpgdm
|
||||
:straight (:local-repo "~/other/emacs-ironsworn")
|
||||
:straight (:local-repo "~/src/emacs-ironsworn")
|
||||
:init
|
||||
(setq rpgdm-ironsworn-project (expand-file-name "~/other/emacs-ironsworn")
|
||||
(setq rpgdm-ironsworn-project (expand-file-name "~/src/emacs-ironsworn")
|
||||
;; Ignore org links that call my RPG functions:
|
||||
org-link-elisp-skip-confirm-regexp (rx string-start (optional "(") "rpgdm-"
|
||||
(or "tables-" "ironsworn-")
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for configuring org for capturing notes.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-capturing-notes.org
|
||||
;; ~/src/hamacs/ha-capturing-notes.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -188,11 +188,15 @@ And a less-disruptive keybinding:
|
|||
#+end_src
|
||||
* External Capturing
|
||||
Using =emacsclient=, the operating system or other applications can trigger a call to capture content into Emacs. I started with the functions from [[https://macowners.club/posts/org-capture-from-everywhere-macos/][this essay]], which made a nice approach to opening and closing a frame:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun start-capture-frame (&optional template-key)
|
||||
"Create a new frame and run `org-capture'."
|
||||
(interactive)
|
||||
(make-frame '((name . "capture")
|
||||
(title . "Emacs Capture Window")
|
||||
(window-system . ns)
|
||||
(popup-frame . t)
|
||||
(top . 300)
|
||||
(left . 700)
|
||||
(width . 80)
|
||||
|
@ -216,7 +220,7 @@ Wouldn’t it be grand if when we finished capturing, the frame automatically cl
|
|||
#+end_src
|
||||
|
||||
This external shell script calls the function to kick everything off from applications that aren’t Emacs:
|
||||
#+begin_src sh :shebang "#!/bin/bash" :tangle ~/bin/emacs-capture
|
||||
#+begin_src sh :shebang "#!/bin/bash" :tangle ~/bin/emacs-capture :chmod 755
|
||||
/usr/local/bin/emacsclient -s work -n -e "(start-capture-frame)"
|
||||
#+end_src
|
||||
|
||||
|
|
|
@ -19,13 +19,12 @@ A literate programming file for configuring Emacs.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-config.org
|
||||
;; ~/src/hamacs/ha-config.org
|
||||
;; Using `find-file-at-point', and tangle the file to recreate this.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Basic configuration of Emacs. Should be executed early in the
|
||||
;; loading sequence.
|
||||
;; Basic configuration of Emacs. Start early in the loading sequence.
|
||||
;;
|
||||
;;; Code:
|
||||
#+end_src
|
||||
|
@ -351,7 +350,7 @@ The [[https://gitlab.com/ideasman42/emacs-undo-fu][undo-fu]] isn’t much to the
|
|||
(global-set-key (kbd "s-S-z") 'undo-fu-only-redo))
|
||||
#+end_src
|
||||
|
||||
While I usually use ~C-/~ for [[help:undo][undo]] (and ~C-?~ for [[help:undo-redo][redo]]), when I’m on the Mac, I need to cover my bases.
|
||||
While I generally use ~C-/~ for [[help:undo][undo]] (and ~C-?~ for [[help:undo-redo][redo]]), when I’m on the Mac, I need to cover my bases.
|
||||
|
||||
** Leader Sequences
|
||||
Pressing the ~SPACE~ can activate a /leader key sequence/ I define in my [[file:ha-leader.org][ha-leader]] file.
|
||||
|
@ -368,15 +367,19 @@ Since I seldom remember keybindings, or even function names, for major-modes, I
|
|||
|
||||
(setq major-mode-hydra-title-generator
|
||||
'(lambda (mode)
|
||||
(if (symbolp mode)
|
||||
(setq mode (symbol-name mode))
|
||||
(setq mode (pp-to-string mode)))
|
||||
|
||||
(let ((title (thread-last mode
|
||||
(symbol-name)
|
||||
(string-replace "-" " ")
|
||||
(string-replace " mode" "")
|
||||
(s-titleize))))
|
||||
(concat "ϻ " title " Commands")))))
|
||||
#+end_src
|
||||
|
||||
For this feature, I may want to pull it out into its own file, so as to keep all of its features together... however, those feature often /depend/ of the functions they are calling. If so, we would have a series like this:
|
||||
Scattered throughout my configuration, I use =major-mode-hydra-define= where I’m configuring that mode. For instance, for the built-in Info, I can make:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package major-mode-hydra
|
||||
:config
|
||||
|
@ -464,7 +467,7 @@ In the shell, IDEs and other systems, the key binding is typically ~TAB~. In mod
|
|||
*** Corfu
|
||||
The default completion system either inserts the first option directly in the text (without cycling, so let’s hope it gets it right the first time), or presents choices in another buffer (who wants to hop to it to select an expansion).
|
||||
|
||||
After using [[http://company-mode.github.io/][company]] for my completion back-end, I switch to [[https://github.com/minad/corfu][corfu]] as it works with the variable-spaced font of my org files (also see [[https://takeonrules.com/2022/01/17/switching-from-company-to-corfu-for-emacs-completion/][this essay]] for my initial motivation).
|
||||
After using [[http://company-mode.github.io/][company]] for my completion back-end, I switched to [[https://github.com/minad/corfu][corfu]] as it works with the variable-spaced font of my org files (also see [[https://takeonrules.com/2022/01/17/switching-from-company-to-corfu-for-emacs-completion/][this essay]] for my initial motivation).
|
||||
#+begin_src emacs-lisp
|
||||
(use-package corfu
|
||||
:custom
|
||||
|
@ -523,9 +526,11 @@ And since I'll be associating snippets with new files all over my configuration,
|
|||
"Autofill file buffer matching FILENAME-RE regular expression.
|
||||
The contents inserted from the YAS SNIPPET-NAME."
|
||||
;; The define-auto-insert takes a regular expression and an ACTION:
|
||||
;; ACTION may also be a vector containing successive single actions.
|
||||
;; ACTION may also be a vector containing _successive_ single actions.
|
||||
;; This means running this twice results in two repeated expansions, so:
|
||||
(unless (assoc filename-re auto-insert-alist 'equal)
|
||||
(define-auto-insert filename-re
|
||||
(vector snippet-name 'ha-autoinsert-yas-expand)))
|
||||
(vector snippet-name 'ha-autoinsert-yas-expand))))
|
||||
#+end_src
|
||||
|
||||
As an example of its use, any Org files loaded in /this project/ should insert my config file:
|
||||
|
@ -656,7 +661,7 @@ I appreciated [[https://github.com/abo-abo/ace-link][ace-link]]’s idea for hyp
|
|||
"o" 'link-hint-open-link))
|
||||
#+end_src
|
||||
|
||||
Can I open a link in another window? The idea with this is that I can select a link, and with multiple windows open, I can specify where the =*eww*= window should show the link. If only two windows, then the new EWW buffer shows in the /other/ one.
|
||||
Can I open a link in another window? The idea with this is that I can select a link, and with multiple windows open, I can specify where the =*eww*= window should show the link. If only two windows, then the new EWW buffer shows in the /src/ one.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun link-hint-open-link-ace-window ()
|
||||
|
@ -856,7 +861,7 @@ Granted, this list is essentially a list of projects that I'm currently developi
|
|||
(add-to-list 'ha-workspace-projects-personal
|
||||
'("technical" "~/technical" ("ansible.org")))
|
||||
(add-to-list 'ha-workspace-projects-personal
|
||||
'("hamacs" "~/other/hamacs" ("README.org" "ha-config.org")))
|
||||
'("hamacs" "~/src/hamacs" ("README.org" "ha-config.org")))
|
||||
#+end_src
|
||||
|
||||
Given a list of information about project-workspaces, can we create them all?
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for configuring Emacs to show a startup screen.
|
|||
;; While obvious, GNU Emacs does not include this file or project.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard/other/hamacs/ha-dashboard.org
|
||||
;; ~/src/hamacs/ha-dashboard.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -139,7 +139,7 @@ The [[https://github.com/emacs-dashboard/emacs-dashboard][emacs-dashboard]] proj
|
|||
(native-comp-available-p))
|
||||
"with Native Compilation" "")
|
||||
(ha-dashboard-version))
|
||||
dashboard-startup-banner "~/other/hamacs/support/levitating-gnu.png"
|
||||
dashboard-startup-banner "~/src/hamacs/support/levitating-gnu.png"
|
||||
dashboard-center-content t
|
||||
dashboard-set-init-info t
|
||||
dashboard-projects-switch-function 'project-switch-project
|
||||
|
@ -231,7 +231,7 @@ Simple function to display a file in the top-right corner (if the file exists):
|
|||
(defun ha-show-learn-this ()
|
||||
""
|
||||
(interactive)
|
||||
(let ((filename "~/other/hamacs/learn-this.org")
|
||||
(let ((filename "~/src/hamacs/learn-this.org")
|
||||
(curr-win (get-buffer-window (buffer-name))))
|
||||
(when (file-exists-p filename)
|
||||
(split-window-below 15)
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for configuring Emacs to edit files of data.
|
|||
;; While obvious, GNU Emacs does not include this file or project.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard.abrams/other/hamacs/ha-data.org
|
||||
;; ~/src/hamacs/ha-data.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
258
ha-demos.org
Normal file
258
ha-demos.org
Normal file
|
@ -0,0 +1,258 @@
|
|||
#+title: Demonstrations in Emacs
|
||||
#+author: Howard X. Abrams
|
||||
#+date: 2024-10-18
|
||||
#+filetags: emacs hamacs
|
||||
#+lastmod: [2024-10-19 Sat]
|
||||
|
||||
A literate programming file for creating and running demonstrations
|
||||
|
||||
#+begin_src emacs-lisp :exports none
|
||||
;;; ha-demos --- creating and running demonstrations -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; © 2024 Howard X. Abrams
|
||||
;; Licensed under a Creative Commons Attribution 4.0 International License.
|
||||
;; See http://creativecommons.org/licenses/by/4.0/
|
||||
;;
|
||||
;; Author: Howard X. Abrams <http://gitlab.com/howardabrams>
|
||||
;; Maintainer: Howard X. Abrams
|
||||
;; Created: October 18, 2024
|
||||
;;
|
||||
;; While obvious, GNU Emacs does not include this file or project.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard.abrams/src/hamacs/ha-demos.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
#+end_src
|
||||
|
||||
* Introduction
|
||||
Once made demonstrations /within/ Emacs with my [[https://github.com/howardabrams/demo-it][demo-it]] project. While on MELPA, I wanted to use my own cloned version to make sure I can keep debugging it.
|
||||
|
||||
#+begin_src emacs-lisp :tangle no
|
||||
(use-package demo-it
|
||||
:straight (:local-repo "~/src/demo-it")
|
||||
;; :straight (:host github :repo "howardabrams/demo-it")
|
||||
:commands (demo-it-create demo-it-start)
|
||||
:custom (demo-it--insert-test-speed :faster))
|
||||
#+end_src
|
||||
|
||||
But I feel I should replace it.
|
||||
* Presentations with Org
|
||||
Used to use [[https://github.com/takaxp/org-tree-slide][org-tree-slide]] for showing org files as presentations. Converted to use [[https://github.com/rlister/org-present][org-present]]. I love the /hooks/ as that makes it easier to handle. My concern with =org-present= is how it solely displays top-level headers.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package org-present
|
||||
:config
|
||||
(defvar ha-org-present-mode-line mode-line-format "Cache previous mode-line format state")
|
||||
|
||||
(defun ha-org-blocks-hide-headers ()
|
||||
"Make the headers and other block metadata invisible.
|
||||
See `ha-org-blocks-show-headers'."
|
||||
(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 (1+ (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))
|
||||
|
||||
(defun ha-org-present-start ()
|
||||
(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 ()
|
||||
(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))
|
||||
|
||||
:hook
|
||||
(org-present-mode . ha-org-present-start)
|
||||
(org-present-mode-quit . ha-org-present-end)
|
||||
|
||||
:general
|
||||
(:states 'normal :keymaps 'org-present-mode-keymap
|
||||
"+" #'org-present-big
|
||||
"-" #'org-present-small
|
||||
"<" #'org-present-beginning
|
||||
">" #'org-present-end
|
||||
"c" #'org-present-hide-cursor
|
||||
"C" #'org-present-show-cursor
|
||||
"n" #'org-present-next
|
||||
"p" #'org-present-prev
|
||||
"r" #'org-present-read-only
|
||||
"w" #'org-present-read-write
|
||||
"q" #'org-present-quit))
|
||||
#+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:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp :tangle no
|
||||
(define-ha-demo ha-simple-demo
|
||||
(:head "New Demonstration" :i 0) (message "Howdy")
|
||||
(:head "New Demonstration" :i 1) (message "Hi there"))
|
||||
|
||||
(global-set-key (kbd "<f6>") 'ha-simple-demo)
|
||||
(global-set-key (kbd "<f5>") 'org-present-next)
|
||||
(global-set-key (kbd "S-<f5>") 'org-present-previous)
|
||||
(global-set-key (kbd "C-<f5>") 'org-present-quit)
|
||||
#+END_SRC
|
||||
|
||||
To make the contents of the expression easier to write, the =define-ha-demo= as a macro. Otherwise we write a complicated =cond= with lots of duplicated calls to =ha-demo-state-match= (defined later). This macro creates a function, so the first parameter is the name of the function:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(defmacro define-ha-demo (demo-name &rest forms)
|
||||
"Create a demonstration sequence as DEMO-NAME function.
|
||||
Call DEMO-NAME (as an interactive function), executes a function based matching list of states at point.
|
||||
Where FORMS is an even number of _matcher_ and _function_ to call.
|
||||
|
||||
Probably best to explain this in an example:
|
||||
|
||||
(define-demo demo1
|
||||
(:buffer \"demonstrations.py\") (message \"In a buffer\")
|
||||
(:mode 'dired-mode) (message \"In a dired\")
|
||||
(:head \"Raven Civilizations\" (message \"In an org file\")))
|
||||
|
||||
Calling `(demo1)' displays a message based on position of the
|
||||
point in a particular buffer or place in a heading in an Org file.
|
||||
|
||||
You can use the `:i' to specify different forms to call when
|
||||
the trigger matches the first time, versus the second time, etc.
|
||||
|
||||
(define-demo demo2
|
||||
(:buffer \"demonstrations.org\" :i 0) (message \"First time\")
|
||||
(:buffer \"demonstrations.org\" :i 1) (message \"Second time\"))"
|
||||
`(defun ,demo-name ()
|
||||
(interactive)
|
||||
(let ((state (list :buffer (buffer-name)
|
||||
:mode major-mode
|
||||
:head (when (eq major-mode 'org-mode)
|
||||
(org-get-heading)))))
|
||||
(cond
|
||||
,@(seq-map (lambda (tf-pair)
|
||||
(seq-let (trigger func) tf-pair
|
||||
(list
|
||||
`(ha-demo-state-match ',trigger state)
|
||||
func)))
|
||||
(seq-partition forms 2))))))
|
||||
#+END_SRC
|
||||
|
||||
The matching function, =ha-demo-state-match= looks in a cache, the =demo-prev-state= hash table, for the number of times we have triggered that state, and /add/ that value into a new state variable we use to match, =:itful-state= (yeah, naming is hard).
|
||||
|
||||
*Note:* If we match, we want to return non-nil, and update this new incremented value back in our cache:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(defun ha-demo-state-match (triggers state)
|
||||
"Return non-nil if STATE contains 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
|
||||
the iteration... if this function returns non-nil."
|
||||
|
||||
;; If the first element is either parameter is NOT a list,
|
||||
;; we group it into a list of tuples:
|
||||
(when (not (listp (car triggers)))
|
||||
(setq triggers (seq-partition triggers 2)))
|
||||
(when (not (listp (car state)))
|
||||
(setq state (seq-partition state 2)))
|
||||
|
||||
(let* ((iteration (gethash state ha-demo-prev-state 0))
|
||||
(itful-state (cons `(:i ,iteration) state)))
|
||||
(when (ha-demo-match triggers itful-state)
|
||||
(puthash state (1+ iteration) ha-demo-prev-state))))
|
||||
#+END_SRC
|
||||
|
||||
Notice the two =when= expressions for using =seq-partition= for converting a /property-style/ list like =(:a 1 :b 2 :c 3)= into an more standard /associative/ list, like =((:a 1) (:b 2) (:c 3))=.
|
||||
|
||||
Let’s test:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp :tangle no
|
||||
(ert-deftest ha-demo-state-match-test ()
|
||||
;; Not specifying a state should always work:
|
||||
(should (ha-demo-state-match
|
||||
'(:a 1) '((:a 1) (:b 2) (:c 4))))
|
||||
(should (ha-demo-state-match
|
||||
'(:a 1) '((:a 1) (:b 2) (:c 4))))
|
||||
|
||||
;; Reset number of iterations of possible states:
|
||||
(clrhash ha-demo-prev-state)
|
||||
|
||||
;; With a clear hash, we should match on the
|
||||
;; first (0) iteration:
|
||||
(should (ha-demo-state-match
|
||||
'(:a 1 :i 0) '((:a 1) (:b 3) (:c 4))))
|
||||
;; Which should then match the next state:
|
||||
(should (ha-demo-state-match
|
||||
'(:a 1 :i 1) '((:a 1) (:b 3) (:c 4))))
|
||||
;; But should not match any other state:
|
||||
(should (not (ha-demo-state-match
|
||||
'(:a 1 :i 5) '((:a 1) (:b 2) (:c 3))))))
|
||||
#+END_SRC
|
||||
|
||||
But can I check if I have triggered a state once before? Let’s keep track of the /states/ that have returned true before, in a hash table where the key is the /state/ (a list of =:buffer=, =:mode=, =:head=, etc.) and the /value/ is the number of times triggered at that state:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(defvar ha-demo-prev-state (make-hash-table :test 'equal)
|
||||
"Matched states in keys, and store number of matches as values.")
|
||||
#+END_SRC
|
||||
|
||||
Now, we have a new match function takes the /state/ and /triggers/, where the trigger could include an /iteration/, =:i= that limits a match. For instance:
|
||||
|
||||
- =(:buffer "foobar.txt" :i 0)= :: triggers the first time we call this function in this buffer.
|
||||
- =(:buffer "foobar.txt" :i 1)= :: triggers the second time we call this function in this buffer.
|
||||
|
||||
If the =triggers= doesn’t contain an =:i=, it matches every time when meeting the other conditions.
|
||||
|
||||
Let’s create a function that could accept a list of /triggering keys/, and then compare that with another list representing the “current state” of the point, including the buffer, the mode, or the heading in an Org file. In this case, the magic happens by calling =seq-difference=:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(defun ha-demo-match (triggers state)
|
||||
"Return t if all elements of TRIGGERS are in STATE.
|
||||
Where TRIGGERS and STATE are lists of key/value tuple
|
||||
pairs, e.g. `((:a 1) (:b 2))'."
|
||||
;; If difference returns anything, we've failed:
|
||||
(not (seq-difference triggers state)))
|
||||
#+END_SRC
|
||||
|
||||
* Technical Artifacts :noexport:
|
||||
Let's =provide= a name so we can =require= this file:
|
||||
|
||||
#+begin_src emacs-lisp :exports none
|
||||
(provide 'ha-demos)
|
||||
;;; ha-demos.el ends here
|
||||
#+end_src
|
||||
|
||||
#+DESCRIPTION: creating and running demonstrations
|
||||
|
||||
#+PROPERTY: header-args:sh :tangle no
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle yes
|
||||
#+PROPERTY: header-args :results none :eval no-export :comments no mkdirp yes
|
||||
|
||||
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil date:nil
|
||||
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil
|
||||
#+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
|
|
@ -19,7 +19,7 @@ A literate programming file to configure the Emacs UI.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-display.org
|
||||
;; ~/src/hamacs/ha-display.org
|
||||
;; Using `find-file-at-point', and tangle the file to recreate this one .
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -228,7 +228,8 @@ I probably don't need to have such a ranking system, as chances are good I have
|
|||
(or
|
||||
(seq-first
|
||||
(seq-filter (lambda (font) (when (x-list-fonts font) font))
|
||||
'("SN Pro" ; https://supernotes.app/open-source/sn-pro
|
||||
'("Atkinson Hyperlegible"
|
||||
"SN Pro" ; https://supernotes.app/open-source/sn-pro
|
||||
"Literata" ; Clean, readable with litagures
|
||||
;; Next best can be downloaded here:
|
||||
;; https://fontesk.com/xcharter-typeface/
|
||||
|
@ -372,7 +373,7 @@ Most of the time, Emacs is on my desk is a darkened room, so I choose the dark t
|
|||
(load-theme 'doom-wilmersdorf t)
|
||||
(ignore-errors
|
||||
;; TODO: File in progress!
|
||||
(load-file "~/other/hamacs/ha-theme-dark.el"))
|
||||
(load-file "~/src/hamacs/ha-theme-dark.el"))
|
||||
(ha-word-processor-fonts))
|
||||
#+end_src
|
||||
|
||||
|
@ -473,13 +474,14 @@ Display these two symbols as one:
|
|||
#+end_src
|
||||
|
||||
And turn the prettifier on:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(global-prettify-symbols-mode 1)
|
||||
#+end_src
|
||||
|
||||
In Emacs 28.1, we have better Unicode 14 support. Which means, we need to install [[https://github.com/googlefonts/noto-emoji][Noto Color Emoji]]. My systems, seems to work fine, but I’m leaving this code here in case I have issues, as I might use what Apple supplies when on a Mac (thanks [[http://xahlee.info/emacs/emacs/emacs_list_and_set_font.html][Xah Lee]]):
|
||||
#+begin_src emacs-lisp
|
||||
;; set font for symbols
|
||||
Also, we need a font for the symbols, and both Apple and Linux supplies different ones:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(set-fontset-font t 'symbol
|
||||
(cond
|
||||
((ha-running-on-macos?)
|
||||
|
@ -489,19 +491,28 @@ In Emacs 28.1, we have better Unicode 14 support. Which means, we need to instal
|
|||
(cond
|
||||
((member "Symbola" (font-family-list)) "Symbola")))))
|
||||
|
||||
#+END_SRC
|
||||
|
||||
In Emacs 28.1, we have better Unicode 14 support. Which means, we need to install either [[https://fonts.google.com/noto/specimen/Noto+Emoji][Noto Emoji]] or [[https://github.com/googlefonts/noto-emoji][Noto Color Emoji]]. Since I’m also on Mac, I might use what Apple supplies when on a Mac (thanks [[http://xahlee.info/emacs/emacs/emacs_list_and_set_font.html][Xah Lee]]):
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
;; set font for emoji (should come after setting symbols)
|
||||
(set-fontset-font t 'emoji
|
||||
(cond
|
||||
((member "Apple Color Emoji" (font-family-list)) "Apple Color Emoji")
|
||||
((member "Noto Color Emoji" (font-family-list)) "Noto Color Emoji")
|
||||
((member "Noto Emoji" (font-family-list)) "Noto Emoji")
|
||||
((member "Symbola" (font-family-list)) "Symbola")))
|
||||
#+end_src
|
||||
|
||||
Test this out: 😄 😱 😸 👸 👽 🙋
|
||||
|
||||
Not use what I'm doing with the [[https://github.com/domtronn/all-the-icons.el][all-the-icons]] package, but the Doom Modeline uses much of this.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package all-the-icons)
|
||||
#+end_src
|
||||
|
||||
*Note:* Install everything with the function, =all-the-icons-install-fonts=.
|
||||
* Ligatures
|
||||
Seems like getting ligatures to work in Emacs has been a Holy Grail. On Mac, I've used special builds that have hacks, but now with Emacs 27 and Harfbuzz, I should be able to get --> to look like it should.
|
||||
|
|
49
ha-email.org
49
ha-email.org
|
@ -19,7 +19,7 @@ A literate configuration file for email using Notmuch.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-email.org
|
||||
;; ~/src/hamacs/ha-email.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -97,7 +97,9 @@ Next, we need some basic configuration settings and some global keybindings:
|
|||
:map notmuch-tree-mode-map
|
||||
("C" . notmuch-mua-new-mail)))
|
||||
#+end_src
|
||||
|
||||
And some leader-based keybindings:
|
||||
|
||||
#+begin_src emacs-lisp :noweb yes
|
||||
(use-package notmuch
|
||||
:config
|
||||
|
@ -105,19 +107,17 @@ And some leader-based keybindings:
|
|||
"a n" '("new mail" . notmuch-retrieve-messages)
|
||||
"a c" '("compose mail" . compose-mail))
|
||||
|
||||
(major-mode-hydra-define notmuch-hello-mode nil
|
||||
(major-mode-hydra-define notmuch-hello-mode (:quit-key "q")
|
||||
("Mail"
|
||||
(("u" notmuch-retrieve-messages "new mail")
|
||||
("m" notmuch "read mail"))
|
||||
"Messages"
|
||||
(("c" notmuch-mua-new-mail "compose")
|
||||
("C" hey-notmuch-reply-later "reply-later"))))
|
||||
|
||||
<<hey-show-keybindings>>
|
||||
<<hey-search-keybindings>>)
|
||||
|
||||
("C" hey-notmuch-reply-later "reply-later")))))
|
||||
#+end_src
|
||||
|
||||
Also, let's do some basic configuration of Emacs' mail system:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(setq mm-text-html-renderer 'shr
|
||||
mail-specify-envelope-from t
|
||||
|
@ -138,6 +138,8 @@ Do I want to sign messages by default? Nope.
|
|||
** Addresses
|
||||
I need to incorporate an address book again, but in the meantime, searching through a history of past email works well enough.
|
||||
#+begin_src emacs-lisp
|
||||
(use-package notmuch
|
||||
:config
|
||||
(setq notmuch-address-selection-function
|
||||
(lambda (prompt collection initial-input)
|
||||
(completing-read prompt
|
||||
|
@ -145,7 +147,7 @@ I need to incorporate an address book again, but in the meantime, searching thro
|
|||
nil
|
||||
t
|
||||
nil
|
||||
'notmuch-address-history)))
|
||||
'notmuch-address-history))))
|
||||
#+end_src
|
||||
** Sending Messages
|
||||
Do I need to set up [[https://marlam.de/msmtp/][MSMTP]]? No, as Notmuch will do that work.
|
||||
|
@ -164,7 +166,7 @@ Using [[https://isync.sourceforge.io/][isync]] (or is it =mbsync=) for mail retr
|
|||
|
||||
There are global settings:
|
||||
#+begin_src conf :tangle ~/.mbsyncrc :noweb yes
|
||||
# Note: We now tangle this file from ~/other/hamacs/ha-email.org
|
||||
# Note: We now tangle this file from ~/src/hamacs/ha-email.org
|
||||
Create Both
|
||||
SyncState *
|
||||
MaxMessages 100
|
||||
|
@ -173,6 +175,7 @@ There are global settings:
|
|||
|
||||
The following section is for my /personal/ (not too general) account.
|
||||
The file generally can have a =Pass= entry for the encrypted passcode, but to show how to connect to more than one accounts, I'm using a GPG daemon:
|
||||
|
||||
#+begin_src conf :tangle ~/.mbsyncrc :noweb yes
|
||||
# PERSONAL ACCOUNT
|
||||
IMAPAccount personal
|
||||
|
@ -252,7 +255,7 @@ The general settings file that goes into =~/.notmuch-config=:
|
|||
|
||||
#+begin_src conf-unix :tangle ~/.notmuch-config
|
||||
# .notmuch-config - Configuration file for the notmuch mail system
|
||||
# Note: We now tangle this file from ~/other/hamacs/ha-email.org
|
||||
# Note: We now tangle this file from ~/src/hamacs/ha-email.org
|
||||
#
|
||||
# For more information about notmuch, see https://notmuchmail.org
|
||||
#+end_src
|
||||
|
@ -326,7 +329,7 @@ Then we need a shell script called when beginning a retrieval, =pre-new= that si
|
|||
|
||||
#+begin_src shell :tangle ~/.mail/.notmuch/hooks/pre-new :shebang "#!/bin/bash"
|
||||
# More info about hooks: https://notmuchmail.org/manpages/notmuch-hooks-5/
|
||||
# Note: We now tangle this file from ~/other/hamacs/ha-email.org
|
||||
# Note: We now tangle this file from ~/src/hamacs/ha-email.org
|
||||
|
||||
echo "Starting not-much 'pre-new' script"
|
||||
|
||||
|
@ -339,7 +342,7 @@ And a =post-new= hook based on a filtering scheme that mimics the Hey.com workfl
|
|||
|
||||
#+begin_src shell :tangle ~/.mail/.notmuch/hooks/post-new :shebang "#!/bin/bash"
|
||||
# Based On: https://gist.githubusercontent.com/frozencemetery/5042526/raw/57195ba748e336de80c27519fe66e428e5003ab8/post-new
|
||||
# Note: We now tangle this file from ~/other/hamacs/ha-email.org
|
||||
# Note: We now tangle this file from ~/src/hamacs/ha-email.org
|
||||
#
|
||||
# Install this by moving this file to <maildir>/.notmuch/hooks/post-new
|
||||
# NOTE: you need to define your maildir in the vardiable nm_maildir (just a few lines below in this script)
|
||||
|
@ -439,6 +442,8 @@ To allow me to keep Vedang's and my code side-by-side in the same Emacs variable
|
|||
A list of pre-defined searches act like "Folder buttons" at the top to quickly see files that match those /buckets/:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package notmuch
|
||||
:config
|
||||
(setq notmuch-saved-searches '((:name "Imbox"
|
||||
:query "tag:inbox AND tag:screened AND tag:unread"
|
||||
:key "i"
|
||||
|
@ -470,7 +475,7 @@ A list of pre-defined searches act like "Folder buttons" at the top to quickly s
|
|||
;; notmuch-saved-searches)
|
||||
(:name "Old Projects"
|
||||
:query "tag:old-project AND NOT tag:unread"
|
||||
:key "X")))
|
||||
:key "X"))))
|
||||
#+end_src
|
||||
** Helper Functions
|
||||
|
||||
|
@ -637,20 +642,24 @@ This means:
|
|||
** Bucket Keybindings
|
||||
A series of keybindings to quickly send messages to one of the pre-defined buckets.
|
||||
#+name: hey-show-keybindings
|
||||
#+begin_src emacs-lisp :tangle no
|
||||
(major-mode-hydra-define notmuch-show-mode nil
|
||||
#+begin_src emacs-lisp
|
||||
(use-package notmuch
|
||||
:config
|
||||
(major-mode-hydra-define notmuch-show-mode (:quit-key "q")
|
||||
("Messages"
|
||||
(("c" notmuch-mua-new-mail "compose")
|
||||
("C" hey-notmuch-reply-later "reply-later"))))
|
||||
|
||||
(define-key notmuch-show-mode-map (kbd "C") 'hey-notmuch-reply-later)
|
||||
(define-key notmuch-show-mode-map (kbd "C") 'hey-notmuch-reply-later))
|
||||
#+end_src
|
||||
|
||||
The bindings in =notmuch-search-mode= are available when looking at a list of messages:
|
||||
|
||||
#+name: hey-search-keybindings
|
||||
#+begin_src emacs-lisp :tangle no
|
||||
(major-mode-hydra-define notmuch-search-mode nil
|
||||
#+begin_src emacs-lisp
|
||||
(use-package notmuch
|
||||
:config
|
||||
(major-mode-hydra-define notmuch-search-mode (:color blue :title "Notmuch")
|
||||
("Mail"
|
||||
(("r" notmuch-search-reply-to-thread "reply")
|
||||
("R" notmuch-search-reply-to-thread-sender "reply-all")
|
||||
|
@ -667,7 +676,7 @@ The bindings in =notmuch-search-mode= are available when looking at a list of me
|
|||
("p" hey-notmuch-move-sender-to-papertrail "send to papertrail")
|
||||
("f" hey-notmuch-move-sender-to-thefeed "send to feed")
|
||||
("C" hey-notmuch-reply-later "reply")
|
||||
("c" notmuch-mua-new-mail) "compose")))
|
||||
("c" notmuch-mua-new-mail "compose"))))
|
||||
|
||||
;; And if I can remember the keybindings...
|
||||
(define-key notmuch-search-mode-map (kbd "r") 'notmuch-search-reply-to-thread)
|
||||
|
@ -683,7 +692,7 @@ The bindings in =notmuch-search-mode= are available when looking at a list of me
|
|||
(define-key notmuch-search-mode-map (kbd "I") 'hey-notmuch-move-sender-to-screened)
|
||||
(define-key notmuch-search-mode-map (kbd "P") 'hey-notmuch-move-sender-to-papertrail)
|
||||
(define-key notmuch-search-mode-map (kbd "f") 'hey-notmuch-move-sender-to-thefeed)
|
||||
(define-key notmuch-search-mode-map (kbd "C") 'hey-notmuch-reply-later)
|
||||
(define-key notmuch-search-mode-map (kbd "C") 'hey-notmuch-reply-later))
|
||||
#+end_src
|
||||
** Org Integration
|
||||
The gods ordained that Mail and Org should dance together, so step one is composing mail with org:
|
||||
|
|
|
@ -18,7 +18,7 @@ A literate programming file for configuring the Emacs Shell.
|
|||
;; While obvious, GNU Emacs does not include this file or project.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard.abrams/other/hamacs/ha-eshell.org
|
||||
;; ~/src/hamacs/ha-eshell.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for configuring Evil mode in Emacs.
|
|||
;; While obvious, GNU Emacs does not include this file or project.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard.abrams/other/hamacs/ha-evil.org
|
||||
;; ~/src/hamacs/ha-evil.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for configuring =elfeed= in Emacs.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-feed-reader.org
|
||||
;; ~/src/hamacs/ha-feed-reader.org
|
||||
;; Using `find-file-at-point', and tangle the file to recreate this one .
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for defining leaders with general
|
|||
;; While obvious, GNU Emacs does not include this file or project.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard.abrams/other/hamacs/ha-leader.org
|
||||
;; ~/src/hamacs/ha-leader.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -41,7 +41,7 @@ I'm not trying an experiment where specially-placed function keys on my fancy er
|
|||
:states '(normal visual motion)
|
||||
:keymaps 'override
|
||||
:prefix "SPC"
|
||||
:non-normal-prefix "M-SPC"
|
||||
:non-normal-prefix "s-SPC"
|
||||
:global-prefix "<f13>")
|
||||
|
||||
(general-create-definer ha-local-leader
|
||||
|
@ -195,7 +195,7 @@ And ways to load my tangled org-files:
|
|||
"h h" '(:ignore t :which-key "hamacs")
|
||||
"h h f" '("features" . ha-hamacs-features)
|
||||
"h h e" '("edit" . ha-hamacs-find-file)
|
||||
"h h j" `("heading jump" . ,(lambda () (interactive) (ha-hamacs-edit-file-heading "~/other/hamacs")))
|
||||
"h h j" `("heading jump" . ,(lambda () (interactive) (ha-hamacs-edit-file-heading "~/src/hamacs")))
|
||||
"h h h" '("reload" . ha-hamacs-load)
|
||||
"h h a" '("reload all" . ha-hamacs-reload-all)
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming configuration file for IRC communiction.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-irc.org
|
||||
;; ~/src/hamacs/ha-irc.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file of functions for formatting Emacs text and code into
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/org-clipboard.org
|
||||
;; ~/src/hamacs/org-clipboard.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -18,8 +18,10 @@ A literate programming configuration file for extending the Journaling capabilit
|
|||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/org-journaling.org
|
||||
;; ~/src/hamacs/org-journaling.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -72,7 +74,7 @@ And pull ‘er up:
|
|||
|
||||
This depends on the following [[file:~/.doom.d/snippets/org-journal-mode/__journal][snippet/template file]]:
|
||||
|
||||
#+begin_src snippet :tangle ~/other/hamacs/templates/journal
|
||||
#+begin_src snippet :tangle ~/src/hamacs/templates/journal
|
||||
#+title: Journal Entry- `(ha-journal-file-datestamp)`
|
||||
|
||||
$0
|
||||
|
@ -81,7 +83,7 @@ $0
|
|||
And the code to connect that template to those files:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(ha-auto-insert-file (rx "journal/" (regexp org-journal-rx)) "journal"))
|
||||
(ha-auto-insert-file (rx "journal/" (regexp org-journal-rx)) "journal")
|
||||
#+END_SRC
|
||||
|
||||
Note that when I create a new journal entry, I want a title that should insert a date to match the file's name, not necessarily the current date (see below).
|
||||
|
@ -122,6 +124,7 @@ Capturing a task (that when uncompleted, would then spillover to following days)
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(defun org-journal-find-location ()
|
||||
"Create or load a new journal buffer. Used for `org-capture'."
|
||||
(org-journal-new-entry)
|
||||
(goto-char (point-max)))
|
||||
|
||||
|
@ -166,6 +169,8 @@ Given this splitter function, we create a function that takes some sort of opera
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(defun find-file-number-change (f)
|
||||
"Return a filename based on applying F to current buffer.
|
||||
Where F would be something like `1+' or `1-'."
|
||||
(let* ((filename (buffer-file-name))
|
||||
(parts (split-string-with-number
|
||||
(file-name-base filename)))
|
||||
|
@ -181,9 +186,8 @@ And this allows us to create two simple functions that can load the "next" and "
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(defun find-file-increment ()
|
||||
"Takes the current buffer, and loads the file that is 'one
|
||||
more' than the file contained in the current buffer. This
|
||||
requires that the current file contain a number that can be
|
||||
"Load file that is _one more_ than the file in current buffer.
|
||||
This requires that the current file contain a number that can be
|
||||
incremented."
|
||||
(interactive)
|
||||
(find-file (find-file-number-change '1+)))
|
||||
|
@ -191,9 +195,8 @@ And this allows us to create two simple functions that can load the "next" and "
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(defun find-file-decrement ()
|
||||
"Takes the current buffer, and loads the file that is 'one
|
||||
less' than the file contained in the current buffer. This
|
||||
requires that the current file contain a number that can be
|
||||
"Load file that is _one less_ than the file in current buffer.
|
||||
This requires that the current file contain a number that can be
|
||||
decremented."
|
||||
(interactive)
|
||||
(find-file (find-file-number-change '1-)))
|
||||
|
|
|
@ -26,7 +26,7 @@ A literate programming file for literate programming in Emacs Org Files.
|
|||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original
|
||||
;; literate file at:
|
||||
;; /home/howard/other/hamacs/ha-org-literate.org
|
||||
;; ~/src/hamacs/ha-org-literate.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<svg xmlns='http://www.w3.org/2000/svg' class="pikchr" viewBox="0 0 260.64 76.32">
|
||||
<path d="M2.16,38.16L74.16,38.16" style="fill:none;stroke-width:2.16;stroke:rgb(255,255,255);" />
|
||||
<path d="M74.16,74.16L182.16,74.16L182.16,2.16L74.16,2.16Z" style="fill:none;stroke-width:2.16;stroke:rgb(255,255,255);" />
|
||||
<text x="128.16" y="28.08" text-anchor="middle" fill="rgb(255,255,255)" dominant-baseline="central">Hello,</text>
|
||||
<text x="128.16" y="48.24" text-anchor="middle" fill="rgb(255,255,255)" dominant-baseline="central">World!</text>
|
||||
<polygon points="254.16,38.16 242.64,42.48 242.64,33.84" style="fill:rgb(255,255,255)"/>
|
||||
<path d="M182.16,38.16L248.4,38.16" style="fill:none;stroke-width:2.16;stroke:rgb(255,255,255);" />
|
||||
<path d="M2.16,38.16L74.16,38.16" style="fill:none;stroke-width:2.16;stroke:rgb(238,238,238);" />
|
||||
<path d="M74.16,74.16L182.16,74.16L182.16,2.16L74.16,2.16Z" style="fill:none;stroke-width:2.16;stroke:rgb(238,238,238);" />
|
||||
<text x="128.16" y="28.08" text-anchor="middle" fill="rgb(238,238,238)" dominant-baseline="central">Hello,</text>
|
||||
<text x="128.16" y="48.24" text-anchor="middle" fill="rgb(238,238,238)" dominant-baseline="central">World!</text>
|
||||
<polygon points="254.16,38.16 242.64,42.48 242.64,33.84" style="fill:rgb(238,238,238)"/>
|
||||
<path d="M182.16,38.16L248.4,38.16" style="fill:none;stroke-width:2.16;stroke:rgb(238,238,238);" />
|
||||
</svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 733 B After Width: | Height: | Size: 733 B |
|
@ -19,7 +19,7 @@ A literate programming file for publishing my website using org.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/org-publishing.org
|
||||
;; ~/src/hamacs/org-publishing.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -40,7 +40,12 @@ While the following packages come with Emacs, they aren't necessarily loaded:
|
|||
Render my code with my font colors:
|
||||
|
||||
#+begin_src emacs-lisp :results silent
|
||||
(use-package htmlize)
|
||||
(use-package htmlize
|
||||
:conf
|
||||
;; But I turn the source code coloring off to use a CSS stylesheet I
|
||||
;; control, as otherwise, switching between dark and light themes
|
||||
;; make the code difficult to read:
|
||||
(setq org-html-htmlize-output-type 'css))
|
||||
#+end_src
|
||||
|
||||
Also, we need Jack, and his HTML prowess:
|
||||
|
@ -132,7 +137,10 @@ My main blog made up a collection of org files:
|
|||
(:link (@ :rel "shortcut icon" :href "/img/dragon-head.svg"))
|
||||
(:link (@ :rel "icon" :href "/img/dragon.svg"))
|
||||
(:link (@ :rel "me" :href "https://emacs.ch/@howard"))
|
||||
(:meta (@ :http-equiv "X-Clacks-Overhead" :content "GNU Terry Pratchett"))))))
|
||||
(:meta (@ :http-equiv "X-Clacks-Overhead" :content "Darol Allen"))
|
||||
(:meta (@ :http-equiv "X-Clacks-Overhead" :content "George Vanecek"))
|
||||
(:meta (@ :http-equiv "X-Clacks-Overhead" :content "Rick Cooper"))
|
||||
(:meta (@ :http-equiv "X-Clacks-Overhead" :content "Terry Pratchett"))))))
|
||||
#+end_src
|
||||
|
||||
Why not break out the images and other static files into a separate project:
|
||||
|
@ -208,7 +216,7 @@ As above, we can separate the publishing of the images and other static files:
|
|||
`("tech-notes-static"
|
||||
:base-directory "~/technical/"
|
||||
:base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|svg"
|
||||
:publishing-directory ,(concat org-mode-publishing-directory "/other/")
|
||||
:publishing-directory ,(concat org-mode-publishing-directory "/src/")
|
||||
:recursive t
|
||||
:publishing-function org-publish-attachment))
|
||||
#+end_src
|
||||
|
@ -217,7 +225,7 @@ I’ve been committing my literate-style Emacs configuration for years now, and
|
|||
#+begin_src emacs-lisp
|
||||
(add-to-list 'org-publish-project-alist
|
||||
`("hamacs"
|
||||
:base-directory "~/other/hamacs"
|
||||
:base-directory "~/src/hamacs"
|
||||
:publishing-directory ,(concat org-mode-publishing-directory "hamacs/")
|
||||
:publishing-function org-html-publish-to-html
|
||||
:recursive t
|
||||
|
@ -238,7 +246,7 @@ I’ve been committing my literate-style Emacs configuration for years now, and
|
|||
|
||||
(add-to-list 'org-publish-project-alist
|
||||
`("hamacs-static"
|
||||
:base-directory "~/other/hamacs"
|
||||
:base-directory "~/src/hamacs"
|
||||
:base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|svg"
|
||||
:publishing-directory ,(concat org-mode-publishing-directory "hamacs")
|
||||
:recursive t
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate program for configuring org files for work-related notes.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/org-sprint.org
|
||||
;; ~/src/hamacs/org-sprint.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -30,7 +30,7 @@ At the beginning of each Sprint, I create a new org file dedicated to it. This w
|
|||
|
||||
I want a single keybinding that always displays the current Sprint note file, regardless of the Sprint. This means, I need to have functions that can calculate what this is.
|
||||
|
||||
To have the Org Capture features to be able to write to correct locations in the current file, I need each file to follow a particular format. I create a [[file:snippets/org-mode/__sprint.org][sprint note template]] that will be automatically expanded with a new sprint.
|
||||
To have the Org Capture features to be able to write to correct locations in the current file, I need each file to follow a particular format. I create a [[file:templates/sprint.org][sprint note template]] that will be automatically expanded with a new sprint.
|
||||
|
||||
This template needs the following functions:
|
||||
- =sprint-current-name= to be both the numeric label as well as the nickname
|
||||
|
|
|
@ -20,7 +20,7 @@ A literate programming file for making Org file more readable.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-org-word-processor.org
|
||||
;; ~/src/hamacs/ha-org-word-processor.org
|
||||
;; Using `find-file-at-point', and tangle the file to recreate this one .
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -275,8 +275,7 @@ Well, using the =composition-function-table=, we can finally get some ligatures
|
|||
#+end_src
|
||||
This is now fine and ffantastic!
|
||||
* Org Beautify
|
||||
I really want to use the Org Beautify package, but it overrides my darker themes (and all I really want is headlines to behave).
|
||||
|
||||
The Org Beautify package, overrides my darker themes, and headlines should behave, so I manually set these:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun ha-word-processor-fonts ()
|
||||
|
@ -301,13 +300,9 @@ I really want to use the Org Beautify package, but it overrides my darker themes
|
|||
(dolist (face '(org-block org-code org-verbatim org-table org-drawer
|
||||
org-table org-formula org-special-keyword org-block
|
||||
org-property-value org-document-info-keyword))
|
||||
(set-face-attribute face nil :inherit 'fixed-pitch :height 0.9))
|
||||
(set-face-attribute face nil :inherit 'fixed-pitch :height 'unspecified))
|
||||
|
||||
;; While we are at it, let’s make sure the code blocks are using my fixed with font:
|
||||
(set-face-attribute 'org-table nil :height 1.0)
|
||||
(set-face-attribute 'org-formula nil :height 1.0)
|
||||
|
||||
(set-face-attribute 'org-block-begin-line nil :height 0.9)
|
||||
(set-face-attribute 'org-block-begin-line nil :height 0.85)
|
||||
(set-face-attribute 'org-block-end-line nil :height 0.8)
|
||||
|
||||
(set-face-attribute 'org-drawer nil :height 0.8)
|
||||
|
@ -390,53 +385,6 @@ However, I'm just going to have to write a function to clean this.
|
|||
(replace-match (match-string 1) nil :no-error)))
|
||||
#+end_src
|
||||
Now that is some complicated regular expressions.
|
||||
* Presentations
|
||||
Used to use [[https://github.com/takaxp/org-tree-slide][org-tree-slide]] for showing org files as presentations. Converted to use [[https://github.com/rlister/org-present][org-present]]. I love the /hooks/ as that makes it easier to pull out much of my =demo-it= configuration. My concern with =org-present= is that it only jumps from one top-level to another top-level header.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package org-present
|
||||
:config
|
||||
(defvar ha-org-present-mode-line mode-line-format "Cache previous mode-line format state")
|
||||
|
||||
(defun ha-org-blocks-hide-headers ()
|
||||
"Make the headers and other block metadata invisible.
|
||||
See `ha-org-blocks-show-headers'."
|
||||
(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 (1+ (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))
|
||||
|
||||
(defun ha-org-present-start ()
|
||||
(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)
|
||||
(setq mode-line-format nil)
|
||||
(sit-for 3) ; Wait for the cursor to stop blinking
|
||||
(org-present-hide-cursor))
|
||||
|
||||
(defun ha-org-present-end ()
|
||||
(org-present-small)
|
||||
(ha-org-blocks-show-headers)
|
||||
(setq mode-line-format ha-org-present-mode-line)
|
||||
(org-present-show-cursor))
|
||||
|
||||
:hook
|
||||
(org-present-mode . ha-org-present-start)
|
||||
(org-present-mode-quit . ha-org-present-end))
|
||||
#+end_src
|
||||
* Technical Artifacts :noexport:
|
||||
Note, according to [[https://www.reddit.com/r/emacs/comments/vahsao/orgmode_use_capitalized_property_keywords_or/][this discussion]] (and especially [[https://scripter.co/org-keywords-lower-case/][this essay]]), I’m switching over to lower-case version of org properties. Using this helper function:
|
||||
|
||||
|
|
124
ha-org.org
124
ha-org.org
|
@ -3,7 +3,7 @@
|
|||
#+date: 2020-09-18
|
||||
#+tags: emacs org
|
||||
#+startup: inlineimages
|
||||
#+lastmod: [2024-09-02 Mon]
|
||||
#+lastmod: [2024-10-25 Fri]
|
||||
|
||||
A literate programming file for configuring org-mode and those files.
|
||||
|
||||
|
@ -560,7 +560,7 @@ Of course, since we are dealing with Emacs, any good idea will be assimilated. J
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package pikchr-mode
|
||||
:straight (:local-repo "~/other/pikchr-mode")
|
||||
:straight (:local-repo "~/src/pikchr-mode")
|
||||
:custom
|
||||
(pikchr-executable "~/bin/pikchr"))
|
||||
#+end_src
|
||||
|
@ -586,7 +586,37 @@ And this example shows off the syntax colorization:
|
|||
For the results:
|
||||
#+ATTR_HTML: :width 300 :background white
|
||||
[[file:ha-org-pikchr-02.svg]]
|
||||
*** Mermaid
|
||||
At work, I’ve been integrating [[https://mermaidjs.github.io/][Mermaid]] into our documentation, =foobar=.
|
||||
|
||||
Assuming we have installed the [[https://github.com/mermaid-js/mermaid-cli][Mermaid CLI]]:
|
||||
|
||||
#+BEGIN_SRC sh
|
||||
npm install -g @mermaid-js/mermaid-cli
|
||||
#+END_SRC
|
||||
|
||||
We edit the code with [[https://github.com/abrochard/mermaid-mode][mermaid-mode]]:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(use-package mermaid-mode
|
||||
:config
|
||||
(setq mermaid-mmdc-location "/opt/homebrew/bin/mmdc"))
|
||||
#+END_SRC
|
||||
|
||||
We can make Mermaid diagrams in Emacs Org files using [[https://github.com/arnm/ob-mermaid][ob-mermaid]]:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(use-package ob-mermaid
|
||||
:config
|
||||
(setq ob-mermaid-cli-path "/opt/homebrew/bin/mmdc"))
|
||||
#+END_SRC
|
||||
|
||||
#+BEGIN_SRC mermaid :file ha-org-mermaid.png :theme dark :background-color transparent
|
||||
sequenceDiagram
|
||||
A-->B: Works!
|
||||
#+END_SRC
|
||||
|
||||
[[file:ha-org-mermaid.png]]
|
||||
*** Next Image
|
||||
When I create images or other artifacts that I consider /part/ of the org document, I want to have them based on the org file, but with a prepended number. Keeping track of what numbers are now free is difficult, so for a /default/ let's figure it out:
|
||||
|
||||
|
@ -687,6 +717,7 @@ Global keybindings available to all file buffers:
|
|||
|
||||
"o n" '(:ignore t :which-key "narrow")
|
||||
"o n s" '("subtree" . org-narrow-to-subtree)
|
||||
"o n S" '("tree -> win" . org-tree-to-indirect-buffer)
|
||||
"o n b" '("block" . org-narrow-to-block)
|
||||
"o n e" '("element" . org-narrow-to-element)
|
||||
"o n w" '("widen" . widen))
|
||||
|
@ -796,7 +827,11 @@ I've been working on my own [[http://www.howardism.org/Technical/Emacs/focused-w
|
|||
:config
|
||||
(ha-leader
|
||||
"o f" '("begin focus" . ha-focus-begin)
|
||||
"o F" '("break focus" . ha-focus-break)))
|
||||
"o F" '("break focus" . ha-focus-break))
|
||||
:bind
|
||||
(("<f12>" . ha-focus-begin)
|
||||
("S-<f12>" . ha-focus-interrupt)
|
||||
("s-<f12>" . ha-focus-timer-left)))
|
||||
#+end_src
|
||||
** Spell Checking
|
||||
Let's hook some spell-checking into org files, and actually all text files. I’m making this particularly delicious.
|
||||
|
@ -908,6 +943,10 @@ Once in the dictionary buffer, acquiesce these keybindings:
|
|||
Also note that the dictionary has links to other pages, so ~n~ and ~TAB~ jumps to the next link and ~RET~ opens that link.
|
||||
** Grammar and Prose Linting
|
||||
Flagging cliches, weak phrasing and other poor grammar choices.
|
||||
|
||||
We are trying a lot of checkers, so we need to /chain/ them with a call to =flycheck-add-next-checker=:
|
||||
|
||||
=write-good= —> =proselint= —> =textlint= —> =languagetool=?
|
||||
*** Writegood
|
||||
The [[https://github.com/bnbeckwith/writegood-mode][writegood-mode]] is effective at highlighting passive and weasel words.
|
||||
#+begin_src emacs-lisp
|
||||
|
@ -948,6 +987,10 @@ With overlapping goals to =write-good=, the [[https://github.com/amperser/prosel
|
|||
#+begin_src sh
|
||||
brew install proselint
|
||||
#+end_src
|
||||
And on Linux:
|
||||
#+BEGIN_SRC sh
|
||||
sudo apt install python3-proselint
|
||||
#+END_SRC
|
||||
|
||||
Next, create a configuration file, =~/.config/proselint/config= file, to turn on/off checks:
|
||||
#+begin_src js :tangle ~/.config/proselint/config.json :mkdirp yes
|
||||
|
@ -971,17 +1014,17 @@ And tell [[https://www.flycheck.org/][flycheck]] to use this:
|
|||
*** Textlint
|
||||
The [[https://textlint.github.io/][textlint]] project comes with =flycheck=, as long as there is an executable:
|
||||
#+begin_src sh :results silent
|
||||
npm install -g textlint
|
||||
sudo npm install -g textlint
|
||||
# And all the rules
|
||||
npm install -g textlint-rule-alex
|
||||
npm install -g textlint-rule-diacritics
|
||||
npm install -g textlint-rule-en-max-word-count
|
||||
npm install -g textlint-rule-max-comma
|
||||
npm install -g textlint-rule-no-start-duplicated-conjunction
|
||||
npm install -g textlint-rule-period-in-list-item
|
||||
npm install -g textlint-rule-stop-words
|
||||
npm install -g textlint-rule-terminology
|
||||
npm install -g textlint-rule-unexpanded-acronym
|
||||
sudo npm install -g textlint-rule-alex
|
||||
sudo npm install -g textlint-rule-diacritics
|
||||
sudo npm install -g textlint-rule-en-max-word-count
|
||||
sudo npm install -g textlint-rule-max-comma
|
||||
sudo npm install -g textlint-rule-no-start-duplicated-conjunction
|
||||
sudo npm install -g textlint-rule-period-in-list-item
|
||||
sudo npm install -g textlint-rule-stop-words
|
||||
sudo npm install -g textlint-rule-terminology
|
||||
sudo npm install -g textlint-rule-unexpanded-acronym
|
||||
#+end_src
|
||||
I create a configuration file in my home directory:
|
||||
#+begin_src js :tangle ~/.textlintrc
|
||||
|
@ -1003,19 +1046,52 @@ I create a configuration file in my home directory:
|
|||
}
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Add =textlint= to the /chain/ for Org files:
|
||||
#+begin_src emacs-lisp
|
||||
(use-package flycheck
|
||||
:config
|
||||
(setq flycheck-textlint-config (format "%s/.textlintrc" (getenv "HOME")))
|
||||
(flycheck-add-next-checker 'proselint 'textlint))
|
||||
(flycheck-add-next-checker 'proselint 'textlint t))
|
||||
#+end_src
|
||||
|
||||
*** Language Tool
|
||||
Another flycheck feature is to use [[http://languagetool.org][LanguageTool]] connection to [[https://github.com/emacs-languagetool/flycheck-languagetool][flycheck-languagetool]]:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp :tangle no
|
||||
(use-package flycheck-languagetool
|
||||
:ensure t
|
||||
:hook (text-mode . flycheck-languagetool-setup)
|
||||
:init
|
||||
(setq flycheck-languagetool-server-jar (expand-file-name "~/other/LanguageTool/languagetool-server.jar")
|
||||
flycheck-languagetool-server-args (expand-file-name "~/.config/languagetool/config.properties")))
|
||||
#+END_SRC
|
||||
|
||||
And connect it to the chain:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp :tangle no
|
||||
(use-package flycheck
|
||||
:config (flycheck-add-next-checker 'textlint 'languagetool t)
|
||||
|
||||
;; May have to specify a Java on one of my Mac machines:
|
||||
(when (file-exists-p "/opt/homebrew/opt/openjdk")
|
||||
(add-to-list 'exec-path "/opt/homebrew/opt/openjdk/bin")))
|
||||
#+END_SRC
|
||||
|
||||
This check complains about whitespace in Org files (duh), so let’s create a configuration file where we can disable that rule (and any other we can require):
|
||||
|
||||
#+BEGIN_SRC conf :tangle ~/.config/languagetool/config.properties :mkdirp ~/.config/languagetool
|
||||
disabledRuleIds: WHITESPACE
|
||||
#+END_SRC
|
||||
|
||||
Gotta admit that Language Tool doesn’t seem to help much. $ 100 ?
|
||||
** Perfect Sentence
|
||||
Chris Malorana’s [[https://www.youtube.com/watch?v=E-yk_V5TnNU][video tutorial]] demonstrates the ability to extrude a single sentence into another buffer, edit different versions of that sentence, and replace one version into the original buffer. Similar to how org-mode edits blocks.
|
||||
Chris Malorana’s [[https://www.youtube.com/watch?v=E-yk_V5TnNU][video tutorial]] demonstrates the ability to extrude a single sentence into another buffer, edit different versions of that sentence, and replace one version into the original buffer. For instance, how org-mode edits blocks.
|
||||
|
||||
The idea is based on Jordan Peterson's writing app, Essay. Love the idea, and thought I might work on it. The difference is that I want my version more resilient and not as dependent on the context.
|
||||
Malorana based this idea on Jordan Peterson's writing app, [[https://essay.app/guide][Essay]]. Thought I might work on it, but I want my version more resilient and not as dependent on the context.
|
||||
|
||||
When we create a new buffer, we set the following /buffer-local/ variables, so we know where to return:
|
||||
|
||||
When we create a new buffer, we want a number of /buffer-local/ variables, so that we know where to return:
|
||||
#+begin_src emacs-lisp
|
||||
(defvar-local ha-sentence-buffer nil
|
||||
"The name of the buffer to return when completed.")
|
||||
|
@ -1026,6 +1102,7 @@ The idea is based on Jordan Peterson's writing app, Essay. Love the idea, and t
|
|||
#+end_src
|
||||
|
||||
My first thought is how to select the sentence. Sure, sometimes that should be the /region/, but we can also use the help:bounds-of-thing-at-point to define the start and the end of the current sentence:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun ha-sentence--select-region (type-of-thing &optional start end)
|
||||
"Return a tuple of the start and end of the selected sentence."
|
||||
|
@ -1034,17 +1111,19 @@ My first thought is how to select the sentence. Sure, sometimes that should be t
|
|||
((and start end) (cons start end))
|
||||
(t (bounds-of-thing-at-point type-of-thing))))
|
||||
#+end_src
|
||||
In the original buffer, we want to edit a /sentence/, but in the editing buffer, a single sentence may expand to multiple sentences, so we need to change whether we select a ='sentence= or a ='defun= (for a paragraph).
|
||||
|
||||
In the original buffer, we want to edit a /sentence/, but in the editing buffer, a single sentence may expand to more than one, so we need to change whether we select a ='sentence= or a ='defun= (for a paragraph).
|
||||
|
||||
With this function, we can call [[help:cl-destructuring-bind][destructuring-bind]] to define what section we want to edit by assigning the =start= and =end= values. Now we create another buffer window, set the local variables, and insert the region/sentence we requested:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun ha-sentence-break (&optional start end)
|
||||
"Break a sentence out and work it in a new buffer.
|
||||
A sentence chosen is based on the location of a point,
|
||||
We base the chosen sentence chosen on the location of a point,
|
||||
or the active region."
|
||||
(interactive)
|
||||
(cl-destructuring-bind (start . end) (ha-sentence--select-region 'sentence start end)
|
||||
(cl-destructuring-bind (start . end)
|
||||
(ha-sentence--select-region 'sentence start end)
|
||||
(let ((orig-mode major-mode)
|
||||
(orig-buffer (current-buffer))
|
||||
(orig-sentence (buffer-substring-no-properties start end)))
|
||||
|
@ -1065,7 +1144,10 @@ With this function, we can call [[help:cl-destructuring-bind][destructuring-bind
|
|||
(kill-new orig-sentence))))
|
||||
#+end_src
|
||||
|
||||
With the new buffer displayed, the sentence to edit is shown, and the idea is to write different versions of that sentence. When we have the version we like, we hit ~C-c C-c~ which calls [[help:ha-sentence-choose][ha-sentence-choose]] /to choose/ the version that replaces the old one. But what if a sentence becomes multiple sentences? Well, in that case, we need to select the text before hitting the ~C-c C-c~ sequence. The buffer-local variables tell us which buffer to return, and what text to replace.
|
||||
With the new buffer displayed, we show the sentence to edit, with the idea to write different versions of that sentence. When we have the version we like, we hit ~C-c C-c~ which calls [[help:ha-sentence-choose][ha-sentence-choose]] /to choose/ the version that replaces the old one. But what if, during the editing process, we create more than one sentence?
|
||||
|
||||
In that case, we need to select the text before hitting the ~C-c C-c~ sequence. The buffer-local variables tell us which buffer to return, and what text to replace.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun ha-sentence-choose (&optional start end)
|
||||
"Choose a sentence and go back to the other window."
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming version for Emacs code to generate and store passwords.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-passwords.org
|
||||
;; ~/src/hamacs/ha-passwords.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ Configuring Ansible and YAML
|
|||
;; While obvious, GNU Emacs does not include this file
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard.abrams/other/hamacs/ha-programming-ansible.org
|
||||
;; ~/src/hamacs/ha-programming-ansible.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for programming in Clojure.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-programming-clojure.org
|
||||
;; ~/src/hamacs/ha-programming-clojure.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for configuring Emacs for Lisp programming.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard.abrams/other/hamacs/ha-lisp.org
|
||||
;; ~/src/hamacs/ha-lisp.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -18,7 +18,7 @@ A literate programming file for configuring Emacs to use [[https://www.haskell.o
|
|||
;; While obvious, GNU Emacs does not include this file or project.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-programming-haskell.org
|
||||
;; ~/src/hamacs/ha-programming-haskell.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -18,7 +18,7 @@ A literate programming file for integrating the [[https://ocaml.org/][OCaml prog
|
|||
;; While obvious, GNU Emacs does not include this file or project.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-programming-ocaml.org
|
||||
;; ~/src/hamacs/ha-programming-ocaml.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for configuring Python.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-programming-python.org
|
||||
;; ~/src/hamacs/ha-programming-python.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for configuring Emacs to support the Ruby programmin
|
|||
;; While obvious, GNU Emacs does not include this file or project.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard.abrams/other/hamacs/ha-programming-ruby.org
|
||||
;; ~/src/hamacs/ha-programming-ruby.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -48,8 +48,8 @@ While we /could/ use a large project templating system, I keep it simple. For ea
|
|||
#+end_example
|
||||
For instance:
|
||||
#+begin_src sh
|
||||
mkdir -p ~/other/ruby-xp # Change me
|
||||
cd ~/other/ruby-xp
|
||||
mkdir -p ~/src/ruby-xp # Change me
|
||||
cd ~/src/ruby-xp
|
||||
mkdir -p lib test
|
||||
#+end_src
|
||||
|
||||
|
@ -66,7 +66,7 @@ Now, do the following steps.
|
|||
#+end_src
|
||||
|
||||
3. Create a minimal =Gemfile=:
|
||||
#+begin_src ruby :tangle ~/other/ruby-xp/Gemfile
|
||||
#+begin_src ruby :tangle ~/src/ruby-xp/Gemfile
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rake', group: :development
|
||||
|
@ -80,7 +80,7 @@ Now, do the following steps.
|
|||
#+end_src
|
||||
|
||||
5. Create a minimal =Rakefile=:
|
||||
#+begin_src ruby :tangle ~/other/ruby-xp/Rakefile
|
||||
#+begin_src ruby :tangle ~/src/ruby-xp/Rakefile
|
||||
task default: %w[test]
|
||||
|
||||
task :run do
|
||||
|
@ -93,7 +93,7 @@ Now, do the following steps.
|
|||
#+end_src
|
||||
|
||||
6. Create the first program:
|
||||
#+begin_src ruby :tangle ~/other/ruby-xp/lib/hello_world.rb
|
||||
#+begin_src ruby :tangle ~/src/ruby-xp/lib/hello_world.rb
|
||||
# frozen_string_literal: true
|
||||
|
||||
# The basic greeting class
|
||||
|
@ -117,7 +117,7 @@ Now, do the following steps.
|
|||
#+end_src
|
||||
|
||||
7. Create the first test:
|
||||
#+begin_src ruby :tangle ~/other/ruby-xp/test/hello_world_test.rb
|
||||
#+begin_src ruby :tangle ~/src/ruby-xp/test/hello_world_test.rb
|
||||
require 'test/unit'
|
||||
require_relative '../lib/hello_world'
|
||||
|
||||
|
@ -142,7 +142,7 @@ For projects from work, I have found we need to isolate the Ruby environment. On
|
|||
#+end_src
|
||||
|
||||
A better solution is to create a container to hold the Ruby environment. Begin with a =Dockerfile=:
|
||||
#+begin_src dockerfile :tangle ~/other/ruby-xp/Dockerfile
|
||||
#+begin_src dockerfile :tangle ~/src/ruby-xp/Dockerfile
|
||||
## -*- dockerfile-image-name: "ruby-xp" -*-
|
||||
FROM alpine:3.13
|
||||
|
||||
|
@ -177,7 +177,7 @@ A better solution is to create a container to hold the Ruby environment. Begin w
|
|||
#+end_src
|
||||
|
||||
Next, create a =.envrc= in the project’s directory:
|
||||
#+begin_src sh :tangle ~/other/ruby-xp/.envrc
|
||||
#+begin_src sh :tangle ~/src/ruby-xp/.envrc
|
||||
CONTAINER_NAME=ruby-xp:latest
|
||||
CONTAINER_WRAPPERS=(bash ruby irb gem bundle rake solargraph rubocop)
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for configuring Rust with Emacs.
|
|||
;; While obvious, GNU Emacs does not include this file or project.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard.abrams/other/hamacs/ha-programming-rust.org
|
||||
;; ~/src/hamacs/ha-programming-rust.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file configuring Emacs.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; /Users/howard.abrams/other/hamacs/ha-programming-scheme.org
|
||||
;; ~/src/hamacs/ha-programming-scheme.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate programming file for helping me program.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-programming.org
|
||||
;; ~/src/hamacs/ha-programming.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
|
|
@ -19,7 +19,7 @@ A literate configuration for accessing remote systems.
|
|||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
||||
;; ~/other/hamacs/ha-remoting.org
|
||||
;; ~/src/hamacs/ha-remoting.org
|
||||
;; And tangle the file to recreate this one.
|
||||
;;
|
||||
;;; Code:
|
||||
|
@ -296,7 +296,7 @@ Perhaps a Unit test is in order:
|
|||
#+begin_src emacs-lisp :tangle no
|
||||
(ert-deftest ha--terminal-name-from-dir-test ()
|
||||
(should
|
||||
(string= (ha-shell--name-from-dir "~/other/hamacs/") "Terminal: hamacs"))
|
||||
(string= (ha-shell--name-from-dir "~/src/hamacs/") "Terminal: hamacs"))
|
||||
(should
|
||||
(string= (ha-shell--name-from-dir "~/work/foo/bar") "Terminal: foo/bar"))
|
||||
(should
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
# -*- mode: snippet -*-
|
||||
# name: sprint
|
||||
# key: __sprint
|
||||
# --
|
||||
#+TITLE: `(sprint-current-name)`
|
||||
#+AUTHOR: `user-full-name`
|
||||
#+EMAIL: `user-mail-address`
|
||||
#+DATE: `(sprint-date-range)`
|
||||
#+CATEGORY: sprint
|
||||
#+FILETAGS: :work:
|
||||
|
||||
* Work Issues
|
||||
$0
|
||||
|
||||
* Onboarding Work
|
||||
See [[file:Onboarding-Work.org][Onboard-Work]] for all details.
|
||||
|
||||
* Distractions and Support
|
||||
Anything that doesn't fit the above goes here.
|
||||
|
||||
* Meeting Notes :meeting:
|
||||
* Scrum Status :status:
|
||||
|
||||
* Sprint Demonstration
|
||||
New approach for giving presentations. First create [[file:`(file-name-sans-extension (buffer-name))`-demo.org][`(file-name-sans-extension (buffer-name))`-demo.org]], and then add the bits to the code below.
|
||||
|
||||
#+BEGIN_SRC emacs-lisp :results silent
|
||||
(defun org-present-file (filename)
|
||||
(find-file (filename))
|
||||
(delete-other-windows)
|
||||
(org-present))
|
||||
|
||||
(demo-it-create :advanced-mode :single-window
|
||||
(org-present-file "`(file-name-sans-extension (buffer-name))`-demo.org")
|
||||
(org-present-next)
|
||||
(osx-browse-url-forwork "https://...")
|
||||
(demo-it-load-fancy-file "~/work/wpc4/wpc/dashboards/wpc4/hypervisor.yml" :line 116 133)
|
||||
;; ...
|
||||
)
|
||||
#+END_SRC
|
||||
|
||||
Have fun and start the show: =demo-it-start= and hit ~F5~.
|
||||
* Notes for Next Sprint
|
||||
|
||||
|
||||
#+DESCRIPTION: Notes taken during Sprint #`(sprint-number)`
|
||||
#+PROPERTY: header-args: :results drawer :tangle no :eval no-export :comments org
|
||||
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil skip:nil author:nil email:nil creator:nil timestamp:nil ^:nil
|
||||
|
||||
# Local Variables:
|
||||
# eval: (org-content 2)
|
||||
# End:
|
|
@ -1,7 +0,0 @@
|
|||
# -*- mode: snippet -*-
|
||||
# name: example-block
|
||||
# key: <e
|
||||
# --
|
||||
#+begin_example
|
||||
$0
|
||||
#+end_example
|
|
@ -1,7 +0,0 @@
|
|||
# -*- mode: snippet -*-
|
||||
# name: quote-block
|
||||
# key: <q
|
||||
# --
|
||||
#+BEGIN_QUOTE
|
||||
$0
|
||||
#+END_QUOTE
|
Loading…
Reference in a new issue