Previously, on the Emacs stack exchange:
In Org mode, when I open a link (C-c C-o) (…) (that) contains a wildcard, such as
file:3_o*.pdf, Emacs opens it through
diredinstead (…) within Emacs.
I would instead have it open the first match of that pattern in the system application …
The handling of
file: links is hard-coded in Org mode. If there is any wildcard in the given
org-link-open will nope out of the situation and instead call
dired. And while one could change Org mode’s source code in the local elisp files, I remembered that you can change the arguments or results of functions with advices.
I opted for an advice
org-link-open with the following code:
(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)
So whenever you open a link with C-c C-o (
org-open-at-point which calls
org-link-open), you end up with a concrete file.
I recommend using a custom link type like
first: or wrapping the code above minor mode, as the advice is somewhat invasive and might surprise users that really want to get a list of matching files instead.
I’m open to any feedback on the elisp code, especially since I’m still a elisp newbie.