Categories: geek » emacs » org

View topic page - RSS - Atom - Subscribe via email

Shuffling my Org Mode unscheduled tasks

| emacs, org

I enjoyed listening to Podcast #1,029: Treat Your To-Do List Like a River, and Other Mindset Shifts for Making Better Use of Your Time | The Art of Manliness (thanks @ctietze@mastodon.social for the recommendation) and checking out the Autofocus method (main website with translations) for reviewing your TODO list without worrying too much about prioritization. I also had an opportunity to reflect on similar topics in a conversation with John Wiegley and Adam Porter about personal information management (which I'll be blogging about once John has a chance to review the draft).

This nudged me to experiment with randomizing my unscheduled task list. I'm not trying to finish everything on my list, I'm just mixing it up so that I enjoy keeping things on my radar and picking something to do. org-ql lets me create randomly-sorted views, so I wrote some code to show me a shuffled list of my unscheduled TODO tasks and SOMEDAY tasks.

(defun my-org-ql-shuffle-todo ()
  (interactive)
  (org-ql-search (org-agenda-files)
    '(and
      (todo "TODO" "STARTED")
      (not (done))
      (not (scheduled))
      (not (deadline))
      (not (ts-active))
      (not (tags "cooking")))
    :sort 'random))

(defun my-org-ql-shuffle-someday ()
  (interactive)
  (org-ql-search (org-agenda-files)
    '(and
      (todo "SOMEDAY")
      (not (done))
      (not (scheduled))
      (not (deadline))
      (not (ts-active))
      (not (tags "cooking")))
    :sort 'random))

I can't make it part of my org-agenda-custom-commands yet because of an open issue, but having separate commands is a starting point. It's surprisingly fun. I used org-agenda-follow-mode to quickly flip through the tasks while looking at the agenda. I've already noticed some tasks to cancel and picked some tasks to do. Could be neat!

This is part of my Emacs configuration.
View org source for this post

Thinking about 12 aspects of personal information/knowledge management

| pkm, org

Here is a totally rough list of aspects that I came up with to start thinking about how I do personal information/knowledge management and how I want to explore other people's systems.

(text from sketch duplicated as headings below)

Use: What do you want to use it for, and how?

I mostly work on code, so I need to keep things like TODOs and setup instructions.

I also want to organize resources and refer people to them.

It's important to me to get things out of my head because unfinished thoughts in my head are intrusive (Ovsiankina effect). They get in the way of being able to enjoy time with the kiddo. I need to be able to get them out into a system that I can trust, so that I can stop thinking about it until it's time to think about it again. I don't have a lot of computer time, so I want to be able to pick things up quickly when I do.

Capture: How do you get stuff in?

Most of the time, I add quick questions or ideas using Orgzly Revived on my phone because I'm not close to a computer. Sometimes I look up web pages that relate to something, and then I can share that with Orgzly using the Android share menu. If I'm close to a computer, then I can use org-capture.

I also use my Supernote to sketch/write ideas.

I use my phone for audio braindumps.

Challenge: I want to write down more context because I occasionally come across notes that don't make sense to me.

Retrieval: How do you get stuff out?

I usually tend to work on things that I've recently thought about, so I'm working out of my inbox or out of a few active projects. Either the relevant items I've captured are still there in my inbox or in the project's tree, or I can quickly organize them before I dive into my work.

Sometimes I need to retrieve something that's a lot older, such as when I want to recommend something I remember seeing a year or two ago. This is challenging because I often don't remember the exact words that will bring it up. I can help that a little bit by adding my own words when I create the note, but I don't feel like that's a solid solution yet. I think that this is a challenge that's going to get worse as my brain gets fuzzier. Finding things using approximate matches could be interesting. Most of the time, I end up relying on an Internet search, because then I can take advantage of the variety of words used in other people's descriptions of the thing.

Blog posts (and funneling my toots and sketches into blog posts) makes things slightly more findable. I've come across things I've completely forgotten writing about.

Challenge: When I'm trying to move too quickly instead of writing things down, then there's nothing to retrieve years later when I'm picking a project back up again. For example, when I finally dusted off my time-tracking project so that I could upgrade the Rails version, I had to do a lot of figuring out. That tells me I need to write more notes. As I run into things that I didn't write down well enough (or as I bump into things I could've sworn I wrote about but I just can't find my notes), I try to write down what I've figured out, where I looked, and what words I used in order to look for it. Maybe that will make it more findable in the future.

Priorities: How do you get the right stuff out?

I tend to work on a few recent thoughts, so I can generally schedule them for the day that I think I'll be able to work on them. Then I can use my Org Mode agenda to get a short list of the things that I want to work on. When that's done, I can then go through the more general things–still biased towards what's recent, what's in my inbox, what I've been thinking about lately. It takes extra time to context shift back into older things.

My life generally doesn't have a lot of urgent commitments, so it's mostly a matter of thinking: What do I feel like working on? What's the most annoying thing I need to work around? What am I curious about? Then I can go to that project or thought.

Sometimes I'll use the TODO status to distinguish between things that I want to do someday versus things that I could do sooner. Pushing things off to SOMEDAY is especially handy for ideas that are not very fleshed out yet. My newly created tasks default to SOMEDAY so that it takes me an active effort to say, okay, this stuff is on my list of things to focus on.

Sometimes I use the [#A] and [#C] priority marker in Org Mode to move things to the top or bottom of my list.

In general, I don't worry too much about making sure that I'm working on the absolute best thing at the time, because that stuff takes planning, too.

Time: How do you deal with dates/times/conditions?

Scheduling something on a particular day is how I pick a short list of things that I want to do. These things don't always happen. Sometimes I end up procrastinating something for another few weeks out or a month out. If I do that too often, I usually end up cancelling it, because clearly there are other things I want to do.

There are also the things I've got to schedule once in a while that I don't actively think about until the reminder pops up, like renewing my passport. The Org agenda takes care of that.

I like to keep journal entries so that I can look back and see the progress I've made.

Revision: How do you add to or refine things?

I might start off with just a quick question or idea. Depending on what I have time for, I might flush out that idea in an audio braindump or a sketch. I can convert either of those things into text and dump them into my note for editing, or I can sit down and flesh out the idea further by writing it, with the eventual goal of turning it into either a toot or a post. Maybe some of them will get turned into videos. So that's how I gradually refine things.

I would like to get better at this. Maybe I can keep track of which thoughts could benefit from sketching or doing a brain dump, or refining those sketches or brain dumps into posts. Which posts are almost there and just need a little bit more work? Which ones do I want to turn into a video?

Since the sketching and the braindumping can happen in parallel, it's probably more about tags rather than TODO states.

One improvement could be showing me where these ideas are in the pipeline so that if I'm at my computer and I want to get something out the door, I can make a list of posts that are almost there. If I'm heading out for a walk to the store, then I can make a list of the things to think about out loud. Then I can have my system do the transcript and stick it back into the pipeline so I can edit it.

How do I take those fragments of thoughts, put them together, and turn them into a finished chunk?

When it comes to refining sketches, I can just flip open my supernote and I add more stuff to it. It's very easy to pick up and put down again. I like that.

Audio is harder to work with in terms of refining an idea, but maybe I'll figure out the workflow for that someday. The draft for this post came from a sketch and an audio braindump.

There's also this idea of refining a project. When I do my first pass through my inbox, I'm just basically throwing things in the rough direction of where I'm probably going to want them. I'll refile things very roughly into Consulting or EmacsConf or whatever else. Refining in that context would be collecting several resources and putting them under one subtree, or making sense of something, mapping out the resources for a topic, or summarizing.

If I've saved a web page, it becomes a lot easier to learn from and find again if I use my own words to describe what I'm learning from it. That's another area that I could definitely do better in.

Refining is easier to do when I'm on my computer, but when I'm on my computer, I tend to want to make stuff rather than edit stuff. If I'm refining something with the goal of making it a post, that sometimes happens. But if I want to review a page whose link I saved, sometimes that ends up very low on my priority list. I'm throwing all these things into my SOMEDAY list and not actually getting around to them yet. Maybe someday!

Connection: How do you link things together?

Most of the time, I refile things so they're roughly close to where other things I need are. I can just scroll to find connected items.

I don't have many things that need to be in multiple places in my In my outline. When I do, I tend to use links to connect the ideas. I like linking between blog posts and sketches.

I don't have a good facility for backlinks yet. I should make this easier for myself, either by just opening the blog post that I'm referring to so that I can quickly add a link to it going the other way–a manual backlink that lets me provide the context–or maybe adding some backlink support to my static site generator.

Anyhow, at least the forward links are fine. I've got some completion to help me with that. Web searches are helpful just in case my completion doesn't work, as right now my completion only works with title searches. If I am a little fuzzier about what I've called something, then I will search the Internet, grab the URL, and pop in the link.

Most of the linking happens in my blog posts because the blog posts live outside my outline. They are just roughly organized by date and category. So if I want to build on another thought, I've got to link to it. Fortunately, I've got the URL, so it's easy to link to things.

I can link to things within Org Mode. I probably should more often, and it will probably involve getting the hang of Org IDs. It hasn't been as big a need for me for now because I try to push things into blog posts as much as possible.

Sometimes it makes sense to have a URL or a link that works for both the exported version and my own internal notes. I want some things to open up in Emacs instead. Then I might have a custom link type to make that easier.

Externals: How do you refer to things outside your system?

There are a lot of things that I want to think about or refer to that aren't within my Org Mode files. Fortunately, Org Mode makes it super easy to link to the things, so that part is fairly solid.

There are some kinds of things that I don't have an easy way of thinking about or working with yet, like audio.

Work ideas are harder for me to link to now that I can't access the company's WebEx chat on my personal phone, so I just write down a couple of keywords to remind myself what to think about or search for. I also tend to read my e-mail on my phone, so I don't have Org Mode's fancy linking. I write down or copy a few keywords and tag the note with "email" to help me remember where to look. Life would be much easier if I could do all of these things within Emacs so that I could just create a task and it would automatically be annotated with the link to the original stuff, but we've got to work with what we've got.

Sharing: How do you share with others?

I've been gradually refining my workflow for turning my notes ito blog posts. Org Mode is fantastic for this. I can have source blocks, I can export to various formats, it's all good. I'm also exploring the idea of turning some things into richer text–adding diagrams or sketches, or narrating it, or turning it into a video.

My main thing is I want to get thoughts, ideas, and questions from my notes into some kind of public chunk. Toots are nice because I can get smaller thoughts out instead of waiting until I've fleshed them out further. Blog posts are ideal.

I want to experiment with this by using audio braindumps and sketches to explore ideas faster and use non-computer time to help with writing.

Maintenance: How do you tidy or trim?

Part of maintenance is figuring out what's out of date and what I can archive to make it easier for me to just see the current stuff. I periodically go through my inbox and archive things or refile things into projects. I am slowly getting the hang of archiving things instead of deleting things, since disk space is cheap. Once in a while, I'll go through my Org file to archive inactive projects and neaten things up.

On the public side, I could probably do automated things like link-checking, but it's been pretty low priority. Most of the time, I end up updating posts when I look up them up in order to link to them or when people ask me about them. I have a snippet that makes it a little easier to note an update, but I should probably improve it to handle adding an update to a post that's already been updated before.

I don't have a list of recently modified but not newly posted posts, which might be a good idea for exposing that to blog readers.

I also want to create more evergreen pages that organize resources, kind of like my blog outline but more granular. I still want to have the last modified date as text in the page itself, but it doesn't have to be part of the permalink.

Discovery: How do you stumble upon things?

I have a lot in my notes that I've completely forgotten about. One of the benefits of keeping most of my notes online is that when people come across those notes, their links or comments help me find them again.

I've also added a random blog post button on my blog, and I'm trying to shift some doom-scrolling to use that instead.

For my personal notes, I don't bump into things as much because org-refile is very efficient for getting to just the thing I want to look at. For the most part, things get hidden away under their sub-trees until I feel like working on that particular area, so it might be years before I touch something again, if at all.

I could probably add some kind of randomness thing, but I don't really struggle with finding things to work on when I'm on my computer. There's usually something else more pressing that I want to work on, so it hasn't been an issue.

I do want to add a random sketch thing, though. I think it could be fun to cycle my background through the files in my public sketches on my desktop or my phone lockscreen.

Longevity: How do you keep it around?

Using plain text and free and open source software is really important to me because I want it to be easy to back up and I want to be able to trust that it's going to be around. Having seen many things get bought up or taken down… Yeah, I want to have my own notes. I feel reasonably confident, based on other people's experiences, that if I want to keep using my notes in another 20 years or more, it'll probably still be there as long as I don't do anything silly with the data.

For my sketches, I put titles and tags in the filenames. I've been using Google Cloud Vision to do handwriting recognition so that I have some kind of text that presumably I could search, although I haven't built that part yet.

Audio is a bit more ephemeral, but it might still be interesting to hear archived audio.

One of these days, I should make an organized backup of the things that I've shared on YouTube and other places. Videos take much more space.

Another thing that I'm thinking of long-term, once in a while, is how to keep going into this, how to keep it easy for me to access, use, add to, and share as I get older. I hear menopause might really do a number on my brain. People report having a hard time remembering words and thinking thoughts. It would be nice to have approximate search in place by then so that I can still find things, or at least have shared as much as possible.

My long-term plan (in case stuff happens) is to have whatever notes might be helpful be publicly available already so that theoretically someone could use the Internet Archive or a static mirror or to get back to it. Even in the case where I die and my hosting stops being paid for, the core things about it, I think, have been well-demonstrated and can be easily picked up by somebody else if they want to.

Planet Emacslife is a blog aggregator. The idea of Emacs News is fairly straightforward and somebody else could step into it easily. The ideas are not dependent on me, whic his nice.

My posts and code are out there too. They're not immortal, and they don't have to do be. If they're useful in the moment, that's already enough. If somebody comes across them months or years later and finds them useful, that's a bonus. I use them to think through something, so that's already a win.

Wrapping up

I'd love to hear about your personal information/knowledge management systems, whether you want to think about it using these aspects or your own framework. Let's share notes!

View org source for this post

Change Org Mode TODO keyword color based on the state and the current Modus theme

| emacs, org

I use modus-theme-toggle to switch between modus-vivendi-tinted and modus-operandi-tinted depending on whether I want a dark background or a light one. I also customize my org-todo-keyword-faces to visually distinguish TODO, DONE, WAITING, and SOMEDAY. This is how to colour them based on the current Modus theme.

(defun my-org-todo-set-keyword-faces ()
  (setq org-todo-keyword-faces
        `(("TODO" . (:foreground ,(modus-themes-get-color-value 'blue-warmer) :weight bold))
          ("DONE" . (:foreground ,(modus-themes-get-color-value 'green-warmer) :weight bold))
          ("WAITING" . (:foreground ,(modus-themes-get-color-value 'red-warmer) :weight bold))
          ("SOMEDAY" . (:foreground ,(modus-themes-get-color-value 'fg-dim) :weight bold))))
  (when (derived-mode-p 'org-mode)
    (font-lock-fontify-buffer)))
(with-eval-after-load 'modus-themes
  (add-hook 'modus-themes-after-load-theme-hook #'my-org-todo-set-keyword-faces))
2024-10-14-17-21-48.svg
Figure 1: Light background
2024-10-14-17-22-31.svg
Figure 2: Dark background
This is part of my Emacs configuration.
View org source for this post

Using Emacs Lisp to export TXT/EPUB/PDF from Org Mode to the Supernote via Browse and Access

| supernote, org, emacs

I've been experimenting with the Supernote's Browse and Access feature because I want to be able to upload files quickly instead of waiting for Dropbox to synchronize. First, I want to store the IP address in a variable:

my-supernote-ip-address
(defvar my-supernote-ip-address "192.168.1.221")

Here's how to upload:

(defun my-supernote-upload (filename &optional supernote-path)
  (interactive "FFile: ")
  (setq supernote-path (or supernote-path "/INBOX"))
  (let* ((boundary (mml-compute-boundary '()))
         (url-request-method "POST")
         (url-request-extra-headers
          `(("Content-Type" . ,(format "multipart/form-data; boundary=%s" boundary))))
         (url-request-data
          (mm-url-encode-multipart-form-data
           `(("file" . (("name" . "file")
                        ("filename" . ,(file-name-nondirectory filename))
                        ("content-type" . "application/octet-stream")
                        ("filedata" . ,(with-temp-buffer
                                         (insert-file-contents-literally filename)
                                         (buffer-substring-no-properties (point-min) (point-max)))))))
           boundary)))
    (with-current-buffer
        (url-retrieve-synchronously
         (format "http://%s:8089%s" my-supernote-ip-address supernote-path))
      (re-search-backward "^$")
      (prog1 (json-read)
        (kill-buffer)))))

HTML isn't supported. Text works, but it doesn't support annotation. PDF or EPUB could work. It would make sense to register this as an export backend so that I can call it as part of the usual export process.

(defun my-supernote-org-upload-as-text (&optional async subtree visible-only body-only ext-plist)
  "Export Org format, but save it with a .txt extension."
  (interactive (list nil current-prefix-arg))
  (let ((filename (org-export-output-file-name ".txt" subtree))
        (text (org-export-as 'org subtree visible-only body-only ext-plist)))
    ;; consider copying instead of exporting so that #+begin_export html etc. is preserved
    (with-temp-file filename
      (insert text))
    (my-supernote-upload filename)))

(defun my-supernote-org-upload-as-pdf (&optional async subtree visible-only body-only ext-plist)
  (interactive (list nil current-prefix-arg))
  (my-supernote-upload (org-latex-export-to-pdf async subtree visible-only body-only ext-plist)))

(defun my-supernote-org-upload-as-epub (&optional async subtree visible-only body-only ext-plist)
  (interactive (list nil current-prefix-arg))
  (my-supernote-upload (org-epub-export-to-epub async subtree visible-only ext-plist)))

(org-export-define-backend
    'supernote nil
    :menu-entry '(?s "Supernote"
                     ((?s "as PDF" my-supernote-org-upload-as-pdf)
                      (?e "as EPUB" my-supernote-org-upload-as-epub)
                      (?o "as Org" my-supernote-org-upload-as-text))))

Adding this line to my Org file allows me to use \spacing{1.5} for 1.5 line spacing, so I can write in more annotations..

#+LATEX_HEADER+: \usepackage{setspace}

Sometimes I use custom blocks for HTML classes. When LaTeX complains about undefined environments, I can define them like this:

#+LATEX_HEADER+: \newenvironment{whatever_my_custom_environment_is_called}

Now I can export a subtree or file to my Supernote for easy review.

I wonder if multimodal AI models can handle annotated images with editing marks…

This is part of my Emacs configuration.
View org source for this post

Include inline SVGs in Org Mode HTML and Markdown exports

Posted: - Modified: | emacs, org
  • [2024-10-14 Mon]: Fixed path when inlining file URLs.
  • [2024-10-07 Mon]: Now I can specify #+ATTR_HTML :data-link t to make it link instead of include.
  • [2024-09-26 Thu]: Whoops, forgot to make sure ox-11ty is also covered.

In my Org Mode HTML and Markdown exports, I usually want to include SVGs inline so that I can use links. Sometimes I also want to use Javascript and CSS to modify elements within the images. I used to use a my-include: link to do this, but I realized that I can also modify this behaviour by making my own functions that call org-html-link or org-md-link and then put those functions in org-export-backend-transcoders.

Here is an example of an SVG:

g Graphviz Graphviz Org Mode Org Mode Graphviz->Org Mode SVG HTML HTML Org Mode->HTML Markdown Markdown Org Mode->Markdown

The following code overrides HTML and Markdown exports to include SVGs.

(defun my-ox-link-path (link _ info)
  (let* ((raw-path (org-element-property :path link)))
    (setq raw-path
          (org-export-file-uri
           (org-publish-file-relative-name raw-path info)))
    ;; Possibly append `:html-link-home' to relative file
    ;; name.
    (let ((home (and (plist-get info :html-link-home)
                     (org-trim (plist-get info :html-link-home)))))
      (when (and home
                 (plist-get info :html-link-use-abs-url)
                 (not (file-name-absolute-p raw-path)))
        (setq raw-path (concat (file-name-as-directory home) raw-path))))
    raw-path))

(defun my-org-html-link (link desc info)
  (if (and
       (string= (org-element-property :type link) "file")
       (not (plist-get (org-export-read-attribute :attr_html (org-element-parent-element link))
                       :data-link))
       (org-export-inline-image-p link (plist-get info :html-inline-image-rules)))
      (let ((path (org-element-property :path link)))
        (if (string= (file-name-extension path) "svg")
            (with-temp-buffer
              (insert-file-contents-literally path)
              (buffer-string))
          (org-html-link link desc info)))
    (org-html-link link desc info)))

(defun my-org-md-link (link desc info)
  (if (and (string= (org-element-property :type link) "file")
           (not (plist-get (org-export-read-attribute :attr_html (org-element-parent-element link))
                       :data-link)))
      (let ((path (org-element-property :path link)))
        (if (string= (file-name-extension path) "svg")
            (with-temp-buffer
              (insert-file-contents-literally path)
              (buffer-string))
          (org-md-link link desc info)))
    (org-md-link link desc info)))

(defun my-org-11ty-link (link desc info)
  (if (and (string= (org-element-property :type link) "file")
           (not (plist-get (org-export-read-attribute :attr_html (org-element-parent-element link))
                       :data-link)))
      (let ((path (org-element-property :path link)))
        (if (string= (file-name-extension path) "svg")
            (with-temp-buffer
              (insert-file-contents-literally path)
              (buffer-string))
          (org-11ty-link link desc info)))
    (org-11ty-link link desc info)))

(with-eval-after-load 'ox-html
  (setf
   (alist-get 'link (org-export-backend-transcoders (org-export-get-backend 'html)))
   'my-org-html-link))
(with-eval-after-load 'ox-md
  (setf
   (alist-get 'link (org-export-backend-transcoders (org-export-get-backend 'md)))
   'my-org-md-link))
(with-eval-after-load 'ox-11ty
  (setf
   (alist-get 'link (org-export-backend-transcoders (org-export-get-backend '11ty)))
   'my-org-11ty-link))
This is part of my Emacs configuration.
View org source for this post

org-attaching the latest image from my Supernote via Browse and Access

Posted: - Modified: | emacs, supernote, org

[2024-09-29 Sun]: Use sketch links when possible. Recolor before cropping so that the grid is removed.

2024-09-26-01 Supernote A5X Browse and Access %23supernote.png
Figure 1: Diagram of different ways to get drawings off my Supernote A5X
Text from sketch

Supernote A5X

  • Screen mirroring (pixelated) -> Puppeteer screenshot (or maybe .mjpeg?)
  • Browse & Access (HTTP) -> latest file: recognize text, recolor, crop, upload?
  • Dropbox/Google Drive (slow) -> batch process: recognize text, recolor, upload

Bonus: Autocropping encourages me to just get stuff out there even if I haven't filled a page

ideas: remove template automatically? I wonder if I can use another color…

2024-09-26-01

I want to quickly get drawings from my Supernote A5X into Emacs so that I can include them in blog posts. Dropbox/Google Drive sync is slow because it synchronizes all the files. The Supernote can mirror its screen as an .mjpeg stream. I couldn't figure out how to grab a frame from that, but I did find out how to use Puppeteer to take an screenshot of the Supernote's screen mirror. Still, the resulting image is a little pixelated. If I turn on Browse and Access, the Supernote can serve directories and files as webpages. This lets me grab the latest file and process it. I don't often have time to fill a full A5 page with thoughts, so autocropping the image encourages me to get stuff out there instead of holding on to things.

(defvar my-supernote-ip-address "192.168.1.221")
(defun my-supernote-get-exported-files ()
  (let ((data (plz 'get (format "http://%s:8089/EXPORT" my-supernote-ip-address)))
        (list))
    (when (string-match "const json = '\\(.*\\)'" data)
      (sort
       (alist-get 'fileList (json-parse-string (match-string 1 data) :object-type 'alist :array-type 'list))
       :key (lambda (o) (alist-get 'date o))
       :lessp 'string<
       :reverse t))))

(defun my-supernote-org-attach-latest-exported-file ()
  (interactive)
  ;; save the file to the screenshot directory
  (let ((info (car (my-supernote-get-exported-files)))
        new-file
        renamed)
    ;; delete matching files
    (setq new-file (expand-file-name
                    (replace-regexp-in-string " " "%20" (alist-get 'name info) (org-attach-dir))))
    (when (file-exists-p new-file)
      (delete-file new-file))
    (org-attach-attach
     (format "http://%s:8089%s" my-supernote-ip-address
             (alist-get 'uri info))
     nil
     'url)
    (setq new-file (my-latest-file (org-attach-dir)))
    ;; recolor
    (my-sketch-recolor-png new-file)
    ;; autocrop that image
    (my-image-autocrop new-file)
    ;; possibly rename
    (setq renamed (my-image-recognize-get-new-filename new-file))
    (when renamed
      (setq renamed (expand-file-name renamed (org-attach-dir)))
      (rename-file new-file renamed t)
      (my-image-store renamed) ; file it in my archive
      (setq new-file renamed))
    ;; use a sketch link if it has an ID
    (if (string-match "^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9] "
                      (file-name-base renamed))
        (org-insert-link nil (concat "sketchFull:" (file-name-base renamed)))
      ;; insert the link
      (org-insert-link nil (concat "attachment:" (replace-regexp-in-string "#" "%23" (file-name-nondirectory new-file)))))
    (org-redisplay-inline-images)))
This is part of my Emacs configuration.
View org source for this post

Archiving public toots on my blog

| mastodon, emacs, org

I want to compile my global microblog posts into weekly posts so that they're archived on my blog. It might make sense to make them list items so that I can move them around easily.

my-mastodon-insert-my-statuses-since
(defun my-mastodon-insert-my-statuses-since (date)
  (interactive (list (org-read-date "Since date: ")))
  (insert
   (format "#+begin_toot_archive\n%s\n#+end_toot_archive\n"
           (mapconcat
            (lambda (o)
              (format "- %s\n  #+begin_quote\n  #+begin_export html\n%s\n  #+end_export\n  #+end_quote\n\n"
                      (org-link-make-string (assoc-default 'url o) (assoc-default 'created_at o))
                      (org-ascii--indent-string (assoc-default 'content o) 2))
              ;; (format "#+begin_quote\n#+begin_export html\n%s\n#+end_export\n#+end_quote\n\n%s\n\n"
              ;;        (assoc-default 'content o)
              ;;        (org-link-make-string (assoc-default 'url o) (assoc-default 'created_at o)))
              )
            (seq-filter
             (lambda (o)
               (string= (assoc-default 'visibility o) "public"))
             (my-mastodon-fetch-posts-after
              (format "accounts/%s/statuses?count=40&exclude_reblogs=t&exclude_replies=t" (mastodon-auth--get-account-id))
              date))
            ""))))

Here's a little thing I used to convert a two-level list into my collapsible sections:

my-org-convert-list-to-collapsible-details
(defun my-org-convert-list-to-collapsible-details ()
  (interactive)
  (let ((list (org-list-to-lisp t)))
    (mapc (lambda (o)
            (when (stringp (car o))
              (insert
               (format
                "#+begin_my_details %s :open t\n%s#+end_my_details\n"
                (car o)
                (mapconcat
                 (lambda (s)
                   (concat "- " (string-trim (org-ascii--indent-string (car s) 2)) "\n"))
                 (cdr (cadr o)))))))
          (cdr list))))

And here are my toots from the past week, roughly categorized into collapsible sections:

EmacsConf
  • 2024-09-17T21:55:39.065Z CFP, draft schedule

    The #EmacsConf call for proposals (https://emacsconf.org/2024/cfp/) target date is this Friday (Sept 20), so I've started drafting the schedule. Thanks to my SVG schedule visualization code and function for checking availability constraints from last year ( https://sachachua.com/blog/2023/09/emacsconf-backstage-scheduling-with-svgs/), it took only about an hour to sketch this out: https://emacsconf.org/2024/organizers-notebook/#draft-schedule . We can run two tracks simultaneously and I can also slightly reduce the buffer between talks, so there's plenty of space for more #Emacs talks if people want to propose them or nudge people to propose them. =)

  • 2024-09-15T17:07:41.935Z diversity

    I feel complicated feelings about #EmacsConf and diversity. On one hand, yes, I would love to have a mix of speakers that reflects the mix of interesting stories and people I come across in the #Emacs community. (I wouldn't get rid of or discourage anyone; I just want more! :) )

    On the other hand, preparing and giving a presentation is a lot of work, and I have first-hand appreciation of how difficult it can be to find time to think - much less predict a specific time to have a conversation. (I'm only just beginning to be able to have some thinking time that isn't accompanied by the guilt of letting my kiddo binge-watch YouTube videos or the uncertainties of sacrificing my sleep, and I still rarely schedule anything for myself.)

    In addition, there are little risks that other people might not even have on their radar. All it takes is one person developing a parasocial relationship or fixation, or someone getting grumpy about someone's pronouns or personal characteristics or opinions, and then deciding to go and ruin someone's day (or life)... I'd hate to encourage someone to put themselves out there and end up with that happening to them, even if it's not at all their fault or mine.

    So yeah, it's a little hard for me to reach out. I can deal with impostor syndrome making people feel like they might not have much to say (share what you're learning! We're all figuring things out together), but I'm not so sure about the other concerns. While I'd like to think that in the Emacs community we often have a convivial atmosphere, sometimes it gets weird here too.

    I'm not sure what to do here aside from thinking out loud. I wish I could wave a magic wand and solve some structural issues that could make things more equitable, but that's waaay above my paygrade. I can keep working on figuring out how to make use of fragmented time, and maybe that will help other people too. I like working on the captions for EmacsConf; they help me a lot, too. I can experiment with workflows for sharing what I'm learning in a way that doesn't require a lot of focus time, speech fluency (I occasionally stutter and have to redo things), or a powerful computer. (Emacs is totally my nonlinear video editor.) I can make an indirect request for more people to consider proposing a talk for https://emacsconf.org/2024/cfp/ (target date is Sept 20, but I think the other organizers are considering extending it too), even with all the caveats my anxious brain suggests. (I know, I'm terrible at sales. :) ) And really, EmacsConf isn't important in the grand scheme of things, it's just a fun excuse to get together and connect with other people who like this stuff too. :)

    I wonder how this can be better. Thoughts?

Emacs
  • 2024-09-17T15:07:41.153Z consult-omni

    All right, I just got consult-omni and a Google custom search JSON API key set up so that I can call consult-omni-google, type keywords, pick the correct match, and insert it as an Org Mode link (or linkify the current region). I can think of more tweaks (embark-act on the current word or region to linkify it), but this is already pretty neat.

  • 2024-09-16T14:05:06.263Z - user-init-file

    Is there already an interactive #emacs command for opening user-init-file? I think that could be handy for newbies if we could just tell them to use "M-x visit-user-init-file" or even "Select 'Open init file' from the menu", although I suppose by the time we ask them to fiddle with the init file to add stuff to it, it's fine to encourage them to be comfortable with C-h v user-init-file and then maybe even teach them about M-x ffap at that point. Hmm...

  • 2024-09-16T13:51:12.091Z - casual-symbol-overlay

    Trying out casual-symbol-overlay (http://yummymelon.com/devnull/announcing-casual-symbol-overlay.html) by hooking it into embark-act, which I've bound to `C-.`:

    ```emacs-lisp
    (use-package casual-symbol-overlay
    :if my-laptop-p
    :init
    (with-eval-after-load 'embark
    (keymap-set embark-symbol-map "z" #'casual-symbol-overlay-tmenu)))
    ```

  • 2024-09-11T17:12:03.791Z no nested lists for Org Babel

    TIL that #OrgMode Babel only takes the top level of nested lists passed in via :var (https://orgmode.org/manual/Environment-of-a-Code-Block.html - Note that only the top-level list items are passed along. Nested list items are ignored.) When I try the manual example on my computer, I do indeed get only the top-level list items, unlike the nested data from https://mail.gnu.org/archive/html/emacs-orgmode/2020-10/msg00536.html . Of course, now that makes me want nested lists for both input and output...

Mastodon
Moving to P52
  • 2024-09-18T00:03:09.981Z WhisperX

    Now that I have word-level timestamps from WhisperX (https://sachachua.com/blog/2024/09/using-whisperx-to-get-word-level-timestamps-for-audio-editing-with-emacs-and-subed-record/), I think I'll be able to write an elisp equivalent of the merging/splitting strategies of https://github.com/jianfch/stable-ts?tab=readme-ov-file#regrouping-words to merge subtitles considering gap, duration, length, and maximum number of words.

  • 2024-09-15T17:08:17.757Z upgrade

    (reposting, forgot to make it public)

    I installed a 2TB Crucial T500 NVMe into my Lenovo P52 so that I can try dual-booting into Linux, since it was hard to figure out how I could get all my usual conveniences in WSL.

    A preliminary test with a fresh Kubuntu install showed that my 11ty static blog generation takes about the same time as it does on the X230T, which is a little surprising considering the newer processor and the faster SSD, but maybe I'll have to look for speed gains elsewhere there. I think whisper.cpp is a lot more usable on this computer though, so I'm looking forward to taking advantage of that. The P52 might also make video editing possible, and it might support more modern monitors. It is a fair bit larger and heavier, though. I might end up still using both.

    Anyway, I decided to redo the install by cloning my previous SSD. I want to see if I can skip the step of setting all those things up (although I'll need to redo the Syncthing config, of course). I don't have the extra parts that would let me install the 2.5" SSD from my X230T directly into the P52, but W- has a drive dock that works off USB 2.0. Slow and steady, but that's fine, I can run things overnight. I woke up today to find out that dd doesn't handle extended partitions and needs me to dd them one by one. That's cool, I'll just have that running in the background today.

    If the clone doesn't work or if it's too much trouble to take the clone and give it its own identity, I'll probably wipe it and do another install. Since the X230T is on Kubuntu, I think I'll keep it on Kubuntu as well, to minimize the things I need to keep in my head as I switch between computers. My home directory is in a separate partition, so I can keep it if I want to try something different.

    Now I just have to wait a few hours for these dd commands...

  • 2024-09-11T14:14:55.602Z static blog

    My "plugins is not iterable" issue got fixed when I downgraded `@11ty/eleventy` from `@beta` to `@2.0.1`. Yay, that's one thing off my list!

Other tech stuff
Parenting
  • 2024-09-17T12:28:29.082Z emotion check-in

    I appreciate my kiddo's grade 3 teacher. =) She's currently doing the morning check-in of emotions (how's everyone feeling) using 9 images of Grogu with different facial expressions, which gets the kids (1) laughing, (2) interpreting facial expressions that aren't explicitly labeled, and (3) figuring out what they're feeling.

  • 2024-09-12T12:50:02.014Z pull system

    The kiddo is 8 and I'm developing a better understanding of what "fiercely independent" means. One of the things I'm working on learning is how to shut up and trust the process. =) I've started thinking of it like the pull system of Lean manufacturing principles. Things work out better when I wait for her to ask a question (to pull from me) because at that point, she's ready to hear the answer.

As it turns out, org-list-to-org uses the Org export mechanism, so it quietly discards things like #+begin_export html blocks. I decided to hard-code assumptions about the list's structure instead, which works for now.

View org source for this post