ORG-DOWNLOAD-YANK FIX FOR "NOT A URL" ERROR




It's broken
----------------------------------------------------------------------
There's an open bug in the Emacs package `org-download-yank' that
makes it difficult to use file addresses yanked from a dired buffer as
the source of an image to be inserted in an org-mode document. The
intended functionality is that the user can open a dired buffer,
navigate to a file, type "0 w", switch to their org-mode buffer, and
invoke `org-download-yank' to have that image inserted into the org
file and stored in an assets folder. Instead, the function raises a
"Not a URL" error.

The source of the issue is trivial. The `org-download-yank' function
raises errors for any argument (technically, the last entry in the
kill ring) that does not posses a URL type.

,----
|   ;; excerpt from org-download.el:org-download-yank
|   (let ((k (current-kill 0)))
|     (unless (url-type (url-generic-parse-url k))
|       (user-error "Not a URL: %s" k))
`----

Given a value like "/home/roygbyte/someimage.png",
`url-generic-parse-url' will return a struct. The `type' field is the
URI scheme, which the example path does not contain. So, obviously it
fails.

Based on other issues raised in the project repo, the behavior of
dired may have changed, and the package author moved onto other
interests. Thus, the behavior was not fixed for newer version of
Emacs. So it goes.

I use `org-download-yank' function enough for my phlog workflow that I
needed a fix. Fortunately, I really like introspecting Emacs and
writing Elisp. It didn't take too long, and I learned some new things
with my solution, below.


Fixing it
----------------------------------------------------------------------
My approach was to use `advice-add' to hook a function `:before' any
invokation of `org-download-yank'. In my function, I take modify the
last kill into a URL-like file path by prefixing it with "file:". It's
a simple fix and the most straightfoward, non-invaisive solution I
could summon. As you can see, the conditional block is nearly
identical to what's used in `org-download-yank'. The fun bit that I
got to learn about was the kill ring, including the second parameter
of `kill-new' which will modify the current kill.

,----
|   (defun modify-file-path-for-org-download-yank ()
|     "org-download-yank has a bug where an image yanked from dired using
|   `0 w` will raise 'Not a URL' error. This function, when added as
|   advice to org-download-yank, makes it work. It prepends `file:`
|   to the front of the last kill." 
|     (let ((k (current-kill 0)))
|       (when (and (not (url-type (url-generic-parse-url k)))
Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
|         (kill-new (concat "file:" k) t)))) ;; `t` to replace front of kill ring
|   (advice-add 'org-download-yank :before #'modify-file-path-for-org-download-yank)
`----

Footnotes
----------------------------------------------------------------------