Compare commits

...

14 commits

Author SHA1 Message Date
Howard Abrams
4629cbf1a0 Fixed issues with my focus mode 2024-10-25 16:22:59 -07:00
Howard Abrams
de7770280a Ignoring my theme for my website and writing the style myself.
Plus a bug fix for mail.
2024-10-20 21:40:36 -07:00
Howard Abrams
f1ddcec3ab Edit an Org section in another buffer 2024-10-19 13:43:11 -07:00
Howard Abrams
db4c460453 Tweaks to the display of Org files 2024-10-19 13:42:17 -07:00
Howard Abrams
bc06c77df5 Added Mermaid diagram support
Work is using Hugo and this is a big partl
2024-10-19 13:41:06 -07:00
Howard Abrams
06643aa146 Connected all the prose linters together
And added the languagetool ... not sure if it adds anything, so I'm
not actually enabling it at this time.
2024-10-19 13:39:45 -07:00
Howard Abrams
3c2c266009 Minor capturing changes 2024-10-19 13:37:45 -07:00
Howard Abrams
b067964930 Trying out a new variable-pitch font
And fixed up my emoji font: 😏
2024-10-19 13:35:37 -07:00
Howard Abrams
6d92980311 Migration from ~/other to ~/src
Why was it any other way?
2024-10-19 13:34:01 -07:00
Howard Abrams
2bd14a876a Create new demonstration code
This replaces demo-it, but I will be bringing some, more general
functions, over from it.
2024-10-19 13:26:27 -07:00
Howard Abrams
990cc577dc Fix annoying bug of possible multiple inserts
Now the sprint and inserts are better.
2024-10-01 15:13:38 -07:00
Howard Abrams
3b1427a8db Switching to a new Mastodon server 2024-10-01 15:13:38 -07:00
Howard Abrams
809a542e6d Fixed a stray paren
And fixed some warnings in the resulting code.
2024-09-28 08:37:22 -07:00
Howard Abrams
ffe662ced0 Get the mail system working again.
Wrapping code in `use-package` expressions instead of `noweb`
references, allows me to execute sections, resulting in
easier-to-maintain code.
2024-09-28 08:35:56 -07:00
41 changed files with 656 additions and 385 deletions

View file

@ -22,7 +22,7 @@ No longer need to install [[https://apps.apple.com/us/app/xcode/id497799835?mt=1
If I want to build from source (and not build from Homebrew), install all the dependencies first, by running:
#+begin_src sh
brew install pkg-config automake texinfo jpeg giflib\
brew install pkg-config automake texinfo jpeg giflib\
libtiff jansson libpng librsvg gnutls cmake
#+end_src

View file

@ -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:

View file

@ -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

View file

@ -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:

View file

@ -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.

View file

@ -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 chats, lets 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-")

View file

@ -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 @@ Wouldnt 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 arent 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

View file

@ -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]] isnt 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 Im 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 Im 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 Im 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 lets 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?

View file

@ -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)

View file

@ -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
View 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))=.
Lets 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? Lets 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= doesnt contain an =:i=, it matches every time when meeting the other conditions.
Lets 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

View file

@ -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 Im 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 Im 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.

View file

@ -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,7 +442,9 @@ 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
(setq notmuch-saved-searches '((:name "Imbox"
(use-package notmuch
:config
(setq notmuch-saved-searches '((:name "Imbox"
:query "tag:inbox AND tag:screened AND tag:unread"
:key "i"
:search-type 'tree)
@ -470,35 +475,35 @@ 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
With good bucket definitions, we should be able to scan the mail quickly and deal with the entire lot of them:
#+begin_src emacs-lisp
(defun hey-notmuch-archive-all ()
(defun hey-notmuch-archive-all ()
"Archive all the emails in the current view."
(interactive)
(notmuch-search-archive-thread nil (point-min) (point-max)))
(defun hey-notmuch-delete-all ()
(defun hey-notmuch-delete-all ()
"Archive all the emails in the current view.
Mark them for deletion by cron job."
Mark them for deletion by cron job."
(interactive)
(notmuch-search-tag-all '("+deleted"))
(hey-notmuch-archive-all))
(defun hey-notmuch-search-delete-and-archive-thread ()
(defun hey-notmuch-search-delete-and-archive-thread ()
"Archive the currently selected thread. Add the deleted tag as well."
(interactive)
(notmuch-search-add-tag '("+deleted"))
(notmuch-search-archive-thread))
(defun hey-notmuch-tag-and-archive (tag-changes &optional beg end)
(defun hey-notmuch-tag-and-archive (tag-changes &optional beg end)
"Prompt the user for TAG-CHANGES.
Apply the TAG-CHANGES to region and also archive all the emails.
When called directly, BEG and END provide the region."
Apply the TAG-CHANGES to region and also archive all the emails.
When called directly, BEG and END provide the region."
(interactive (notmuch-search-interactive-tag-changes))
(notmuch-search-tag tag-changes beg end)
(notmuch-search-archive-thread nil beg end))
@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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)

View file

@ -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:

View file

@ -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:

View file

@ -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-)))

View file

@ -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:

View file

@ -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

View file

@ -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 @@ Ive 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 @@ Ive 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

View file

@ -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

View file

@ -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, lets 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]]), Im switching over to lower-case version of org properties. Using this helper function:

View file

@ -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, Ive 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. Im 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 lets 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 doesnt seem to help much. $ 100 ?
** Perfect Sentence
Chris Maloranas [[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 Maloranas [[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."

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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 projects 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)

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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

View file

@ -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:

View file

@ -1,7 +0,0 @@
# -*- mode: snippet -*-
# name: example-block
# key: <e
# --
#+begin_example
$0
#+end_example

View file

@ -1,7 +0,0 @@
# -*- mode: snippet -*-
# name: quote-block
# key: <q
# --
#+BEGIN_QUOTE
$0
#+END_QUOTE