align見たいな何か

は致命的な問題があったので削除。
何故か普通に使えるようになったけど、理由が分からないのでしばらく保留することにした。

■追記
チョット調べたら、siteinit.lに書いていた昔作った奴と関数の名前が被っていたので、酷いことに成っていたようなので、書いた物自体の問題ではなかった様子。なので、マタ貼り付けてみた。

■具体的に何をするか
ひげぽん OSとか作っちゃうかMona- - M-x align が便利すぎる件
http://d.hatena.ne.jp/higepon/20060913/1158141500
この文面から勝手に理解した限りで似たような動きをするかもしれないもの。

indentとか整形?

;------------------------------------------------------------
;次の単語の所に移動?(ちょっと違うけど)
;syntaxとか言うのを使うともっとかっこよく出来るのかもしれない。
;が、良く知らないので辞めておいた。
(defun goto-any-word-level(&optional (level 1))
  (interactive "p")
  (goto-bol)
  (let ((tmp 0)
		(eol (save-excursion (goto-eol) (point))))
	(while (> level tmp)
	  (unless (eolp)
		(skip-chars-forward " \t ")
		(scan-buffer "[^ \t ]*" :regexp t :tail t :limit eol))
	  (setq tmp (+ tmp 1)))
	))

で、其れを使った感じで、下みたいなのを作った。

;------------------------------------------------------------
;x語目をインデント
  (defun level-indent (from to &optional (level 1))
	(interactive "*r" )
	;マークとカーソルの位置がどちらが上にあってもいいように変更
	(if (> from to)
		(rotatef from to))
	(save-excursion
	  (goto-char to)
	  (let ((toc (current-line-number))(max-colum 1))
		(goto-char from)
		;リージョン内でlevel番目の単語が一番後ろにある行を調べ、その位置を記憶
		(while (>= toc (current-line-number))
		  (goto-any-word-level level);これは再利用しそうなので別の関数に
		  (if (and (< max-colum (current-column)) (not (eolp)))
			  (setq max-colum (current-column)))
		  (unless (forward-line)
			(return)))
		(message "colum ~A get" max-colum) ;一応確認用
		;ここから調べた後ろの所まで他の行に空白を入れ込む
		(goto-char from);取り合えず作業開始する先頭行に移動
		(while (>= toc (current-line-number))
		  (goto-any-word-level level)
		  ;indentの所に移動した時点で行末でなければ
		  (unless (eolp)
			;ここで実際に空白を挿入
			(insert " " (+ (- max-colum (current-column)) 1))
#|insertの部分は↓のでもいいかも。
			(while (>= max-colum (current-column))
			  (insert " "))

(while (looking-at "[ \t ]")
  (delete-char))
下のも↑とかでもいいかも。早い方がいいけど調べては居ない。
|#
			(if (looking-at "[ \t ]*")
				(delete-region (match-beginning 0) (match-end 0))))
			(unless (forward-line)
			  (return)))
		  )))

で、更に

;------------------------------------------------------------
;リージョン範囲で兎に角インデント
(defun any-indent (from to &optional (max 1))
  (interactive "*r" )
  ; マークとカーソル位置のどちらが大きくてもいいよう入れ替え
  (if (> from to)
	  (rotatef from to))
  (save-excursion
	(save-restriction
	  (narrow-to-region from to ) ; 一応危険な書き換えがないように。
	  (handler-case				; indent-regionが出来ないモードもあるようなので。
		  (indent-region from to)
		(error (c)
		  (plain-error "このモードは特定のインデントがないかも")))

	  ;ここから#|一番大きい単語の所をチェック
	  (goto-char from )
	  (while (>= to (point))
		(goto-any-word-level max)
		(while (not (eolp))
		  (goto-any-word-level max)
		  (setq max (+ max 1)))
		(unless (forward-line)
		  (return)))
	  ;|#ここまではアレなら抜きで

	  (let ((level 1))
		;indentを実行する
		(while (>= max level)
		  (level-indent from to level)
		  (setq level (+ level 1))))
	  )))

こんな感じにしたので、リージョン範囲でEmacsのalign見たいな動きをするかもしれない。*1で、align-currentとか言うのがあるらしいのでそういう感じに動くんじゃないかと思ったのを

;マークするのが面倒だったので今いるパラグラフっぽい所だけ、indent
(defun any-indent-current ()
  (interactive "*")
  (save-excursion
	(mark-paragraph)
	(any-indent (point) (mark))))
;commentをM-;ので位置を考慮してもいいかも。

なんとなく、前に作ったと書いていたのを無理やり改造して多少マシにとかやってみたけど、思った以上に躓いた。というか、何か色々問題が残って良そう。改行しない日本語のを段落っぽくするというのも、作ってみたんだけど*2あんまりにも似たようなコードがダラダラしそうだったので辞めておいた。上の方の移動の所とから見ると、適当に泥団子をこねているうちに作ったのがバレそう。ばれてもいいんだけど。

■一応モジュール?とかいうのにしてみた。

ここに置いた
作っている時に出たゴミが少し残っているけど、特に問題はないはず。少し変えたので、何となく、こっちの方が多少エラーに強いかも。
追記:なんかゴミ消したりしてたら失敗して居たらしい。ので直しておいた。

■のこっている問題点

  1. 遅い
  2. 長い
  3. 下の奴みたいなのを全部リージョンに入れてindentすると上と下のブロックでindentが多少変になる。
main(){
int foo    =   'bar';     # o  hooo ho;
int   foooo   =   'bar';   #         o hoge;
int fo = 'bar';   #   o hoge;
int  f =   'bar';                #   o hogel;
for(){
};
(return);
}

$foo =   'bar';     #
$foooo   =   'bar';   #
$fo = 'bar';   #
$f =   'bar';                #

 感想、Emacsのalignは眺めた感じ、多分とても良く出来ているんじゃないかと思った。何しろ、コードが随分短い(そんな理由だけど)。まあlispが違うので殆ど意味が分からないのとかもあるんだけど、何でcarとかcdrが出てくるのかよく分からない。
EmacsWiki: align.el
http://www.emacswiki.org/cgi-bin/wiki/align.el
今眺めていた、少し何か分かったような気もしないでもない。いや、よく分かってないんだけどね。

*1:まあ、alignというのを使ったことがないので本当は似ているのか怪しいけど

*2:というか、途中でそんな感じになった