段組で読む。

長い記事を読むために、段組で文を読めるようにしてみた。ワイドで右が空いてると、あまり意味がないもんね。
下はそのためのコマンドで、表示中のバッファを段組にするもの。fast-scrollのように操作する。C-gとかで元に戻る。
ちょいと長いけど、@wikiよりはてなの方が露出が高いので、一応置いておく。

(defun read-long-sentence (column &aux end)
  (interactive "n何段?")
  (save-window-excursion
    (delete-other-windows)
    (labels ((go-next-window nil (set-window (next-window (selected-window)))))
      (let ((line (window-height)))
	(if (> column 0)
	    (dotimes (x (1- column))
	      (set-local-window-flags
	       (selected-window)
	       (+ *window-flag-line-number*
		  *window-flag-vscroll-bar*
		  *window-flag-mode-line*)
	       nil)
	      (split-window-vertically (truncate (/ (1- (screen-width)) column)))
	      (go-next-window)))
	(refresh-screen)
	(dotimes (x column)
	  (go-next-window)
	  (scroll-window (* line x)))
	(refresh-screen)
	(labels ((scrl (arg)
		   (dotimes (x column)
		     (scroll-window arg)
		     (go-next-window))))
	  (while  (case (peek-char *standard-input* ed:*keyboard*)
		    ((#\Left) (scrl (- line)) t)
		    ((#\Right) (scrl line) t)
		    ((#\Up) (scrl -1) t)
		    ((#\Down) (scrl 1) t)
		    ((#\PageUp) (scrl (* (- line) column)) t)
		    ((#\PageDown) (scrl (* line column)) t)
		    (t nil))
	    (refresh-screen)
	    (read-char ed:*keyboard*))))
      (setq end (current-virtual-line-number))))
    (goto-virtual-line end))

上手く行かなくて直してもらおうと思ってたけど、記事を書くのに見直したら問題点が分かったよ!
ああ、副作用は嫌だ。これを関数型言語と呼ぶのは憚れるね。
どんな風に間違っていたかというと、表示ラインがどんどん変化していくことを勘定してなくて、下のように書いていたのだ。

;間違ってる部分だけ。
(dotimes (x (1- column))
  (set-local-window-flags
   (selected-window)
   (+ *window-flag-line-number*
      *window-flag-vscroll-bar*
      *window-flag-mode-line*)
   nil)
  (split-window-vertically (truncate (/ (1- (screen-width)) column)))
  (set-window (next-window (selected-window)))
  (scroll-window (- line 2))))