Pages

Sunday, October 19, 2008

Blogging with Emacs

玩了幾個晚上,總算可以順利從 emacs 裡將文章送到 Blog 了。

自從開始用 emacs 後就一直改用 muse 在寫筆記和報告,設定好以後可以透過 LaTeX 轉換成 PDF 檔,相當方便。用習慣後也曾興起透過 muse 寫 Blog 的念頭,找了很多資料,也知道有很多人實作成功,但說真的要拿來用還是有點問題,主要還是 elisp 不熟,而且大部份的實作竟然都是直接在 emacs 裡寫 html 後送出去 (還有人推薦用 nxml);就算直接在後台寫也有方便的 wysiwyg editor,但 emacs 還有 muse 這個好東西,何必那麼苦命呢。

目前的做法還是透過 xml-rpcweblogger,後來找到有人針對 wordpress 的修改,安裝上並不難,只需稍微自訂一下就可以使用。

首先必須透過 weblogger-setup-weblog 建立設定檔,可以有多組設定,每一組設定會有一個名字作為識別。要注意的是預設並不儲存密碼,往後傳送資料時必須手動輸入。如果想偷懶可以設定一下 weblogger-save-password,建立設定資料時就會自動儲存密碼。

開始撰寫文章時先 M-x weblogger-start-entry,會自動建立簡單的樣板,填入 Subject 與內容即可。需要加上 Category 的話,可以在 header section 手動加入一行 "Keywords: ",各分類之間以逗點分隔 (必須是 server 上存在的 Category 名稱)。目前似乎還不支援 Tag。發布文件的方式很簡單,熱鍵跟存檔一樣是 C-x C-s,也可以用 C-c C-c 存成 Draft。日後需要修改時也可以把文章抓回來修改後再回存,相當方便1

Weblogger 的使用不難,比較麻煩的是跟 muse 銜接的部份,研究了一晚找出需要的資料結構,原來是建構在 message-mode 之上,所以得先產生類似 message header 的資料。這部份我直接以 html style 為基礎,建立一個新的 muse style 來處理:

(muse-derive-style "my-blog" "html"
                   :suffix ".wp.html"
                   :header
"Subject: <lisp>(muse-publishing-directive \"title\")</lisp>
From: <lisp>(muse-publishing-directive \"author\")</lisp>
Keywords: <lisp>(muse-publishing-directive \"desc\")</lisp>
--text follows this line--
"
                   :footer ""
                   :browser   'find-file
                   :regexps `((100000 "!!more!!" 0 more) )
                   :functions '((more . muse-mywp-markup-more))
                   :strings '(
(image-link      . "<a target=\"_blank\" class=\"image-link\" href=\"%s\">
<img src=\"%s.%s\"></a>")
(url             . "<a target=\"_blank\" href=\"%s\">%s</a>")
(link            . "<a target=\"_blank\" href=\"%s\">%s</a>")
(link-and-anchor . "<a target=\"_blank\" href=\"%s#%s\">%s</a>")))

當然在 project 部份也要新增一個項目

(setq muse-project-alist
	'(("blog" ("~/Note/blog" )
		(:base "my-blog" :path "~/Note/blog/convert"))))

本來的想法是找出 muse 資料的產生方式,直接丟到 webloger buffer,但是一堆括號看到頭暈,所以用了比較笨的方式:先用 muse 轉換過,再呼叫修改過的 weblogger 函式將結果轉換出必要的資料結構,最後丟上 server。

修改這些其實還算簡單,但我有個需求是要同時送到多個地方備份用,這可要我命了...因為裡面一堆全域變數,從帳號設定對應到內部資料結構的部份又太複雜 (誰說用 functional language 不會有 side-effect...XD),所以我還是用最笨的方式,每次連線前先重置相關的全域變數:

(defun muse-blog-start-entry ()
  (unless weblogger-entry-ring
    (setq weblogger-entry-ring
      (make-ring weblogger-max-entries-in-ring)))
  (ring-insert weblogger-entry-ring '(("content" "")))
  (setq weblogger-ring-index 0)
  (unless weblogger-server-username
    (setq weblogger-server-username ""))
  (unless weblogger-server-password
    (setq weblogger-server-password ""))
  (weblogger-edit-entry (weblogger-entry-buffer-to-struct)))

(defun muse-blog-send-post (&optional blogConfName) "send current to blog" (unless blogConfName (read-from-minibuffer "Select a blog conf: " blogConfName)) (setq weblogger-server-username nil) (setq weblogger-server-password nil) (setq weblogger-server-url nil) (setq weblogger-weblog-id nil) (weblogger-select-configuration blogConfName) (weblogger-start-entry) (set-buffer-modified-p t) (weblogger-save-entry t) (bury-buffer))

(defvar muse-blog-conf-name-alist nil)

(defun muse-blog-publish () (interactive) (when muse-blog-conf-name-alist (mapcar 'muse-blog-send-post muse-blog-conf-name-alist)))

使用前需要先設定 muse-blog-conf-name-alist,內容是一個字串的 list,就是先前在 weblogger 中建立的 profile 名稱,發布文章時就會丟到所有在清單中的 Blog 位置。

muse 文稿的部份,要注意的是利用了三個 directives:title、author 與 desc,分別對應到 message header 中的 Subject、From 與 Keywords。以本文為例,開頭的前幾行如下:

#title Blogging with Emacs
#author letoh
#desc note, emacs

產生出來的 header 如下:

Subject: Blogging with Emacs
From: letoh
Keywords: note, emacs
--text follows this line--

到這樣已經相當好用了,同一份 muse 文件除了生成 LaTeX / ConTeXt 文稿或 PDF 外,也可以發布到 Blog 上,當然產生 static page 或整理起來變成 Wiki 更不是問題。只剩一個小小的缺憾,就是還沒把 blogger 分舵加進來,因為 blogger 已經不用 xmlrpc,改用 Blogger Data API 了,這兩天再努力看看吧。有任何建議也歡迎指教。


1. 實際使用後發現抓回來的文章如果包含 <!--more--> (wordpress 設定摘要位置用的記號),只會抓回摘要的部份;此時若回存會把文章後半部份蓋掉XD 修改方法還在研究中...


This article was originally posted on this site.

No comments:

Post a Comment