web-dev-qa-db-ja.com

クリップボードの画像を保存せずにEmacsOrgモードファイルに貼り付けます

Emacs Orgモードをリサーチログとして使用しているので、スクリーンショット画像を介して何かを追跡したい場合がありますが、絶対に保存したくありません。だから私は、Wordがクリップボードからそれらをコピーするように、それらの図を私の組織モードファイルに挿入する方法があるのだろうか?

27
lina

必要な機能は現在実装されていませんが、「絶対に保存したくない」という意見がある場合は、大量の画像を調査ログに保存することに懐疑的です。

とにかく、あなたが望む機能は、近年、org-modeメーリングリストで数回表現されています-チェックしてください

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

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))
19
assem

OSXユーザーの場合。以下はAssemの answer を褒め称えます。

importコマンドが機能していなかったので、-i引数を使用してscreencaptureに交換しました。また、絶対パスよりも相対パスを使用する方が便利だと思います。

(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))

更新:改善

最近、スクリプトを少し改善しました。スクリーンショットをサブディレクトリに配置し、必要に応じてディレクトリを作成し、画像が実際に作成された場合にのみemacsにリンクを挿入します(つまり、ESCを押しても何もしません)。また、UbuntuとOSXの両方で動作します。

(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 "]]"))))
10
Gilly

(使用する場合)@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を編集]

その間に、上記はうまく機能しないことがわかりました。技術的には機能しますが、ファイル名と一致するフォルダー名が多数生成され、類似した名前のフォルダーがあるため、ファイルを選択するのが面倒になります。

代わりに、すべての組織ファイルを同じフォルダーに保持し、すべての画像を含む「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)
)

参照されていない画像をアーカイブするためのorg/imgフォルダー内の小さなbashスクリプト:

#!/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
7
Leo Ufimtsev

ここでの答えは、emacs内でプロセスを開始することに焦点を当てています。 macosでの別の方法は、cmd-ctl-shift-4を使用してシステムクリップボードにスクリーンショット画像を配置してから、Emacsに戻り、emacs LISPを使用して pngpaste を呼び出して画像を書き込むことです。クリップボードからファイルへ、そして画像ファイルで必要なことは何でもします(org、LaTeXに挿入するか、ネイティブのEmacsインライン画像などとして)。

たとえば、組織に挿入するには:

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

組織ファイルと一緒に属する画像やその他の資料が、明確に関連付けられたディレクトリに配置されているのが好きです。私はこれにorg-attachmentメカニズムを使用しており、数年前にMELPAからも入手可能なパッケージ org-attachment-screenshot を書きました。添付ファイルのディレクトリ名(ドキュメント名+接尾辞など)を定義する機能を提供でき、標準の添付ファイル機能もサポートします。エントリに基づいて添付ファイルを定義し、エントリ内で継承する場合。実行するスナップショットコマンドのカスタマイズ可能な変数も提供します。ご覧ください。

3
dfeich

私の解決策はWindowsプラットフォーム用です。私が基にした彼の解決策を与えてくれたAssemに感謝します。

コマンドライン引数として指定されたパスにクリップボード(ある場合)の画像を書き込むC#コンソールアプリCbImage2Fileを作成しました。 System.Windows.FormsAssemblyへの参照が必要になります。

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-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)

この関数はファイルパスを計算し、C#アプリを呼び出してpngファイルを作成し、次に画像タグを追加してからorg-display-inline-imagesを呼び出して画像を表示します。クリップボードに画像がない場合は、C#アプリからの応答に貼り付けられます。

3
Tahir Hassan

org-download パッケージはこのために設計されています。

2
blujay

Windows 10ユーザーの場合、すぐに使用できるツールで動作するように@assemが提供する回答を変更しました。

(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"))
   (Shell-command "snippingtool /clip")
   (Shell-command (concat "powershell -command \"Add-Type -AssemblyName System.Windows.Forms;if ($([System.Windows.Forms.Clipboard]::ContainsImage())) {$image = [System.Windows.Forms.Clipboard]::GetImage();[System.Drawing.Bitmap]$image.Save('" filename "',[System.Drawing.Imaging.ImageFormat]::Png); Write-Output 'clipboard content saved as file'} else {Write-Output 'clipboard does not contain image data'}\""))
   (insert (concat "[[file:" filename "]]"))
   (org-display-inline-images))

全体の記事は見つけることができます ここ

1
Sastibe