テキストエディタからはてなダイアリーのプレビュー画面を開く

先日の記事を書くときは、いちいちコピーして、編集画面を開いて貼りつけてなんてやってて面倒だったので。
自分が使うことしか考えていないので要Vimperator

file:///dev/null?hatenadiary-forward,/path/to/entry_text.txtみたいなURLが開かれることをVimperatorプラグインで検知してプレビューを開く仕組み。 テキストエディタ側ではfirefox file:///dev/null?hatenadiary-forward,<テキストファイルのパス名>を実行すればよい

~/.vimperator/plugins/hatenadiary-forward.js

var INDICATION_URL = "file:///dev/null?hatenadiary-forward";
var EDIT_PAGE_URL = "http://d.hatena.ne.jp/oupo/draft";

var RE_INDICATION_URL = "^"+util.escapeRegex(INDICATION_URL);
autocommands.remove("PageLoad", RE_INDICATION_URL);
autocommands.add("PageLoad", RE_INDICATION_URL, function () {
	var url = content.location.href;
	var path = url.match(RE_INDICATION_URL+",(.+)")[1];
	gBrowser.removeCurrentTab();
	var text = File(path).read();
	change(text);
});

function change(text) {
	openEditPage(function() { changeCurrentContent(text) });
}

function changeCurrentContent(text) {
	var doc = content.document.wrappedJSObject;
	var edit_anchor = doc.querySelector("#edit-tab");
	var textarea = doc.querySelector("#textarea-edit");
	var preview_anchor = doc.querySelector("#preview-tab");
	var body = doc.querySelector("#preview-frame").contentDocument.body;

	var scrollTop = body.scrollTop;
	edit_anchor.click();
	textarea.value = text;
	preview_anchor.click();
	body.scrollTop = scrollTop;
}

function findTabWhichOpenedEditPage() {
	for (var tab in util.Array.itervalues(gBrowser.mTabs)) {
		var browser = gBrowser.getBrowserForTab(tab);
		var uri = browser.currentURI.spec;
		if (uri.indexOf(EDIT_PAGE_URL) === 0) {
			return tab;
		}
	}
	return null;
}

function openEditPage(callback) {
	var tab = findTabWhichOpenedEditPage();
	if (tab) {
		gBrowser.selectedTab = tab;
		callback();
		return;
	}
	var tab = gBrowser.addTab(EDIT_PAGE_URL);
	gBrowser.selectedTab = tab;
	var browser = gBrowser.getBrowserForTab(tab);
	browser.addEventListener("load", onLoad, true);

	function onLoad() {
		browser.removeEventListener("load", onLoad, true);
		callback();
	}
}

~/src/convert-tex.rb

数式書くとき [] [tex: 1 + 1 = \infty] [] みたいにtex記法使うの面倒だったので、数式は$で囲めばtex記法に変換してくれるようにした。
その変換をするのがこのスクリプト
あと色んな略記法を自分で勝手に決めたり。

# encoding: utf-8
def fix(x)
  if x =~ /\n/
    x = "\\begin{eqnarray}" + x.gsub("\n") { "\\\\" } + "\\end{eqnarray}"
  end
  x = x.gsub(/\(mod (.+?)\)/) { "\\pmod{#$1}" }
  x = x.gsub(/\bmod\b/, "\\bmod")
  x = x.gsub("!=", "\\ne ")
  x = x.gsub("==", "\\equiv ")
  x = x.gsub("<=>", "\\Leftrightarrow ")
  x = x.gsub("<=", "\\le ")
  x = x.gsub(">=", "\\ge ")
  #x = x.gsub(", ", "\\ ,\\ \\ ")
  x = x.gsub("...", "\\cdots")
  x = x.gsub("((", "( (") # あやまって脚注と解釈される模様..
  x = x.gsub(/<(?=\w)/, "< ") # HTMLタグ?と判別されておかしくなるのでスペースを開ける
  x = x.gsub(/\s+/, " ") # 文字数サイズ削減
  x
end

src = ARGF.read
print src.gsub(/\$([^$]+)\$/) { "[tex:#{fix($1)}]" }.gsub(/^\t(.+)/) { "   #$1" }

~/.vimrc

:HatenaDiaryForwardというコマンドを打てば、現在編集中のテキストを変換してプレビューする。

function! HatenaDiaryForward()
	let src = join(getline(1, '$'), "\n")
	let convertedSrc = system("ruby ~/src/convert-tex.rb", src)
	let tmp = tempname()
	call writefile(split(convertedSrc, "\n"), tmp, 'b')
	silent exec ":!firefox file:///dev/null?hatenadiary-forward," . tmp
	redraw!
endfunction
command! HatenaDiaryForward call HatenaDiaryForward()

この記事を書くときに気づいた問題

pre記法の中の$もそのまま変換してしまう。なのでこの記事を書いている間は変換を無効にしている^^;
どうしよう。ちゃんとパースしてpre記法かどうかを判断するとか大掛かりになっていやだなあ。

筆者: oupo (連絡先: oupo.nejiki@gmail.com)