Categories: geek » emacs

View topic page - RSS - Atom - Subscribe via email

Remove open Org Mode clock entries

| emacs, org

Pedro pointed out that I had some incomplete clock entries in my Emacs configuration. org-resolve-clocks prompts you for what to do with each open clock entry in your Org agenda files and whatever Org Mode files you have open.

If you don't feel like cancelling each clock with C, I also wrote this function to delete all open clocks in the current file.

(defun my-org-delete-open-clocks ()
  (interactive)
  (flush-lines
   (rx
    line-start
    (zero-or-more space)
    "CLOCK:"
    (one-or-more space)
    (regexp org-ts-regexp-inactive)
    (zero-or-more space)
    line-end)))
This is part of my Emacs configuration.
View org source for this post

2025-03-10 Emacs news

| emacs, emacs-news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Mastodon #emacs, Bluesky #emacs, Hacker News, lobste.rs, programming.dev, lemmy.world, lemmy.ml, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

View org source for this post

Getting an Org link URL from a string; debugging regex groups

| elisp, org

Sometimes I want to get the URL from a string whether the string contains a bare URL (https://example.com) or an Org bracketed link ([[https://example.com]] or [[https://example.com][Example]], ignoring any extra non-link text (blah https://example.com blah blah). org-link-any-re seemed like the right regular expression to use, but I started to get a little dizzy looking at all the parenthesis and I couldn't figure out which matching group to use. I tried using re-builder. That highlighted the groups in different colours, but I didn't know what the colours meant. All the matching information is in (match-data), but integer pairs can be a little hard to translate back to substrings. So I wrote an Emacs Lisp function to gave me the matching groups:

(defun my-match-groups (&optional object)
  "Return the matching groups, good for debugging regexps."
  (seq-map-indexed (lambda (entry i)
                     (list i entry
                           (and (car entry)
                                (if object
                                    (substring object (car entry) (cadr entry))
                                  (buffer-substring (car entry) (cadr entry))))))
                   (seq-partition
                    (match-data t)
                    2)))

There's probably a standard way to do this, but I couldn't figure out how to find it.

Anyway, if I give it a string with a bracketed link, I can tell that the URL ends up in group 2:

(let ((text "blah [[https://example.com][example]] blah blah"))
  (when (string-match org-link-any-re text)
    (pp-to-string (my-match-groups text))))
((0 (5 37) "[[https://example.com][example]]")
 (1 (5 37) "[[https://example.com][example]]")
 (2 (7 26) "https://example.com")
 (3 (28 35) "example"))

When I use a string with a bare link, I can see that the URL ends up in group 7:

(let ((text "blah https://example.com blah blah"))
  (when (string-match org-link-any-re text)
    (pp-to-string (my-match-groups text))))
((0 (5 24) "https://example.com")
 (1 (nil nil) nil) (2 (nil nil) nil)
 (3 (nil nil) nil) (4 (nil nil) nil)
 (5 (nil nil) nil) (6 (nil nil) nil)
 (7 (5 24) "https://example.com")
 (8 (5 10) "https") (9 (11 24) "//example.com"))

This makes it so much easier to refer to the right capture group. So now I can use those groups to extract the URL from a string:

(defun my-org-link-url-from-string (s)
  "Return the link URL from S."
  (when (string-match org-link-any-re s)
    (or
     (match-string 7 s)
       (match-string 2 s))))

This is handy when I summarize Emacs News links from Mastodon or from my inbox. Sometimes I add extra text after a link that I've captured from my phone, and I don't want that included in the URL. Sometimes I have a bracketed link that I've copied from org-capture note. Now I don't have to worry about the format. I can just grab the link I want.

View org source for this post

2025-03-03 Emacs news

| emacs, emacs-news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Mastodon #emacs, Bluesky #emacs, Hacker News, lobste.rs, programming.dev, lemmy.world, lemmy.ml, communick.news, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

View org source for this post

Working with smaller chunks of thoughts; adding anchors to paragraphs in Org Mode HTML export

Posted: - Modified: | org, js

I write my blog posts in Org Mode and export them to Eleventy with ox-11ty, which is derived from the ox-html backend.

Sometimes I want to link to something in a different blog post. This lets me build on thoughts that are part of a post instead of being a whole post on their own.

If I haven't added an anchor to the blog post yet, I can add one so that I can link to that section. For really old posts where I don't have an Org source file, I can edit the HTML file directly and add an id="some-id" so that I can link to it with /url/to/post#some-id. Most of my new posts have Org source, though. I have a my-blog-edit-org function and a my-blog-edit-html function in my Emacs configuration to make it easier to jump to the Org file or HTML for a blog post.

If the section has a heading, then it's easy to make that linkable with a custom name. I can use org-set-property to set the CUSTOM_ID property to the anchor name. For example, this voice access section has a heading that has CUSTOM_ID, as you can see in the . If I don't mind having long anchor names, I can use the my-assign-custom-ids function from my config to automatically set them based on the outline path.

my-assign-custom-ids
(defun my-assign-custom-ids ()
  (interactive)
  (let ((custom-ids
         (org-map-entries (lambda () (org-entry-get (point) "CUSTOM_ID")) "CUSTOM_ID={.}")))
    (org-map-entries
     (lambda ()
       (let ((slug
              (replace-regexp-in-string
               "^-\\|-$" ""
               (replace-regexp-in-string "[^A-Za-z0-9]+" "-"
                                         (downcase (string-join (org-get-outline-path t) " "))))))
         (while (member slug custom-ids)
           (setq slug (read-string "Manually set custom ID: ")))
         (org-entry-put (point) "CUSTOM_ID" slug)))
     "-CUSTOM_ID={.}")))

Adding anchors to paragraphs

If the part that I want to link to is not a heading, I can add an ID by using the #+ATTR_HTML: :id ... directive, like this snippet from my reflection on landscapes and art:

  #+ATTR_HTML: :id interest-development
  That reminds me a little of another reflection
  I've been noodling around on interest development...

Text fragments

Text fragments are even more powerful, because I can link to a specific part of a paragraph. I can link to one segment with something like #::text=text+to+highlight~. I can specify multiple text fragments to highlight by using #::text=first+text+to+highlight&text=second+text~, and the browser will automatically scroll to the first highlighted section. I can specify a longer section by using text=textStart,textEnd. Example: #:~:text=That%20is%20the%20gap,described The text fragments documentation has more options, including using prefixes and suffixes to disambiguate matches.

Text fragment links require rel="noopener" for security, so I added JKC-Codes/eleventy-plugin-automatic-noopener to my 11ty config.

Update 2025-03-20: Quick ways to link to a text fragment:

  • On my Android phone, selecting text in Google Chrome and sharing it automatically includes the text and a link to the text fragment.
  • In Google Chrome on my iPad, my process is:
    1. Select the text and choose "Copy Link with Highlight".
    2. Tap the selected text again and share it.
    3. Paste the link after the shared text.
  • There's this Text Fragment extension for Firefox.
  • I have some Emacs Lisp to link to currently-selected text using Spookfox. Spookfox connects Emacs to Firefox using a browser extension. Once it's properly set up and connected, it allows Emacs to evaluate things in the Firefox context.

These seem like good starting points for addressing smaller chunks of thoughts.

View org source for this post

2025-02-24 Emacs news

| emacs, emacs-news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Mastodon #emacs, Bluesky #emacs, Hacker News, lobste.rs, programming.dev, lemmy.world, lemmy.ml, communick.news, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

View org source for this post

2025-02-17 Emacs news

| emacs, emacs-news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Mastodon #emacs, Bluesky #emacs, Hacker News, lobste.rs, programming.dev, lemmy.world, lemmy.ml, communick.news, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

View org source for this post