0

I got How to paste images into Emacs org-mode running in Windows Subsystem for Linux running, so I can paste images in emacs org-mode, but I would like to get all images in the same directory, f.e. ~/MyImages.

Could anyone help me to get this code adapted so that all images are saved in one directory?

This was my original code I used, inspired by the Blog Post of Alex Rampp. I first take a screenshot with CTRL+SHIFT+s which is the Windows way of taking a screenshot to clipboard and then in my org-file I run my function my-org-paste-image.

    (defun my-org-paste-image ()
  "Paste an image into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (interactive)
  (let* ((target-file
          (concat
           (make-temp-name
            (concat (buffer-file-name)
                    "_"
                    (format-time-string "%Y%m%d_%H%M%S_"))) ".png"))
         (wsl-path
         (concat (as-windows-path(file-name-directory target-file))
                  "\\"
                  (file-name-nondirectory target-file)))
         (ps-script
          (concat "(Get-Clipboard -Format image).Save('" wsl-path "')")))

    (powershell ps-script)

    (if (file-exists-p target-file)
        (progn (insert (concat "[[" target-file "]]"))
               (org-display-inline-images))
      (user-error
       "Error pasting the image, make sure you have an image in the clipboard!"))
    ))

(defun as-windows-path (~/MyFiles/images)
  "Takes a unix path and returns a matching WSL path
(e.g. \\\\wsl$\\Ubuntu-20.04\\tmp)"
  ;; substring removes the trailing \n
  (substring
   (shell-command-to-string
    (concat "wslpath -w " ~/MyFiles/images)) 0 -1))

(defun powershell (script)
  "executes the given script within a powershell and returns its return value"
  (call-process "powershell.exe" nil nil nil
                "-Command" (concat "& {" script "}")))

2 Answers 2

2

https://web.archive.org/web/20221016111150/https://alexrampp.de/2020/11/07/how-to-paste-images-into-emacs-org-mode-running-in-windows-subsystem-for-linux/

The code there doesn't compile at all. I am not sure how you ran that ...

Try this ... I know nothing about windows or powershell or wsl.

When you run M-x my-org-paste-image, you will be prompted for image directory, and the name of the image file. An empty image file will be created, and this empty image file will be immediately deleted. This image file name is then passed on to the screenshot program.

Let me know if you need further help.

(I have retained the original docstring, so the docstring is slightly misleading)

(You should also probably change the path as it is inserted in to the org buffer)

(defun my-org-paste-image (image-dir image-name)
  "Paste an image into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (interactive "DImage Directory: \nsStart Image Name with: ")
  (let* ((target-file
          ;; This creates an empty file
          (let ((temporary-file-directory image-dir))
            (make-temp-file (format "%s%s_%s"
                                    (file-name-as-directory image-dir)
                                    image-name
                                    (format-time-string "%Y%m%d_%H%M%S_"))
                            nil ".png")))
         (wsl-path
          (concat (as-windows-path (file-name-directory target-file))
                  "\\"
                  (file-name-nondirectory target-file)))
         (ps-script
          (concat "(Get-Clipboard -Format image).Save('" wsl-path "')")))
    ;; Delete the empty file
    (message "Deleting empty file %s" target-file)
    (delete-file target-file t)
    (powershell ps-script)
    (if (file-exists-p target-file)
        (progn (insert (concat "[[" (file-relative-name target-file) "]]"))
               (org-display-inline-images))
      (user-error
       "Error pasting the image, make sure you have an image in the clipboard!"))))

(defun as-windows-path (unix-path)
  "Takes a unix path and returns a matching WSL path."
  ;; (e.g. \\wsl$\Ubuntu-20.04\tmp)
  ;; substring removes the trailing \n
  (substring
   (shell-command-to-string
    (concat "wslpath -w " unix-path))
   0 -1))

(defun powershell (script)
  "executes the given script within a powershell and returns its return value"
  (call-process "powershell.exe" nil nil nil
                "-Command" (concat "& {" script "}")))


5
  • Thank for your help, it is a interesting approach, but not still working correct. What your code does is this: it does ask for a directory and file name. But it does not give me a inline image because the created link in not correct. What I get is this: [[images/Screenshot_20221023_165329_XKafzV.png]] But what I need is this:[[~/MyFiles/images/Screenshot_20221023_165329_XKafzV.png]] So any help would be welcome. Meanwhile I start trying to learn emacs-lisp, although I am not a developper; but as I got inspired by Protesilaos Stravou, I will try.
    – KenDJMN
    Commented Oct 23, 2022 at 20:29
  • Change (concat "[[" (file-relative-name target-file) "]]") to (concat "[[" "file:" (file-relative-name target-file) "]]").
    – user31220
    Commented Oct 24, 2022 at 1:12
  • I have been testng the code with your last recommendations. What I get are relative path names in the image link. [[file:../MyFiles/images/screenshot_20221026_045002_wsMbB1.png]] [[file:../../MyFiles/images/screenshot_20221026_044903_0fG8kx.png]] What I would like is a absolute path name to be able to move my files to other directories, when re-organizing my directory structure and still having a valid link for the inline images. [[file:~/MyFiles/images/screenshot_20221026_045002_wsMbB1.png]] I tried to adapt the code to my wish, but I don't manage.
    – KenDJMN
    Commented Oct 26, 2022 at 5:14
  • Change (concat "[[" (file-relative-name target-file) "]]") to (concat "[[" "file:" target-file "]]") or (concat "[[" "file:" (expand-file-name target-file) "]]")
    – user31220
    Commented Oct 26, 2022 at 5:17
  • Modified the earlier commit a bit. If you can confirm in next few minutes, I will be able to help further. If not, you have to rely on other people---I am deleting my profile.
    – user31220
    Commented Oct 26, 2022 at 5:23
-1

Thanks to user31220, I was able to get my code correct. This is the final result.

     (defun my-org-paste-image (image-dir image-name)
        "Paste an image into a time stamped unique-named file in the
      same directory as the org-buffer and insert a link to this file."
        (interactive "DImage Directory: \nsStart Image Name with: ")
        (let* ((target-file
            ;; This creates an empty file
            (let ((temporary-file-directory image-dir))
              (make-temp-file (format "%s%s_%s"
                          (file-name-as-directory image-dir)
                          image-name
                          (format-time-string "%Y%m%d_%H%M%S_"))
                      nil ".png")))
           (wsl-path
            (concat (as-windows-path (file-name-directory target-file))
                "\\"
                (file-name-nondirectory target-file)))
           (ps-script
            (concat "(Get-Clipboard -Format image).Save('" wsl-path "')")))
          ;; Delete the empty file
          (message "Deleting empty file %s" target-file)
          (delete-file target-file t)
          (powershell ps-script)
          (if (file-exists-p target-file)
          (progn (insert (concat "[[" "file:" (expand-file-name target-file) "]]"))
             (org-display-inline-images))
        (user-error
         "Error pasting the image, make sure you have an image in the clipboard!"))))
    
      (defun as-windows-path (unix-path)
        "Takes a unix path and returns a matching WSL path."
        ;; (e.g. \\wsl$\Ubuntu-20.04\tmp)
        ;; substring removes the trailing \n
        (substring
         (shell-command-to-string
          (concat "wslpath -w " unix-path))
         0 -1))
    
      (defun powershell (script)
        "executes the given script within a powershell and returns its return value"
        (call-process "powershell.exe" nil nil nil
              "-Command" (concat "& {" script "}")))
    
      (global-set-key "\C-cs" 'my-org-paste-image)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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