kなんとかの日記 このページをアンテナに追加

2010-02-03

助けて! CarbonEmacs で文字化けしたファイルを復活させたい

| 22:15 |  助けて! CarbonEmacs で文字化けしたファイルを復活させたい - kなんとかの日記 を含むブックマーク

CarbonEmacs で、文字コードを間違えて保存してしまったらしく、はてなダイアリーの下書き用ファイルが全部文字化けしてしまいました。

たとえば:

一方、ロシアKernel#empty? を定義した。

というテキストが

\347\255\235\200\346\357\277\275\273\200\302\303\243\303\257\277\275\302\304\207\277\302\200\302\303\242\357\275\252\302\302\257 Kernel#empty? \343\202\350\205\237\303\202\302\232\350\207\304\217\277\275\302\303\202\302\227\343\201\237\343\200\202

となってしまっています。

最後のバックアップが2日前。その間に書きかけたテキストが長めなので、できれば文字化けしたのを復旧させたいんですが、どうしたらいいんでしょうかね。

なんか1文字が4バイトっぽいんですが、これってEmacsの内部文字コードなのかな?誰かヒントをプリーズ。

rubikitchrubikitch 2010/02/03 23:54 Emacsが文字コードを間違って認識しているかもしれません。
C-x RET r (revert-buffer-with-coding-system) でエンコーディングを入力すると復旧できるかも…

kwatchkwatch 2010/02/05 20:33 文字コードの認識がどうのこうのではなく、間違ったエンコーディングで保存したために、データそのものが壊れてしまったようです。nkfやらlvやらC-x C-m c emacs-internalやらしてみましたけどだめでした。
そういえば以前yasnippet紹介していただきありがとうございました。

2009-02-23

expand-abbrev を拡張する

| 22:50 |  expand-abbrev を拡張する - kなんとかの日記 を含むブックマーク

背景

Emacs の便利機能のひとつ expand-abbrev (略語展開)。簡単に説明すると、たとえば「gei」と入力して ESC-/ を押すと「document.getElementById」に展開したり、「main」を「public static void main(String[] arg)」に展開できたりする。

展開する文字列はモードごとに変えることができて、たとえば「encoding」を ruby-mode では「# -*- coding: utf-8 -*-」に展開し、html-mode では「<meta http-equiv="Content-Type" content="text/html; charset=utf8" />」に展開する、ということができる。

もちろん展開する文字列はあらかじめ登録しておくする必要があるんだけど、この登録が C-x a i g や C-x a i l で簡単にできるのも、Emacs が便利な点のひとつ (いちいちメニュー操作をする必要がない)。


問題点

これはこれで便利なんだけど、Eclipseテンプレート機能とかと比べると、Emacs の機能は弱い。特に、できることが「文字列を展開する」ことだけなのがつらい。せめて、展開後の文字列の指定可所にカーソルを移動するぐらいのことはできてほしい。


解決案

というわけで、自分なりに expand-abbrev を拡張してみた。これを使うと、展開後の文字列に「<|CURSOR|>」があればそこにカーソルを移動し、「<|INDENT|>」があれば適切にインデントしてくれる。


具体例

たとえば「it」を「it "<|CURSOR|>" do\n<|INDENT|>\n<|INDENT|>end"」に登録しておけば、「it」を入力して ESC-/ を押すと、

it "" do
  
end

に展開してくれ、カーソルが「"」と「"」の間に移動する。また 2 行目と 3 行目は適切にインデントされる。


ソース

閉じカッコの書き方が変なのは仕様だ。だってこうしないと S 式の読み書きができないんだもん!


;;; ------------------------------------
;;; my-expand-abbrev
;;; ------------------------------------
(defvar my-expand-abbrev-assoc
  '(
    ("CURSOR" . (let ()
                  nil
                  ))
    ("INDENT" . (let ()
                  (replace-match "")
                  (funcall (key-binding "\C-i"))
                  ))
    ("FILE"   . (let ((basename (file-name-nondirectory (buffer-file-name))))
                  (replace-match basename t)
                  ))
    ("LINE"   . (let ()
                  (replace-match (line-number-at-pos))
                  ))
    )
  );defvar

(defun my-expand-abbrev ()
  "Expand abbrev and '<|KEYWORD|>'."
  (interactive)
  (let (start-pos end-pos)
    ;; set start-pos and end-pos
    (setq end-pos (point))
    (backward-word)
    (setq start-pos (point))
    (goto-char end-pos)
    ;; expand abbrev
    (if (not (expand-abbrev))
        nil
      ;; expand <|KEYWORD|>
      (save-excursion
        (while (re-search-backward "<|\\([A-Z]+\\)|>" start-pos t)
          (let* ((keyword (match-string 1))
                 (pair (assoc keyword my-expand-abbrev-assoc)))
            (if (and pair
                     (listp (cdr pair)))
                (eval (cdr pair))
              );if
            );let*
          );while
        );save-excursion
      ;; go to <|CURSOR|> position if it exists
      (setq end-pos (point))
      (goto-char start-pos)
      (if (search-forward "<|CURSOR|>" end-pos t)
          (replace-match "")
        (goto-char end-pos)
        );if
      );if
    );let
  );defun

;; ESC-/ ってちょっと打ちにくいよね?
(global-set-key "\C-l" 'my-expand-abbrev)

EmacsLisp の添削は大歓迎。


考察

似たようなライブラリは他にもあるだろう。知っている人は教えてちょーだい!

amacouamacou 2009/02/23 23:54 yasnippetは強力ですよ。
http://code.google.com/p/yasnippet/

rubikitchrubikitch 2009/02/24 00:47 yasnippetは流行り。標準添付のskeletonは読みづらいものの複雑な処理もできる。
ほかにもいろいろ。
http://www.emacswiki.org/cgi-bin/emacs/CategoryTemplates

それと、paredit.elさえ使えばカッコは空気です。