Emacs + MozRepl + Github Markdown APIを使った Markdown Viewer

websocket.el + Amon2でリアルタイム Markdown Viewer - Life is very short


Websocketを使った Realtime Markdown Viewerなるものを websocket.elで
作ってみたんですが、必要なものがいろいろ多すぎた等の意見を頂いたので
よりシンプルに作ってみました。

必要なもの


githubAPIを叩く部分は Emacs Lispで実装しました。
url-httpモジュールは頭ごなしに使いづらいかと思ってましたけど、
そこまでではないかなと思いました。非同期 APIも同期 APIも用意して
くれていますし。まあ Perlやら Rubyやらのものに比べると
低レベルすぎる感は否めないですけど。


なおレンダリングに WebAPIを使っているのでオンライン環境でないと
使えないです。

コード

(eval-when-compile
  (require 'cl))

(require 'url)
(require 'url-http)
(require 'moz)

(defgroup moz-markdown-viewer nil
  "Markdown Viewer with MozRepl"
  :group 'markdown
  :prefix "moz-markdown-viewer:")

(defvar moz-markdown-viewer:api-url "https://api.github.com/markdown/raw")

(defun moz-markdown-viewer:escape-html (html)
  (replace-regexp-in-string
   "\n" "
"
   (replace-regexp-in-string
    "\"" """
    (replace-regexp-in-string "'" "'" html))))

(defun moz-markdown-viewer:update (html)
  (let ((escaped (moz-markdown-viewer:escape-html html)))
    (comint-send-string
     (inferior-moz-process)
     (format "document.getElementById('rendered').innerHTML = \"%s\";" escaped))))

(defun moz-markdown-viewer:escape-input (input)
  (replace-regexp-in-string "\\\\" "\\\\\\\\" input))

(defun moz-markdown-viewer:callback (status)
  (goto-char (point-min))
  (unless (re-search-forward "^$" nil t)
    (error "Not found Responce header"))
  (let ((input (buffer-substring (1+ (point)) (point-max))))
    (moz-markdown-viewer:update (moz-markdown-viewer:escape-input input))))

(defun moz-markdown-viewer:post (input)
  (let ((url-request-method "POST")
        (url-request-data input)
        (url-request-extra-headers '(("Content-Type" . "text/x-markdown"))))
    (url-retrieve moz-markdown-viewer:api-url 'moz-markdown-viewer:callback)))

(defvar moz-markdown-viewer:ready nil)

;;;###autoload
(defun moz-markdown-viewer:render ()
  (interactive)
  (unless moz-markdown-viewer:ready
    (error "Please Enable moz-markdown-viewer-mode"))
  (let ((input (buffer-substring-no-properties (point-min) (point-max))))
    (moz-markdown-viewer:post input)))

(defvar moz-markdown-viewer:html-file "viewer.html")

(defvar moz-markdown-viewer:html-path
  (when load-file-name
    (let ((installed-dir (file-name-directory load-file-name)))
      (concat installed-dir moz-markdown-viewer:html-file))))

;;;###autoload
(defun moz-markdown-viewer:setup ()
  (interactive)
  (when (yes-or-no-p "Open HTML in Firefox? ")
    (browse-url-firefox moz-markdown-viewer:html-path))
  (comint-send-string
   (inferior-moz-process)
   "repl.enter(content);")
  (setq moz-markdown-viewer:ready t))

(provide 'moz-markdown-viewer)

使い方

  1. Firefoxを起動し, MozReplを startする
  2. M-x moz-markdown-viewer:setup を実行. Firefoxでページを開くか問われます

あとは M-x moz-markdown-viewer:renderを好きなタイミングで実行するだけです。
save-hookに関連付けるなり、タイマに関連付けるなり、キーバインドを割り振れば
よいでしょう。

イメージ

おわりに

Emacs Advent Calendarのネタがあれば投稿しようかと思います。
まだいいネタが浮かばないですが・・・。