Skip to main content TerryFunggg Blog

Deploy Org Agenda Files on Save

Issued

我過往同步 org agenda files 方法:

  1. Github repo 用 git push/pull 去同步我的 agenda files。但是在多台電腦切換就會變得麻煩,而且不夠靈活。
  2. 把 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
end

ruby 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?