Showing 593 to 596

Don't expand-file-name, just error

An insight from learning to write fast #elisp: "just-in-case" code can make things slower.

Example situation: you want to ensure that a provided string is an absolute filename, so you wrap it in expand-file-name or file-truename. But these are expensive. Instead, if you know it's usually going to be absolute, just assert that it is:

(unless (file-name-absolute-p PATH)
  (error "Expected absolute filename but got: %s" PATH))

… and then proceed without ever calling expand-file-name.

Bonus tip: the other use of expand-file-name is faster with file-name-concat instead.

Alternatively, this is also good:

(let (file-name-handler-alist)
  (expand-file-name PATH))
Created (5 months ago)

Take-5

"Take-5" is my shorthand for "taking 5 minutes by-the-clock to think about it".

The technique may be as old as the hourglass, and it sounds trivial but it's one of the most useful I've learned.

To clarify, you must use an external physical thing such as a timer (or another person), set it to vibrate after 5 minutes, so there is something external to your mind that takes care of the question "when am I done thinking?".

Or else, on truly hard questions, you are likely to blank out for ten seconds and then stop like "yep, no idea".

The harder a question, the faster we give up.nil On "impossible" questions? We're liable to give up as a reflex, cutting the conscious mind out of even the assessment of impossibility.

5 minutes sounds short, but it can seem like an eternity. And that is a very good trick to do some genuinely original thinking.

What links here

  • Worth solving
  • Till arbetsterapeut
  • Portal: CFAR stuff
  • Portal: Modigo
Created (6 months ago)

Taking ownership of org-id

#emacs

Let's say most of your Org files sit in a folder /home/kept/notes/ but some others are outside, scattered here and there, plus you'd like to try not depending on Org-roam's M-x org-roam-update-org-id-locations all the time.

The challenges with org-id:

  1. The classic way to tell it where to look for IDs is adding the directories to org-agenda-files.
    • Unfortunately with thousands of files, this slows down the agenda something extreme. Not an option.
  2. An alternative way is to populate org-id-extra-files or org-agenda-text-search-extra-files.
    • See snippet A below.
      • Unfortunately with thousands of files, this slows down M-x customize-group for either org-id or org-agenda, to a grinding halt.
  3. To sidestep the small problem with #2, you could trust in org-id to keep itself updated, because it does that every time your Emacs creates or searches for an ID. You regenerate org-id-locations once (or well, once every time you wipe .emacs.d). See snippets B or C.
  4. org-id complains about duplicate IDs because it's also looking in e.g. the versioned backups generated by Logseq
    • So, you need some sort of exclusion ruleset.
      • For an elisp-only way, see snippets A or B.
      • A natural way is to obey .ignore or .gitignore, if you already keep such files. I've found no elisp gitignore parser, but see snippet C for a way to use ripgrep's builtin parser.
    • Why org-roam didn't give you this problem? If I'm reading the source code right, it has actually been suppressing org-id errors!

Snippet A

;; Populate `org-id-extra-files'
(dolist (file (mapcan (lambda (dir)
                        (directory-files-recursively dir "\\.org$"))
                      '(;; Example values
                        "/home/kept/notes/"
                        "/home/kept/project1/"
                        "/home/kept/project2/")))
  (or (string-search "/logseq/bak/" file)
      (string-search "/logseq/version-files/" file)
      (string-search ".sync-conflict-" file)
      (push file org-id-extra-files)))

;; Then either run M-x org-id-update-id-locations or restart Emacs.

Snippet B

;; Populate org-id without setting `org-id-extra-files'.  Only do it if
;; `org-id-locations' is gone.
(when (or (and (not (file-exists-p org-id-locations-file))
               (null org-id-locations))
          (if (null org-id-locations)
              (org-id-locations-load)
            (if (listp org-id-locations)
                (null org-id-locations)
              (hash-table-empty-p org-id-locations))))
  (org-id-update-id-locations
   (seq-remove (lambda (file)
                 (or (string-search "/logseq/bak/" file)
                     (string-search "/logseq/version-files/" file)
                     (string-search ".sync-conflict-" file)))
               (mapcan (lambda (dir)
                         (directory-files-recursively dir "\\.org$"))
                       '(;; Example values
                         "/home/kept/notes/"
                         "/home/kept/project1/"
                         "/home/kept/project2/"))))
  (org-id-locations-save))

Snippet C

;; Populate org-id without setting `org-id-extra-files'. Only do it if
;; `org-id-locations' is gone.
(when (or (and (not (file-exists-p org-id-locations-file))
               (null org-id-locations))
          (if (null org-id-locations)
                     (org-id-locations-load)
                   (if (listp org-id-locations)
                       (null org-id-locations)
                     (hash-table-empty-p org-id-locations))))
  (dolist (default-directory '(;; Example values
                               "/home/kept/notes/"
                               "/home/kept/project1/"
                               "/home/kept/project2/"))
    ;; Borrow ripgrep's ability to obey .ignore/.gitignore
    (org-id-update-id-locations
     (split-string (shell-command-to-string "rg -ilt org :ID:") "\n" t))
    (org-id-locations-save)))

Bonus snippet: full reset

;; FOR TESTING: wipe all records
;; You ONLY need to wipe if it won't shut up about duplicates!
(progn
  (delete-file org-id-locations-file)
  (setq org-id-locations nil)
  (setq org-id--locations-checksum nil)
  (setq org-agenda-text-search-extra-files nil)
  (setq org-id-files nil)
  (setq org-id-extra-files nil))

Sudden amnesia

Every time your Emacs quits unexpectedly, it can forget many ID locations! To ensure it remembers, either use a hook like

(add-hook 'after-save-hook
 (defun my-save-id-soon ()
   (run-with-idle-timer 10 nil #'org-id-locations-save)))

or enable persist-state and add the hook

(add-hook 'persist-state-saving-functions
          (lambda ()
            (when (fboundp 'org-id-locations-save)
              (org-id-locations-save))))

Final fix

All these issues go away now that I let org-node populate ID locations for me, via its user option org-node-extra-id-dirs.

Created (9 months ago)

Nested notes enable folgezettel (note-sequences)

#org-roam

The packages zk, orgrr and denote mandate the rule of "one note per file". So how do they do note-sequences?

Well. In orgrr, you'd manually give special IDs to notes that should be parts of sequences, and then use commands like orgrr-show-sequence to work with them.

In org-roam, which permits nested notes, you'd just have a series of headings in a single file… you know, a conventional org-mode file.

I like that better. You can export it to PDF or HTML. There are ways to isolate and export a subtree from one file, but it's not as convenient (yet) to tell Org to concatenate multiple whole files and export them as one.

I suppose zk/orgrr/denote users could use org-transclusion to get the same effect.

Multiple sequences?

Hm… the concept of orgrr-show-sequence has merit. Nesting org-roam nodes only gives you one sequence. What if you want a node to be part of several?

For example, say you have a node about Isaac Newton, which could be part of both a Philosophy sequence and a Math sequence.

Well, you could have a "Math" note that transcludes all other math notes, and a "Philosophy" note that transcludes all the philosophy notes. And that works whether you use orgrr or org-roam. But yea, org-roam's ability to nest nodes suddenly became less important.

What links here

Created (10 months ago)
Updated (9 months ago)
Showing 593 to 596