トップページ | 『無敵の者たちの伝説』 (Legend of the Invincibles) の紹介 »

2014年9月 6日 (土)

poファイル向けEmacs font lock

po-modeを使わない場合に、poファイルにEmacsのfont lockで色を付ける設定をしてみました。Local Variablesを使うものと、最後に自前のモードを作ったのも載せておきます。

最初はLocal Variablesでファイルを読んだ時に自動的に設定されるようにしました。これはevalを使うので読み込み時にunsafeであると警告が出ます。

下のコードを最後msgidのコメントとして書いておきます。

# Local Variables:
# mode: Fundamental
# coding: utf-8-unix
# eval: (font-lock-add-keywords nil '(("^#.*$" 0 'font-lock-comment-face t) ("\"[^\"\n]*\"" . 'font-lock-string-face) "msgid" "msgstr"))
# End:
msgid "Sentinel for poedit."
msgstr "これがないとpoeditがコメントを消してしまう。

poeditは、コメントをmsgidの持ち物と思っているらしく、msgidの直前に書いてないとコメントが消えてしまいました。gettext系のツールはおそらくみんなそうなっています。だから最後のmsgidのコメントとして書いておけばいいでしょう。

続きで、msgcatみたいにたくさん色を使う設定も示しておきます。

上のevalの行だけ置き換えてください。色の付け方はmsgcatと完全に同じではありません。例えばmsgcatはfuzzyのmsgstr文字列を赤くしますが、これは「#, fuzzy」の方を赤くしました。

# eval: (progn (defun my-font-lock-region nil (save-excursion (goto-char font-lock-beg) (if (re-search-backward "^ *[#m]" nil t) (setq font-lock-beg (point)) (setq font-lock-beg (point-min))) (goto-char font-lock-end) (if (re-search-forward "^ *[#m]" nil t) (progn (beginning-of-line) (setq font-lock-end (point))) (setq font-lock-end (point-max))))) (setq font-lock-extend-region-functions '(my-font-lock-region)) (setq font-lock-multiline t) (font-lock-add-keywords nil '(("^ *\\(msgid\\)\\(\\( *\".*\" *\n\\)+\\)" (1 'font-lock-keyword-face) (2 '(foreground-color . "MediumVioletRed"))) ("^ *\\(msgstr\\)\\(\\( *\".*\" *\n\\)+\\)" (1 'font-lock-keyword-face) (2 '(foreground-color . "RoyalBlue"))) ("^ *#\\..*\n" 0 '((foreground-color . "forestgreen") bold)) ("^ *#:.*\n" 0 '(foreground-color . "DodgerBlue")) ("^ *#,.*\n" 0 '(foreground-color . "red")) ("^ *#\\( .*\\)?\n" 0 'font-lock-comment-face))))

. (ピリオド)は改行とマッチしないわりに、\\s- (ホワイトスペース)は改行とマッチしたりして面倒でしたので、空白文字以外のホワイトスペースは対応しないことにしました。

このコードのmy-font-lock-regionの定義はEmacsWikiに載っているコードを参考にしていますが、そのコードの最初の後方検索に失敗するとあきらめるところはよく分かりません。検索に失敗するのはバッファの最初か最後にいるときなので、バッファ端にすればいいと思うのですが。というわけで修正しました。

で、大きくなってアホくさくなってきたので、当初の目論見はあきらめてモードを作ってみました。

;;; My PO Mode
;;; 色付けのみ
(defun my-po-font-lock-region nil
  (save-excursion
    (goto-char font-lock-beg)
    (if (re-search-backward "^ *[#m]" nil t)
        (setq font-lock-beg (point))
        (setq font-lock-beg (point-min)))
    (goto-char font-lock-end)
    (if (re-search-forward "^ *[#m]" nil t)
        (progn (beginning-of-line)
               (setq font-lock-end (point)))
        (setq font-lock-end (point-max)))))
(defvar my-po-font-lock-list
      '(("^ *\\(msgid\\)\\(\\( *\".*\" *\n\\)+\\)" (1 'font-lock-keyword-face) (2 '(foreground-color . "MediumVioletRed")))
        ("^ *\\(msgstr\\)\\(\\( *\".*\" *\n\\)+\\)" (1 'font-lock-keyword-face) (2 '(foreground-color . "RoyalBlue")))
        ("^ *#\\..*\n" 0 '((foreground-color . "forestgreen") bold))
        ("^ *#:.*\n" 0 '(foreground-color . "DodgerBlue"))
        ("^ *#,.*\n" 0 '(foreground-color . "red"))
        ("^ *#\\( .*\\)?\n" 0 'font-lock-comment-face)))
(defun my-po-mode ()
  "My PO Mode"
  (interactive)
  (kill-all-local-variables)
  (setq mode-name "My PO")
  (setq major-mode 'my-po-mode)

  (setq font-lock-extend-region-functions '(my-po-font-lock-region))
  (setq font-lock-multiline t)
  (setq font-lock-defaults '(my-po-font-lock-list t))

  (run-hooks 'my-po-mode-hook))
(provide 'my-po-mode)
(add-to-list 'auto-mode-alist '("\\.po$" . my-po-mode))

genericを使ったやつも試したのですが、syntactic fontificationの設定をされてしまうようで、"文字列"に色付けがされてしまいました。上の明示的に指定するパターン中の文字列はOverrideで回避できますが、POファイルのコメント中などに「"」があるとおかしくなります。さらにfont-lock-keywords-onlyをnon-nilにすれば完全に回避できますが、そこまでgenericにこだわる理由は見つからなかったので使わないことにしました。

トップページ | 『無敵の者たちの伝説』 (Legend of the Invincibles) の紹介 »

パソコン・インターネット」カテゴリの記事

コメント

コメントを書く

コメントは記事投稿者が公開するまで表示されません。

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/2064309/57296168

この記事へのトラックバック一覧です: poファイル向けEmacs font lock:

トップページ | 『無敵の者たちの伝説』 (Legend of the Invincibles) の紹介 »