;;; show-old-window-pos.el --- Show old window position briefly after it changes.
;; Copyright (C) 2008 David De La Harpe Golden
;; Author: David De La Harpe Golden
;; Version: 3
;; Keywords: scrolling
;; show-old-window-pos.el is free software; you can redistribute it
;; and/or modify it under the terms of the GNU General Public License
;; as published by the Free Software Foundation; either version 3 of
;; the License, or (at your option) any later version.
;; show-old-window-pos.el is distributed in the hope that it will be
;; useful, but WITHOUT ANY WARRANTY; without even the implied warranty
;; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see .
;;; Commentary:
;; This package provides fringe marks that show where in the buffer
;; the window used to be showing for a couple of seconds when the
;; window position changes through scrolling etc.
;; This is done via timers, and is on a "best effort" basis only.
;;; Code:
(defgroup show-old-window-pos nil
"Indicate (in the fringe) the old window position for a bit when scrolling."
:version "23.1"
:group 'windows)
(defface show-old-window-pos-fringe
'((t (:foreground "darkcyan")))
"Face for old window position fringe mark."
:group 'show-old-window-pos
:version "23.1")
(defcustom show-old-window-pos-linger-time 2
"How long the fringe marks showing old window position should be visible for."
:type 'integer
:group 'show-old-window-pos
:version "23.1")
(defcustom show-old-window-pos-each-time-commands
'(scroll-up scroll-down scroll-other-window scroll-other-window-down)
"What commands should always show the immediately preceding old window position.
Typically, one would want only commands that cause large scrolls
or other window changes listed here."
:type '(repeat symbol)
:group 'show-old-window-pos
:version "23.1")
(defvar show-old-window-pos-overlays (make-hash-table :weakness 'key))
(defun show-old-window-pos-overlays-ensure-hash-table ()
(unless (hash-table-p show-old-window-pos-overlays)
(setq show-old-window-pos-overlays (make-hash-table :weakness 'key))))
(defun show-old-window-pos-add-overlay (window)
(show-old-window-pos-overlays-ensure-hash-table)
(let ((overlay (make-overlay
(window-start window)
(- (window-end window) 1)
(window-buffer window))))
(overlay-put overlay 'window window)
(puthash window overlay show-old-window-pos-overlays)))
(defun show-old-window-pos-overlays-showhide ()
(show-old-window-pos-overlays-ensure-hash-table)
(mapcar (lambda (visible-frame)
(mapcar
(lambda (window)
(let ((old-pos-overlay
(gethash window show-old-window-pos-overlays)))
(unless old-pos-overlay
(show-old-window-pos-add-overlay window))
(if (equal (window-start window)
(overlay-start old-pos-overlay))
(overlay-put old-pos-overlay 'before-string nil)
(overlay-put
old-pos-overlay 'before-string
(concat
(propertize "[" 'display
(list 'left-fringe 'top-left-angle
'show-old-window-pos-fringe))
(propertize "[" 'display
(list 'right-fringe 'top-right-angle
'show-old-window-pos-fringe)))))
(if (equal (- (window-end window) 1)
(overlay-end old-pos-overlay))
(overlay-put old-pos-overlay 'after-string nil)
(overlay-put
old-pos-overlay 'after-string
(concat
(propertize "]" 'display
(list 'left-fringe 'bottom-left-angle
'show-old-window-pos-fringe))
(propertize "]" 'display
(list 'right-fringe
'bottom-right-angle
'show-old-window-pos-fringe)))))))
(window-list visible-frame)))
(visible-frame-list)))
(defun show-old-window-pos-overlays-update-pos ()
(show-old-window-pos-overlays-ensure-hash-table)
(mapcar (lambda (visible-frame)
(mapcar (lambda (window)
(let ((old-pos-overlay
(gethash window show-old-window-pos-overlays)))
(if old-pos-overlay
(move-overlay old-pos-overlay
(window-start window)
(- (window-end window) 1)
(window-buffer window))
(show-old-window-pos-add-overlay window))))
(window-list visible-frame)))
(visible-frame-list))
(show-old-window-pos-overlays-showhide)
(redisplay))
(defun show-old-window-pos-maybe-reset-old-pos ()
"Pre-command-hook that resets the old window pos before certain commands."
(when (memq this-command show-old-window-pos-each-time-commands)
(show-old-window-pos-overlays-update-pos)))
(define-minor-mode show-old-window-pos-mode
"Toggle show-old-window-pos-mode.
In show-old-window-pos-mode, if the fringes are present, fringe
marks will show the position the old window was showing in its
buffer for `show-old-window-pos-linger-time' seconds when the
window changes position."
:global t
:group 'show-old-window-pos
:init-value nil
:link '(emacs-commentary-link "show-old-window-pos.el")
(if show-old-window-pos-mode
(progn
(add-hook 'pre-command-hook 'show-old-window-pos-maybe-reset-old-pos)
(run-with-idle-timer 0 t 'show-old-window-pos-overlays-showhide)
(run-with-idle-timer show-old-window-pos-linger-time
t 'show-old-window-pos-overlays-update-pos))
(cancel-function-timers 'show-old-window-pos-overlays-showhide)
(cancel-function-timers 'show-old-window-pos-overlays-update-pos)
(remove-hook 'pre-command-hook 'show-old-window-pos-maybe-reset-old-pos)
;; Explicitly delete overlays.
(maphash (lambda (key val)
(if (overlayp val)
(delete-overlay val)))
show-old-window-pos-overlays)
(setq show-old-window-pos-overlays nil)))
(provide 'show-old-window-pos)
;;; show-old-window-pos.el ends here