Подтвердить что ты не робот

Вставьте изображение в буфер обмена в файл режима Emacs Org без сохранения его

Поскольку я использую режим Emacs Org в качестве журнала исследований, иногда я хочу отслеживать что-то с помощью снимков экрана, и я определенно не хочу их сохранять. Поэтому мне интересно, есть ли способ вставить эти фигуры в мой файл режима org, например, со словом, копирующим их из буфера обмена?

4b9b3361

Ответ 1

Точная функциональность, которую вы хотите, в настоящее время не реализована, но я скептически отношусь к сохранению большого количества изображений в журнале исследований, если вы считаете, что вы "определенно не хотите их сохранять".

В любом случае, функциональность, которую вы желаете, была выражена в списке рассылки org-mode несколько раз за последние годы - проверьте

http://comments.gmane.org/gmane.emacs.orgmode/33770

http://www.mail-archive.com/[email protected]/msg50862.html

Первая ссылка включает в себя некоторый код для запуска утилиты скриншота (через ImageMagick) для [уникального] сохранения файла и вставки встроенной ссылки в буфер org-mode.

Как указано в этом потоке, код был улучшен и добавлен в страницу хакеров в режиме org-mode, которая содержит много полезных драгоценных камней:

http://orgmode.org/worg/org-hacks.html

(defun my-org-screenshot ()
  "Take a screenshot into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (interactive)
  (setq filename
        (concat
         (make-temp-name
          (concat (buffer-file-name)
                  "_"
                  (format-time-string "%Y%m%d_%H%M%S_")) ) ".png"))
  (call-process "import" nil nil nil filename)
  (insert (concat "[[" filename "]]"))
  (org-display-inline-images))

Ответ 2

Для пользователей OS X. Следующие комплименты Assem answer.

Команда import не работала для меня, поэтому я поменял ее на screencapture аргументом -i. Я также считаю более удобным использовать относительный путь для ссылки, а не абсолютный.

(defun my-org-screenshot ()
  "Take a screenshot into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (interactive)
  (setq filename
        (concat
         (make-temp-name
          (concat (file-name-nondirectory (buffer-file-name))
                  "_"
                  (format-time-string "%Y%m%d_%H%M%S_")) ) ".png"))
  (call-process "screencapture" nil nil nil "-i" filename)
  (insert (concat "[[./" filename "]]"))
  (org-display-inline-images))

Обновление: улучшения

Недавно я немного улучшил script. Теперь он помещает скриншоты в подкаталог, при необходимости создает каталог и только вставляет ссылку в emacs, если изображение было фактически создано (т.е. Ничего не делает, если вы нажмете ESC). Он также работает как на Ubuntu, так и на OS X.

(defun my-org-screenshot ()
  "Take a screenshot into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (interactive)
  (org-display-inline-images)
  (setq filename
        (concat
         (make-temp-name
          (concat (file-name-nondirectory (buffer-file-name))
                  "_imgs/"
                  (format-time-string "%Y%m%d_%H%M%S_")) ) ".png"))
  (unless (file-exists-p (file-name-directory filename))
    (make-directory (file-name-directory filename)))
  ; take screenshot
  (if (eq system-type 'darwin)
      (call-process "screencapture" nil nil nil "-i" filename))
  (if (eq system-type 'gnu/linux)
      (call-process "import" nil nil nil filename))
  ; insert into file if correctly taken
  (if (file-exists-p filename)
    (insert (concat "[[file:" filename "]]"))))

Ответ 3

(если используется), я использовал код @assem (спасибо v.much btw) и создал версию, которая вместо этого создает подпапку (если она не существует), например: ${filename} IMG/ Затем помещает изображение, подобное img_date.png, в эту папку а затем вставляет относительный путь в буфер, например:
[[ ./${filename}IMG/img_2015...png ]]

Вот код:

(defun my-org-screenshot ()
"Take a screenshot into a time stamped unique-named file in the
sub-directory (%filenameIMG) as the org-buffer and insert a link to this file."
(interactive)

(setq foldername (concat (buffer-file-name) "IMG/"))
(if (not (file-exists-p foldername))
  (mkdir foldername))

(setq imgName (concat "img_" (format-time-string "%Y_%m_%d__%H_%M_%S") ".png"))
(setq imgPath (concat (buffer-file-name) "IMG/" imgName))

(call-process "import" nil nil nil imgPath)

(setq relativeFilename (concat "./"
    (buffer-name) "IMG/" imgName))

(insert (concat "[[" relativeFilename "]]"))
(org-display-inline-images)
)

[Изменить 2015.04.09]

В то же время, я нашел, что это не работает. Технически он работает, но он генерирует много имен папок, которые соответствуют именам файлов, что делает его утомительным для выбора файлов, поскольку есть папка с похожим именем.

Вместо этого я решил использовать решение, в котором я сохраняю все свои файлы org в одной папке и имею подпапку "img" со всеми моими изображениями.

Я использую такой код для захвата изображений:

(defun my/img-maker ()
 "Make folder if not exist, define image name based on time/date" 
  (setq myvar/img-folder-path (concat default-directory "img/"))

  ; Make img folder if it doesn't exist.
  (if (not (file-exists-p myvar/img-folder-path)) ;[ ] refactor thir and screenshot code.
       (mkdir myvar/img-folder-path))

  (setq myvar/img-name (concat "img_" (format-time-string "%Y_%m_%d__%H_%M_%S") ".png"))
  (setq myvar/img-Abs-Path (concat myvar/img-folder-path myvar/img-name)) ;Relative to workspace.

  (setq myvar/relative-filename (concat "./img/" myvar/img-name))
  (insert "[[" myvar/relative-filename "]]" "\n")
)

(defun my/org-screenshot ()
  "Take a screenshot into a time stamped unique-named file in the
 sub-directory (%filenameIMG) as the org-buffer and insert a link to this file."
  (interactive)
  (my/img-maker)
  ;(make-frame-invisible)
  (lower-frame)
  (call-process "import" nil nil nil myvar/img-Abs-Path)

  (raise-frame)
  ;(make-frame-visible)
  (org-display-inline-images)
)

и немного bash script в моей папке org/img для архивации неопубликованных изображений:

#!/bin/sh 

cd ~/git/LeoUfimtsev.github.io/org/img/
mkdir ~/git/LeoUfimtsev.github.io/org/img/archive
FILES=~/git/LeoUfimtsev.github.io/org/img/*.png
for f in $FILES
do
  var_grep_out=$(grep --directories=skip $(basename $f) ../*)
  if [ -z "$var_grep_out" ];
  then 
     echo "Archiving: $f"
     mv $f archive/
  fi
done

Ответ 4

Мне нравятся изображения и другие материалы, которые принадлежат вместе с файлом org, который должен быть расположен в явно связанной директории. Я использую механизм привязки org для этого и написал несколько лет назад пакет org-attachment-screenshot, который также доступен от MELPA. Это позволяет предоставить функцию для определения имени каталога (например, имя документа + некоторый постфикс) для вложений и также будет поддерживать стандартные функциональные возможности вложения, например. если вы хотите определить вложения на основе записей и наследовать записи. Также предоставляет настраиваемую переменную для команды моментального снимка, которая должна быть выполнена. Пожалуйста, смотрите.

Ответ 5

Мое решение для платформы Windows. Большое спасибо Assem за то, что он дал свое решение, на котором я основывался.

Я написал приложение консоли С# CbImage2File, которое записывает изображение в буфер обмена (если оно есть) в путь, указанный в качестве аргумента командной строки. Вам понадобится ссылка на сборку System.Windows.Forms.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CbImage2File
{
    class Program
    {
        private static int FAILURE = 1;

        private static void Failure(string description)
        {
            Console.Error.WriteLine("Clipboard does not contain image data");
            Environment.Exit(FAILURE);
        }

        [STAThread]
        static void Main(string[] args)
        {
            var image = System.Windows.Forms.Clipboard.GetImage();

            if (image == null)
            {
                Failure("Clipboard does not contain image data");
            }

            if (args.Length == 0)
            {
                Failure("You have not specified an output path for the image");
            }

            if (args.Length > 1)
            {
                Failure("You must only specify a file path (1 argument)");
            }

            var filePath = args[0];
            var folderInfo = new System.IO.FileInfo(filePath).Directory;

            if (!folderInfo.Exists)
            {
                System.IO.Directory.CreateDirectory(folderInfo.FullName);
            }

            image.Save(filePath);
        }
    }
}

Я использую Greenshot, чтобы сделать снимок экрана, который (через его конфигурацию) автоматически копирует скриншот в буфер обмена.

Затем я использую ярлык C-S-v для вставки изображения в буфер режима org с помощью функции org-insert-image-from-clipboard:

(defun org-insert-image-from-clipboard ()
  (interactive)
  (let* ((the-dir (file-name-directory buffer-file-name))
     (attachments-dir (concat the-dir "attachments"))
     (png-file-name (format-time-string "%a%d%b%Y_%H%M%S.png"))
     (png-path (concat attachments-dir "/" png-file-name))
     (temp-buffer-name "CbImage2File-buffer"))
    (call-process "C:/_code/CbImage2File/CbImage2File/bin/Debug/CbImage2File.exe" nil temp-buffer-name nil png-path)
    (let ((result (with-current-buffer temp-buffer-name (buffer-string))))
      (progn
    (kill-buffer temp-buffer-name)
    (if (string= result "")
        (progn 
          (insert (concat "[[./attachments/" png-file-name "]]"))
          (org-display-inline-images))
      (insert result))))))

(define-key org-mode-map (kbd "C-S-v") 'org-insert-image-from-clipboard)

Эта функция выработает путь к файлу, а затем вызовет приложение С# для создания файла png, затем добавит тег изображения, а затем вызовет org-display-inline-images, чтобы показать изображение. Если в буфере обмена нет изображения, он будет вставлять ответ из приложения С#.

Ответ 6

В ответах здесь основное внимание уделяется инициированию процесса в emacs. Альтернативой, на macos, является размещение снимка экрана в системном буфере обмена с помощью cmd-ctl-shift-4, а затем для возврата в Emacs и использования emacs lisp для вызова pngpaste, чтобы записать изображение из буфера обмена в файл и сделать все, что вам нужно, с файлом изображения (вставить в org, LaTeX или в качестве встроенного образа Emacs и т.д.).

Например, чтобы вставить в org:

(defun org-insert-clipboard-image (&optional file)
  (interactive "F")
  (shell-command (concat "pngpaste " file))
  (insert (concat "[[" file "]]"))
  (org-display-inline-images))

Ответ 7

Для этого создан пакет org-download.