読者です 読者をやめる 読者になる 読者になる

xyzzyでスムーズスクロール (xyttr Advent Calendar 8日目)

この記事はxyttr Advent Calendar 2011の記事です。

もはやxyttrの機能とは何も関係ないですが、スマフォやタブレットPC用のアプリにある慣性スクロールをxyzzyでそれっぽく再現するコマンドをこさえてみました。
放っておくと数千行になるタイムラインバッファ上でカカッと移動したい時に便利かもしれません。

慣性スクロールっぽい何か for #xyzzy

;;; -*- mode:lisp; package:smooth -*-

;;; 慣性スクロールっぽい何か for xyzzy

;;; 設定
;; (require "smooth")
;; (global-set-key #\C-\, 'smooth:scroll-forward)
;; (global-set-key #\C-. 'smooth:scroll-backward)

(provide "smooth")

(defpackage :smooth
  (:use :lisp :editor))

(in-package :smooth)
(export '(*counter-max* *counter-dec* *max-speed*
	  scroll-forward scroll-backward))

(defparameter *counter-max* 50)
(defparameter *counter-dec* 2)
(defparameter *max-speed* 2)

(defvar *counter* 0)

(defun start-scrolling (win dir)
  (let ((com *this-command*)
	(buf (window-buffer win))
	(row (get-window-line))
	(dec *counter-dec*))
    (labels ((scroll ()
	       (when (and (eq *last-command* com)
			  (eq (selected-window) win)
			  (not (deleted-buffer-p buf))
			  (eq buf (selected-buffer)))
		 (let ((d (min (ceiling *counter* 10) *max-speed*)))
		   (unless (next-line (* dir d))
		     (setq *counter* 0)))
		 (recenter row)
		 (refresh-screen)
		 (if (> (decf *counter* dec) 2)
		     (start-timer (/ 1.0 *counter*) #'scroll t)
		   (setq *counter* 0)))))
      (stop-timer #'scroll)
      (setq *counter* *counter-max*
	    *last-command* com)
      (scroll))))

(defun scroll-forward ()
  (interactive)
  (start-scrolling (selected-window) 1))

(defun scroll-backward ()
  (interactive)
  (start-scrolling (selected-window) -1))

速度、減速の早さ等は3つのパラメータ変数で調整できます。

(require "smooth")
(setq smooth:*counter-max* 60  ; 総移動量に影響
      smooth:*counter-dec* 2   ; 減速係数
      smooth:*max-speed* 3)    ; 初速

(in-package :xyttr)
(define-key *xyttr-timeline-keymap* #\, 'smooth:scroll-forward)
(define-key *xyttr-timeline-keymap* #\. 'smooth:scroll-backward)

ちょっと分かりにくいですが上記の設定でスクロールする様子を録画してみました。
*counter-max*は50〜100, *counter-dec*と*max-speed*は1〜5あたりで調整するのが良いと思われます。

最初はネタのつもりで書き始めたのですが、実際使ってみると
カーソルキー移動(or C-n, C-p)に比べて

  • 押しっぱなしにしなくて良い
  • kbdaccを使わなくても高速にスクロールできる

Page-Up, Page-Downと比べて

  • 移動量が分かりやすい
  • 無駄に楽しい

等の利点がありました。
もうちょっと分かりやすいパラメータ指定の方法を考えてみてから、NetInstaller用パッケージを用意したいと思います。