Skip to content

Commit c4cf169

Browse files
author
Musa Al-hassy
committed
Introduce Hyperbole section
1 parent a5359da commit c4cf169

File tree

3 files changed

+596
-79
lines changed

3 files changed

+596
-79
lines changed

.aspell.en.pws

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
personal_ws-1.1 en 428
1+
personal_ws-1.1 en 431
22
ACSII
33
AST
44
ASTs
@@ -42,6 +42,7 @@ Excerption
4242
Executables
4343
Falah
4444
Fallsview
45+
Fontify
4546
GDoc
4647
Genericity
4748
Gerrit
@@ -329,6 +330,7 @@ overhwheliming
329330
parallelize
330331
parameterisation
331332
parenthesisation
333+
parsers
332334
pointfree
333335
pointwise
334336
polymorphism
@@ -355,6 +357,7 @@ rebased
355357
redistributable
356358
reduct
357359
referentially
360+
regexes
358361
repl
359362
representable
360363
requireds

init.el

Lines changed: 190 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3521,6 +3521,10 @@ Usage:
35213521
(bind-key* "C-c c" (def-capture "Inbox Entry 📩" "Inbox 📩 \t\t\t:inbox:" "* TODO %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n"))
35223522
;; Capture: Now that I know how to query my agenda, how do I get things into it efficiently?:1 ends here
35233523

3524+
# [[file:init.org::*Why the evening ritual reduces anxiety?][Why the evening ritual reduces anxiety?:1]]
3525+
*** End-of-workday Shut-down Ritual: ~C-c r d~ <2025-04-14 Mon 15:30-15:45 +1d>
3526+
# Why the evening ritual reduces anxiety?:1 ends here
3527+
35243528
;; [[file:init.org::*Questionnaire setup][Questionnaire setup:1]]
35253529
(require 'eieio)
35263530

@@ -3667,7 +3671,9 @@ and 2 of them are randomly selected as part of the daily review.
36673671
(defun my/read-daily-review-properties ()
36683672
"Returns a list of (PROPERTY . VALUE) pairs that could be `org-set-property' on a headline.
36693673
3670-
Makes use of `my/daily-review-questionnaire'."
3674+
Makes use of `my/daily-review-questionnaire'.
3675+
3676+
At any time, press `C-.' to toggle adding a customised explanatory note to go along with a selection."
36713677
(-let [(mandatory-questions random-questions) (-split-on :random my/daily-review-questionnaire)]
36723678
(let* ((max-possible-score 0)
36733679
(properties
@@ -3684,19 +3690,30 @@ Makes use of `my/daily-review-questionnaire'."
36843690
(if is-open-ended?
36853691
(read-from-minibuffer prompt)
36863692
(cl-incf max-possible-score (apply #'max (mapcar #'my/option-score options)))
3687-
(consult--read (--map (my/option-label it) options)
3688-
:prompt prompt
3689-
:require-match t
3690-
:annotate (lambda (label)
3691-
(format "\t%s" (my/option-description (assoc-by-label options label))))
3692-
:lookup (lambda (label _ _ _)
3693-
(-let [option (assoc-by-label options label)]
3694-
;; If label ends in “…”, prompt for a note.
3695-
(when (s-ends-with? "" label)
3696-
(-let [note (s-trim (read-from-minibuffer "Care to elaborate? [ENTER to skip] "))]
3697-
(unless (s-blank? note)
3698-
(setf (my/option-description option) note))))
3699-
(pretty-print option)))))))))
3693+
;; If the user presses “C-.” they toggle on “note entry”.
3694+
(let (note-has-been-requested
3695+
(my/note-map (make-sparse-keymap)))
3696+
(define-key my/note-map (kbd "C-.")
3697+
(lambda () (interactive)
3698+
(setq note-has-been-requested (not note-has-been-requested))
3699+
(message (if note-has-been-requested "[You can enter a note after making a selection!]"
3700+
"[No entry note will be requested after selection.]"))))
3701+
(set-keymap-parent my/note-map minibuffer-local-map) ;; So that ⟨ENTER⟩ finalises the minibuffer, and not a literal new line!
3702+
(minibuffer-with-setup-hook
3703+
(lambda () (use-local-map (copy-keymap my/note-map)))
3704+
(consult--read (--map (my/option-label it) options)
3705+
:prompt prompt
3706+
:require-match t
3707+
:annotate (lambda (label)
3708+
(format "\t%s" (my/option-description (assoc-by-label options label))))
3709+
:lookup (lambda (label _ _ _)
3710+
(-let [option (assoc-by-label options label)]
3711+
;; If label ends in “…” or “C-.” pressed, prompt for a note.
3712+
(when (or (s-ends-with? "" label) note-has-been-requested)
3713+
(-let [note (s-trim (read-from-minibuffer "Enter an explanatory note [ENTER to skip] "))]
3714+
(unless (s-blank? note)
3715+
(setf (my/option-description option) note))))
3716+
(pretty-print option)))))))))))
37003717
;; Prepend a computed “daily score” property. Hopefully this value increases with time.
37013718
(cons
37023719
(thread-last properties
@@ -3763,7 +3780,7 @@ Further reading:
37633780

37643781
(insert (my/fancy-date-string) " ")
37653782
;; Let's add some properties by prompting the user, me.
3766-
(-let [properties (when nil my/read-daily-review-properties)]
3783+
(-let [properties (my/read-daily-review-properties)]
37673784
(cl-loop for (property . value) in properties
37683785
do (org-set-property property value))
37693786
;; Add Daily Score to the start of the headline
@@ -3819,10 +3836,13 @@ Further reading:
38193836

38203837
(insert "\n#+end_stats_of_the_day\n\n")
38213838

3839+
(my/show-life-purpose-statement-then-remove-it-after-I-read-it)
38223840

38233841
(insert "\n💬" (my/word-of-the-day))
3842+
(org-fill-paragraph)
38243843

38253844
;; I think it'd be neat to insert my clocked-in / logs of the day here.
3845+
;; Look at what I clocked into this day/week! Get a great idea of what I've done with my time, in detail. Also, see ~C-c a v L~.
38263846
(save-excursion ;; I want cursor to stay here.
38273847
(let (todays-agenda org-agenda-finalize-hook)
38283848
(org-agenda-list 1)
@@ -3831,8 +3851,12 @@ Further reading:
38313851
(org-agenda-quit)
38323852
(insert "\n\n#+begin_agenda_for_the_day\n")
38333853
(insert todays-agenda)
3834-
(insert "#+end_agenda_for_the_day\n")
3835-
(insert "⟨🤔 Did I get everything I wanted done? Perhaps, I underestimated time for things? 🗯️⟩")))
3854+
(insert "#+end_agenda_for_the_day")
3855+
(insert "\n⟨🤔 Did I get everything I wanted done? Perhaps, I underestimated time for things? 🗯️⟩")
3856+
(insert "\n~C-c a w v c~ to check for time gaps and review time for the past week. And to see what I worked on, and where I spent too much time or too little.")))
3857+
(insert "\nSay, “Today, my purpose was to have fun and do a good job at work! I did it! (。◕‿◕。)”")
3858+
3859+
38363860
;;
38373861
;; MA: Consider adding other journal prompts here, whose replies may be long-form.
38383862
;; E.g., pick one, or two, random prompts.
@@ -3841,6 +3865,29 @@ Further reading:
38413865

38423866

38433867

3868+
3869+
3870+
(cl-defun my/show-life-purpose-statement-then-remove-it-after-I-read-it ()
3871+
(set-mark-command nil)
3872+
(-let [purpose " When people say “What are you doing?”,
3873+
You say ⟪“Things that please me.”⟫
3874+
They say “Toward what end?”,
3875+
and you say ⟪“Pleasure.”⟫
3876+
They say “But really, what are you working on?”
3877+
You say ⟪“Having a good time!”⟫
3878+
"]
3879+
;; NOTE: explore more faces via M-x highlight-phrase.
3880+
(insert (propertize purpose 'font-lock-face 'hi-green)))
3881+
(while (not (equal "yes"
3882+
(consult--read '("yes" "no") :prompt "Read “Life Purpose”?"
3883+
:annotate (lambda (it) (format "%s"
3884+
(if (equal it "no")
3885+
"C'mon man, read it"
3886+
"That's right, live the good life!")))))))
3887+
(backward-delete-char 1))
3888+
3889+
3890+
38443891
(defun my/word-of-the-day ()
38453892
(let (result)
38463893
(org-web-tools-read-url-as-org "https://www.merriam-webster.com/word-of-the-day")
@@ -3993,16 +4040,17 @@ Further reading:
39934040
(load-file "~/Dropbox/private.el") ;; Loads “my\⋯” variables
39944041
;;
39954042
(cl-defun my/age-in-days-weeks-years (&optional (birthdate my\birthday))
3996-
"Prompt for birthdate (YYYY-MM-DD) and display age in days, weeks, and years."
4043+
"Prompt for birthdate (YYYY-MM-DD) and display age in days, weeks, months, and years."
39974044
(interactive)
39984045
(let* ((birth-time (date-to-time (concat birthdate " 00:00:00")))
39994046
(now (current-time))
40004047
(days-old (/ (float-time (time-subtract now birth-time)) 86400))
40014048
(weeks-old (/ days-old 7))
4049+
(months-old (/ days-old 30.44)) ;; average month length
40024050
(years-old (/ days-old 365.25))) ;; approximate year with leap years
4003-
(cl-format nil "I am now ~:d days old, which is ~:d weeks old, which is ~,1f years old"
4004-
(floor days-old) (floor weeks-old) years-old)))
4005-
;;
4051+
(cl-format nil "I am now ~:d days old; which is ~:d weeks old; which is ~:d months old; which is ~,1f years old."
4052+
(floor days-old) (floor weeks-old) (floor months-old) years-old)))
4053+
;;
40064054
;; Elisp's “format” is not as capable as Common Lisp's “format”.
40074055
;; E.g., there's no equivalent of (cl-format nil "~:d" 1000000)
40084056
;; which prints numbers with comma separators.
@@ -4106,7 +4154,9 @@ TODO:
41064154
(cl-defun my/yank-html-media (_media-type contents)
41074155
(insert (s-replace " " " " (shell-command-to-string
41084156
(-let [delimiter "EOF"] ;; A unique “here-document delimiter”, unlikely to be part of ‘contents’
4109-
(format "pandoc -f html -t org <<%s\n%s\n%s" delimiter contents delimiter)))))))
4157+
;; NOTE: `shell-quote-argument` does too much here; e.g., copied code blocks wont paste nicely.
4158+
;; For now, I want $FOO to be pasted as itself, and not interpreted as a Shell variable.
4159+
(format "pandoc -f html -t org <<%s\n%s\n%s" delimiter (s-replace "$" "\\$" contents) delimiter)))))))
41104160

41114161
(yank-media-handler
41124162
"STRING"
@@ -4893,3 +4943,121 @@ method."
48934943

48944944
)
48954945
;; Testing that things are as they should be:1 ends here
4946+
4947+
;; [[file:init.org::*Hyperbole: “DWIM at point”][Hyperbole: “DWIM at point”:1]]
4948+
(use-package hyperbole)
4949+
(hyperbole-mode +1)
4950+
(setq hsys-org-enable-smart-keys t)
4951+
;; Hyperbole: “DWIM at point”:1 ends here
4952+
4953+
;; [[file:init.org::*~MyModule::72~ means “find the file named ~MyModule~, somewhere, and jump to line 72”][~MyModule::72~ means “find the file named ~MyModule~, somewhere, and jump to line 72”:1]]
4954+
(defun my/open-::-file-path (path)
4955+
"PATH is something like FooModule::72 or FooModule::interface_bar"
4956+
;; (message-box path)
4957+
(-let [(file regex) (s-split "::" path)]
4958+
;; brew install fd
4959+
;; NOTE: fd is fast!
4960+
(-let [results (shell-command-to-string (format "fd \"^%s\\..*$\" %s" file my\work-dir))]
4961+
;; (message-box results)
4962+
(find-file (car (s-split "\n" results)))
4963+
(-let [line (string-to-number regex)]
4964+
(if (= 0 line)
4965+
(progn (beginning-of-buffer) ;; In case file already open
4966+
(re-search-forward (s-replace "_" " " regex) nil t))
4967+
(goto-line line))))))
4968+
4969+
(defib my/::-file-paths ()
4970+
"Find the file whose name is at point and jump to the given regex or line number."
4971+
(let ((case-fold-search t)
4972+
(path-id nil)
4973+
(my-regex "\\b\\(\\w+::[^ ]+\\)"))
4974+
(if (or (looking-at my-regex)
4975+
(save-excursion
4976+
(my/move-to-::-phrase-start)
4977+
(looking-at my-regex)))
4978+
(progn (setq path-id (match-string-no-properties 1))
4979+
(ibut:label-set path-id
4980+
(match-beginning 1)
4981+
(match-end 1))
4982+
(hact 'my/open-::-file-path path-id)))))
4983+
4984+
4985+
(defun my/move-to-::-phrase-start ()
4986+
"Move cursor to the start of a phrase like MyFile::13."
4987+
(interactive)
4988+
(let ((case-fold-search t)
4989+
(pattern "\\b\\(\\w+::[^ ]+\\)")
4990+
(max-lookback 20) ; Maximum distance to look back
4991+
(pos (point)))
4992+
(catch 'found
4993+
(while (and (> pos (point-min))
4994+
(<= (- pos (point)) max-lookback))
4995+
(goto-char pos)
4996+
(when (looking-at pattern)
4997+
(goto-char (match-beginning 0))
4998+
(throw 'found t))
4999+
(setq pos (1- pos))))))
5000+
5001+
;; Some highlighting so I'm prompted to use “M-RET”
5002+
(font-lock-add-keywords
5003+
'org-mode
5004+
'(("\\b[^ ]*::[^ ]*" 0 'highlight prepend))
5005+
t)
5006+
;; ~MyModule::72~ means “find the file named ~MyModule~, somewhere, and jump to line 72”:1 ends here
5007+
5008+
;; [[file:init.org::*Fontify Org Radio Targets and have ~M-RET~ Jump to Them][Fontify Org Radio Targets and have ~M-RET~ Jump to Them:1]]
5009+
(defun get-radio-targets ()
5010+
"Extract all radio targets from the current Org buffer"
5011+
(interactive)
5012+
(let ((targets nil)
5013+
(case-fold-search t))
5014+
(cl-loop for file in (cons "~/.emacs.d/init.org" org-agenda-files)
5015+
do (save-excursion
5016+
(find-file file)
5017+
(save-restriction
5018+
(widen)
5019+
(goto-char (point-min))
5020+
(while (re-search-forward "<<<\\(.*?\\)>>>" nil t)
5021+
(push (list (downcase (substring-no-properties (match-string 1))) file (line-number-at-pos)) targets)))))
5022+
targets))
5023+
5024+
(setq my/radio-targets (get-radio-targets))
5025+
(setq my/radio-regex (eval `(rx (or ,@(mapcar #'cl-first my/radio-targets)))))
5026+
5027+
(font-lock-add-keywords
5028+
'org-mode
5029+
(--map (list (cl-first it) 0 ''highlight 'prepend) my/radio-targets)
5030+
t)
5031+
5032+
5033+
;; In programming modes, just show an underline.
5034+
(add-hook
5035+
'prog-mode-hook
5036+
(lambda ()
5037+
(font-lock-add-keywords
5038+
nil
5039+
(--map (list (cl-first it) 0 ''(:underline t) 'prepend) my/radio-targets)
5040+
t)))
5041+
5042+
5043+
(defun my/jump-to-radio (radio)
5044+
"RADIO is a downcased name."
5045+
(-let [(name file line) (assoc radio my/radio-targets)]
5046+
(find-file file)
5047+
(goto-line line)))
5048+
5049+
5050+
(defib my/radio-target ()
5051+
"Jump to the definition of this word, as an Org radio target"
5052+
(let ((case-fold-search t)
5053+
(radio nil))
5054+
(if (or (looking-at my/radio-regex)
5055+
(save-excursion
5056+
(re-search-backward "\\b")
5057+
(looking-at my/radio-regex)))
5058+
(progn (setq radio (downcase (match-string-no-properties 0)))
5059+
(ibut:label-set radio
5060+
(match-beginning 0)
5061+
(match-end 0))
5062+
(hact 'my/jump-to-radio radio)))))
5063+
;; Fontify Org Radio Targets and have ~M-RET~ Jump to Them:1 ends here

0 commit comments

Comments
 (0)