+++ /dev/null
-;;; centered-cursor-mode-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
-\f
-;;;### (autoloads nil "centered-cursor-mode" "centered-cursor-mode.el"
-;;;;;; (23994 46793 360841 112000))
-;;; Generated autoloads from centered-cursor-mode.el
-
-(autoload 'ccm-visible-text-lines "centered-cursor-mode" "\
-Visible text lines
-
-\(fn)" nil nil)
-
-(autoload 'centered-cursor-mode "centered-cursor-mode" "\
-Makes the cursor stay vertically in a defined
-position (usually centered).
-
-\(fn &optional ARG)" t nil)
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; centered-cursor-mode-autoloads.el ends here
+++ /dev/null
-;;; -*- no-byte-compile: t -*-
-(define-package "centered-cursor-mode" "20190306.1006" "cursor stays vertically centered" 'nil :commit "90e6d68a74d134f67c32d0621d64db90703c46eb" :keywords '("convenience") :authors '(("André Riemann" . "andre.riemannNOSPAMweb.de")) :maintainer '("André Riemann" . "andre.riemannNOSPAMweb.de") :url "https://github.com/andre-r/centered-cursor-mode.el")
+++ /dev/null
-;;; centered-cursor-mode.el --- cursor stays vertically centered
-
-;; Copyright (C) 2007 André Riemann
-
-;; Author: André Riemann <andre.riemannNOSPAMweb.de>
-;; Maintainer: André Riemann <andre.riemannNOSPAMweb.de>
-;; Created: 2007-09-14
-;; Keywords: convenience
-;; Package-Version: 20190306.1006
-
-;; URL: https://github.com/andre-r/centered-cursor-mode.el
-;; Compatibility: tested with GNU Emacs 24, 26, 27
-;; Version: 0.5.11
-;; Last-Updated: 2019-03-06
-
-;; This file 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 2, or (at your option)
-;; any later version.
-
-;; This file 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 GNU Emacs; see the file COPYING. If not, write to the Free
-;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; Makes the cursor stay vertically in a defined position (usually
-;; centered). The vertical position can be altered, see key definition
-;; below.
-
-;; To load put that in .emacs:
-;; (require 'centered-cursor-mode)
-;; To activate do:
-;; M-x centered-cursor-mode
-;; for buffer local or
-;; M-x global-centered-cursor-mode
-;; for global minor mode.
-;; Also possible: put that in .emacs
-;; (and
-;; (require 'centered-cursor-mode)
-;; (global-centered-cursor-mode +1))
-;; to always have centered-cursor-mode on in all buffers.
-
-;;; TODO:
-;; - the code is a mess
-;; - ccm-vpos-inverted doesn't work with ccm-vpos == 0, because first
-;; position from top is 0 and from bottom -1
-;; - interactive first start isn't animated when calling global-...
-;; because it starts the modes for each buffer and interactive-p fails
-;; for that
-;; - more bugs?
-
-;;; Change Log:
-;; 2019-03-06 kqr
-;; * more customisable way to inhibit recentering after a command:
-;; new defcustom ccm-inhibit-centering-when
-;; * new ignored command evil-mouse-drag-region
-;; 2019-02-24 Gollum999
-;; * Fix aggressive centering while dragging mouse (selecting text doesn't scroll)
-;; 2019-02-05 andre-r
-;; * tip from MATTHIAS Andreas
-;; - replaced forward-line with next-line in ccm-scroll-up and ccm-scroll-down;
-;; scrolled too far in visual-line-mode
-;; 2018-01-12 andre-r
-;; * #3: Centering does not take line-height into account
-;; - added new function for calculating visible lines
-;; * #2: Bug with collapsed lines (eg. org-mode)
-;; - used count-screen-lines instead of count-lines
-;; 2017-08-30 chrm
-;; * Fixed a bug with recentering at end of file
-;; 2015-10-01 Hinrik Örn Sigurðsson <hinrik.sigNOSPAMgmail.com>
-;; * Avoided calling count-lines when unnecessary, which
-;; fixes slow scrolling in large files
-;; 2015-03-01 andre-r
-;; * fixed bug where Emacs without X support (emacs-nox) didn't find mouse-wheel-mode
-;; 2009-08-31 andre-r
-;; * replaced window-body-height with window-text-height
-;; (partially visible lines are not counted in window-text-height)
-;; * bug fixed in ccm-vpos-recenter
-;; (some parentheses where wrong after the last update)
-;; 2009-02-23 andre-r
-;; * some simplifications
-;; 2009-02-22 andre-r
-;; * some tips from Drew Adams:
-;; - new local variable coding:utf-8
-;; - made recenter-sequence a defvar
-;; - added groups scrolling and convenience
-;; - replaced mouse-4 and mouse-5 with
-;; mouse-wheel-up-event and mouse-wheel-down-event
-;; - added scroll-bar-toolkit-scroll to ccm-ignored-commands
-;; - made ccm-ignored-commands customisable
-;; * removed a bug where it didn't work with more than one window
-;; displaying the same buffer
-;; * added function for page up and down scrolling
-;; (standard ones didn't work well with this mode)
-;; * made the animation delay customisable
-;; * made the initial vertical position customisable
-;; * made the behaviour at the end of the file customisable
-;; 2008-02-02 andre-r
-;; * fixed bug that led to wrong-type-argument
-;; when opening a new buffer
-;; * some other minor stuff
-;; 2007-09-24 andre-r
-;; * added global minor mode
-;; 2007-09-21 andre-r
-;; * not recentering at end of buffer
-;; * defvar animate-first-start-p
-;; 2007-09-14 andre-r
-;; * inital release
-
-;; This file is *NOT* part of GNU Emacs.
-
-;;; Code:
-
-
-(require 'mouse-wheel-mode nil 'noerror)
-
-(defgroup centered-cursor nil
- "Makes the cursor stay vertically in a defined position (usually centered).
-Instead the cursor the text moves around the cursor."
- :group 'scrolling
- :group 'convenience
- :link '(emacs-library-link :tag "Source Lisp File" "centered-cursor-mode.el")
- :link '(url-link "http://www.emacswiki.org/cgi-bin/wiki/centered-cursor-mode.el"))
-
-(defcustom ccm-step-size 2
- "Step size when animated recentering."
- :group 'centered-cursor
- :tag "Animation step size"
- :type 'integer)
-
-(defcustom ccm-step-delay 0.02
- "Delay between animation steps.
-If you want a different animation speed."
- :group 'centered-cursor
- :tag "Animation step delay"
- :type 'number)
-
-(defcustom ccm-ignored-commands '(mouse-drag-region
- mouse-set-region
- mouse-set-point
- widget-button-click
- scroll-bar-toolkit-scroll
- evil-mouse-drag-region)
- "After these commands recentering is ignored.
-This is to prevent unintentional jumping (especially when mouse
-clicking). Following commands (except the ignored ones) will
-cause an animated recentering to give a feedback and not just
-jumping to the center."
- :group 'centered-cursor
- :tag "Ignored commands"
- :type '(repeat (symbol :tag "Command")))
-
-(defcustom ccm-inhibit-centering-when '(ccm-ignored-command-p
- ccm-mouse-drag-movement-p)
- "A list of functions which are allowed to inhibit recentering.
-If any of these return t, recentering is canceled."
- :group 'centered-cursor
- :tag "Inhibit centering when"
- :type '(repeat (symbol :tag "Function")))
-
-;;;###autoload
-(defun ccm-visible-text-lines ()
- "Visible text lines"
- (/ (- (window-pixel-height) (window-header-line-height) (window-mode-line-height))
- (default-line-height)))
-
-(defcustom ccm-vpos-init '(round (ccm-visible-text-lines) 2)
- "This is the screen line position where the cursor initially stays."
- :group 'centered-cursor
- :tag "Vertical cursor position"
- :type '(choice (const :tag "Center" (round (ccm-visible-text-lines) 2))
- (const :tag "Golden ratio" (round (* 21 (ccm-visible-text-lines)) 34))
- (integer :tag "Lines from top" :value 10)))
-(make-variable-buffer-local 'ccm-vpos-init)
-
-(defcustom ccm-vpos-inverted 1
- "Inverted vertical cursor position.
-Defines if the initial vertical position `ccm-vpos-init' is
-measured from the bottom instead from the top."
- :group 'centered-cursor
- :tag "Inverted cursor position"
- :type '(choice (const :tag "Inverted" -1)
- (const :tag "Not inverted" 1)))
-(make-variable-buffer-local 'ccm-vpos-inverted)
-
-(defcustom ccm-recenter-at-end-of-file nil
- "Recenter at the end of the file.
-If non-nil the end of the file is recentered. If nil the end of
-the file stays at the end of the window."
- :group 'centered-cursor
- :tag "Recenter at EOF"
- :type '(choice (const :tag "Don't recenter at the end of the file" nil)
- (const :tag "Recenter at the end of the file" t)))
-(make-variable-buffer-local 'ccm-recenter-end-of-file)
-
-(defvar ccm-vpos nil
- "This is the screen line position where the cursor stays.")
-(make-variable-buffer-local 'ccm-vpos)
-
-(defvar animate-first-start-p nil
- "Whether or not to animate at first start. It is set to nil, if
-centered-cursor-mode is called non-interactively.")
-(make-variable-buffer-local 'animate-first-start-p)
-
-(defvar recenter-sequence nil
- "Before animated recentering a list is generated first with positions
-to successively recenter to")
-(make-variable-buffer-local 'recenter-sequence)
-
-(defvar ccm-map
- (let ((ccm-map (make-sparse-keymap)))
- (define-key ccm-map [(control meta -)] 'ccm-vpos-up)
- (define-key ccm-map [(control meta +)] 'ccm-vpos-down)
- (define-key ccm-map [(control meta =)] 'ccm-vpos-down)
- (define-key ccm-map [(control meta ?0)] 'ccm-vpos-recenter)
- (when (and (boundp 'mouse-wheel-mode) mouse-wheel-mode)
- (mapc (lambda (key)
- (define-key ccm-map key 'ccm-mwheel-scroll))
- (list (vector mouse-wheel-up-event)
- (vector mouse-wheel-down-event)
- (vector (list 'control mouse-wheel-up-event))
- (vector (list 'control mouse-wheel-down-event))
- (vector (list 'shift mouse-wheel-up-event))
- (vector (list 'shift mouse-wheel-down-event)))))
- (define-key ccm-map [(meta v)] 'ccm-scroll-down)
- (define-key ccm-map [(control v)] 'ccm-scroll-up)
- (define-key ccm-map [prior] 'ccm-scroll-down)
- (define-key ccm-map [next] 'ccm-scroll-up)
- ccm-map)
- "Keymap used in centered-cursor-mode.")
-
-
-(defun ccm-mwheel-scroll (event)
- "Very similar to `mwheel-scroll', but does not use `scroll-down'
-and `scroll-up' but `previous-line' and `next-line', that is, the
-cursor is moved and thus the text in the window is scrolled
-due to `recenter'.
-
-The customizable variable `mouse-wheel-scroll-amount' is used to
-determine how much to scroll, where nil instead of a number means
-the same as in mwheel-scroll, scroll by a near full screen.
-
-This command exists, because mwheel-scroll caused strange
-behaviour with automatic recentering."
-;; (interactive (list last-input-event))
- (interactive "e")
- (when (region-active-p)
- (deactivate-mark))
- (let* ((mods (delq 'click (delq 'double (delq 'triple (event-modifiers event)))))
- (amt (assoc mods mouse-wheel-scroll-amount)))
- ;;(message "%S" mods)
- (if amt
- (setq amt (or (cdr amt)
- (- (ccm-visible-text-lines)
- next-screen-context-lines)))
- (let ((list-elt mouse-wheel-scroll-amount))
- (while (consp (setq amt (pop list-elt))))))
- (if mouse-wheel-follow-mouse
- (select-window (posn-window (event-start event))))
- (let ((button (mwheel-event-button event)))
- (cond
- ((eq button mouse-wheel-down-event)
- (forward-line (- amt)))
- ;;(princ amt))
- ((eq button mouse-wheel-up-event)
- (forward-line amt))
- ;;(princ amt))
- (t (error "Bad binding in ccm-mwheel-scroll"))))))
-
-(defun ccm-scroll-down (&optional arg)
- "Replaces `scroll-down' because with scroll-down
-`centered-cursor-mode' sometimes doesn't reach the top of the
-buffer. This version actually moves the cursor with
-`previous-line'. Since with centered-cursor-mode the cursor is in
-a fixed position the movement appears as page up."
- (interactive "P")
- (let ((amt (or arg (- (ccm-visible-text-lines)
- next-screen-context-lines))))
- (next-line (- amt))))
-
-(defun ccm-scroll-up (&optional arg)
- "Replaces `scroll-up' to be consistent with `ccm-scroll-down'.
-This version actually moves the cursor with `previous-line'.
-Since with centered-cursor-mode the cursor is in a fixed position
-the movement appears as page up."
- (interactive "P")
- (let ((amt (or arg (- (ccm-visible-text-lines)
- next-screen-context-lines))))
- (next-line amt)))
-
-
-(defun ccm-vpos-down (arg)
- "Adjust the value of the screen line (where the cursor stays) by arg.
-Negative values for arg are possible. Just the variable ccm-vpos
-is set."
- (interactive "p")
- (or arg (setq arg 1))
- (let ((new-pos (if (< ccm-vpos 0)
- (- ccm-vpos arg)
- (+ ccm-vpos arg)))
- ;; see pos-visible-in-window-p
- (vpos-max (if (< ccm-vpos 0)
- -1
- (- (ccm-visible-text-lines) 1)))
- (vpos-min (if (< ccm-vpos 0)
- (- (ccm-visible-text-lines))
- 0)))
- (setq ccm-vpos
- (cond
- ((< new-pos vpos-min)
- vpos-min)
- ((> new-pos vpos-max)
- vpos-max)
- (t
- new-pos)))))
-
-(defun ccm-vpos-up (arg)
- "See `ccm-vpos-down'."
- (interactive "p")
- (or arg (setq arg 1))
- (ccm-vpos-down (- arg)))
-
-(defun ccm-vpos-recenter ()
- "Set the value of the screen line (where the cursor stays) in
-the center. Just the variable ccm-vpos is set."
- (interactive)
- (if (equal (current-buffer)
- (window-buffer (selected-window)))
- (setq ccm-vpos (* (eval ccm-vpos-init)
- ccm-vpos-inverted))))
-
-(defun ccm-ignored-command-p ()
- "Check if the last command was one listed in CCM-IGNORED-COMMANDS."
- (member this-command ccm-ignored-commands))
-
-(defun ccm-mouse-drag-movement-p ()
- "Check if the last input event corresponded to a mouse drag event."
- (mouse-movement-p last-command-event))
-
-(defun ccm-position-cursor ()
- "Do the actual recentering at the position `ccm-vpos'."
- (unless (seq-some #'funcall ccm-inhibit-centering-when)
- (unless ccm-vpos
- (ccm-vpos-recenter))
- (unless (minibufferp (current-buffer))
- (if (equal (current-buffer)
- (window-buffer (selected-window)))
- (let* ((current-line
- (if (< ccm-vpos 0)
- ;; one-based, from bottom, negative
- (- (count-screen-lines (point)
- ;; window-end is sometimes < 0
- ;; when opening a help buffer
- (if (> (window-end) 0)
- (window-end)
- 1)))
- ;; zero-based, from top, positive
- (+ (count-screen-lines (window-start) (point))
- ;; count-lines returns different value in column 0
- (if (= (current-column) 0) 0 -1))))
- (diff (- ccm-vpos current-line))
- (step-size ccm-step-size)
- (step-delay ccm-step-delay)
- (vpos-inverted ccm-vpos-inverted)
- (recenter-at-end-of-file ccm-recenter-at-end-of-file))
-
- (let* ((bottom-vpos (if (< ccm-vpos 0)
- (- ccm-vpos)
- (- (ccm-visible-text-lines) ccm-vpos)))
- (correction (save-excursion
- (if (or (= (point) (point-max))
- (progn
- (goto-char (point-max))
- (zerop (current-column))))
- 1 0)))
- (window-is-at-bottom (or (= (window-end) (point-max)) ; doesn't work when scrolling (eg. pgdwn)
- (= (line-end-position ccm-vpos) (point-max)) ; doesn't work on repls second to last line, because the prompt gets inserted later?
- ))
- ;; lines from point to end of buffer
- (bottom-lines (if window-is-at-bottom
- (+ (count-screen-lines (point) (point-max))
- correction))))
-
- ;; only animate if the point was moved rather far away
- ;; before by a mouseclick (see ccm-ignored-commands)
- ;; or if minor mode is just entered interactively
- (if (not (and (> (abs diff) 4)
- (or (member last-command ccm-ignored-commands)
- animate-first-start-p)))
-
- (recenter (if (and window-is-at-bottom
- (< bottom-lines bottom-vpos)
- (not recenter-at-end-of-file))
- ;; if near the bottom, recenter in the
- ;; negative screen line that equals the
- ;; bottom buffer line, i.e. if we are in
- ;; the second last line (-2) of the
- ;; buffer, the cursor will be recentered
- ;; in -2
- (- bottom-lines)
- ccm-vpos))
-
- (setq animate-first-start-p nil)
- ;; first build a list with positions to successively recenter to
- (setq recenter-sequence
- ;; reverse: because we build the list not FROM -> TO but
- ;; TO -> FROM because if step size in number-sequence is
- ;; bigger than one, TO might not included, that means the
- ;; ccm-vpos would not be reached
- ;; cdr: don't recenter the current-line
- (if (and window-is-at-bottom
- (< bottom-lines bottom-vpos)
- (not recenter-at-end-of-file))
- ;; this one is for animation near the bottom
- (cdr (reverse (number-sequence
- (- bottom-lines)
- (if (< ccm-vpos 0)
- current-line
- (- (- (ccm-visible-text-lines) current-line)))
- (* (/ diff (abs diff)) (- step-size)))))
- (cdr (reverse (number-sequence
- ccm-vpos
- current-line
- (* (/ diff (abs diff)) (- step-size)))))))
- ;; (message "%d %d %d (%d): %S" current-line ccm-vpos bottom-lines diff recenter-sequence)
- (while recenter-sequence
- ;; actual animation
- (recenter (pop recenter-sequence))
- (if (car recenter-sequence) (sit-for step-delay t))))))))))
-
-(defun ccm-first-start (animate)
- "Called from centered-cursor-mode. Animate at first start, if
-centered-cursor-mode is called interactively."
- (let ((animate-first-start-p animate))
- (ccm-vpos-recenter)
- (ccm-position-cursor)))
-
-;;(defalias 'ccm 'centered-cursor-mode)
-;;;###autoload
-(define-minor-mode centered-cursor-mode
- "Makes the cursor stay vertically in a defined
-position (usually centered)."
- :init-value nil
-;; :lighter nil
- :lighter " ¢"
- :keymap ccm-map
- (cond
- (centered-cursor-mode
- (ccm-first-start (interactive-p))
- (add-hook 'post-command-hook 'ccm-position-cursor t t)
- (add-hook 'window-configuration-change-hook 'ccm-vpos-recenter t t))
- (t
- (remove-hook 'post-command-hook 'ccm-position-cursor t)
- (remove-hook 'window-configuration-change-hook 'ccm-vpos-recenter t))))
-
-
-(define-global-minor-mode global-centered-cursor-mode centered-cursor-mode
- centered-cursor-mode)
-
-(provide 'centered-cursor-mode)
-
-;;; Help:
-;; (info "(elisp)Defining Minor Modes")
-;; (info "(elisp)Screen Lines")
-;; (info "(elisp)Hooks")
-;; (info "(elisp)Customization")
-;; (find-function 'mwheel-scroll)
-
-;; Local Variables:
-;; coding: utf-8
-;; End:
-
-;;; centered-cursor-mode.el ends here
--- /dev/null
+;;; centered-cursor-mode-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*-
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "centered-cursor-mode" "centered-cursor-mode.el"
+;;;;;; (0 0 0 0))
+;;; Generated autoloads from centered-cursor-mode.el
+
+(autoload 'ccm-visible-text-lines "centered-cursor-mode" "\
+Visible text lines" nil nil)
+
+(autoload 'centered-cursor-mode "centered-cursor-mode" "\
+Makes the cursor stay vertically in a defined
+position (usually centered).
+
+This is a minor mode. If called interactively, toggle the
+`Centered-Cursor mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `centered-cursor-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+\(fn &optional ARG)" t nil)
+
+(put 'global-centered-cursor-mode 'globalized-minor-mode t)
+
+(defvar global-centered-cursor-mode nil "\
+Non-nil if Global Centered-Cursor mode is enabled.
+See the `global-centered-cursor-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `global-centered-cursor-mode'.")
+
+(custom-autoload 'global-centered-cursor-mode "centered-cursor-mode" nil)
+
+(autoload 'global-centered-cursor-mode "centered-cursor-mode" "\
+Toggle Centered-Cursor mode in all buffers.
+With prefix ARG, enable Global Centered-Cursor mode if ARG is
+positive; otherwise, disable it.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.
+Enable the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+Centered-Cursor mode is enabled in all buffers where
+`centered-cursor-mode' would do it.
+
+See `centered-cursor-mode' for more information on Centered-Cursor
+mode.
+
+\(fn &optional ARG)" t nil)
+
+(register-definition-prefixes "centered-cursor-mode" '("animate-first-start-p" "ccm-" "recenter-sequence"))
+
+;;;***
+\f
+;;;### (autoloads nil nil ("centered-cursor-mode-pkg.el") (0 0 0
+;;;;;; 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; centered-cursor-mode-autoloads.el ends here
--- /dev/null
+(define-package "centered-cursor-mode" "20200507.1529" "cursor stays vertically centered" 'nil :commit "e9ee518d314ef7fb105a1e0cdc33dbb4dfe9d9e4" :authors
+ '(("André Riemann" . "andre.riemannNOSPAMweb.de"))
+ :maintainers
+ '(("André Riemann" . "andre.riemannNOSPAMweb.de"))
+ :maintainer
+ '("André Riemann" . "andre.riemannNOSPAMweb.de")
+ :keywords
+ '("convenience")
+ :url "https://github.com/andre-r/centered-cursor-mode.el")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
--- /dev/null
+;;; centered-cursor-mode.el --- cursor stays vertically centered
+
+;; Copyright (C) 2007 André Riemann
+
+;; Author: André Riemann <andre.riemannNOSPAMweb.de>
+;; Maintainer: André Riemann <andre.riemannNOSPAMweb.de>
+;; Created: 2007-09-14
+;; Keywords: convenience
+
+;; URL: https://github.com/andre-r/centered-cursor-mode.el
+;; Compatibility: tested with GNU Emacs 24, 26, 27
+;; Version: 0.5.12
+;; Last-Updated: 2020-05-07
+
+;; This file 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 2, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to the Free
+;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Makes the cursor stay vertically in a defined position (usually
+;; centered). The vertical position can be altered, see key definition
+;; below.
+
+;; To load put that in .emacs:
+;; (require 'centered-cursor-mode)
+;; To activate do:
+;; M-x centered-cursor-mode
+;; for buffer local or
+;; M-x global-centered-cursor-mode
+;; for global minor mode.
+;; Also possible: put that in .emacs
+;; (and
+;; (require 'centered-cursor-mode)
+;; (global-centered-cursor-mode +1))
+;; to always have centered-cursor-mode on in all buffers.
+
+;;; TODO:
+;; - the code is a mess
+;; - ccm-vpos-inverted doesn't work with ccm-vpos == 0, because first
+;; position from top is 0 and from bottom -1
+;; - interactive first start isn't animated when calling global-...
+;; because it starts the modes for each buffer and interactive-p fails
+;; for that
+;; - more bugs?
+
+;;; Change Log:
+;; 2020-05-07 hlissner
+;; * autoload global-centered-cursor-mode
+;; 2019-03-06 kqr
+;; * more customisable way to inhibit recentering after a command:
+;; new defcustom ccm-inhibit-centering-when
+;; * new ignored command evil-mouse-drag-region
+;; 2019-02-24 Gollum999
+;; * Fix aggressive centering while dragging mouse (selecting text doesn't scroll)
+;; 2019-02-05 andre-r
+;; * tip from MATTHIAS Andreas
+;; - replaced forward-line with next-line in ccm-scroll-up and ccm-scroll-down;
+;; scrolled too far in visual-line-mode
+;; 2018-01-12 andre-r
+;; * #3: Centering does not take line-height into account
+;; - added new function for calculating visible lines
+;; * #2: Bug with collapsed lines (eg. org-mode)
+;; - used count-screen-lines instead of count-lines
+;; 2017-08-30 chrm
+;; * Fixed a bug with recentering at end of file
+;; 2015-10-01 Hinrik Örn Sigurðsson <hinrik.sigNOSPAMgmail.com>
+;; * Avoided calling count-lines when unnecessary, which
+;; fixes slow scrolling in large files
+;; 2015-03-01 andre-r
+;; * fixed bug where Emacs without X support (emacs-nox) didn't find mouse-wheel-mode
+;; 2009-08-31 andre-r
+;; * replaced window-body-height with window-text-height
+;; (partially visible lines are not counted in window-text-height)
+;; * bug fixed in ccm-vpos-recenter
+;; (some parentheses where wrong after the last update)
+;; 2009-02-23 andre-r
+;; * some simplifications
+;; 2009-02-22 andre-r
+;; * some tips from Drew Adams:
+;; - new local variable coding:utf-8
+;; - made recenter-sequence a defvar
+;; - added groups scrolling and convenience
+;; - replaced mouse-4 and mouse-5 with
+;; mouse-wheel-up-event and mouse-wheel-down-event
+;; - added scroll-bar-toolkit-scroll to ccm-ignored-commands
+;; - made ccm-ignored-commands customisable
+;; * removed a bug where it didn't work with more than one window
+;; displaying the same buffer
+;; * added function for page up and down scrolling
+;; (standard ones didn't work well with this mode)
+;; * made the animation delay customisable
+;; * made the initial vertical position customisable
+;; * made the behaviour at the end of the file customisable
+;; 2008-02-02 andre-r
+;; * fixed bug that led to wrong-type-argument
+;; when opening a new buffer
+;; * some other minor stuff
+;; 2007-09-24 andre-r
+;; * added global minor mode
+;; 2007-09-21 andre-r
+;; * not recentering at end of buffer
+;; * defvar animate-first-start-p
+;; 2007-09-14 andre-r
+;; * inital release
+
+;; This file is *NOT* part of GNU Emacs.
+
+;;; Code:
+
+
+(require 'mouse-wheel-mode nil 'noerror)
+
+(defgroup centered-cursor nil
+ "Makes the cursor stay vertically in a defined position (usually centered).
+Instead the cursor the text moves around the cursor."
+ :group 'scrolling
+ :group 'convenience
+ :link '(emacs-library-link :tag "Source Lisp File" "centered-cursor-mode.el")
+ :link '(url-link "http://www.emacswiki.org/cgi-bin/wiki/centered-cursor-mode.el"))
+
+(defcustom ccm-step-size 2
+ "Step size when animated recentering."
+ :group 'centered-cursor
+ :tag "Animation step size"
+ :type 'integer)
+
+(defcustom ccm-step-delay 0.02
+ "Delay between animation steps.
+If you want a different animation speed."
+ :group 'centered-cursor
+ :tag "Animation step delay"
+ :type 'number)
+
+(defcustom ccm-ignored-commands '(mouse-drag-region
+ mouse-set-region
+ mouse-set-point
+ widget-button-click
+ scroll-bar-toolkit-scroll
+ evil-mouse-drag-region)
+ "After these commands recentering is ignored.
+This is to prevent unintentional jumping (especially when mouse
+clicking). Following commands (except the ignored ones) will
+cause an animated recentering to give a feedback and not just
+jumping to the center."
+ :group 'centered-cursor
+ :tag "Ignored commands"
+ :type '(repeat (symbol :tag "Command")))
+
+(defcustom ccm-inhibit-centering-when '(ccm-ignored-command-p
+ ccm-mouse-drag-movement-p)
+ "A list of functions which are allowed to inhibit recentering.
+If any of these return t, recentering is canceled."
+ :group 'centered-cursor
+ :tag "Inhibit centering when"
+ :type '(repeat (symbol :tag "Function")))
+
+;;;###autoload
+(defun ccm-visible-text-lines ()
+ "Visible text lines"
+ (/ (- (window-pixel-height) (window-header-line-height) (window-mode-line-height))
+ (default-line-height)))
+
+(defcustom ccm-vpos-init '(round (ccm-visible-text-lines) 2)
+ "This is the screen line position where the cursor initially stays."
+ :group 'centered-cursor
+ :tag "Vertical cursor position"
+ :type '(choice (const :tag "Center" (round (ccm-visible-text-lines) 2))
+ (const :tag "Golden ratio" (round (* 21 (ccm-visible-text-lines)) 34))
+ (integer :tag "Lines from top" :value 10)))
+(make-variable-buffer-local 'ccm-vpos-init)
+
+(defcustom ccm-vpos-inverted 1
+ "Inverted vertical cursor position.
+Defines if the initial vertical position `ccm-vpos-init' is
+measured from the bottom instead from the top."
+ :group 'centered-cursor
+ :tag "Inverted cursor position"
+ :type '(choice (const :tag "Inverted" -1)
+ (const :tag "Not inverted" 1)))
+(make-variable-buffer-local 'ccm-vpos-inverted)
+
+(defcustom ccm-recenter-at-end-of-file nil
+ "Recenter at the end of the file.
+If non-nil the end of the file is recentered. If nil the end of
+the file stays at the end of the window."
+ :group 'centered-cursor
+ :tag "Recenter at EOF"
+ :type '(choice (const :tag "Don't recenter at the end of the file" nil)
+ (const :tag "Recenter at the end of the file" t)))
+(make-variable-buffer-local 'ccm-recenter-end-of-file)
+
+(defvar ccm-vpos nil
+ "This is the screen line position where the cursor stays.")
+(make-variable-buffer-local 'ccm-vpos)
+
+(defvar animate-first-start-p nil
+ "Whether or not to animate at first start. It is set to nil, if
+centered-cursor-mode is called non-interactively.")
+(make-variable-buffer-local 'animate-first-start-p)
+
+(defvar recenter-sequence nil
+ "Before animated recentering a list is generated first with positions
+to successively recenter to")
+(make-variable-buffer-local 'recenter-sequence)
+
+(defvar ccm-map
+ (let ((ccm-map (make-sparse-keymap)))
+ (define-key ccm-map [(control meta -)] 'ccm-vpos-up)
+ (define-key ccm-map [(control meta +)] 'ccm-vpos-down)
+ (define-key ccm-map [(control meta =)] 'ccm-vpos-down)
+ (define-key ccm-map [(control meta ?0)] 'ccm-vpos-recenter)
+ (when (and (boundp 'mouse-wheel-mode) mouse-wheel-mode)
+ (mapc (lambda (key)
+ (define-key ccm-map key 'ccm-mwheel-scroll))
+ (list (vector mouse-wheel-up-event)
+ (vector mouse-wheel-down-event)
+ (vector (list 'control mouse-wheel-up-event))
+ (vector (list 'control mouse-wheel-down-event))
+ (vector (list 'shift mouse-wheel-up-event))
+ (vector (list 'shift mouse-wheel-down-event)))))
+ (define-key ccm-map [(meta v)] 'ccm-scroll-down)
+ (define-key ccm-map [(control v)] 'ccm-scroll-up)
+ (define-key ccm-map [prior] 'ccm-scroll-down)
+ (define-key ccm-map [next] 'ccm-scroll-up)
+ ccm-map)
+ "Keymap used in centered-cursor-mode.")
+
+
+(defun ccm-mwheel-scroll (event)
+ "Very similar to `mwheel-scroll', but does not use `scroll-down'
+and `scroll-up' but `previous-line' and `next-line', that is, the
+cursor is moved and thus the text in the window is scrolled
+due to `recenter'.
+
+The customizable variable `mouse-wheel-scroll-amount' is used to
+determine how much to scroll, where nil instead of a number means
+the same as in mwheel-scroll, scroll by a near full screen.
+
+This command exists, because mwheel-scroll caused strange
+behaviour with automatic recentering."
+;; (interactive (list last-input-event))
+ (interactive "e")
+ (when (region-active-p)
+ (deactivate-mark))
+ (let* ((mods (delq 'click (delq 'double (delq 'triple (event-modifiers event)))))
+ (amt (assoc mods mouse-wheel-scroll-amount)))
+ ;;(message "%S" mods)
+ (if amt
+ (setq amt (or (cdr amt)
+ (- (ccm-visible-text-lines)
+ next-screen-context-lines)))
+ (let ((list-elt mouse-wheel-scroll-amount))
+ (while (consp (setq amt (pop list-elt))))))
+ (if mouse-wheel-follow-mouse
+ (select-window (posn-window (event-start event))))
+ (let ((button (mwheel-event-button event)))
+ (cond
+ ((eq button mouse-wheel-down-event)
+ (forward-line (- amt)))
+ ;;(princ amt))
+ ((eq button mouse-wheel-up-event)
+ (forward-line amt))
+ ;;(princ amt))
+ (t (error "Bad binding in ccm-mwheel-scroll"))))))
+
+(defun ccm-scroll-down (&optional arg)
+ "Replaces `scroll-down' because with scroll-down
+`centered-cursor-mode' sometimes doesn't reach the top of the
+buffer. This version actually moves the cursor with
+`previous-line'. Since with centered-cursor-mode the cursor is in
+a fixed position the movement appears as page up."
+ (interactive "P")
+ (let ((amt (or arg (- (ccm-visible-text-lines)
+ next-screen-context-lines))))
+ (next-line (- amt))))
+
+(defun ccm-scroll-up (&optional arg)
+ "Replaces `scroll-up' to be consistent with `ccm-scroll-down'.
+This version actually moves the cursor with `previous-line'.
+Since with centered-cursor-mode the cursor is in a fixed position
+the movement appears as page up."
+ (interactive "P")
+ (let ((amt (or arg (- (ccm-visible-text-lines)
+ next-screen-context-lines))))
+ (next-line amt)))
+
+
+(defun ccm-vpos-down (arg)
+ "Adjust the value of the screen line (where the cursor stays) by arg.
+Negative values for arg are possible. Just the variable ccm-vpos
+is set."
+ (interactive "p")
+ (or arg (setq arg 1))
+ (let ((new-pos (if (< ccm-vpos 0)
+ (- ccm-vpos arg)
+ (+ ccm-vpos arg)))
+ ;; see pos-visible-in-window-p
+ (vpos-max (if (< ccm-vpos 0)
+ -1
+ (- (ccm-visible-text-lines) 1)))
+ (vpos-min (if (< ccm-vpos 0)
+ (- (ccm-visible-text-lines))
+ 0)))
+ (setq ccm-vpos
+ (cond
+ ((< new-pos vpos-min)
+ vpos-min)
+ ((> new-pos vpos-max)
+ vpos-max)
+ (t
+ new-pos)))))
+
+(defun ccm-vpos-up (arg)
+ "See `ccm-vpos-down'."
+ (interactive "p")
+ (or arg (setq arg 1))
+ (ccm-vpos-down (- arg)))
+
+(defun ccm-vpos-recenter ()
+ "Set the value of the screen line (where the cursor stays) in
+the center. Just the variable ccm-vpos is set."
+ (interactive)
+ (if (equal (current-buffer)
+ (window-buffer (selected-window)))
+ (setq ccm-vpos (* (eval ccm-vpos-init)
+ ccm-vpos-inverted))))
+
+(defun ccm-ignored-command-p ()
+ "Check if the last command was one listed in CCM-IGNORED-COMMANDS."
+ (member this-command ccm-ignored-commands))
+
+(defun ccm-mouse-drag-movement-p ()
+ "Check if the last input event corresponded to a mouse drag event."
+ (mouse-movement-p last-command-event))
+
+(defun ccm-position-cursor ()
+ "Do the actual recentering at the position `ccm-vpos'."
+ (unless (seq-some #'funcall ccm-inhibit-centering-when)
+ (unless ccm-vpos
+ (ccm-vpos-recenter))
+ (unless (minibufferp (current-buffer))
+ (if (equal (current-buffer)
+ (window-buffer (selected-window)))
+ (let* ((current-line
+ (if (< ccm-vpos 0)
+ ;; one-based, from bottom, negative
+ (- (count-screen-lines (point)
+ ;; window-end is sometimes < 0
+ ;; when opening a help buffer
+ (if (> (window-end) 0)
+ (window-end)
+ 1)))
+ ;; zero-based, from top, positive
+ (+ (count-screen-lines (window-start) (point))
+ ;; count-lines returns different value in column 0
+ (if (= (current-column) 0) 0 -1))))
+ (diff (- ccm-vpos current-line))
+ (step-size ccm-step-size)
+ (step-delay ccm-step-delay)
+ (vpos-inverted ccm-vpos-inverted)
+ (recenter-at-end-of-file ccm-recenter-at-end-of-file))
+
+ (let* ((bottom-vpos (if (< ccm-vpos 0)
+ (- ccm-vpos)
+ (- (ccm-visible-text-lines) ccm-vpos)))
+ (correction (save-excursion
+ (if (or (= (point) (point-max))
+ (progn
+ (goto-char (point-max))
+ (zerop (current-column))))
+ 1 0)))
+ (window-is-at-bottom (or (= (window-end) (point-max)) ; doesn't work when scrolling (eg. pgdwn)
+ (= (line-end-position ccm-vpos) (point-max)) ; doesn't work on repls second to last line, because the prompt gets inserted later?
+ ))
+ ;; lines from point to end of buffer
+ (bottom-lines (if window-is-at-bottom
+ (+ (count-screen-lines (point) (point-max))
+ correction))))
+
+ ;; only animate if the point was moved rather far away
+ ;; before by a mouseclick (see ccm-ignored-commands)
+ ;; or if minor mode is just entered interactively
+ (if (not (and (> (abs diff) 4)
+ (or (member last-command ccm-ignored-commands)
+ animate-first-start-p)))
+
+ (recenter (if (and window-is-at-bottom
+ (< bottom-lines bottom-vpos)
+ (not recenter-at-end-of-file))
+ ;; if near the bottom, recenter in the
+ ;; negative screen line that equals the
+ ;; bottom buffer line, i.e. if we are in
+ ;; the second last line (-2) of the
+ ;; buffer, the cursor will be recentered
+ ;; in -2
+ (- bottom-lines)
+ ccm-vpos))
+
+ (setq animate-first-start-p nil)
+ ;; first build a list with positions to successively recenter to
+ (setq recenter-sequence
+ ;; reverse: because we build the list not FROM -> TO but
+ ;; TO -> FROM because if step size in number-sequence is
+ ;; bigger than one, TO might not included, that means the
+ ;; ccm-vpos would not be reached
+ ;; cdr: don't recenter the current-line
+ (if (and window-is-at-bottom
+ (< bottom-lines bottom-vpos)
+ (not recenter-at-end-of-file))
+ ;; this one is for animation near the bottom
+ (cdr (reverse (number-sequence
+ (- bottom-lines)
+ (if (< ccm-vpos 0)
+ current-line
+ (- (- (ccm-visible-text-lines) current-line)))
+ (* (/ diff (abs diff)) (- step-size)))))
+ (cdr (reverse (number-sequence
+ ccm-vpos
+ current-line
+ (* (/ diff (abs diff)) (- step-size)))))))
+ ;; (message "%d %d %d (%d): %S" current-line ccm-vpos bottom-lines diff recenter-sequence)
+ (while recenter-sequence
+ ;; actual animation
+ (recenter (pop recenter-sequence))
+ (if (car recenter-sequence) (sit-for step-delay t))))))))))
+
+(defun ccm-first-start (animate)
+ "Called from centered-cursor-mode. Animate at first start, if
+centered-cursor-mode is called interactively."
+ (let ((animate-first-start-p animate))
+ (ccm-vpos-recenter)
+ (ccm-position-cursor)))
+
+;;(defalias 'ccm 'centered-cursor-mode)
+;;;###autoload
+(define-minor-mode centered-cursor-mode
+ "Makes the cursor stay vertically in a defined
+position (usually centered)."
+ :init-value nil
+;; :lighter nil
+ :lighter " ¢"
+ :keymap ccm-map
+ (cond
+ (centered-cursor-mode
+ (ccm-first-start (interactive-p))
+ (add-hook 'post-command-hook 'ccm-position-cursor t t)
+ (add-hook 'window-configuration-change-hook 'ccm-vpos-recenter t t))
+ (t
+ (remove-hook 'post-command-hook 'ccm-position-cursor t)
+ (remove-hook 'window-configuration-change-hook 'ccm-vpos-recenter t))))
+
+;;;###autoload
+(define-global-minor-mode global-centered-cursor-mode centered-cursor-mode
+ centered-cursor-mode)
+
+(provide 'centered-cursor-mode)
+
+;;; Help:
+;; (info "(elisp)Defining Minor Modes")
+;; (info "(elisp)Screen Lines")
+;; (info "(elisp)Hooks")
+;; (info "(elisp)Customization")
+;; (find-function 'mwheel-scroll)
+
+;; Local Variables:
+;; coding: utf-8
+;; End:
+
+;;; centered-cursor-mode.el ends here