Skip to main content
add advice variant
Source Link
Zeta
  • 1.1k
  • 9
  • 19

Custom link type

The manual has some more information on custom types, for example customization options. Note that the current guide uses plists to define the link type via org-add-link-type, but that's a recent(?) addition. I opted for the earlier, still valid syntax from 9.1.

Advice for org-link-open

This advice was tested in Org version 9.3.6 and 9.4-19. It will definitely not work in 9.1.9. Other versions are untested.

(defun my-org-expand-file-link (link)
  "Expand a pattern in LINK to the first matching file.

Returns the original LINK if no file matches the pattern in LINK or if it is not
a link of type 'file:'.  See info node `(org)External links' for more information."
  (let ((type (org-element-property :type link))
        (path (org-element-property :path link)))
    (cond
     ((equal type "file")
      (let ((candidates (file-expand-wildcards path)))
        (if candidates
            (org-element-put-property (org-element-copy link) :path (car candidates))
          link)))
     (t link))))

(defun my-org-link-open-advice (orig-fun link &rest args)
  "Advice for ORIG-FUN that expands patterns in 'file:' LINKs.
See `my-org-expand-file-link' for more information.
Optional argument ARGS are passed as-is."
  (apply orig-fun (my-org-expand-file-link link) args))

(advice-add 'org-link-open :around #'my-org-link-open-advice)

The manual has some more information on custom types, for example customization options. Note that the current guide uses plists to define the link type via org-add-link-type, but that's a recent(?) addition. I opted for the earlier, still valid syntax from 9.1.

Custom link type

The manual has some more information on custom types, for example customization options. Note that the current guide uses plists to define the link type via org-add-link-type, but that's a recent(?) addition. I opted for the earlier, still valid syntax from 9.1.

Advice for org-link-open

This advice was tested in Org version 9.3.6 and 9.4-19. It will definitely not work in 9.1.9. Other versions are untested.

(defun my-org-expand-file-link (link)
  "Expand a pattern in LINK to the first matching file.

Returns the original LINK if no file matches the pattern in LINK or if it is not
a link of type 'file:'.  See info node `(org)External links' for more information."
  (let ((type (org-element-property :type link))
        (path (org-element-property :path link)))
    (cond
     ((equal type "file")
      (let ((candidates (file-expand-wildcards path)))
        (if candidates
            (org-element-put-property (org-element-copy link) :path (car candidates))
          link)))
     (t link))))

(defun my-org-link-open-advice (orig-fun link &rest args)
  "Advice for ORIG-FUN that expands patterns in 'file:' LINKs.
See `my-org-expand-file-link' for more information.
Optional argument ARGS are passed as-is."
  (apply orig-fun (my-org-expand-file-link link) args))

(advice-add 'org-link-open :around #'my-org-link-open-advice)
Source Link
Zeta
  • 1.1k
  • 9
  • 19

Emacs lisp newbie here. As far as I know there are two ways to change this behaviour without changing Org's source code: either a custom link type, or an advice around org-link-open (see (elisp) Advising Functions).

I've opted for the former, as the latter changed between Org versions (you need an advice around org-link-open in Org 9.3.6 an and advice around org-open-at-point in 9.1.9):

(require 'org)

(org-add-link-type "first" 'org-first-open)

(defun org-first-open (pattern)
  "Open the first file that matches PATTERN.
PATTERN should match at least one file."
  (let ((candidates (file-expand-wildcards pattern)))
    (if candidates (org-open-file (car candidates))
      (error "No file matches \"%s\"" pattern))))

You can now use first:3_o*.pdf to get the first result of the wildcard expansion.

The manual has some more information on custom types, for example customization options. Note that the current guide uses plists to define the link type via org-add-link-type, but that's a recent(?) addition. I opted for the earlier, still valid syntax from 9.1.