sense-rectangle-modoki-mode

 使ってないのでいらないとか言いつつ、キーマップの作り方を試してみてたら、ついでにできそうだったので、何となくモード風にしてみた。普通のモードにすると色々支障が出て上手くいかなかったのでマイナーモードらしきものにしてみた。というか、どういう状態になったらモードとか命名されるのかよく分かっていないので、ひょっとしたらモードですらないかもしれないけど。modoki-modeかmode-modokiかよくわからない。

■具体的に何をするか

  1. 矩形リージョンの範囲をハイライト。
  2. 矩形がハイライトされている時はハイライトしている部分を対象にC-wとかM-wが動作するかもしれない。
  3. 矩形がハイライトされている時はC-yが矩形でコピーしたのとかを矩形で貼り付けるかもしれない。
  4. C-qでハイライトがされなくなるかもしれない。
;------------------------------------------------------------
;sense-rectangle-mode-modoki

;lisp-modeの奴を真似てキーマップにしてみた
(defvar *sense-rectangle-keymap* nil)
(unless *sense-rectangle-keymap*
  (setq *sense-rectangle-keymap* (make-sparse-keymap))
  (define-key *sense-rectangle-keymap* #\M-w 'copy-rectangle)
  (define-key *sense-rectangle-keymap* #\C-w 'kill-rectangle)
  (define-key *sense-rectangle-keymap* #\C-y 'yank-rectangle)
  ;modeを抜けるC-gは困ったときのために取っておいてC-qにした。
  (define-key *sense-rectangle-keymap* #\C-q 'sense-rectangle-modoki-mode)
  ;以下は好みで
  (define-key *sense-rectangle-keymap* #\C-o 'open-rectangle)
  (define-key *sense-rectangle-keymap* #\M-o 'clear-rectangle)
  (define-key *sense-rectangle-keymap* #\M-r 'string-rectangle)
  (define-key *sense-rectangle-keymap* #\M-d 'delete-rectangle))
;コメントアウトとかする機能も便利かも
;string-rectangleとかも改良の余地がありそう。
;打ち込んだキーの結果を画面で見ながら編集したい気分。
;サクラエディタとか見たいな感じ

;マイナーモードでキー設定しているの(edict-modeとか)をパクった
(defun sense-rectangle-modoki-mode()
  (interactive)
  (rectangle-region-view-toggle)
  (if *rectangle-region-view-on*
	  (set-minor-mode-map *sense-rectangle-keymap*)
	(unset-minor-mode-map *sense-rectangle-keymap*)))

;矩形のリージョンをハイライト
;色の指定、この辺の所で色とかは好みで好きに
(defvar set-rectangle-reagion-color
	  '(:bold t :foreground 0 :background 2 :underline t))

(defun rectangle-region-view ()
  ;変更部分の重複がないよう前に表示した矩形regionを一度消す。
  (delete-text-attributes 'rectangle-reagion-view)
  ;一応設定がonになっているか確認。
  (when *rectangle-region-view-on*
	;cursor位置を保存して動作後にカーソル位置が変更しないように。
	(save-excursion
	  ;一応使いそうな変数にmarkとcursorの縦横の位置をセット
	  (let ((x1 (current-virtual-column))
		(y1 (current-virtual-line-number))
		(x2) (y2) (tmp))
		(goto-char (mark))
		(setq x2 (current-virtual-column))
		(setq y2 (current-virtual-line-number))
		;markとcursorどちらが上に来てもいいように入れ替え(1より2が大きい)
		(if (> x1 x2) (rotatef x1 x2))
		(if (> y1 y2) (rotatef y1 y2))
		;x軸が同じ位置ならば、描画の必要性がないので抜ける
		(if (= x1 x2)
		(return-from rectangle-region-view t))
		;画面の表示範囲外での描画をしないように。regionが大きすぎるとき対策。
		(if (> (get-window-start-line) y1)
			(goto-virtual-line (get-window-start-line))
		  (goto-virtual-line y1)) ;この辺で色を塗る開始行に移動
		(if (< (+ (get-window-start-line) (window-lines)) y2)
			(setq y2 (+ (get-window-start-line) (1+ (window-lines)))))
		  ;以下regionの範囲を一行ずつ下がりながら色を変えていく。
		(while (>= y2 (current-virtual-line-number))
		  (goto-virtual-column x1) ;色を塗りはじめる桁
		  (setq tmp (point))
		  (goto-virtual-column x2) ;色を塗り終わる桁
		  (apply #'set-text-attribute tmp (point) 
				 'rectangle-reagion-view
				 set-rectangle-reagion-color);色は上に
		  ;一行下に移動して同じことをする。
		  (unless (next-virtual-line)
			(return)))
		;unlessとreturnは次の行がEOFだったりしたら酷い感じだったので、それ対策
		))))

;エラー対策?マークがないときとか、よくわからんけどエラーが出るので
(defun rectangle-region-check()
  (interactive)
  (handler-case
	  (rectangle-region-view)
	(error (c)
	  (delete-text-attributes 'rectangle-reagion-view)
	  ;minibufferでは大抵マークがないのでエラーを無視することに
      (if (minibuffer-window-p (selected-window))
		  (plain-error "爆弾投下" )
		(progn
		  (delete-hook '*post-command-hook* 'rectangle-region-check)
		  (setq *rectangle-region-view-on* nil)
		  (plain-error "マークがないよ" )))
	  )
	))

;toggleで切り替え
(defvar *rectangle-region-view-on* nil)
;フラグでトグル
(defun rectangle-region-view-toggle()
  (interactive)
  (delete-text-attributes 'rectangle-reagion-view)
  (if *rectangle-region-view-on*
	  (progn 
		(delete-hook '*post-command-hook* 'rectangle-region-check)
		(setq *rectangle-region-view-on* nil)
		(message "rectangle-region-view-off"))
	(progn
	  (add-hook '*post-command-hook* 'rectangle-region-check)
	  (setq *rectangle-region-view-on* t)
	  (message "rectangle-region-view-on"))
	))

;;矩形リージョンを表示 なんとなくS-F8に割り当て
(global-set-key #\C-F8 'sense-rectangle-modoki-mode)
;矩形のリージョンメニューのラベル
(set-function-bar-label #\C-F8 "F8 : rectangle-view")

■注意点

  1. 作っておいてなんだけど、殆ど試しても居ないから。変な動きをするかもしれない。
  2. 例によって前と同じくカーソルの動きが少しおかしい。(特に支障はないけど)

さっき間違えて混ぜてしまっていたedict-modeは全く必要がないので消した方が良い。単に参考にするために上に表示させてパクっていたときの残骸が混入してただけです。

■その他
何となく、パッケージと言う奴にしてもいいような気はしたけど、パッケージの意味がよく分かっていないので、辞めておいた。
文字の挿入をもっとインタラクティブっぽくするのもstring-rectangleを改造したようなので全部のキーを設定すれば生けるのかな。色を塗る奴の最後の動作の所を色じゃなくて文字挿入にすればそれでもいいかも。まあ、使ったことが殆どないので、それを作る意味があるのかよく分からない。string-rectangleでも殆ど何の問題もなさそう。そんなことまでするなら矩形ナローイングもどきを作って置換とかが便利そうに思った。

■前の
himadatenodeの日記 - 矩形regionに色を付ける
http://d.hatena.ne.jp/himadatanode/20060923/p2

ついでに使えるかもしれないの。
himadatenodeの日記 - 矩形のリージョン操作
http://d.hatena.ne.jp/himadatanode/20060911/p1