Monthly Archives: 9月 2014

2014-09-30

タブレットで読書

最近10.1インチのAndroidタブレット(Xperia Z2 Tablet)で自炊した本を読んでます。

大きいタブレットだと色々はかどりますね。バッテリーも持ちますし。読むのに疲れたら何か他のものを見たりもできますし(Nexus5でテザリング)。何より版面が見やすいです。

ただ、本のサイズによっては両開きだと文字が小さく、片面だと逆に大きすぎるという場合もあります。今読んでいるのは元がA5サイズですが、まさにそんな感じ。少し文字が小さくなりますが両開きで読んでます。

アプリはezPDF Readerを使ってます。ちゃんとPDFの閉じ方向情報を認識してくれることが必須ですね。両開きで表示したときにページの左右が逆になってしまいますので。余白のカット(ページの切り抜き)表示もできます。

家でも外でも何冊もの本が同じように読めるの良いです。最近は未読の本も有用な本もどんどんスキャンしているのでライブラリも充実してきました。

ちなみに今読んでいるのはアナキズム・イン・ザ・UK -壊れた英国とパンク保育士奮闘記。内容はこことかこことか参照。Life Is A Piece Of Shit ―人生は一片のクソなんだよ。

2014-09-26 ,

JekyllからWordPressへ移行

JekyllからWordpressへ移行しました。

Jekyllは生成が遅すぎて耐えきれなかったというのが第一の理由です。一つ記事を書き終わってから更新をかけると、ほぼすべてのページを再生成するため、どうしても数十秒かかります。すべてのページを再生成しなくても良いように思うかもしれませんが、各ページにあるナビゲーションリンクやタグごとの記事数なんかを書き直さなければなりません。このサイトには1500くらい記事があるのですが1分くらいはかかります。関連記事や記事数といった情報はいったん全部の記事を読み込んでからで無いと求まりませんし。incrementalな再生成も検討されているようなのですが、できるのはまだ先のようなので。

さくらのレンタルサーバで簡単にWordpressを入れる方法が紹介されていたのも移行を後押ししました。

外出先からなど、もっと自由に記事を書きたかったですし。

移行手順は次のような感じでした。

記事の変換はいくつかハマったところがありました。

まずはインポートできる形式を調べたのですが、めぼしいものが見当たりません。結局WordPress間でやりとりするのに使われるであろう形式にこれまでの記事を変換することにしました。
これまでの記事はJekyllのyamlヘッダー付きhtml形式です(昔の独自マークアップ形式やorg-mode形式からhtmlへ変換されたものです)。それをWordpressでインポートできるWXR(WordPress eXtended RSS)へ変換しました。変換に使ったEmacs Lispは次の通り。

(defun jtow-parse-html (file)
  "yamlヘッダー付きhtmlファイルを解析して(記事URL slug タイトル 時刻 タグ文字列リスト 内容文字列)を返します。"
  (with-temp-buffer
    (insert-file file)
    ;; ---
    (beginning-of-buffer)
    (if (not (looking-at "^---\n")) (error "syntax error. '---'"))
    ;; yaml header
    (next-line)
    (let ((yaml-header nil))
      (while (not (looking-at "^---"))
        (if (not (looking-at "^\\([^:]+\\): *\\(.*\\)$"))
            (error "syntax error. %s %s" file (buffer-substring (point-at-bol) (point-at-eol))))
        (push (cons (match-string-no-properties 1) (match-string-no-properties 2)) yaml-header)
        (next-line))
      (next-line)

      ;; check
      (let ((title (cdr (assoc "title" yaml-header)))
            (date (cdr (assoc "date" yaml-header)))
            (tags (cdr (assoc "tags" yaml-header)))
            (content (buffer-substring-no-properties (point) (point-max))))
        (if (not title) (error "title not found. %s" file))
        (if (not date) (error "date not found. %s" file))

        ;; result
        (list
         ;; link
         (concat "http://example.jp/blog/" file)
         ;; postname
         (if (string-match "^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-\\([^.]+\\)\\.html$" file ) (match-string 1 file) nil)
         ;; title
         (substring title 1 -1)
         ;; date
         (jtow-parse-date date)
         ;; tags
         (if tags (split-string tags " " t))
         ;; content
         content))
      )))

(defun jtow-parse-date (d)
  "2014-01-02という形式の文字列からEmacsの時刻形式へ変換します。"
  (let ((tm (parse-time-string d)))
    (encode-time 0 0 0 (nth 3 tm) (nth 4 tm) (nth 5 tm) (* 9 3600))))

(defun jtow-format-date-rfc2822 (time)
  (format-time-string "%a, %d %b %Y 00:00:00 %z" time))

(defun jtow-format-time (time &optional universal)
  (format-time-string "%Y-%m-%d %H:%M:%S" time universal))

(defun jtow-make-item (item)
  "jtow-parse-htmlが返したリストをWXRのitem要素へ変換します。"
  (let ((link (nth 0 item))
        (postname (nth 1 item))
        (title (nth 2 item))
        (date (nth 3 item))
        (tags (nth 4 item))
        (content (nth 5 item)))
    (concat
     "<item>"
     (if link (concat "<link>" link "</link>\n"))
     (if title (concat "<title>" title "</title>\n"))
     (if date (concat "<pubDate>" (jtow-format-date-rfc2822 date) "</pubDate>\n"))
     (if tags (loop for tag in tags concat (format "<category domain=\"post_tag\" nicename=\"%s\"><![CDATA[%s]]></category>\n" (downcase tag) tag)))

     (format "<wp:post_date>%s</wp:post_date>\n" (jtow-format-time date))
     (format "<wp:post_date_gmt>%s</wp:post_date_gmt>\n" (jtow-format-time date t))
     (concat "<wp:post_name>" postname "</wp:post_name>\n")
     "<wp:post_type>post</wp:post_type>\n"
     "<wp:status>publish</wp:status>\n"

     ;; content
     "<content:encoded><![CDATA[" content "]]></content:encoded>\n"
     "</item>\n")))

(defun jtow-dir-html-to-xml (dir outfile)
  "ディレクトリ内のyamlヘッダー付きhtmlファイルからWXRファイルを作成します。"
  (with-temp-file outfile
    (insert
     "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>
<rss version=\"2.0\"
	xmlns:excerpt=\"http://wordpress.org/export/1.2/excerpt/\"
	xmlns:content=\"http://purl.org/rss/1.0/modules/content/\"
	xmlns:wfw=\"http://wellformedweb.org/CommentAPI/\"
	xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
	xmlns:wp=\"http://wordpress.org/export/1.2/\"
>
<channel>
	<title>Example Blog</title>
	<link>http://example.jp/blog</link>
	<description></description>
	<pubDate>Thu, 25 Sep 2014 05:56:52 +0000</pubDate>
	<language>ja</language>
	<wp:wxr_version>1.2</wp:wxr_version>
	<wp:base_site_url>http://example.jp/blog</wp:base_site_url>
	<wp:base_blog_url>http://example.jp/blog</wp:base_blog_url>

	<wp:author>
	<wp:author_id>1</wp:author_id>
	<wp:author_login>foo</wp:author_login>
	<wp:author_email>foo@example.jp</wp:author_email>
	<wp:author_display_name><![CDATA[foo]]></wp:author_display_name>
	<wp:author_first_name><![CDATA[]]></wp:author_first_name>
	<wp:author_last_name><![CDATA[]]></wp:author_last_name>
	</wp:author>

	<generator>http://wordpress.org/?v=4.0</generator>
")

    (loop for file in (directory-files dir nil "\.html$") do (insert (jtow-make-item (jtow-parse-html file))))

    (insert "</channel></rss>")))

;; ex)カレントディレクトリにある.htmlからposts.xmlを作る。
;;(jtow-dir-html-to-xml "." "posts.xml")

私が使っていたyamlヘッダーは主にtags, date, titleだけでしたので、それだけ考慮してあります。

CDATAの障害になる]]>という文字列が使われていないことも確認しました。

一番困ったのが、slug(postname)が重複してはいけないということでした。昔の記事では/blog/2006-01-01-a.htmlのようなURLが多いのですが、aの部分は他の日付でも沢山使われているので重複してしまいます。重複すると自動的にa-2、a-3のように補正されてしまいます。仕方ないので/blog/2006-01-01-060101a.htmlのように確実にユニークになるようにファイル名を置換しました。以前のURLと変わってしまいますが諦めました。

外観のカスタマイズはBootpressテーマをベースにして、気に入らないところをひたすら書き換えては表示してみる繰り返しでした。
それにしてもphpは久しぶりです。しかしまぁ、見えないグローバル変数に依存するコードが多くて分かりづらいですね。WP_Queryが割と万能な模様。

一通りカスタマイズが終わったらテスト用ディレクトリから本番ディレクトリへ移し替えて完成です。

投稿は今まで事実上Emacsからしか出来ませんでしたが、これからはブラウザ、Androidアプリ、Emacsと色々なところから出来るようになりました。

AndroidのWordPressアプリは面白いですね。写真を撮ったそばから投稿できます。

Emacsからの投稿はOrg2blogを導入。el-get経由でインストールしました。bzrが実行できないと言われたのでCygwinのインストーラからbzrをインストール(xml-rpc-elのインストールに必要)。でもWindowsのEmacsを使っていて、かつ、bzrはPythonスクリプトなのでEmacsからexecutable-findで見つからず。bzr.batを作ってsh -c '/bin/bzr %*'のようにしてなんとかel-getからインストールできました。(MELPAをpackageに追加してそこからインストールした方が良かったかも)

Org2blogもAndroidのWordPressアプリもですがslugが入力できません。URLが日本語になってしまいますが、まぁ、これも諦めるしかないでしょうか。(Org2blogでは#+PERMALINKでslugを設定できました)

2014-09-26

9月終了番組

忙しさにかまけて切りに切りまくった今期ですが、最後まで見て面白かったなと思ったのは次の三つでしょうか。

  • グラスリップ
  • 月刊少女 野崎くん
  • ベイビーステップ

グラスリップは、一話を見たときは良くあるテキトーな青春グループ恋愛もの(誰と誰がくっつくか、というだけで延々話を消費してこれといって中身がないもの)なのかなと思ってスルーしかけたのですが、意外と中身がありました。

野崎くんは、「千代ちゃんかわいい」というだけですね。ええ。……いや、コメディなので、色々と可笑しかったです。

ベイビーステップは、勉強が得意な主人公が真面目に考えながらテニスに打ち込む話です。スポーツものとしてはちょっと変わってますよね。