15

There's lots of documentation about inserting or storing org-mode-links, but apparently none about copying them to buffers in other formats.

How do you copy the URL of an org-mode-link from an org file into the clipboard/kill ring with as few keystrokes as possible? I tried org-store-link and org-insert-link, but it dumps the whole org-mode syntax into whatever other buffer you have open.

Example: buffer 1 org-mode, buffer 2 Markdown.

  1. Visit buffer 1, C-s search for link.
  2. Magic happens, URL is in clipboard
  3. Visit buffer 2. C-y to yank URL into buffer.
10

Here is one way of achieving what you want, using text properties.

You can go to the link in the org file you want to copy and execute the command my-org-retrieve-url-from-point this will copy the org link at current point to the clipboard. Before adding the link to clipboard a yank-handler (my-yank-org-link) is registered which is called while pasting the link. The yank-handler checks if the current buffer is in org-mode or a mode derived from org-mode, if so it inserts the link as it is (a org-link), otherwise it extracts the URL from the link and inserts it

(defun my-yank-org-link (text)
  (if (derived-mode-p 'org-mode)
      (insert text)
    (string-match org-bracket-link-regexp text)
    (insert (substring text (match-beginning 1) (match-end 1)))))

(defun my-org-retrieve-url-from-point ()
  (interactive)
  (let* ((link-info (assoc :link (org-context)))
         (text (when link-info
                 ;; org-context seems to return nil if the current element
                 ;; starts at buffer-start or ends at buffer-end
                 (buffer-substring-no-properties (or (cadr link-info) (point-min))
                                                 (or (caddr link-info) (point-max))))))
    (if (not text)
        (error "Not in org link")
      (add-text-properties 0 (length text) '(yank-handler (my-yank-org-link)) text)
      (kill-new text))))

Here is a DWIM version of kill-ring-save, which uses kill-ring-save if region is active or copies the org-link at point

(defun my-smarter-kill-ring-save ()
  (interactive)
  (if (region-active-p)
      (call-interactively #'kill-ring-save)
    (when (eq major-mode 'org-mode)
      (call-interactively #'my-org-retrieve-url-from-point))))

Note: This does not currently distinguish between a URL link and internal links.

  • 1
    I removed the if, because when using the GUI Emacs it always copied the entire link ([[a]][b]]) instead of the URL part (a) – Nitz Feb 1 '15 at 8:06
2

Late to the party (and my first post here, by the way), but I think this might be useful to others too. The accepted answer works perfectly when yanking inside emacs again, but the actual text copied to the system clipboard is still the full org-mode syntax. I wanted something that could copy a link out of both org-mode and emacs. Use cases: I've been doing a lot of web dev lately, and I often use multiple browsers. Only one of them can be the default for the C-c c-o shortcut, and sometimes I want to open a link in a non-default one. Also, pasting links to coworkers on Slack, et cetera.

Long story short, I've come up with this solution by mixing and matching the accepted answer:

(defun my-org-export-url ()
  (interactive)
  (let* ((link-info (assoc :link (org-context)))
         (text (when link-info
                 (buffer-substring-no-properties (or (cadr link-info) (point-min))
                                                 (or (caddr link-info) (point-max))))))
    (if (not text)
        (error "Not in org link")
      (string-match org-bracket-link-regexp text)
      (kill-new (substring text (match-beginning 1) (match-end 1))))))

This will copy to the clipboard the link only part of an org-mode link.

In fact, I have integrated both the previous answer's solution and this new function inside my .emacs, each with its own keybinding. Full code here:

(defun my-yank-org-link (text)
  (if (derived-mode-p 'org-mode)
      (insert text)
    (string-match org-bracket-link-regexp text)
    (insert (substring text (match-beginning 1) (match-end 1)))))

(defun my-org-copy-smart-url ()
  (interactive)
  (let* ((link-info (assoc :link (org-context)))
         (text (when link-info
                 (buffer-substring-no-properties (or (cadr link-info) (point-min))
                                                 (or (caddr link-info) (point-max))))))
    (if (not text)
        (error "Not in org link")
      (add-text-properties 0 (length text) '(yank-handler (my-yank-org-link)) text)
      (kill-new text))))
(global-set-key (kbd "C-c c") 'my-org-copy-smart-url)

(defun my-org-export-url ()
  (interactive)
  (let* ((link-info (assoc :link (org-context)))
         (text (when link-info
                 (buffer-substring-no-properties (or (cadr link-info) (point-min))
                                                 (or (caddr link-info) (point-max))))))
    (if (not text)
        (error "Not in org link")
      (string-match org-bracket-link-regexp text)
      (kill-new (substring text (match-beginning 1) (match-end 1))))))
(global-set-key (kbd "C-c e") 'my-org-export-url)

I've chosen the C-c e and C-c c keybindings because they are good mnemonics for export and copy and they are unused in org-mode. They also somehow fit with the already existing keybinding C-c C-o for opening links.

1

Another possibility: With the cursor on the link, execute org-insert-link. This is normally C-c C-l. With evil mode (or maybe just with Spacemacs) , i l also works. This enters the link insert flow with the link value pre-populated. You can then do M-x evil-yank-line while the minibuffer has the contents of the link address.

  • This method is basically what I use, specifically I go C-c C-l M-S-<backspace> C-g. – Omar Jun 6 at 3:02
  • It works but not so efficient. – itirazimvar Sep 8 at 21:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.