Categories: geek » emacs

View topic page - RSS - Atom - Subscribe via email
Recommended links:

Reading more blogs; Emacs Lisp: Listing blogs based on an OPML file

| emacs, blogging

Nudged by Dave Winer's post about old-school bloggers and my now-nicely-synchronizing setup of NetNewsWire (iOS) and FreshRSS (web), I gave Claude AI this prompt to list bloggers (with the addition of "Please include URLs and short bios.") and had fun going through the list it produced. A number of people were no longer blogging (unreachable sites or inactive blogs), but I found a few that I wanted to add to my feed reader.

Here is my people.opml at the moment (slightly redacted, as I read my husband's blog as well). This list has some non-old-school bloggers as well and some sketchnoters, but that's fine. It's a very tiny slice of the awesomeness of the Internet out there, definitely not exhaustive, just a start. I've been adding more by trawling through indieblog.page and the occasional interesting post on news.ycombinator.com.

It makes sense to make an HTML version to make it easier for people to explore, like those old-fashioned blog rolls. Ooh, maybe some kind of table like indieblog.page, listing a recent item from each blog. (I am totally not surprised about my tendency to self-nerd-snipe with some kind of Emacs thing.) This uses my-opml-table and my-rss-get-entries, which I have just added to my Emacs configuration.

my-opml-table
(defun my-opml-table (xml)
  (sort
   (mapcar
    (lambda (o)
      (let ((latest (car (condition-case nil (my-rss-get-entries (dom-attr o 'xmlUrl))
                           (error nil)))))
        (list
         (if latest
             (format-time-string "%Y-%m-%d" (plist-get latest :date))
           "")
         (org-link-make-string
          (or (dom-attr o 'htmlUrl)
              (dom-attr o 'xmlUrl))
          (replace-regexp-in-string " *|" "" (dom-attr o 'text)))
         (if latest
             (org-link-make-string
              (plist-get latest :url)
              (or (plist-get latest :title) "(untitled)"))
           ""))))
    (dom-search
     xml
     (lambda (o)
       (and
        (eq (dom-tag o) 'outline)
        (dom-attr o 'xmlUrl)
        (dom-attr o 'text)))))
   :key #'car
   :reverse t))

my-rss-get-entries: Return a list of the form ((:title … :url … :date …) …).
(defun my-rss-get-entries (url)
  "Return a list of the form ((:title ... :url ... :date ...) ...)."
  (with-current-buffer (url-retrieve-synchronously url)
    (set-buffer-multibyte t)
    (goto-char (point-min))
    (when (re-search-forward "<\\?xml\\|<rss" nil t)
      (goto-char (match-beginning 0))
      (sort
       (let* ((feed (xml-parse-region (point) (point-max)))
              (is-rss (> (length (xml-get-children (car feed) 'entry)) 0)))
         (if is-rss
             (mapcar
              (lambda (entry)
                (list
                 :url
                 (or
                  (xml-get-attribute
                   (car
                    (or
                     (seq-filter (lambda (x) (string= (xml-get-attribute x 'rel) "alternate"))
                                 (xml-get-children entry 'link))
                     (xml-get-children entry 'link)))
                   'href)
                  (dom-text (dom-by-tag entry 'guid)))
                 :title
                 (elt (car (xml-get-children entry 'title)) 2)
                 :date
                 (date-to-time (elt (car (xml-get-children entry 'updated)) 2))))
              (xml-get-children (car feed) 'entry))
           (mapcar (lambda (entry)
                     (list
                      :url
                      (or (caddr (car (xml-get-children entry 'link)))
                          (dom-text (dom-by-tag entry 'guid)))
                      :title
                      (caddr (car (xml-get-children entry 'title)))
                      :date
                      (date-to-time (elt (car (xml-get-children entry 'pubDate)) 2))))
                   (xml-get-children (car (xml-get-children (car feed) 'channel)) 'item))))
       :key (lambda (o) (plist-get o :date))
       :lessp #'time-less-p
       :reverse t))))

(my-opml-table (xml-parse-file "~/Downloads/people.opml"))
2025-03-19 Flutterby! Bug replicators
2025-03-19 kottke.org A History Professor Answers Questions About Dictators
2025-03-19 Dan's Daily Posting ahead
2025-03-19 Dave Winer (untitled)
2025-03-19 Doc Searls Come from Everywhere
2025-03-19 Jack Baty Fixing the terrible scrolling behavior with Logitech MX Master on macOS
2025-03-19 Jeremy Friesen Crocus
2025-03-19 Matt Maldre Does the word ‘fascinating’ come from ‘facet’?
2025-03-19 Matt Webb An appreciation for the Useless Machine
2025-03-19 Wil Wheaton I made a thing!
2025-03-19 Sketchy Ideas 10 Lessons from The Psychology of Money in Visuals
2025-03-18 Ava cool links VIII: open access and AI, oppression, euro cloud
2025-03-18 Jessica Smith Big Ideas for Little Philosophers
2025-03-18 Maria Popova How to Get Out of Your Own Way: John Berryman on Defeating the Three Demons of Creative Work
2025-03-18 Om Malik Goodbye Torque. Hello TeraFLOPS!
2025-03-18 Tim Bray Long Links
2025-03-18 Warren Ellis status, week of 18mar25
2025-03-18 Sketchnote Lab Real-World Sketching Workshop with Mike Rohde, coming Saturday, April 26, 2025!
2025-03-17 Matthew Haughey A marathon trip
2025-03-17 Michael Lopp The Product Engineer
2025-03-17 Pete Prodoehl Editing a Bear Theme
2025-03-17 Protesilaos Stavrou On the Stoic harmony with nature
2025-03-16 Abhijit's Sketchnotes Second jobs, pay cuts, glass bottles and Oscars
2025-03-16 Illustrated Life Loving a Bent Nib
2025-03-16 QAspire Consulting - Tanmay Vora Thriving in the Age of AI: Head, Hands, and Heart
2025-03-16 The Visual Drawer Motivation Isn't Magic: It's Structure!
2025-03-15 genehack.blog Weeknote #25 (20250309-20250315)
2025-03-15 Jeffrey Zeldman Your opt-innie wants to talk to your opt-outtie.
2025-03-15 oylenshpeegul Ruth
2025-03-15 Mike Monteiro How to hide a painting
2025-03-14 Henrik Karlsson King of the sea snakes
2025-03-14 Kevin Kelly Best Thing Since Sliced Bread?
2025-03-14 Andy Draws Planting Seeds of Kindness
2025-03-13 Chris Hannah I Challenged Myself to Build a Website Using Cursor
2025-03-13 Marie K. Ekeberg Pi Day 2025 - Let’s have fun with numbers!
2025-03-13 David’s Substack Sources For Graphic Nonfiction Online
2025-03-11 Manuel Uberti A sense of belonging
2025-03-10 Nicholas Carr Strong Men and Strong Machines
2025-03-09 kupajo Start With the End in Mind
2025-03-09 Penelope Trunk I hate having to earn money, but I like knowing what makes me valuable
2025-03-06 Clarity Canvas Weekly by Tanmay Vora Thriving in the Age of AI: Head, Hands, and Heart
2025-03-04 LetSketchin’s Newsletter #84 - What's your motivation to join this newsletter
2025-03-03 Keep the Creative Juices Flowing Have you ever had an UN-IDEA?
2025-03-02 but she's a girl… ZSA Voyager
2025-02-25 Rhys Lindmark 2025 Update
2025-02-24 Derek Sivers Why did I move to New Zealand?
2025-02-23 Scott McCloud New for Spring: The Cartoonists Club!
2025-02-07 James Endres Howell What can one person do?
2025-01-03 Anil Dash Understanding DOGE as Procurement Capture
2024-12-21 Arne Bahlo My favorite things of 2024
2024-12-11 The Sketchy Anthropologist Getting Started with Sketchnotes [2]: Eva Lotta-Lamm - Domestika Sketchnoting Course
2024-11-21 Avdi Grimm You’re not selling a solution
2024-11-08 Joi Ito Morning Thick Tea and Yuen
2024-01-15 Blaine Mooers Track daily writing progress by project in 2024 and 2025
2022-11-13 Howard Rheingold Compendium of Podcasts Featuring Howard

I'm rebuilding my feed list from scratch. I want to read more. I read the aggregated feeds at planet.emacslife.com every week as part of preparing Emacs News. Maybe I'll go over the list of blogs I aggregate there, widen it to include all posts instead of just Emacs-specific ones, and see what resonates. Emacs people tend to be interesting. Here is an incomplete list based on people who've posted in the past two years or so, based on this work-in-progress planetemacslife-expanded.opml. (I haven't tweaked all the URLs yet. I stopped at around 2023 and made the rest of the elements xoutline instead of outline so that my code would skip them.)

(my-opml-table (xml-parse-file "~/Downloads/planetemacslife-expanded.opml"))
2025-03-19 Irreal The Power Of Isearch
2025-03-19 James Dyer Ollama-Buddy 0.9.8: Transient Menu, Model Managing, GGUF Import, fabric Prompts and History Editing
2025-03-19 Emacs Redux Relative Line Numbers
2025-03-19 Jeremy Friesen Crocus
2025-03-19 Michal Sapka I stopped writing alt-text to most images here
2025-03-18 Lars Ingebrigtsen WoRdPrEsS ReWrItEs My PoStS
2025-03-18 William Denton Art is the imposition of form on experience
2025-03-18 Will Schenk Knowledge Navigator
2025-03-17 Listful Andrew Hash tables look better in Emacs 30
2025-03-17 Sacha Chua Org Mode: Merge top-level items in an item list
2025-03-17 Protesilaos Stavrou On the Stoic harmony with nature
2025-03-17 Marcin Borkowski Bash script and passwords
2025-03-17 Christian Tietze NSPopover in NSTextView With Links Is Broken: Accessibility Hierarchy Slowdown
2025-03-17 TAONAW Mode (untitled)
2025-03-17 John D. Cook Lessons Learned With the Z3 SAT/SMT Solver
2025-03-16 Grant Rettke Interesting new gptel v0.9.8 features and commits since v0.9.7
2025-03-16 Magnus Using lens-aeson to implement FromJSON
2025-03-16 200ok Atomize: A Simple CLI Tool for Managing Atom Feeds
2025-03-16 Aimé Bertrand Raycast - Activate Entra Role via PIM with Graph
2025-03-15 Tim Heaney Ruth
2025-03-15 Susam Pal MathB 1.3.0
2025-03-14 Bozhidar Batsov Updating my toolbox: Ghostty and Fish
2025-03-14 Matt Maguire Japanese Electronic Dictionary (Casio XD-G9850)
2025-03-13 Alvaro Ramirez Journelly open for beta
2025-03-13 Charles Choi Announcing Casual Make
2025-03-13 Marie K. Ekeberg Pi Day 2025 - Let’s have fun with numbers!
2025-03-11 Eric MacAdie 2025-03 Austin Emacs Meetup
2025-03-11 Manuel Uberti A sense of belonging
2025-03-10 Norm XML Resolver updates
2025-03-09 Andrey Listopadov Dynamic font-lock for Fennel
2025-03-08 Arthur A. Gleckler Backup Sampling
2025-03-08 Alex Popescu TIL Succinct Data Structures
2025-03-07 Kisaragi Hiu Plasma: Avoiding having to type the login password again when first using Git / GPG
2025-03-07 The Emacs Cat Using Emacs Org Mode for Reproducibility Testing
2025-03-06 Mickey Petersen Replacing tmux and GNU screen with Emacs
2025-03-05 Amit Patel Emacs Tree-sitter custom highlighting, part 3
2025-03-05 Kris Carta My Delivery Sheet
2025-03-05 Ben Simon G's Baltimore Adventure - The USS Torsk
2025-03-02 Thanos Apollo Emacs Note Taking & Journaling using org-gnosis [Video]​
2025-03-02 But She's a Girl ZSA Voyager
2025-02-28 Mario Jason Braganza 2025
2025-02-28 Gijs Hillenius The bathwater of our 21st century
2025-02-25 James Cherti Toggling symbol highlighting in Emacs with unique colors for each symbol using built-in functions
2025-02-24 Peter J. Jones Automatic Theme Switching in Emacs
2025-02-24 Benjamin Slade C-c-c-conjecturing, and dealing with recursion in Emacs (more excursus)
2025-02-23 Ruslan Bekenev Emacs: glasses-mode
2025-02-23 J.e.r.e.m.y B.r.y.a.n.t Emacs 30.1 released including which-key
2025-02-23 Vineet Naik Premature automation
2025-02-22 Rahul Juliato Compiling Emacs 30.1 from the source on Debian
2025-02-22 Mark Tomczak Running Sandstorm From a Raid 1 Drive Array
2025-02-22 whatacold Rewrite of a Flask Web App in Clojure
2025-02-22 localauthor Ežerų Dugne
2025-02-18 Peter Povinec Speed Dialing Your Favorite Files
2025-02-18 Rodrigo Morales Compile zathura 0.5.11 in Ubuntu 24.04 LTS
2025-02-17 William Gallard Hatch Don't Ossify Defaults
2025-02-13 Anand Tamariya Emacs Font is wider
2025-02-13 yuri tricys Etymology: From Cupidity to Romance And Roses
2025-02-12 Erik L. Arneson maybe: A command-line tool that succeeds sometimes
2025-02-12 Luke Plant Christ the True and Better Frodo
2025-02-12 Unwound Stack Peppering Passwords in Rust
2025-02-08 Tory Anderson snippets that defy orgmode tangling
2025-02-08 Chris Maiorana From Emacs To Microsoft Word (And Beyond, Really)
2025-02-08 Anything goes PiZero OTG: Host or Peripheral
2025-02-03 Meta Redux Projectile Introduces Significant Caching Improvements
2025-02-02 Gene Goykhman Quickly summing up the whole stack in Emacs Calc
2025-02-02 Bz01 Using spritely hoot on nixos
2025-02-01 Jack Baty FYI: I have a new blog and RSS feed
2025-01-29 Tony Zorman Speeding up LaTeX compilation
2025-01-26 Arialdo Martini Emacs: a peek under Imenu’s hood
2025-01-25 Yi Tang Setup ssh-agent Systemd Service for Emacs
2025-01-23 punchagan Some useful Git configuration for Windows
2025-01-14 Srijan Choudhary 2025-01-15-001
2025-01-10 Isa Mert Gurbuz .emacs.d/.init.el
2025-01-07 Stefan van der Walt Pomodoros with org-timer
2025-01-03 Wai Hon Distinguish Repeated Tasks in Org Agenda
2025-01-01 Karthik Chikmagalur Tool use with gptel: looking for testers!
2024-12-21 Arne Bahlo My favorite things of 2024
2024-12-18 Maryanne Wachter Why is multithreading Selenium lousy on MacOS?
2024-12-13 Lambda Land What's New in Emacs: Last Decade Edition
2024-12-06 Jean-Christophe Helary Building "vanilla" emacs on macOS, with MacPorts, and more…
2024-11-21 JD Gonzales Kamal Tip - Private Network only Database Server
2024-11-15 Jonathan Lamothe Organizing My Life with org-mode
2024-11-14 Hristos N. Triantafillou Void Linux On A Framework Laptop: Two Years Later
2024-11-14 Hanno git-annex: Managing my most ancient data
2024-11-07 Ryan Rix Two Updates: Org+Nix dev streams, and my new DNS resolver
2024-11-03 Emacs Notes Enable completions for `Font Family’ field in `M-x customize-face RET’
2024-11-02 Ben Whitley Denote Project Tasks
2024-10-27 Andrea A useful function to contribute to Scala Metals lsp server with Emacs
2024-10-24 Summer Emacs ERC Flipping Buffers
2024-10-03 Jiewawa Useful Emacs commands for reading
2024-09-11 Sanel Zukan evil-mode in terminal without Alt/Meta
2024-09-08 Troy Hinckley What is the best pointer tagging method?
2024-08-16 Wiktor Gołgowski Org-roam: custom linking during capture
2024-08-14 Jonas Bernoulli Forge 0.4.0 and 0.4.1 released
2024-08-11 Nicolas Martyanoff Controlling link opening in Emacs
2024-07-31 T. V. Raman Emacspeak — A Speech Odyssey
2024-07-30 jao eww to org
2024-07-27 Peter Tillemans Refactoring Emacs Config using Org
2024-07-07 Timo Geusch If you get this error from Time Machine on Samba, check available disk space
2024-06-23 Peter Vágner Emacs A11y Tip #3: Emacs with speechd-el running on Termux for Android
2024-06-05 Zachary Kanfer Less: a Survival Guide
2024-05-23 Jürgen Hötzel Gnome Search Provider: Emacs Integration
2024-05-22 Gretzuni B/logroll
2024-05-14 Bryan Murdock How To Retroactively Annex Files Already in a Git Repo
2024-05-02 Evan Moses Home Assistant: using target in blueprints
2024-04-11 Emacs TIL The Night Before A Coding Interview
2024-03-26 M. Rincón Eat Evil
2024-02-12 Cameron Desautels Chinese Zodiac Time for Emacs
2024-01-19 Corwin Brust Emacs 29.2 Windows Binaries
2023-12-10 Alex Bennée A Systems Programmer's Perspectives on Generative AI
2023-12-09 Peter Prevos Writing Prose with Emacs
2023-12-05 Thomas Fitzsimmons Product Idea: CRT-alike OLED driver
2023-10-21 What the .emacs.d!? buffers.el-01
2023-08-16 Murilo Pereira I just made my first $1 on the internet!
2023-08-07 Phil Newton Updated Pocket highlights bookmarklet
2023-08-06 Shae Erisson How to use Private Storage on Android
2023-07-18 Phil Jackson Using Djblue's portal for tap in Babashka
2023-06-29 Jiacai Liu Embed git commit in Zig programs
2023-05-21 Fritz Grabo Introducing elfeed-webkit
2023-05-01 Tyler Smith Posts

Making this table was fun. It's nice to see a lot of people also writing and learning out loud. This reminded me a little of EmacsConf - 2020 - talks - Sharing blogs (and more) with org-webring. TODO: Could be fun to have a blogroll page again.

I notice I tend to like:

  • posts about adapting technology to personal interests, more than posts about the industry or generalizations
  • detailed posts about things I'm currently interested in (Emacs, personal knowledge management, some Javascript), more than detailed tech posts about things I've decided not to get into at the moment
  • "I" posts more than "You" posts: personal reflections rather than didactic advice
  • curiosity, fun, experimentation

Looking forward to discovering more!

Related:

See discussion on Mastodon

View org source for this post

Org Mode: Merge top-level items in an item list

| org

I usually summarize Mastodon links, move them to my Emacs News Org file, and then categorize them. Today I accidentically categorized the links while they were still in my Mastodon buffer, so I had two lists with categories. I wanted to write some Emacs Lisp to merge sublists based on the top-level items. I could sort the list alphabetically with C-c ^ (org-sort) and then delete the redundant top-level item lines, but it's fun to tinker with Emacs Lisp.

Example input:

  • Topic A:
    • Item 1
    • Item 2
      • Item 2.1
  • Topic B:
    • Item 3
  • Topic A:
    • Item 4
      • Item 4.1

Example output:

  • Topic B:
    • Item 3
  • Topic A:
    • Item 1
    • Item 2
      • Item 2.1
    • Item 4
      • Item 4.1

The sorting doesn't particularly matter to me, but I want the things under Topic A to be combined. Someday it might be nice to recursively merge other entries (ex: if there's another "Topic A: - Item 2" subitem like "Item 2.2"), but I don't need that yet.

Anyway, we can parse the list with org-list-to-lisp (which can even delete the original list) and recreate it with org-list-to-org, so then it's a matter of transforming the data structure.

(defun my-org-merge-list-entries-at-point ()
  "Merge entries in a nested Org Mode list at point that have the same top-level item text."
  (interactive)
  (save-excursion
    (let* ((list-indentation (save-excursion
                               (goto-char (caar (org-list-struct)))
                               (current-indentation)))
           (list-struct (org-list-to-lisp t))
           (merged-list (my-org-merge-list-entries list-struct)))
      (insert (org-ascii--indent-string (org-list-to-org merged-list) list-indentation)
              "\n"))))

(defun my-org-merge-list-entries (list-struct)
  "Merge an Org list based on its top-level headings"
  (cons (car list-struct)
        (mapcar
         (lambda (g)
           (list
            (car g)
            (let ((list-type (car (car (cdr (car (cdr g))))))
                  (entries (seq-mapcat #'cdar (mapcar #'cdr (cdr g)))))
              (apply #'append (list list-type) entries nil))))
         (seq-group-by #'car (cdr list-struct)))))

A couple of test cases:

(ert-deftest my-org-merge-list-entries ()
  (should
   (equal
    (my-org-merge-list-entries
     '(unordered ("Topic B:" (unordered ("Item 3")))))
    '(unordered ("Topic B:" (unordered ("Item 3"))))))
  (should
   (equal
    (my-org-merge-list-entries
     '(unordered ("Topic B:" (unordered ("Item 3")))
                 ("Topic A:"
                  (unordered ("Item 1")
                             ("Item 2"
                              (unordered ("Item 2.1")))))
                 ("Topic A:"
                  (unordered
                   ("Item 4" (unordered ("Item 4.1")))))))
    '(unordered
      ("Topic B:" (unordered ("Item 3")))
      ("Topic A:"
       (unordered ("Item 1")
                  ("Item 2" (unordered ("Item 2.1")))
                  ("Item 4" (unordered ("Item 4.1")))))))))
View org source for this post

2025-03-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, 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

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