Emacs + Windows + Outlook というエンタープライズな環境でEmacsを使用しているニッチな人のための面白拡張。
背景
Outlook のメールを org-mode の TODO に連携させる の改良版。
前回は直接アジェンダファイルを更新していたが、org-protocolを利用すると、よりスマートに対応出来る。
- アジェンダファイルを再読込しなくても、更新が反映される
- 手元での更新と、Outlookからの更新で衝突が無い
- 書き出すテンプレートを簡単に設定出来る
方針
Outlook からの更新は org-protocol を使用して行う。
- Outlookにマクロを登録して、メール画から簡単にEmacsに送れるようにする
- org-mode上で、Outlookのメールにリンクして直接開けるようにする
手順
- org-protocolをダウンロード
- list-package から org-protocol-jekyll を使用する(自分はどっかから落としてきた) ここだっけかな?
- Windowsに
org-protocol:/
を関連付けする - Emacsでorg-protocolを受け取れるようにする
コード
Outlook側
Outlookのマクロに以下を登録。
メール画面からWriteToOrgFileマクロを呼び出すと実行される。
クイックアクセスツールバーにマクロを登録しておくと Alt+1 等で呼び出せて便利。
ちなみにスクリプトでは自動的に本文をクリップボードにコピーする。
Sub WriteToOrgFile()
' コピペスピードアップの為、最初にIEオブジェクトを生成
Set objIE = CreateObject("InternetExplorer.Application")
Dim mail As MailItem
Set mail = ActiveExplorer.Selection.Item(1)
Dim wshell
Set wshell = CreateObject("WScript.Shell")
Call objIE.navigate("about:blank")
objIE.document.Body.innerText = mail.Body
' JS の encodeURI を使用する
Dim sc
Set sc = CreateObject("ScriptControl")
sc.Language = "JScript"
Dim js
Set js = sc.CodeObject
Subject = js.encodeURI(mail.Subject)
Subject = Replace(Subject, "[", "「")
Subject = Replace(Subject, "]", "」")
'Subject = Replace(Subject, " ", "%20")
Subject = Replace(Subject, "/", "%2F")
'org-protocol:/capture:/x/outlook:$MailEntryId/$MailSubject/" の形式でURLが実行される
captureUrl = "org-protocol:/capture:/x/outlook:" & mail.EntryID & "/" & Subject & "/"
' 本文をクリップボードに格納して、後で利用出来るように非同期で実行する
' 事前にコピーすると capture によってクリップボードがリンクで上書きされる
Call wshell.Run(captureUrl)
' 必要に応じて本文を使用出来るようにクリップボードにコピーする
Body = Replace(mail.Body, vbCrLf, Chr(10))
Body = js.encodeURI(Body)
Call copyText(mail.Body, objIE)
End Sub
Private Sub copyText(text, objIE)
OLECMDID_COPY = 12
OLECMDID_SELECTALL = 17
If objIE Is Nothing Then
Set objIE = CreateObject("InternetExplorer.Application")
Call objIE.navigate("about:blank")
objIE.document.Body.innerText = text
End If
Call objIE.execWB(OLECMDID_SELECTALL, 0)
Call objIE.execWB(OLECMDID_COPY, 0)
Call objIE.Quit
End Sub
レジストリ側
これを登録すると、 org-protocol:/
の形式のURLをEmacsに送れるようになる。
REGEDIT4
[HKEY_CLASSES_ROOT\org-protocol]
@="URL:Org Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\org-protocol\shell]
[HKEY_CLASSES_ROOT\org-protocol\shell\open]
[HKEY_CLASSES_ROOT\org-protocol\shell\open\command]
@="\"C:\\tools\\emacs\\bin\\emacsclientw.exe\" \"%1\""
Emacsのパスは環境に合わせて変える。
Emacs側
前回と同じスクリプト
;; outlook 形式のURLを開く
;; see http://lists.gnu.org/archive/html/emacs-orgmode/2008-08/msg00172.html
(defun org-open-outlook-url (uid)
"Open an outlook format url"
(interactive "sGUID: ")
(w32-shell-execute nil (format "outlook:%s" uid)))
(org-add-link-type "outlook" 'org-open-outlook-url)
;; org-protocol
;; see http://orgmode.org/worg/org-contrib/org-protocol.html
(require 'org-protocol)
CaptureのTemplateの設定。必要に応じてカスタマイズ。
(add-to-list 'org-capture-templates (quote ( ("x" "From external" entry (file+headline (concat my-project-directory "org/tasks.org") "*Task Stuck*") "* ACTN %?%a :outlook:
:PROPERTIES:
:CREATED_AT: %U
:END:
%c
%i" :empty-lines 1 t TODO))))
課題
org-protocolはemacsclientを使用してURLをEmacsに送る。
実行後、何故かemacsclientのプロセスが残ってしまう。
メモリなどは影響が無いが、気持ち悪い。
まとめ
前回より大分スマートになった。
あとはプロセスが自動的に消えれば完璧なんだけど・・。
taskkill
なんかで無理やりやってもいいけど。