macOS で org-protocol を設定する

公開:2021/01/11
更新:2021/01/11
6 min読了の目安(約5400字TECH技術記事

はじめに

今年はSpacemacs + org-mode でタスク管理、メモを取ろうと思っています。

org-protocol と org-catpture を使えばブラウザから素早くメモをとることができるのですが、
設定が大変だったので備忘録として残します。

動いている様子

環境

  • macOS 10.15.7
  • GNU Emacs 27.1
  • Spacemacs developブランチ

設定

Emacs のインストール

brew tap d12frosted/emacs-plus
brew install emacs-plus@27 --with-spacemacs-icon
brew link emacs-plus@27
ln -s /usr/local/opt/emacs-plus@27/Emacs.app /Applications

システム環境設定 → ユーザとグループ → ログイン項目 で Emacs を起動するようにしておく。

EmacsClient.app を作成

  • Script Editor を起動
  • 下記コードを貼り付け
on emacsclient(input)
	do shell script "/usr/local/bin/emacsclient -n -a \"/Applications/Emacs.app/Contents/MacOS/Emacs\" '" & input & "' && open -a Emacs"
end emacsclient

on open location input
	emacsclient(input)
end open location

on open inputs
	repeat with raw_input in inputs
		set input to POSIX path of raw_input
		emacsclient(input)
	end repeat
end open

on run
	do shell script emacsclient("")
	tell application "Emacs" to activate
end run
  • アプリケーションとして /Applications/EmacsClient.app に保存
  • /Applications/Emacsclient.app/Contents/Info.plist を編集、key/string ペアの下に下記コードを追加
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLName</key>
    <string>org-protocol handler</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>org-protocol</string>
    </array>
  </dict>
</array>
  • 保存して、Finder で Emacsclient.app を1回起動しておく(関連付けされる?)

Spacemacsの設定

関連しそうなところのみ抜粋

設定場所は自信がないけど、とりあえず動いているのでヨシ

    dotspacemacs-configuration-layers '(org)
    dotspacemacs-enable-server t
(defun dotspacemacs/user-config ()
  (require 'org-protocol)
  (with-eval-after-load 'org
    (add-to-list 'org-modules 'org-protocol)
    (setq org-capture-templates
      '(
        ("t" "Task" entry (file+headline "~/Dropbox/memo/org/gtd.org" "Inbox")
          "* TODO %? \nCREATED: %U\n %i")
        ("T" "Task from protocol" entry (file+headline "~/Dropbox/memo/org/gtd.org" "Inbox")
          "* TODO %? [[%:link][%:description]] \nCREATED: %U\n#+BEGIN_QUOTE\n%i\n#+END_QUOTE\n")
        ("L" "ReadItLater" entry (file+headline "~/Dropbox/memo/org/gtd.org" "ReadItLater")
          "* TODO %? [[%:link][%:description]] \nCREATED: %U\n#+BEGIN_QUOTE\n%i\n#+END_QUOTE\n")
        ("m" "Memo" entry (file+headline org-default-notes-file "Memo")
          "* %? %U %i")
        ("M" "Memo from protocol" entry (file+headline org-default-notes-file "Memo")
          "* %? [[%:link][%:description]] \nCaptured On: %U\n#+BEGIN_QUOTE\n%i\n#+END_QUOTE\n")
        ))
    )
  )

参考までに、 https://github.com/hushin/dotfiles でファイル管理しています。

動作確認

org-protocol://capture?template=t を開いて、 Emacsclient.app 経由で Emacs の org-capture が起動することを確認。

ブラウザの設定

// org
const escapeChars = ['(', ')', "'"]
const escapeForOrg = (text) => {
  let _text = text
  escapeChars.forEach((char) => {
    _text = _text.replaceAll(char, escape(char))
  })
  return _text
}
const getUrl = (path, query) => {
  const queryString = Object.entries(query)
    .map(
      ([key, value]) =>
        `${encodeURIComponent(key)}=${escapeForOrg(encodeURIComponent(value))}`
    )
    .join('&')
  return [path, queryString].join('?')
}
const orgCapture = (template) => {
  const url = getUrl('org-protocol://capture', {
    template,
    url: window.location.href,
    title: document.title.replace(/\|/g, '-'),
    body: window.getSelection(),
  })
  console.log(`orgCapture: ${url}`)
  window.location.href = url
}
mapkey('ocm', '#14org-capture memo', () => {
  orgCapture('M')
})
mapkey('oct', '#14org-capture todo', () => {
  orgCapture('T')
})
mapkey('ocl', '#14org-capture read it later', () => {
  orgCapture('L')
})

おまけ: 試したこと・参考にしたもの