文字コードの再読読み込み

 今まであんまり気にしてなかったけど今日グリモンに触ってたら、webの他の人のスクリプトとか結構文字化けするというか。当然だけどWindowsとは違う文字コード使う人たちもいるわけで。文字化けも結構あって、かなり面倒なんじゃないかと思ってみた。多分これだけ面倒だと他の人も何らかの対策はしていそうだけど、そんな事は気にせずにムシャクシャしてやった。反省はしてない。やっぱり反省して少し調べてみる事にした。

■思った事とか
 xyzzyの現状の文字コードの切り替えには少々問題があるような気がしてみた。
適当な問題点

  1. 意外と自動判別が外れる。
  2. 文字コードを変えての再読読み込みに手間が掛かりすぎる*1
  3. 文字コードの指定が細かすぎて補完とかが使い難い。
  4. 良く使う文字コードだけで良いから速く切り替えたい

本体の問題は仕方がないので*2、なかったことにして取り合えず再読読み込みに手間が掛からない方法を探してみた。

■現状の方法1

C-u C-x C-v

で、ファイルを開きなおす。この場合は選ぶと、Encoding:と聞かれたら文字コードを指定できる。Tabとかで一応補完もあるけど、果てしなく面倒。

■現状の方法2

C-x C-k F           change-default-fileio-encoding
C-x C-k N           change-default-eol-code
C-x C-k c           change-clipboard-encoding
C-x C-k f           change-fileio-encoding
C-x C-k n           change-eol-code

C-x C-kシリーズに色々変えれるのはある様子だけど、文字化けが解消するタイプじゃなくて、デフォルトの設定とかを変える奴のようなので、あんまり役に立たない予感。多分、改行とか文字コード変換して保存してしまう。再読読み込みするものじゃないような気がする。
詳しくはこの辺でも
http://hie.s64.xrea.com/xyzzy/note/encoding.html#a


■現状の方法3
今開いているのファイルを開きなおす違う文字コード

C-u M-x revert-buffer

これで文字コードを指定。
http://hie.s64.xrea.com/xyzzy/note/encoding.html#b


■色々な文字化け対抗手段
Emacs風のキーバインド文字コードを変えてファイルを読み直す。
http://white.s151.xrea.com/blog/emacs
今のところコレが便利そう。

;; revert-buffer-with
(defun revert-buffer-with-coding-system (encoding)
  (interactive "zEncoding: ")
  (revert-buffer encoding))
(global-set-key '(#\C-x #\RET #\r) 'revert-buffer-with-coding-system)


popup-menu
から文字コード選択で認識しなおす。
from http://pc11.2ch.net/test/read.cgi/software/1191681847/184

(defun revert-buffer-encoding-popup2 ()
  (interactive)
  (let ((menu (create-popup-menu)))
	(mapc #'(lambda (x)
			  (add-menu-item menu nil (car x)
							 #'(lambda ()
								 (interactive)
								 (revert-buffer (cdr x)))))
		  `(("utf-8". ,*encoding-utf8n*)
			("sjis" . ,*encoding-sjis*)
			("auto" . ,*encoding-auto*)
			("euc-jp" . ,*encoding-euc-jp*)))
	(track-popup-menu menu)))
(global-set-key '(#\C-c #\e) 'revert-buffer-encoding-popup2)

ただ、これ[C-c e]はデフォだと英語辞書機能で結構使うので(個人的には)、他のキーに割り当てた方が良いような気はする。


set-sjis-crlf-hook*3というのがあるので参考になるかも。これは指定ディレクトリ以下のみ文字コード・改行コードを SJIS CRLF に指定するものらしい。

指定ディレクトリ内のファイル文字/改行コードを一気に変換、 指定ディレクトリ以下のみ文字コード・改行コード指定
http://hie.s64.xrea.com/xyzzy/note/encoding.html


■自分好みの感じにしてみたもの
も一応作ってみた。

■具体的にすること
 [C-x C-k r] を押すと文字コードが切り替わる。更にrを連打すると押すたびにコードが切り替わる切り替わる順番は、euc-jp,utf8n,sjisの順番で切り替わる。自分はこの三つばかり使いそうな気がするので、utf16とかjisとかも結構使う人居そうなのでその辺は少し微妙だけど。とか思ったので、一応引数でencodeのリストをもらえるようにしておいた。引数付ける場合の例は下の方に。キーは[C-x C-k]がどうやらemacsの[C-x RET]に対応している雰囲気なので、[C-x RET r]っぽい感じのキーでトグルできるようにするイメージ。後、普段から頻繁に使うわけじゃないので[C-x C-k r]くらい押しにくくても良いかと思ったけど。silogの奴を使ってどの文字コードか分からないのを何度も押して探してたら、これは面倒だと言う気がしてきたので、一度動かしたらr押し捲るだけでトグルが楽かなぁと。後、文字コード多すぎて選ぶの面倒だし。三つくらいでいいやとか。

(defun revert-buffer-toggle(&optional encodinglist)
  "良く使うのだけtoggleが楽で良いという不精な考えで"
  (interactive)
  (let ((encode (if encodinglist
					encodinglist
				  (list *encoding-euc-jp* *encoding-utf8n* *encoding-sjis*)))
		key)
	(loop
	  (revert-buffer (car encode))
	  (refresh-screen)
	  (message "char set ~A...~A" (car encode) (cdr encode))
	  (setq encode (append (cdr encode)(list (car encode)))
			key (read-char *keyboard*))
	  (when (not (eq key #\r))
		  (unread-char key)
		  (return-from revert-buffer-toggle))
	  )))

(global-set-key '(#\C-x #\C-k #\r) 'revert-buffer-toggle)

 もしトグルさせるencodeのlistが気に食わない時は好きな順番でlistを作って渡せばソレでトグルする

(defun hogehoge()
  (interactive)
  (revert-buffer-toggle (list *encoding-euc-jp* *encoding-utf8n*)))
(global-set-key '(#\C-x #\C-k #\r) 'hogehoge)

引数の中身がまともなencodeingとかだと言うのは調べないというか、調べると大変そうなので間違っても別に大した問題は起きないだろうと言う事で放置。と思ったけど引数が文字コードのlistじゃない時は適当にエラー出すようにしてみた。余り試していないのでまともに動くか不明。

(defun revert-buffer-toggle(&optional encodinglist)
  "良く使うのだけtoggleが楽で良いという不精な考えで"
  (interactive)
  (let ((encode (list *encoding-euc-jp* *encoding-utf8n* *encoding-sjis*))
		key)
	(if (and encodinglist
			 (dolist (item encodinglist t)
			   (when (not (char-encoding-p item))
				 (plain-error "引数には文字コードのlistを渡してください。")
				 (return-from revert-buffer-toggle))))
		(setq encode encodinglist))
	(loop
	  (revert-buffer (car encode))
	  (refresh-screen)
	  (message "char set : ~A" (char-encoding-name (car encode)))
	  (setq encode (append (cdr encode)(list (car encode)))
			key (read-char *keyboard*))
	  (when (not (eq key #\r))
		(unread-char key)
		(return-from revert-buffer-toggle))
	  )))