(備忘録 xyzzy) schemeコメントアウト用カスタマイズ(4/19訂正)(6/26更に訂正)

xyzzyのカスタマイズをしてみた。

schemeソースコードを書く際、
選択範囲をコメントアウト、アンコメントするためのカスタマイズ。

Windows上でGaucheで日本語を使うための設定 - nibosiiwasi’s blog
これにも書いたが、
私は以下のscheme-modeを使わさせて頂いている。
github.com


このscheme-mode.lに下記のコードを追加し、適当なキーバインドを設定して、バイトコンパイルした。

追記2017年4月19日22:50

追記ここから

本記事で、私nibosiiwasiが書いたコードの中に、バグを発見しました。
バッファ(ファイル)の最後まで選択して実行するとフリーズするバグを発見しましたので、訂正致しました。eobpでバッファ末尾かどうかチェックすることにより、このバグを取り除きました。この時刻以前のコードを使われている方は、下記のコードをお使い下さい。
誠に申し訳ございませんでした。

追記ここまで

追記2017年6月25日21:10

追記ここから
前回の訂正でも、バグがとりきれてませんでした。同じバグです。
申し訳ありませんでした。

今回の訂正内容
eobpでバッファ末尾の判定直前のタイミングで
(goto eol)
を追加訂正しました。

これで、バグは解消したと思います。
まだ不具合ございましたら、コメント欄で教えて下さい。

追記ここまで


;2017年6月25日訂正内容 eobp判定直前に(goto eol)を追加

; 選択範囲をコメントアウトする。
(defun scheme-comment-out ()
  (interactive)
  
  ;内部定義
  ;行頭に";"を1個追加する。
  ;insert-comment-in-one-line は、1行に関してのみの操作。
  (defun insert-comment-in-one-line ()
    (goto-bol) ; 行頭にカーソル移動。
    (insert ";"))

  ;ここから本体
  (let ((s-end (max (selection-point) (selection-mark)))
	(s-begin (min (selection-mark) (selection-point))))
    
    (progn
      (goto-char s-begin) ; 選択範囲の最初にカーソルを移動させる

      ;カーソルが選択範囲の最後に行くまで続ける。
      (while (<= (point) s-end)
	(progn
	  (insert-comment-in-one-line)
	  (incf s-end) ;追加した文字数だけ、選択範囲の最後の位置を調整する。
	  (goto-eol)
	  (if (eobp)
	      (return) ;カーソル位置がバッファの末尾の場合、whileループから抜ける
	    (next-line)))) ; そうでなければ次の行にカーソルを移動させwhileループ
      
      (goto-char s-end))));操作後の見やすさのため、カーソルを選択範囲の最後に移動。(お好みで)


;;選択範囲をアンコメントする。
(defun scheme-un-comment ()
  (interactive)
  
  ;内部定義
  ;行頭もしくは行頭,空白後の";"を1個削除する。
  (defun delete-1st-semicolon (limit)
    ;タブはなく、全てスペースでインデントされてると仮定した!
    (if (scan-buffer "^ *;" :limit limit :regexp t :tail t)
	(progn (backward-char) (delete-char) t)
      nil))
  
  ;delete-in-one-line は、1行に関してのみの操作。
  (defun delete-in-one-line ()
    (let ((limit (progn (goto-eol) (point)))) ; limitを行末のカーソル位置とする。
      (progn
	(goto-bol) ; 行頭にカーソル移動。
	(delete-1st-semicolon limit))))

  ;ここから本体
  (let ((s-end (max (selection-point) (selection-mark)))
	(s-begin (min (selection-mark) (selection-point))))
    
    (progn
      (goto-char s-begin) ; 選択範囲の最初にカーソルを移動させる
      (goto-bol) ; 行頭にカーソルを移動。

      ;カーソルが選択範囲の最後に行くまで続ける。
      (while (<= (point) s-end)
	(progn
	  (if (delete-in-one-line)
	      (decf s-end))  ;削除した文字数だけ、選択範囲の最後の位置を調整する。

	  (goto-eol)
	  (if (eobp)
	      (return) ;カーソル位置がバッファの末尾の場合、whileループから抜ける
	    (next-line)))) ; そうでなければ次の行にカーソルを移動させwhileループ
      
      (goto-char s-end))));操作後の見やすさのため、カーソルを選択範囲の最後に移動。(お好みで)


scheme-modeの中の*scheme-mode-map*にキーバインドを追加する。

具体的には、
例えば、こんな感じのコードを

(define-key *scheme-mode-map* '(#\C-c #\C-o) 'scheme-comment-out)
(define-key *scheme-mode-map* '(#\C-c #\C-u) 'scheme-un-comment)

scheme-mode.lの中の次の部分に追加。

(unless *scheme-mode-map*
  (setq *scheme-mode-map* (make-sparse-keymap))
 
 ...

  )

保存して、終了させて、
バイトコンパイルすれば使えるようになる。


次のコードを例にして、実際に使ってみる。

(define (foo a b) ;テスト
  ;テスト
  (+ a b))

これをコメントアウトすると

;(define (foo a b) ;テスト
;  ;テスト
;  (+ a b))

これをアンコメントすると

(define (foo a b) ;テスト
  ;テスト
  (+ a b))

さらにこれをアンコメントすると

(define (foo a b) ;テスト
  テスト
  (+ a b))

という結果になる。


"入門xyzzy:山本,日江,稲原,佐野共著, オーム社" を買って読んでいる。
schemeをやってるからか、わりとスムーズに読める気がする。