Deploy Org Agenda Files on Save
Issued
我過往同步 org agenda files 方法:
- Github repo 用 git push/pull 去同步我的 agenda files。但是在多台電腦切換就會變得麻煩,而且不夠靈活。
- 把 org 文件直接放在移動硬盤裡。最大問題是會把硬盤遺留在某個機子上。
最後我選擇了直接寫 emacs lisp 吧!(雖然不太會寫…)但經過 Google search 找到幾個 function 發現能做到想要的功能 - 在用 Emacs 保存指定的 org files 時進行 sync。這裡的 sync 是把自己的 agenda view 上傳到服務器上, 這樣當我隨時隨地用瀏覽器打 https://some-domain.com/agenda 就可以查看到我的 agenda !
org-mode-hook & after-save-hook
我發現 Emacs 方便地方在於它的很多 packages 或者 mode (php-mode, web-mode, python-mode,etc…) 它都會帶一個 hook function。 在 Emacs 啟動某個 mode 的時候就會觸法它的 hook 。 這個設計在很多系統, Web Framework 等,都有它的身影。 比如 Ruby on Rails:
在 User record 創建之前 call MaybeAddName:
ruby code snippet start
class User < ApplicationRecord
before_create MaybeAddName
end
class MaybeAddName
def self.before_create(record)
if record.name.blank?
record.name = record.login.capitalize
end
end
endruby code snippet end
有了這個 org-mode-hook 就可以把我們想運行的代碼用這個 hook 掛到 org mode上.
當 org mode 載入 emacs buffer 時就會運行:
elisp code snippet start
(add-hook 'org-mode-hook 'my/upload-agenda-after-save-hook)elisp code snippet end
第一個條件達成,接下來就是當 org 文件用 Emacs 儲存的時候觸發上傳 agenda view 功能。在 Emacs 儲存文件的時候就會觸發 after-save-hook :
elisp code snippet start
(defun my/upload-agenda-after-save-hook ()
(add-hook 'after-save-hook 'my/agenda-deploy))elisp code snippet end
s-prefix? & buffer-file-name
接下來問題是,我們不需要所有 org files 在儲存的時候都上傳,我們只需要指定特定幾個文件就可以了。
實際上我的 agenda files 都在 ~/org/gtd/ 里面,所以最簡單就是直接檢查當前 Org files 的文件目錄是不是在 org/gtd 目錄裡面。
這是我目前的 org 目錄:
code snippet start
org
├── deploy.sh
├── gtd
│ ├── agenda.org
│ ├── done.org
│ ├── inbox.org
│ ├── project.org
│ └── read.org
code snippet end
獲得當前正在編輯的文件:
elisp code snippet start
(buffer-file-name)elisp code snippet end
获得指定目录或者文件的 absolute path。
elisp code snippet start
(expand-file-name "~/org/gtd/")elisp code snippet end
組合起來,s-prefix? 詢問當前的文件名是不是 absolute path 的一部分。
elisp code snippet start
(s-prefix? (expand-file-name "~/org/gtd/") (buffer-file-name (current-buffer)))elisp code snippet end
s-prefix: Does S start with PREFIX?