1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-25 07:28:20 +00:00
emacs/lisp/follow.el

1808 lines
66 KiB
EmacsLisp
Raw Normal View History

;;; follow.el --- synchronize windows showing the same buffer -*- lexical-binding: t -*-
;; Copyright (C) 1995-1997, 1999, 2001-2021 Free Software Foundation,
;; Inc.
1996-02-16 01:01:16 +00:00
;; Author: Anders Lindgren
;; Maintainer: emacs-devel@gnu.org
;; Created: 1995-05-25
1998-05-26 09:23:23 +00:00
;; Keywords: display, window, minor-mode, convenience
1996-02-16 01:01:16 +00:00
1996-04-11 18:19:30 +00:00
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
1996-02-16 01:01:16 +00:00
;; 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.
1996-02-16 01:01:16 +00:00
1996-04-11 18:19:30 +00:00
;; GNU Emacs is distributed in the hope that it will be useful,
1996-02-16 01:01:16 +00:00
;; 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. If not, see <https://www.gnu.org/licenses/>.
1996-02-16 01:01:16 +00:00
;;; Commentary:
;; `follow-mode' is a minor mode that combines windows into one tall
;; virtual window.
1996-02-16 01:01:16 +00:00
;;
;; The feeling of a "virtual window" has been accomplished by the use
;; of two major techniques:
;;
2007-09-13 08:08:58 +00:00
;; * The windows always display adjacent sections of the buffer.
1996-02-16 01:01:16 +00:00
;; This means that whenever one window is moved, all the
;; others will follow. (Hence the name Follow mode.)
1996-02-16 01:01:16 +00:00
;;
;; * Should point (cursor) end up outside a window, another
;; window displaying that point is selected, if possible. This
;; makes it possible to walk between windows using normal cursor
1996-02-16 01:01:16 +00:00
;; movement commands.
;;
;; Follow mode comes to its prime when a large screen and two
;; side-by-side window are used. The user can, with the help of Follow
2007-09-13 08:08:58 +00:00
;; mode, use two full-height windows as though they are one.
;; Imagine yourself editing a large function, or section of text,
;; and being able to use 144 lines instead of the normal 72... (your
1996-02-16 01:01:16 +00:00
;; mileage may vary).
;; To test this package, make sure `follow' is loaded, or will be
;; autoloaded when activated (see below). Then do the following:
1996-02-16 01:01:16 +00:00
;;
;; * Find your favorite file (preferably a long one).
1996-02-16 01:01:16 +00:00
;;
;; * Resize Emacs so that it will be wide enough for two full size
;; columns. Delete the other windows and split the window with
;; the commands `C-x 1 C-x 3'.
1996-02-16 01:01:16 +00:00
;;
;; * Give the command:
;; M-x follow-mode <RETURN>
;;
;; * Now the display should look something like (assuming the text "71"
;; is on line 71):
;;
;; +----------+----------+
;; |1 |73 |
;; |2 |74 |
;; |3 |75 |
;; ... ...
1996-02-16 01:01:16 +00:00
;; |71 |143 |
;; |72 |144 |
;; +----------+----------+
;;
;; As you can see, the right-hand window starts at line 73, the line
;; immediately below the end of the left-hand window. As long as
2007-09-13 08:08:58 +00:00
;; `follow-mode' is active, the two windows will follow each other!
1996-02-16 01:01:16 +00:00
;;
;; * Play around and enjoy! Scroll one window and watch the other.
;; Jump to the beginning or end. Press `Cursor down' at the last
;; line of the left-hand window. Enter new lines into the
;; text. Enter long lines spanning several lines, or several
1996-02-16 01:01:16 +00:00
;; windows.
;;
;; * Should you find Follow mode annoying, just type
;; M-x follow-mode <RETURN>
1996-02-16 01:01:16 +00:00
;; to turn it off.
2011-11-19 09:18:31 +00:00
;; The command `follow-delete-other-windows-and-split' maximizes the
1996-02-16 01:01:16 +00:00
;; visible area of the current buffer.
;;
;; I recommend adding it, and `follow-mode', to hotkeys in the global
;; key map. To do so, add the following lines (replacing `[f7]' and
;; `[f8]' with your favorite keys) to the init file:
;;
;; (global-set-key [f8] #'follow-mode)
;; (global-set-key [f7] #'follow-delete-other-windows-and-split)
1996-02-16 01:01:16 +00:00
2011-11-25 07:14:48 +00:00
;; There exist two system variables that control the appearance of
2007-09-13 08:08:58 +00:00
;; lines wider than the window containing them. The default is to
;; truncate long lines whenever a window isn't as wide as the frame.
1996-02-16 01:01:16 +00:00
;;
;; To make sure lines are never truncated, place the following lines
;; in your Init file:
1996-02-16 01:01:16 +00:00
;;
;; (setq truncate-lines nil)
;; (setq truncate-partial-width-windows nil)
;; One way to configure Follow mode is to create one or more functions
;; that do whatever you would like to do. These functions are then
;; added to a hook.
1996-02-16 01:01:16 +00:00
;;
;; The keymap `follow-mode-map' contains key bindings activated by
1996-02-16 01:01:16 +00:00
;; `follow-mode'.
;;
;; Example:
;; (add-hook 'follow-mode-hook 'my-follow-mode-hook)
1996-02-16 01:01:16 +00:00
;;
;; (defun my-follow-mode-hook ()
;; (define-key follow-mode-map "\C-ca" #'your-favorite-function)
;; (define-key follow-mode-map "\C-cb" #'another-function))
1996-02-16 01:01:16 +00:00
;; Usage:
;;
2007-09-13 08:08:58 +00:00
;; To activate, issue the command "M-x follow-mode"
;; and press Return. To deactivate, do it again.
1996-02-16 01:01:16 +00:00
;;
;; The following is a list of commands useful when `follow-mode' is active.
;;
;; `follow-scroll-up' C-c . C-v
;; Scroll text in a Follow mode window chain up.
1996-02-16 01:01:16 +00:00
;;
;; `follow-scroll-down' C-c . v
1996-02-16 01:01:16 +00:00
;; Like `follow-scroll-up', but in the other direction.
;;
;; `follow-delete-other-windows-and-split' C-c . 1
2007-09-13 08:08:58 +00:00
;; Maximize the visible area of the current buffer,
;; and enter Follow mode. This is a very convenient
2011-11-20 19:35:27 +00:00
;; way to start Follow mode, hence we recommend that
2007-09-13 08:08:58 +00:00
;; this command be added to the global keymap.
1996-02-16 01:01:16 +00:00
;;
;; `follow-recenter' C-c . C-l
;; Place point in the center of the middle window,
1996-02-16 01:01:16 +00:00
;; or a specified number of lines from either top or bottom.
;;
;; `follow-switch-to-buffer' C-c . b
1996-02-16 01:01:16 +00:00
;; Switch buffer in all windows displaying the current buffer
;; in this frame.
;;
;; `follow-switch-to-buffer-all' C-c . C-b
2007-09-13 08:08:58 +00:00
;; Switch buffer in all windows in the selected frame.
1996-02-16 01:01:16 +00:00
;;
;; `follow-switch-to-current-buffer-all'
1996-02-16 01:01:16 +00:00
;; Show the current buffer in all windows on the current
;; frame and turn on `follow-mode'.
;;
;; `follow-first-window' C-c . <
1996-02-16 01:01:16 +00:00
;; Select the first window in the frame showing the same buffer.
;;
;; `follow-last-window' C-c . >
1996-02-16 01:01:16 +00:00
;; Select the last window in the frame showing the same buffer.
;;
;; `follow-next-window' C-c . n
1996-02-16 01:01:16 +00:00
;; Select the next window in the frame showing the same buffer.
;;
;; `follow-previous-window' C-c . p
1996-02-16 01:01:16 +00:00
;; Select the previous window showing the same buffer.
;; Well, it seems ok, but what if I really want to look at two different
;; positions in the text? Here are two simple methods to use:
1996-02-16 01:01:16 +00:00
;;
;; 1) Use multiple frames; `follow' mode only affects windows displayed
;; in the same frame. (My apologies to you who can't use frames.)
1996-02-16 01:01:16 +00:00
;;
;; 2) Bind `follow-mode' to key so you can turn it off whenever
;; you want to view two locations. Of course, `follow-mode' can
1996-02-16 01:01:16 +00:00
;; be reactivated by hitting the same key again.
;;
;; Example from my ~/.emacs:
;; (global-set-key [f8] #'follow-mode)
1996-02-16 01:01:16 +00:00
;; Implementation:
1996-02-16 01:01:16 +00:00
;;
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; The main method by which Follow mode aligns windows is via the
;; function `follow-pre-redisplay-function', which is run before each
;; redisplay. This "fixes up" the alignment of other windows which are
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; showing the same Follow mode buffer, on the same frame as the
;; selected window. It does not try to deal with buffers other than
;; the buffer of the selected frame, or windows on other frames.
1996-02-16 01:01:16 +00:00
;;
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; Comint mode specially calls `follow-comint-scroll-to-bottom' on
;; Follow mode buffers. This function scrolls the bottom-most window
;; in a window chain and aligns the other windows accordingly. Follow
;; mode adds a function to `compilation-filter-hook' to align
;; compilation buffers.
1996-02-16 01:01:16 +00:00
;;; Code:
(eval-when-compile (require 'cl-lib))
2007-10-09 15:27:49 +00:00
;;; Variables
1996-02-16 01:01:16 +00:00
1998-03-07 18:19:38 +00:00
(defgroup follow nil
"Synchronize windows showing the same buffer."
1998-05-26 09:23:23 +00:00
:group 'windows
:group 'convenience)
1998-03-07 18:19:38 +00:00
(defcustom follow-mode-hook nil
"Normal hook run by `follow-mode'."
1998-03-07 18:19:38 +00:00
:type 'hook
:group 'follow)
1996-02-16 01:01:16 +00:00
;;; Keymap/Menu
1996-02-16 01:01:16 +00:00
;; Define keys for the follow-mode minor mode map and replace some
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; functions in the global map. All Follow mode special functions can
;; be found on the `C-c .' prefix key.
;;
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; To change the prefix, redefine `follow-mode-prefix' before `follow'
;; is loaded, or see the section on `follow-mode-hook' above for an
;; example of how to bind the keys the way you like.
1996-02-16 01:01:16 +00:00
1998-03-07 18:19:38 +00:00
(defcustom follow-mode-prefix "\C-c."
"Prefix key to use for follow commands in Follow mode.
1996-02-16 01:01:16 +00:00
The value of this variable is checked as part of loading Follow mode.
1998-03-07 18:19:38 +00:00
After that, changing the prefix key requires manipulating keymaps."
:type 'string
:group 'follow)
(defvar follow-mode-map
(let ((mainmap (make-sparse-keymap))
(map (make-sparse-keymap)))
(define-key map "\C-v" #'follow-scroll-up)
(define-key map "\M-v" #'follow-scroll-down)
(define-key map "v" #'follow-scroll-down)
(define-key map "1" #'follow-delete-other-windows-and-split)
(define-key map "b" #'follow-switch-to-buffer)
(define-key map "\C-b" #'follow-switch-to-buffer-all)
(define-key map "\C-l" #'follow-recenter)
(define-key map "<" #'follow-first-window)
(define-key map ">" #'follow-last-window)
(define-key map "n" #'follow-next-window)
(define-key map "p" #'follow-previous-window)
1996-02-16 01:01:16 +00:00
(define-key mainmap follow-mode-prefix map)
1996-02-16 01:01:16 +00:00
;; Replace the standard `end-of-buffer', when in Follow mode. (I
;; don't see the point in trying to replace every function that
1996-02-16 01:01:16 +00:00
;; could be enhanced in Follow mode. End-of-buffer is a special
;; case since it is very simple to define and it greatly enhances
;; the look and feel of Follow mode.)
(define-key mainmap [remap end-of-buffer] #'follow-end-of-buffer)
1996-02-16 01:01:16 +00:00
(define-key mainmap [remap scroll-bar-toolkit-scroll] #'follow-scroll-bar-toolkit-scroll)
(define-key mainmap [remap scroll-bar-drag] #'follow-scroll-bar-drag)
(define-key mainmap [remap scroll-bar-scroll-up] #'follow-scroll-bar-scroll-up)
(define-key mainmap [remap scroll-bar-scroll-down] #'follow-scroll-bar-scroll-down)
(define-key mainmap [remap mwheel-scroll] #'follow-mwheel-scroll)
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
mainmap)
"Minor mode keymap for Follow mode.")
1996-02-16 01:01:16 +00:00
;; When the mode is not activated, only one item is visible to activate
;; the mode.
(defun follow-menu-filter (menu)
(if (bound-and-true-p follow-mode)
menu
'(["Follow mode" follow-mode
:style toggle :selected follow-mode])))
(easy-menu-add-item nil '("Tools")
'("Follow"
:filter follow-menu-filter
["Scroll Up" follow-scroll-up follow-mode]
["Scroll Down" follow-scroll-down follow-mode]
"--"
["Delete Other Windows and Split" follow-delete-other-windows-and-split follow-mode]
"--"
["Switch To Buffer" follow-switch-to-buffer follow-mode]
["Switch To Buffer (all windows)" follow-switch-to-buffer-all follow-mode]
"--"
["First Window" follow-first-window follow-mode]
["Last Window" follow-last-window follow-mode]
["Next Window" follow-next-window follow-mode]
["Previous Window" follow-previous-window follow-mode]
"--"
["Recenter" follow-recenter follow-mode]
"--"
["Follow mode" follow-mode :style toggle :selected follow-mode]))
(defcustom follow-mode-line-text " Follow"
"Text shown in the mode line when Follow mode is active.
Defaults to \" Follow\". Examples of other values
are \" Fw\", or simply \"\"."
:type 'string
:group 'follow)
(defcustom follow-auto nil
"Non-nil activates Follow mode whenever a file is loaded."
:type 'boolean
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
:group 'follow
:set (lambda (symbol value)
(if value
(add-hook 'find-file-hook 'follow-find-file-hook t)
(remove-hook 'find-file-hook 'follow-find-file-hook))
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(set-default symbol value)))
(defcustom follow-hide-ghost-cursors t ; Maybe this should be nil.
"When non-nil, Follow mode attempts to hide the obtrusive cursors
in the non-selected windows of a window group.
This variable takes effect when `follow-mode' is initialized.
Due to limitations in Emacs, this only operates on the followers
of the selected window."
:type 'boolean
:group 'follow)
(defvar follow-cache-command-list
'(next-line previous-line forward-char backward-char right-char left-char)
"List of commands that don't require recalculation.
In order to be able to use the cache, a command should not change the
contents of the buffer, nor should it change selected window or current
buffer.
The commands in this list are checked at load time.
To mark other commands as suitable for caching, set the symbol
property `follow-mode-use-cache' to non-nil.")
(defcustom follow-debug nil
"If non-nil, emit Follow mode debugging messages."
:type 'boolean
:group 'follow)
;; Internal variables:
(defvar follow-internal-force-redisplay nil
"Non-nil when Follow mode should redisplay the windows.")
(defvar follow-active-menu nil
"The menu visible when Follow mode is active.")
(defvar follow-inactive-menu nil
"The menu visible when Follow mode is inactive.")
(defvar follow-inside-post-command-hook-call nil
"Non-nil when inside Follow modes `post-command-hook'.
Used by `follow-window-size-change'.")
(defvar follow-windows-start-end-cache nil
"Cache used by `follow-window-start' and `follow-window-end'.")
(defvar follow-fixed-window nil
"If non-nil, the current window must not be scrolled.
This is typically set by explicit scrolling commands.")
;;; Debug messages
;; This inline function must be as small as possible!
;; Maybe we should define a macro that expands to nil if
;; the variable is not set.
(defsubst follow-debug-message (&rest args)
2011-07-14 01:09:00 +00:00
"Like `message', but only active when `follow-debug' is non-nil."
(if (and (boundp 'follow-debug) follow-debug)
(apply #'message args)))
1996-02-16 01:01:16 +00:00
;;; Cache
(dolist (cmd follow-cache-command-list)
(put cmd 'follow-mode-use-cache t))
;;; The mode
1996-02-16 01:01:16 +00:00
;;;###autoload
(defun turn-on-follow-mode ()
"Turn on Follow mode. Please see the function `follow-mode'."
1996-02-16 01:01:16 +00:00
(follow-mode 1))
;;;###autoload
(defun turn-off-follow-mode ()
"Turn off Follow mode. Please see the function `follow-mode'."
1996-02-16 01:01:16 +00:00
(follow-mode -1))
(put 'follow-mode 'permanent-local t)
1996-02-16 01:01:16 +00:00
;;;###autoload
(define-minor-mode follow-mode
Fix minor mode docstrings for the new meaning of a nil ARG. * abbrev.el (abbrev-mode): * allout.el (allout-mode): * autoinsert.el (auto-insert-mode): * autoarg.el (autoarg-mode, autoarg-kp-mode): * autorevert.el (auto-revert-mode, auto-revert-tail-mode) (global-auto-revert-mode): * battery.el (display-battery-mode): * composite.el (global-auto-composition-mode) (auto-composition-mode): * delsel.el (delete-selection-mode): * desktop.el (desktop-save-mode): * dired-x.el (dired-omit-mode): * dirtrack.el (dirtrack-mode): * doc-view.el (doc-view-minor-mode): * double.el (double-mode): * electric.el (electric-indent-mode, electric-pair-mode): * emacs-lock.el (emacs-lock-mode): * epa-hook.el (auto-encryption-mode): * follow.el (follow-mode): * font-core.el (font-lock-mode): * frame.el (auto-raise-mode, auto-lower-mode, blink-cursor-mode): * help.el (temp-buffer-resize-mode): * hilit-chg.el (highlight-changes-mode) (highlight-changes-visible-mode): * hi-lock.el (hi-lock-mode): * hl-line.el (hl-line-mode, global-hl-line-mode): * icomplete.el (icomplete-mode): * ido.el (ido-everywhere): * image-file.el (auto-image-file-mode): * image-mode.el (image-minor-mode): * iswitchb.el (iswitchb-mode): * jka-cmpr-hook.el (auto-compression-mode): * linum.el (linum-mode): * longlines.el (longlines-mode): * master.el (master-mode): * mb-depth.el (minibuffer-depth-indicate-mode): * menu-bar.el (menu-bar-mode): * minibuf-eldef.el (minibuffer-electric-default-mode): * mouse-sel.el (mouse-sel-mode): * msb.el (msb-mode): * mwheel.el (mouse-wheel-mode): * outline.el (outline-minor-mode): * paren.el (show-paren-mode): * recentf.el (recentf-mode): * reveal.el (reveal-mode, global-reveal-mode): * rfn-eshadow.el (file-name-shadow-mode): * ruler-mode.el (ruler-mode): * savehist.el (savehist-mode): * scroll-all.el (scroll-all-mode): * scroll-bar.el (scroll-bar-mode): * server.el (server-mode): * shell.el (shell-dirtrack-mode): * simple.el (auto-fill-mode, transient-mark-mode) (visual-line-mode, overwrite-mode, binary-overwrite-mode) (line-number-mode, column-number-mode, size-indication-mode) (auto-save-mode, normal-erase-is-backspace-mode, visible-mode): * strokes.el (strokes-mode): * time.el (display-time-mode): * t-mouse.el (gpm-mouse-mode): * tool-bar.el (tool-bar-mode): * tooltip.el (tooltip-mode): * type-break.el (type-break-mode-line-message-mode) (type-break-query-mode): * view.el (view-mode): * whitespace.el (whitespace-mode, whitespace-newline-mode) (global-whitespace-mode, global-whitespace-newline-mode): * xt-mouse.el (xterm-mouse-mode): Doc fix. * emacs-lisp/easy-mmode.el (define-globalized-minor-mode): Fix autogenerated docstring.
2011-10-19 12:54:24 +00:00
"Toggle Follow mode.
1996-02-16 01:01:16 +00:00
Fix minor mode docstrings for the new meaning of a nil ARG. * abbrev.el (abbrev-mode): * allout.el (allout-mode): * autoinsert.el (auto-insert-mode): * autoarg.el (autoarg-mode, autoarg-kp-mode): * autorevert.el (auto-revert-mode, auto-revert-tail-mode) (global-auto-revert-mode): * battery.el (display-battery-mode): * composite.el (global-auto-composition-mode) (auto-composition-mode): * delsel.el (delete-selection-mode): * desktop.el (desktop-save-mode): * dired-x.el (dired-omit-mode): * dirtrack.el (dirtrack-mode): * doc-view.el (doc-view-minor-mode): * double.el (double-mode): * electric.el (electric-indent-mode, electric-pair-mode): * emacs-lock.el (emacs-lock-mode): * epa-hook.el (auto-encryption-mode): * follow.el (follow-mode): * font-core.el (font-lock-mode): * frame.el (auto-raise-mode, auto-lower-mode, blink-cursor-mode): * help.el (temp-buffer-resize-mode): * hilit-chg.el (highlight-changes-mode) (highlight-changes-visible-mode): * hi-lock.el (hi-lock-mode): * hl-line.el (hl-line-mode, global-hl-line-mode): * icomplete.el (icomplete-mode): * ido.el (ido-everywhere): * image-file.el (auto-image-file-mode): * image-mode.el (image-minor-mode): * iswitchb.el (iswitchb-mode): * jka-cmpr-hook.el (auto-compression-mode): * linum.el (linum-mode): * longlines.el (longlines-mode): * master.el (master-mode): * mb-depth.el (minibuffer-depth-indicate-mode): * menu-bar.el (menu-bar-mode): * minibuf-eldef.el (minibuffer-electric-default-mode): * mouse-sel.el (mouse-sel-mode): * msb.el (msb-mode): * mwheel.el (mouse-wheel-mode): * outline.el (outline-minor-mode): * paren.el (show-paren-mode): * recentf.el (recentf-mode): * reveal.el (reveal-mode, global-reveal-mode): * rfn-eshadow.el (file-name-shadow-mode): * ruler-mode.el (ruler-mode): * savehist.el (savehist-mode): * scroll-all.el (scroll-all-mode): * scroll-bar.el (scroll-bar-mode): * server.el (server-mode): * shell.el (shell-dirtrack-mode): * simple.el (auto-fill-mode, transient-mark-mode) (visual-line-mode, overwrite-mode, binary-overwrite-mode) (line-number-mode, column-number-mode, size-indication-mode) (auto-save-mode, normal-erase-is-backspace-mode, visible-mode): * strokes.el (strokes-mode): * time.el (display-time-mode): * t-mouse.el (gpm-mouse-mode): * tool-bar.el (tool-bar-mode): * tooltip.el (tooltip-mode): * type-break.el (type-break-mode-line-message-mode) (type-break-query-mode): * view.el (view-mode): * whitespace.el (whitespace-mode, whitespace-newline-mode) (global-whitespace-mode, global-whitespace-newline-mode): * xt-mouse.el (xterm-mouse-mode): Doc fix. * emacs-lisp/easy-mmode.el (define-globalized-minor-mode): Fix autogenerated docstring.
2011-10-19 12:54:24 +00:00
Follow mode is a minor mode that combines windows into one tall
virtual window. This is accomplished by two main techniques:
1996-02-16 01:01:16 +00:00
* The windows always displays adjacent sections of the buffer.
1996-02-16 01:01:16 +00:00
This means that whenever one window is moved, all the
others will follow. (Hence the name Follow mode.)
1996-02-16 01:01:16 +00:00
* Should point (cursor) end up outside a window, another
window displaying that point is selected, if possible. This
makes it possible to walk between windows using normal cursor
1996-02-16 01:01:16 +00:00
movement commands.
Follow mode comes to its prime when used on a large screen and two or
more side-by-side windows are used. The user can, with the help of
Follow mode, use these full-height windows as though they were one.
Imagine yourself editing a large function, or section of text, and
being able to use 144 or 216 lines instead of the normal 72... (your
1996-02-16 01:01:16 +00:00
mileage may vary).
To split one large window into two side-by-side windows, the commands
`\\[split-window-right]' or \
`\\[follow-delete-other-windows-and-split]' can be used.
1996-02-16 01:01:16 +00:00
Only windows displayed in the same frame follow each other.
1996-02-16 01:01:16 +00:00
This command runs the normal hook `follow-mode-hook'.
1996-02-16 01:01:16 +00:00
Keys specific to Follow mode:
\\{follow-mode-map}"
:lighter follow-mode-line-text
:keymap follow-mode-map
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(if follow-mode
(progn
(add-hook 'compilation-filter-hook 'follow-align-compilation-windows t t)
(add-function :before pre-redisplay-function 'follow-pre-redisplay-function)
(add-hook 'window-size-change-functions 'follow-window-size-change t)
(add-hook 'after-change-functions 'follow-after-change nil t)
(add-hook 'isearch-update-post-hook 'follow-post-command-hook nil t)
(add-hook 'replace-update-post-hook 'follow-post-command-hook nil t)
(add-hook 'ispell-update-post-hook 'follow-post-command-hook nil t)
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
(when isearch-lazy-highlight
(setq-local isearch-lazy-highlight 'all-windows))
(when follow-hide-ghost-cursors
(setq-local cursor-in-non-selected-windows nil))
(setq window-group-start-function 'follow-window-start)
(setq window-group-end-function 'follow-window-end)
(setq set-window-group-start-function 'follow-set-window-start)
(setq recenter-window-group-function 'follow-recenter)
Replace GROUP argument in six window primitives by new functions. * doc/lispref/windows.texi (Window Start and End, Textual Scrolling) * doc/lispref/positions.texi (Screen Lines): Remove optional GROUP argument from description of six window functions. Add in description of new functions window-group-start, window-group-end, set-window-group-start, pos-visible-in-window-group-p, recenter-group and move-to-window-group-line, together with the six variables indirecting to the pertinent group functions. * src/window.c * src/keyboard.c: Revert the commit from 2015-11-11 12:02:48, in so far as it applies to these two files, which added the GROUP argument to six window primitives. * lisp/follow.el (follow-mode): Use updated variable names for the indirected functions. * lisp/isearch.el (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update): Replace calls to window primitives (e.g. window-start) with a GROUP argument by calls to new functions (e.g. window-group-start). * lisp/ispell.el (ispell-command-loop): Replace call to pos-visible-in-window-p with pos-visible-in-window-group-p. * lisp/window.el (window-group-start, window-group-end) (set-window-group-start, recenter-group, pos-visible-in-window-group-p) (selected-window-group, move-to-window-group-line): New functions. (window-group-start-function, window-group-end-function) (set-window-group-start-function, recenter-group-function) (pos-visible-in-window-group-p-function, selected-window-group-function) (move-to-window-group-line-function): New variables.
2015-12-14 16:38:07 +00:00
(setq pos-visible-in-window-group-p-function
'follow-pos-visible-in-window-p)
(setq selected-window-group-function 'follow-all-followers)
(setq move-to-window-group-line-function 'follow-move-to-window-line))
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; Remove globally-installed hook functions only if there is no
;; other Follow mode buffer.
(let ((buffers (buffer-list))
following)
(while (and (not following) buffers)
(setq following (buffer-local-value 'follow-mode (car buffers))
buffers (cdr buffers)))
(unless following
(remove-function pre-redisplay-function 'follow-pre-redisplay-function)
(remove-hook 'window-size-change-functions 'follow-window-size-change)))
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
Replace GROUP argument in six window primitives by new functions. * doc/lispref/windows.texi (Window Start and End, Textual Scrolling) * doc/lispref/positions.texi (Screen Lines): Remove optional GROUP argument from description of six window functions. Add in description of new functions window-group-start, window-group-end, set-window-group-start, pos-visible-in-window-group-p, recenter-group and move-to-window-group-line, together with the six variables indirecting to the pertinent group functions. * src/window.c * src/keyboard.c: Revert the commit from 2015-11-11 12:02:48, in so far as it applies to these two files, which added the GROUP argument to six window primitives. * lisp/follow.el (follow-mode): Use updated variable names for the indirected functions. * lisp/isearch.el (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update): Replace calls to window primitives (e.g. window-start) with a GROUP argument by calls to new functions (e.g. window-group-start). * lisp/ispell.el (ispell-command-loop): Replace call to pos-visible-in-window-p with pos-visible-in-window-group-p. * lisp/window.el (window-group-start, window-group-end) (set-window-group-start, recenter-group, pos-visible-in-window-group-p) (selected-window-group, move-to-window-group-line): New functions. (window-group-start-function, window-group-end-function) (set-window-group-start-function, recenter-group-function) (pos-visible-in-window-group-p-function, selected-window-group-function) (move-to-window-group-line-function): New variables.
2015-12-14 16:38:07 +00:00
(kill-local-variable 'move-to-window-group-line-function)
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
(kill-local-variable 'selected-window-group-function)
Replace GROUP argument in six window primitives by new functions. * doc/lispref/windows.texi (Window Start and End, Textual Scrolling) * doc/lispref/positions.texi (Screen Lines): Remove optional GROUP argument from description of six window functions. Add in description of new functions window-group-start, window-group-end, set-window-group-start, pos-visible-in-window-group-p, recenter-group and move-to-window-group-line, together with the six variables indirecting to the pertinent group functions. * src/window.c * src/keyboard.c: Revert the commit from 2015-11-11 12:02:48, in so far as it applies to these two files, which added the GROUP argument to six window primitives. * lisp/follow.el (follow-mode): Use updated variable names for the indirected functions. * lisp/isearch.el (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update): Replace calls to window primitives (e.g. window-start) with a GROUP argument by calls to new functions (e.g. window-group-start). * lisp/ispell.el (ispell-command-loop): Replace call to pos-visible-in-window-p with pos-visible-in-window-group-p. * lisp/window.el (window-group-start, window-group-end) (set-window-group-start, recenter-group, pos-visible-in-window-group-p) (selected-window-group, move-to-window-group-line): New functions. (window-group-start-function, window-group-end-function) (set-window-group-start-function, recenter-group-function) (pos-visible-in-window-group-p-function, selected-window-group-function) (move-to-window-group-line-function): New variables.
2015-12-14 16:38:07 +00:00
(kill-local-variable 'pos-visible-in-window-group-p-function)
(kill-local-variable 'recenter-window-group-function)
Replace GROUP argument in six window primitives by new functions. * doc/lispref/windows.texi (Window Start and End, Textual Scrolling) * doc/lispref/positions.texi (Screen Lines): Remove optional GROUP argument from description of six window functions. Add in description of new functions window-group-start, window-group-end, set-window-group-start, pos-visible-in-window-group-p, recenter-group and move-to-window-group-line, together with the six variables indirecting to the pertinent group functions. * src/window.c * src/keyboard.c: Revert the commit from 2015-11-11 12:02:48, in so far as it applies to these two files, which added the GROUP argument to six window primitives. * lisp/follow.el (follow-mode): Use updated variable names for the indirected functions. * lisp/isearch.el (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update): Replace calls to window primitives (e.g. window-start) with a GROUP argument by calls to new functions (e.g. window-group-start). * lisp/ispell.el (ispell-command-loop): Replace call to pos-visible-in-window-p with pos-visible-in-window-group-p. * lisp/window.el (window-group-start, window-group-end) (set-window-group-start, recenter-group, pos-visible-in-window-group-p) (selected-window-group, move-to-window-group-line): New functions. (window-group-start-function, window-group-end-function) (set-window-group-start-function, recenter-group-function) (pos-visible-in-window-group-p-function, selected-window-group-function) (move-to-window-group-line-function): New variables.
2015-12-14 16:38:07 +00:00
(kill-local-variable 'set-window-group-start-function)
(kill-local-variable 'window-group-end-function)
(kill-local-variable 'window-group-start-function)
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
(kill-local-variable 'cursor-in-non-selected-windows)
(remove-hook 'ispell-update-post-hook 'follow-post-command-hook t)
(remove-hook 'replace-update-post-hook 'follow-post-command-hook t)
(remove-hook 'isearch-update-post-hook 'follow-post-command-hook t)
(remove-hook 'after-change-functions 'follow-after-change t)
(remove-hook 'compilation-filter-hook 'follow-align-compilation-windows t)))
1996-02-16 01:01:16 +00:00
(defun follow-find-file-hook ()
"Find-file hook for Follow mode. See the variable `follow-auto'."
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(if follow-auto (follow-mode 1)))
1996-02-16 01:01:16 +00:00
;;; User functions
1996-02-16 01:01:16 +00:00
;;; Scroll
1996-02-16 01:01:16 +00:00
(defun follow-get-scrolled-point (dest windows)
"Calculate the correct value for point after a scrolling operation.
DEST is our default position, typically where point was before the scroll.
If `scroll-preserve-screen-position' is non-nil and active, DEST will be
in the same screen position as before the scroll. WINDOWS is the list of
windows in the follow chain.
This function attempts to duplicate the point placing from
`window_scroll_line_based' in the Emacs core source window.c.
Return the new position."
(if (and scroll-preserve-screen-position
(get this-command 'scroll-command))
dest
(let ((dest-column
(save-excursion
(goto-char dest)
(- (current-column)
(progn (vertical-motion 0) (current-column)))))
(limit0
(with-selected-window (car windows)
(save-excursion
(goto-char (window-start))
(vertical-motion 0)
(point))))
(limitn
(with-selected-window (car (reverse windows))
(save-excursion
(goto-char (window-end nil t))
(if (pos-visible-in-window-p)
(point) ; i.e. (point-max)
(1- (point)))))))
(cond
((< dest limit0)
(with-selected-window (car windows)
(save-excursion
(goto-char limit0)
(vertical-motion (cons dest-column 0))
(point))))
((> dest limitn)
(with-selected-window (car (reverse windows))
(save-excursion
(goto-char limitn)
(vertical-motion (cons dest-column 0))
(point))))
(t dest)))))
;; `scroll-up' and `-down', but for windows in Follow mode.
1996-02-16 01:01:16 +00:00
;;
2011-11-17 09:09:20 +00:00
;; Almost like the real thing, except when the cursor ends up outside
1996-02-16 01:01:16 +00:00
;; the top or bottom... In our case however, we end up outside the
2011-11-20 07:30:16 +00:00
;; window and hence we are recentered. Should we let `recenter' handle
1996-02-16 01:01:16 +00:00
;; the point position we would never leave the selected window. To do
;; it ourselves we would need to do our own redisplay, which is easier
;; said than done. (Why didn't I do a real display abstraction from
;; the beginning?)
;;
;; We must sometimes set `follow-internal-force-redisplay', otherwise
;; our post-command-hook will move our windows back into the old
;; position... (This would also be corrected if we would have had a
;; good redisplay abstraction.)
(defun follow-scroll-up-arg (arg)
"Scroll the text in a follow mode window chain up by ARG lines.
If ARG is nil, scroll the size of the current window.
This is an internal function for `follow-scroll-up' and
`follow-scroll-up-window'."
(let ((opoint (point)) (owin (selected-window)))
(while
;; If we are too near EOB, try scrolling the previous window.
(condition-case nil (progn (scroll-up-command arg) nil)
(end-of-buffer
(condition-case nil (progn (follow-previous-window) t)
(error
(select-window owin)
(goto-char opoint)
(signal 'end-of-buffer nil))))))
(unless (and scroll-preserve-screen-position
(get this-command 'scroll-command))
(goto-char opoint))
(setq follow-fixed-window t)))
(defun follow-scroll-down-arg (arg)
"Scroll the text in a follow mode window chain down by ARG lines.
If ARG is nil, scroll the size of the current window.
This is an internal function for `follow-scroll-down' and
`follow-scroll-down-window'."
(let ((opoint (point)))
(scroll-down-command arg)
(unless (and scroll-preserve-screen-position
(get this-command 'scroll-command))
(goto-char opoint))
(setq follow-fixed-window t)))
;;;###autoload
(defun follow-scroll-up-window (&optional arg)
"Scroll text in a Follow mode window up by that window's size.
The other windows in the window chain will scroll synchronously.
If called with no ARG, the `next-screen-context-lines' last lines of
the window will be visible after the scroll.
If called with an argument, scroll ARG lines up.
Negative ARG means scroll downward.
Works like `scroll-up' when not in Follow mode."
(interactive "P")
(cond ((not follow-mode)
(scroll-up-command arg))
((eq arg '-)
(follow-scroll-down-window))
(t (follow-scroll-up-arg arg))))
(put 'follow-scroll-up-window 'scroll-command t)
;;;###autoload
(defun follow-scroll-down-window (&optional arg)
"Scroll text in a Follow mode window down by that window's size.
The other windows in the window chain will scroll synchronously.
If called with no ARG, the `next-screen-context-lines' top lines of
the window in the chain will be visible after the scroll.
If called with an argument, scroll ARG lines down.
Negative ARG means scroll upward.
Works like `scroll-down' when not in Follow mode."
(interactive "P")
(cond ((not follow-mode)
(scroll-down-command arg))
((eq arg '-)
(follow-scroll-up-window))
(t (follow-scroll-down-arg arg))))
(put 'follow-scroll-down-window 'scroll-command t)
;;;###autoload
1996-02-16 01:01:16 +00:00
(defun follow-scroll-up (&optional arg)
"Scroll text in a Follow mode window chain up.
1996-02-16 01:01:16 +00:00
If called with no ARG, the `next-screen-context-lines' last lines of
the bottom window in the chain will be visible in the top window.
If called with an argument, scroll ARG lines up.
Negative ARG means scroll downward.
Works like `scroll-up' when not in Follow mode."
1996-02-16 01:01:16 +00:00
(interactive "P")
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(cond ((not follow-mode)
(scroll-up-command arg))
(arg (follow-scroll-up-arg arg))
(t
(let* ((windows (follow-all-followers))
(end (window-end (car (reverse windows)))))
(if (eq end (point-max))
(if (or (null scroll-error-top-bottom)
(eobp))
(signal 'end-of-buffer nil)
(goto-char (point-max)))
(select-window (car windows))
;; `window-end' might return nil.
(if end
(goto-char end))
(vertical-motion (- next-screen-context-lines))
(set-window-start (car windows) (point)))))))
(put 'follow-scroll-up 'scroll-command t)
1996-02-16 01:01:16 +00:00
;;;###autoload
1996-02-16 01:01:16 +00:00
(defun follow-scroll-down (&optional arg)
"Scroll text in a Follow mode window chain down.
1996-02-16 01:01:16 +00:00
If called with no ARG, the `next-screen-context-lines' top lines of
the top window in the chain will be visible in the bottom window.
If called with an argument, scroll ARG lines down.
Negative ARG means scroll upward.
Works like `scroll-down' when not in Follow mode."
1996-02-16 01:01:16 +00:00
(interactive "P")
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(cond ((not follow-mode)
(scroll-down-command arg))
(arg (follow-scroll-down-arg arg))
(t
(let* ((windows (follow-all-followers))
(win (car (reverse windows)))
(start (window-start (car windows))))
(if (eq start (point-min))
(if (or (null scroll-error-top-bottom)
(bobp))
(signal 'beginning-of-buffer nil)
(goto-char (point-min)))
(select-window win)
(goto-char start)
(vertical-motion (- (- (window-height win)
(if header-line-format 2 1)
next-screen-context-lines)))
(set-window-start win (point))
(goto-char start)
(vertical-motion (- next-screen-context-lines 1))
(setq follow-internal-force-redisplay t))))))
(put 'follow-scroll-down 'scroll-command t)
1996-02-16 01:01:16 +00:00
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(declare-function comint-adjust-point "comint" (window))
(defvar comint-scroll-show-maximum-output)
lisp/*.el: Remove lexical-binding warnings; additional small cleanups. * calculator.el (calculator): Mark unused argument. (calculator-paste, calculator-quit, calculator-integer-p): Use ignore-errors. (calculator-string-to-number, calculator-decimal, calculator-exp) (calculator-op-or-exp): Use string-match-p. * dired-aux.el (dired-compress): Use ignore-errors. (dired-do-chxxx, dired-do-chmod, dired-trample-file-versions) (dired-do-async-shell-command, dired-do-shell-command) (dired-shell-stuff-it, dired-compress-file, dired-insert-subdir) (dired-insert-subdir-validate): Use string-match-p. (dired-map-dired-file-lines, dired-subdir-hidden-p): Use looking-at-p. (dired-add-entry): Use string-match-p, looking-at-p. (dired-insert-subdir-newpos): Remove unused local variable. * dired.el (dired-buffer-more-recently-used-p): Declare. (dired-insert-set-properties, dired-insert-old-subdirs): Use ignore-errors. * filenotify.el (file-notify-callback): Remove unused local variable. * filesets.el (filesets-error): Mark unused argument. (filesets-which-command-p, filesets-filter-dir-names) (filesets-directory-files, filesets-get-external-viewer) (filesets-ingroup-get-data): Use string-match-p. * find-file.el (ff-other-file-name, ff-other-file-name) (ff-find-the-other-file, ff-cc-hh-converter): Remove unused local variables. (ff-get-file-name): Use string-match-p. (ff-all-dirs-under): Use ignore-errors. * follow.el (follow-comint-scroll-to-bottom): Mark unused argument. (follow-select-if-visible): Remove unused local variable. * forms.el (read-file-filter): Move declaration. (forms--make-format, forms--make-parser, forms-insert-record): Quote function with #'. (forms--update): Use string-match-p. Quote function with #'. * help-mode.el (help-dir-local-var-def): Mark unused argument. (help-make-xrefs): Use looking-at-p. (help-xref-on-pp): Use looking-at-p, ignore-errors. * ibuffer.el (ibuffer-ext-visible-p): Declare. (ibuffer-confirm-operation-on): Use string-match-p. * msb.el (msb-item-handler, msb-dired-item-handler): Mark unused arguments. * ses.el (ses-decode-cell-symbol) (ses-kill-override): Remove unused local variable. (ses-create-cell-variable, ses-relocate-formula): Use string-match-p. (ses-load): Use ignore-errors, looking-at-p. (ses-jump-safe): Use ignore-errors. (ses-export-tsv, ses-export-tsf, ses-unsafe): Mark unused arguments. * tabify.el (untabify, tabify): Mark unused arguments. * thingatpt.el (thing-at-point--bounds-of-well-formed-url): Mark unused argument. (bounds-of-thing-at-point, thing-at-point-bounds-of-list-at-point) (thing-at-point-newsgroup-p, form-at-point): Use ignore-errors.
2013-08-10 15:17:29 +00:00
(defun follow-comint-scroll-to-bottom (&optional _window)
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
"Scroll the bottom-most window in the current Follow chain.
This is to be called by `comint-postoutput-scroll-to-bottom'."
(let* ((buffer (current-buffer))
(selected (selected-window))
(is-selected (eq (window-buffer) buffer))
some-window)
(when (or is-selected
(setq some-window (get-buffer-window)))
(let* ((pos (progn (comint-adjust-point nil) (point)))
(win (if is-selected
selected
(car (last (follow-all-followers some-window))))))
(select-window win)
(goto-char pos)
(setq follow-windows-start-end-cache nil)
(follow-adjust-window win)
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(unless is-selected
(select-window selected)
(set-buffer buffer))))))
(defun follow-align-compilation-windows ()
"Align the windows of the current Follow mode buffer.
This is to be called from `compilation-filter-hook'."
(let ((buffer (current-buffer))
(win (get-buffer-window))
(selected (selected-window)))
(when (and follow-mode (waiting-for-user-input-p) win)
(let ((windows (follow-all-followers win)))
(unless (eq (window-buffer selected) buffer)
(setq win (car windows))
(select-window win))
(follow-redisplay windows win t)
(setq follow-windows-start-end-cache nil)
(unless (eq selected win)
(select-window selected)
(set-buffer buffer))))))
;;; Buffer
1996-02-16 01:01:16 +00:00
;;;###autoload
(defun follow-delete-other-windows-and-split (&optional arg)
"Create two side by side windows and enter Follow mode.
1996-02-16 01:01:16 +00:00
Execute this command to display as much as possible of the text
in the selected window. All other windows, in the current
1996-02-16 01:01:16 +00:00
frame, are deleted and the selected window is split in two
side-by-side windows. Follow mode is activated, hence the
1996-02-16 01:01:16 +00:00
two windows always will display two successive pages.
\(If one window is moved, the other one will follow.)
If ARG is positive, the leftmost window is selected. If negative,
1996-02-16 01:01:16 +00:00
the rightmost is selected. If ARG is nil, the leftmost window is
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
selected if the original window is the first one in the frame."
1996-02-16 01:01:16 +00:00
(interactive "P")
(let ((other (or (and (null arg)
1996-02-16 01:01:16 +00:00
(not (eq (selected-window)
(frame-first-window))))
1996-02-16 01:01:16 +00:00
(and arg
(< (prefix-numeric-value arg) 0))))
(start (window-start)))
(delete-other-windows)
(split-window-right)
(if other
1996-02-16 01:01:16 +00:00
(progn
(other-window 1)
(set-window-start (selected-window) start)
(setq follow-internal-force-redisplay t)))
(follow-mode 1)))
(defun follow-switch-to-buffer (buffer)
"Show BUFFER in all windows in the current Follow mode window chain."
1996-02-16 01:01:16 +00:00
(interactive "BSwitch to Buffer: ")
(let ((orig-window (selected-window))
(windows (follow-all-followers)))
(while windows
(select-window (car windows))
(switch-to-buffer buffer)
(setq windows (cdr windows)))
(select-window orig-window)))
(defun follow-switch-to-buffer-all (&optional buffer)
"Show BUFFER in all windows on this frame.
Defaults to current buffer."
(interactive (list (read-buffer "Switch to Buffer: "
1996-02-16 01:01:16 +00:00
(current-buffer))))
(or buffer (setq buffer (current-buffer)))
(let ((orig-window (selected-window)))
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(walk-windows (lambda (win)
(select-window win)
(switch-to-buffer buffer))
'no-minibuf)
1996-02-16 01:01:16 +00:00
(select-window orig-window)
(follow-redisplay)))
(defun follow-switch-to-current-buffer-all ()
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
"Show current buffer in all windows on this frame, and enter Follow mode."
1996-02-16 01:01:16 +00:00
(interactive)
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(unless follow-mode
(follow-mode 1))
1996-02-16 01:01:16 +00:00
(follow-switch-to-buffer-all))
;;; Movement
1996-02-16 01:01:16 +00:00
;; Note, these functions are not very useful, at least not unless you
1996-02-16 01:01:16 +00:00
;; rebind the rather cumbersome key sequence `C-c . p'.
(defun follow-next-window ()
"Select the next window showing the same buffer."
(interactive)
(let ((succ (cdr (follow-split-followers (follow-all-followers)))))
(if succ
(select-window (car succ))
(error "%s" "No more windows"))))
(defun follow-previous-window ()
"Select the previous window showing the same buffer."
(interactive)
(let ((pred (car (follow-split-followers (follow-all-followers)))))
(if pred
(select-window (car pred))
(error "%s" "No more windows"))))
(defun follow-first-window ()
"Select the first window in the frame showing the same buffer."
(interactive)
(select-window (car (follow-all-followers))))
(defun follow-last-window ()
"Select the last window in the frame showing the same buffer."
(interactive)
(select-window (car (reverse (follow-all-followers)))))
;;; Redraw
1996-02-16 01:01:16 +00:00
(defun follow-recenter (&optional arg)
"Recenter the middle window around point.
Rearrange all other windows around the middle window.
1996-02-16 01:01:16 +00:00
With a positive argument, place the current line ARG lines
from the top. With a negative argument, place it -ARG lines
from the bottom."
1996-02-16 01:01:16 +00:00
(interactive "P")
(if arg
(let ((p (point))
(arg (prefix-numeric-value arg)))
(if (>= arg 0)
;; Recenter relative to the top.
(progn
(follow-first-window)
(goto-char p)
(recenter arg))
;; Recenter relative to the bottom.
(follow-last-window)
(goto-char p)
(recenter arg)
;; Otherwise, our post-command-hook will move the window
;; right back.
(setq follow-internal-force-redisplay t)))
;; Recenter in the middle.
(let* ((dest (point))
(windows (follow-all-followers))
(win (nth (/ (- (length windows) 1) 2) windows)))
(select-window win)
(let ((win-s (window-start)))
(goto-char dest)
(recenter)
(when (< dest win-s)
(setq follow-internal-force-redisplay t))))))
1996-02-16 01:01:16 +00:00
(defun follow-redraw ()
"Arrange windows displaying the same buffer in successor order.
This function can be called even if the buffer is not in Follow mode.
Hopefully, there should be no reason to call this function when in
Follow mode since the windows should always be aligned."
(interactive)
(sit-for 0)
(follow-redisplay))
;;; End of buffer
1996-02-16 01:01:16 +00:00
(defun follow-end-of-buffer (&optional arg)
"Move point to the end of the buffer, Follow mode style.
1996-02-16 01:01:16 +00:00
If the end is not visible, it will be displayed in the last possible
window in the Follow mode window chain.
1996-02-16 01:01:16 +00:00
The mark is left at the previous position. With arg N, put point N/10
1996-02-16 01:01:16 +00:00
of the way from the true end."
(interactive "P")
(let ((followers (follow-all-followers))
(pos (point)))
(cond (arg
(select-window (car (reverse followers))))
((follow-select-if-end-visible
1996-02-16 01:01:16 +00:00
(follow-windows-start-end followers)))
(t
(select-window (car (reverse followers)))))
(goto-char pos)
(with-no-warnings
(end-of-buffer arg))))
1996-02-16 01:01:16 +00:00
;;; Display
1996-02-16 01:01:16 +00:00
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(defun follow--window-sorter (w1 w2)
"Sorting function for W1 and W2 based on their positions.
Return non-nil if W1 is above W2; if their top-lines
are at the same position, return non-nil if W1 is to the
left of W2."
(let* ((edge-1 (window-pixel-edges w1))
(edge-2 (window-pixel-edges w2))
(y1 (nth 1 edge-1))
(y2 (nth 1 edge-2)))
(if (= y1 y2)
(< (car edge-1) (car edge-2))
(< y1 y2))))
(defun follow-all-followers (&optional win)
"Return all windows displaying the same buffer as the WIN.
The list is sorted with topmost and leftmost windows first, and
contains only windows in the same frame as WIN. If WIN is nil,
it defaults to the selected window."
(unless (window-live-p win)
(setq win (selected-window)))
(let ((windows (get-buffer-window-list
(window-buffer win) 'no-minibuf (window-frame win))))
(sort windows #'follow--window-sorter)))
1996-02-16 01:01:16 +00:00
(defun follow-split-followers (windows &optional win)
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
"Split WINDOWS into two sets: predecessors and successors.
Return `(PRED . SUCC)' where `PRED' and `SUCC' are ordered starting
1996-02-16 01:01:16 +00:00
from the selected window."
(or win
1996-02-16 01:01:16 +00:00
(setq win (selected-window)))
(let ((pred '()))
(while (not (eq (car windows) win))
(setq pred (cons (car windows) pred))
(setq windows (cdr windows)))
(cons pred (cdr windows))))
(defun follow-calc-win-end (&optional win)
"Calculate the end position for window WIN.
Return (END-POS END-OF-BUFFER).
Actually, the position returned is the start of the line after
the last fully-visible line in WIN. END-OF-BUFFER is t when EOB
is fully-visible in WIN. If WIN is nil, the selected window is
used."
(let* ((win (or win (selected-window)))
(edges (window-inside-pixel-edges win))
(ht (- (nth 3 edges) (nth 1 edges)))
(last-line-pos (posn-point (posn-at-x-y 0 (1- ht) win))))
(if (pos-visible-in-window-p last-line-pos win)
(let ((end (window-end win t)))
(list end (pos-visible-in-window-p (point-max) win)))
(list last-line-pos nil))))
1996-02-16 01:01:16 +00:00
(defun follow-calc-win-start (windows pos win)
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
"Determine the start of window WIN in a Follow mode window chain.
WINDOWS is a list of chained windows, and POS is the starting
position for the first window in the list. If WIN is nil, return
the point below all windows."
(while (and windows (not (eq (car windows) win)))
(let ((old-start (window-start (car windows))))
;; Can't use `save-window-excursion' since it triggers a redraw.
1996-02-16 01:01:16 +00:00
(set-window-start (car windows) pos 'noforce)
(setq pos (car (follow-calc-win-end (car windows))))
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(set-window-start (car windows) old-start 'noforce)
(setq windows (cdr windows))))
pos)
1996-02-16 01:01:16 +00:00
;; The result from `follow-windows-start-end' is cached when using
;; a handful simple commands, like cursor movement commands.
(defsubst follow-cache-valid-p (windows)
"Test if the cached value of `follow-windows-start-end' can be used.
Note that this handles the case when the cache has been set to nil."
(let ((res t)
(cache follow-windows-start-end-cache))
(while (and res windows cache)
(setq res (and (eq (car windows)
(car (car cache)))
(eq (window-start (car windows))
(car (cdr (car cache))))))
(setq windows (cdr windows))
(setq cache (cdr cache)))
(and res (null windows) (null cache))))
1996-02-16 01:01:16 +00:00
(defun follow-windows-start-end (windows)
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
"Return a list of (WIN START END BUFFER-END-P) for window list WINDOWS."
(if (follow-cache-valid-p windows)
follow-windows-start-end-cache
(let ((orig-win (selected-window))
win-start-end)
(dolist (w windows)
(select-window w 'norecord)
(push (cons w (cons (window-start) (follow-calc-win-end)))
win-start-end))
(select-window orig-win 'norecord)
(setq follow-windows-start-end-cache (nreverse win-start-end)))))
(defsubst follow-pos-visible (pos win win-start-end)
1996-02-16 01:01:16 +00:00
"Non-nil when POS is visible in WIN."
(let ((wstart-wend-bend (cdr (assq win win-start-end))))
(and (>= pos (car wstart-wend-bend))
(or (< pos (cadr wstart-wend-bend))
1996-02-16 01:01:16 +00:00
(nth 2 wstart-wend-bend)))))
;; By `aligned' we mean that for all adjacent windows, the end of the
1996-02-16 01:01:16 +00:00
;; first is equal with the start of the successor. The first window
;; should start at a full screen line.
(defsubst follow-windows-aligned-p (win-start-end)
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
"Non-nil if the follower windows are aligned.
The argument, WIN-START-END, should be a list of the form
returned by `follow-windows-start-end'."
(let ((result t))
(while (and win-start-end result)
(if (cdr win-start-end)
(setq result (eq (nth 2 (car win-start-end))
(nth 1 (cadr win-start-end)))))
1996-02-16 01:01:16 +00:00
(setq win-start-end (cdr win-start-end)))
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
result))
1996-02-16 01:01:16 +00:00
;; Check if point is visible in all windows.
;; (So that no one will be recentered.)
1996-02-16 01:01:16 +00:00
(defun follow-point-visible-all-windows-p (win-start-end)
"Non-nil when the `window-point' is visible in all windows."
1996-02-16 01:01:16 +00:00
(let ((res t))
(while (and res win-start-end)
(setq res (follow-pos-visible (window-point (car (car win-start-end)))
(car (car win-start-end))
win-start-end))
1996-02-16 01:01:16 +00:00
(setq win-start-end (cdr win-start-end)))
res))
2011-07-14 01:09:00 +00:00
;; Make sure WIN always starts at the beginning of a whole screen
1996-02-16 01:01:16 +00:00
;; line. If WIN is not aligned the start is updated which probably
;; will lead to a redisplay of the screen later on.
;;
;; This is used with the first window in a follow chain. The reason
;; is that we want to detect that point is outside the window.
1996-02-16 01:01:16 +00:00
;; (Without the update, the start of the window will move as the
;; user presses BackSpace, and the other window redisplay routines
;; will move the start of the window in the wrong direction.)
(defun follow-update-window-start (win)
"Make sure that the start of WIN starts at a full screen line."
(save-excursion
(goto-char (window-start win))
(unless (bolp)
1996-02-16 01:01:16 +00:00
(vertical-motion 0 win)
(unless (eq (point) (window-start win))
1996-02-16 01:01:16 +00:00
(vertical-motion 1 win)
(set-window-start win (point) 'noforce)))))
(defun follow-select-if-visible (dest win-start-end)
"Select and return a window, if DEST is visible in it.
Return the selected window."
(let (win wse)
1996-02-16 01:01:16 +00:00
(while (and (not win) win-start-end)
;; Don't select a window that was just moved. This makes it
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; possible to later select the last window after a
;; `end-of-buffer' command.
(setq wse (car win-start-end))
(when (follow-pos-visible dest (car wse) win-start-end)
(setq win (car wse))
(select-window win))
(setq win-start-end (cdr win-start-end)))
1996-02-16 01:01:16 +00:00
win))
2011-07-14 01:09:00 +00:00
;; Lets select a window showing the end. Make sure we only select it if
;; it wasn't just moved here. (I.e. M-> shall not unconditionally place
;; point in the selected window.)
1996-02-16 01:01:16 +00:00
;;
2011-11-15 07:55:13 +00:00
;; (Compatibility kludge: in Emacs `window-end' is equal to `point-max';
;; in XEmacs, it is equal to `point-max + 1'. Should I really bother
;; checking `window-end' now when I check `end-of-buffer' explicitly?)
1996-02-16 01:01:16 +00:00
(defun follow-select-if-end-visible (win-start-end)
"Select and return a window, if end is visible in it."
(let ((win nil))
(while (and (not win) win-start-end)
;; Don't select a window that was just moved. This makes it
1996-02-16 01:01:16 +00:00
;; possible to later select the last window after a `end-of-buffer'
;; command.
(if (and (eq (point-max) (nth 2 (car win-start-end)))
(nth 3 (car win-start-end))
;; `window-end' might return nil.
(let ((end (window-end (car (car win-start-end)))))
(and end
(eq (point-max) (min (point-max) end)))))
1996-02-16 01:01:16 +00:00
(progn
(setq win (car (car win-start-end)))
(select-window win)))
(setq win-start-end (cdr win-start-end)))
win))
;; Select a window that will display point if the windows would
;; be redisplayed with the first window fixed. This is useful for
1996-02-16 01:01:16 +00:00
;; example when the user has pressed return at the bottom of a window
;; as point is not visible in any window.
1996-02-16 01:01:16 +00:00
(defun follow-select-if-visible-from-first (dest windows)
"Try to select one of WINDOWS without repositioning the topmost window.
If one of the windows in WINDOWS contains DEST, select it, call
`follow-redisplay', move point to DEST, and return that window.
Otherwise, return nil."
(let (win end-pos-end-p)
1996-02-16 01:01:16 +00:00
(save-excursion
(goto-char (window-start (car windows)))
;; Make sure the line start in the beginning of a real screen
;; line.
(vertical-motion 0 (car windows))
(when (>= dest (point))
1996-02-16 01:01:16 +00:00
;; At or below the start. Check the windows.
(save-window-excursion
(let ((windows windows))
(while (and (not win) windows)
(set-window-start (car windows) (point) 'noforce)
(setq end-pos-end-p (follow-calc-win-end (car windows)))
(goto-char (car end-pos-end-p))
;; Visible, if dest above end, or if eob is visible
;; inside the window.
(if (or (car (cdr end-pos-end-p))
(< dest (point)))
1996-02-16 01:01:16 +00:00
(setq win (car windows))
(setq windows (cdr windows))))))))
(when win
(select-window win)
(follow-redisplay windows (car windows))
(goto-char dest))
1996-02-16 01:01:16 +00:00
win))
;;; Redisplay
1996-02-16 01:01:16 +00:00
;; Redraw all the windows on the screen, starting with the top window.
;; The window used as marker is WIN, or the selected window if WIN
;; is nil. Start every window directly after the end of the previous
;; window, to make sure long lines are displayed correctly.
1996-02-16 01:01:16 +00:00
Prefer defvar-local in remaining libraries * lisp/align.el (align-mode-rules-list) (align-mode-exclude-rules-list): * lisp/bookmark.el (bookmark-current-bookmark) (bookmark-annotation-name) (bookmark--annotation-from-bookmark-list): * lisp/calc/calc-embed.el (calc-embedded-all-active) (calc-embedded-some-active): * lisp/comint.el (comint-password-function): * lisp/completion.el (completion-syntax-table): * lisp/dframe.el (dframe-track-mouse-function) (dframe-help-echo-function, dframe-mouse-click-function) (dframe-mouse-position-function, dframe-timer) (dframe-attached-frame, dframe-controlled): * lisp/ehelp.el (electric-help-orig-major-mode): * lisp/eshell/esh-util.el (eshell-path-env): * lisp/expand.el (expand-pos, expand-index, expand-point): * lisp/face-remap.el (text-scale-mode-remapping) (text-scale-mode-lighter, text-scale-mode-amount) (text-scale-remap-header-line, buffer-face-mode-remapping): * lisp/ffap.el (ffap-menu-alist): * lisp/files-x.el (connection-local-variables-alist): * lisp/foldout.el (foldout-fold-list, foldout-mode-line-string): * lisp/follow.el (follow-start-end-invalid): * lisp/forms.el (forms--mode-setup): * lisp/gnus/message.el (message-cross-post-old-target) (message-options): * lisp/help-mode.el (help-xref-stack, help-xref-forward-stack) (help-xref-stack-item, help-xref-stack-forward-item): * lisp/hexl.el (hexl-mode--old-var-vals, hexl-ascii-overlay): * lisp/hilit-chg.el (hilit-chg-string): * lisp/ido.el (ido-eoinput): * lisp/imenu.el (imenu-generic-expression) (imenu-create-index-function, imenu-default-goto-function) (imenu-prev-index-position-function) (imenu-extract-index-name-function, imenu-name-lookup-function) (imenu-syntax-alist, imenu-case-fold-search): * lisp/jka-compr.el (jka-compr-really-do-compress): * lisp/language/ethio-util.el (ethio-prefer-ascii-space): * lisp/leim/quail/hangul.el (hangul-input-method-help-text): * lisp/leim/quail/japanese.el (quail-japanese-package-saved): * lisp/linum.el (linum-overlays, linum-available): * lisp/man.el (Man-original-frame, Man-arguments, Man--sections) (Man--refpages, Man-page-list, Man-current-page) (Man-page-mode-string): * lisp/pcomplete.el (pcomplete-current-completions) (pcomplete-last-completion-length) (pcomplete-last-completion-stub, pcomplete-last-completion-raw) (pcomplete-last-window-config, pcomplete-window-restore-timer): * lisp/reveal.el (reveal-open-spots, reveal-last-tick): * lisp/ruler-mode.el (ruler-mode): * lisp/scroll-lock.el (scroll-lock-preserve-screen-pos-save): * lisp/server.el (server-buffer-clients, server-existing-buffer): * lisp/tab-line.el (tab-line-exclude): * lisp/tar-mode.el (tar-data-buffer, tar-data-swapped): * lisp/thumbs.el (thumbs-current-tmp-filename) (thumbs-current-image-filename, thumbs-extra-images) (thumbs-image-num, thumbs-buffer, thumbs-marked-list): * lisp/tutorial.el (tutorial--point-before-chkeys) (tutorial--point-after-chkeys, tutorial--lang): * lisp/url/url-vars.el (url-current-object) (url-current-mime-headers, url-current-lastloc): * lisp/view.el (view-mode, view-old-buffer-read-only) (view-old-Helper-return-blurb, view-page-size) (view-half-page-size, view-last-regexp, view-return-to-alist) (view-exit-action, view-overlay): * lisp/wid-edit.el (widget-global-map, widget-field-new) (widget-field-list, widget-field-last, widget-field-was): * lisp/woman.el (woman-imenu-done): Prefer defvar-local.
2021-02-02 08:55:40 +00:00
(defvar-local follow-start-end-invalid t
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
"When non-nil, indicates `follow-windows-start-end-cache' is invalid.")
(defun follow-redisplay (&optional windows win preserve-win)
1996-02-16 01:01:16 +00:00
"Reposition the WINDOWS around WIN.
Should point be too close to the roof we redisplay everything
from the top. WINDOWS should contain a list of windows to
2011-07-14 01:09:00 +00:00
redisplay; it is assumed that WIN is a member of the list.
1996-02-16 01:01:16 +00:00
Should WINDOWS be nil, the windows displaying the
same buffer as WIN, in the current frame, are used.
Should WIN be nil, the selected window is used.
If PRESERVE-WIN is non-nil, keep WIN itself unchanged while
repositioning the other windows."
(or win (setq win (selected-window)))
(or windows (setq windows (follow-all-followers win)))
;; Calculate the start of the first window.
(let* ((old-win-start (window-start win))
(try-first-start (follow-estimate-first-window-start
windows win old-win-start))
(try-win-start (follow-calc-win-start
windows try-first-start win))
(start (cond ((= try-win-start old-win-start)
(follow-debug-message "exact")
try-first-start)
((< try-win-start old-win-start)
(follow-debug-message "above")
(follow-calculate-first-window-start-from-above
windows try-first-start win old-win-start))
(t
(follow-debug-message "below")
(follow-calculate-first-window-start-from-below
windows try-first-start win old-win-start)))))
(dolist (w windows)
(unless (and preserve-win (eq w win))
(set-window-start w start))
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
(setq start (car (follow-calc-win-end w))))
(setq follow-start-end-invalid nil)))
1996-02-16 01:01:16 +00:00
(defun follow-estimate-first-window-start (windows win start)
"Estimate the position of the first window.
The estimate is computed by assuming that the window WIN, which
should be a member of WINDOWS, starts at position START."
(let ((windows-before (car (follow-split-followers windows win))))
1996-02-16 01:01:16 +00:00
(save-excursion
(goto-char start)
(vertical-motion 0 win)
(dolist (w windows-before)
(vertical-motion (- (window-text-height w)) w))
(point))))
1996-02-16 01:01:16 +00:00
;; Find the starting point, start at GUESS and search downward.
;; The returned point is always a point below GUESS.
(defun follow-calculate-first-window-start-from-above
1996-02-16 01:01:16 +00:00
(windows guess win start)
(save-excursion
(let ((done nil)
win-start
res)
(goto-char guess)
(while (not done)
(if (not (= (vertical-motion 1 (car windows)) 1))
;; Hit bottom! (Can we really do this?)
1996-02-16 01:01:16 +00:00
;; We'll keep it, since it ensures termination.
(progn
(setq done t)
(setq res (point-max)))
(setq win-start (follow-calc-win-start windows (point) win))
(if (>= win-start start)
(setq done t res (point)))))
1996-02-16 01:01:16 +00:00
res)))
;; Find the starting point, start at GUESS and search upward. Return
;; a point on the same line as GUESS, or above.
(defun follow-calculate-first-window-start-from-below
(windows guess &optional win start)
(setq win (or win (selected-window)))
(setq start (or start (window-start win)))
(save-excursion
(let (done win-start res opoint)
;; Always calculate what happens when no line is displayed in the first
;; window. (The `previous' res is needed below!)
(goto-char guess)
(vertical-motion 0 (car windows))
(setq res (point))
1996-02-16 01:01:16 +00:00
(while (not done)
(setq opoint (point))
(if (not (= (vertical-motion -1 (car windows)) -1))
;; Hit roof!
(setq done t res (point-min))
(setq win-start (follow-calc-win-start windows (point) win))
(cond ((>= (point) opoint)
;; In some pathological cases, vertical-motion may
;; return -1 even though point has not decreased. In
;; that case, avoid looping forever.
(setq done t res (point)))
((= win-start start) ; Perfect match, use this value
(setq done t res (point)))
((< win-start start) ; Walked to far, use previous result
(setq done t))
(t ; Store result for next iteration
(setq res (point))))))
1996-02-16 01:01:16 +00:00
res)))
;;; Avoid tail recenter
1996-02-16 01:01:16 +00:00
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; This sets the window internal flag `force_start'. The effect is
;; that windows only displaying the tail aren't recentered.
1996-02-16 01:01:16 +00:00
;;
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; A window displaying only the tail, is a window whose window-start
;; position is equal to (point-max) of the buffer it displays.
1996-02-16 01:01:16 +00:00
2011-04-19 13:44:55 +00:00
(defun follow-avoid-tail-recenter (&rest _rest)
1996-02-16 01:01:16 +00:00
"Make sure windows displaying the end of a buffer aren't recentered.
2001-03-20 19:52:32 +00:00
This is done by reading and rewriting the start position of
non-first windows in Follow mode."
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(let* ((orig-buffer (current-buffer))
(top (frame-first-window))
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(win top)
who) ; list of (buffer . frame)
;; If the only window in the frame is a minibuffer
;; window, `next-window' will never find it again...
(unless (window-minibuffer-p top)
(while ;; look, no body!
(let ((start (window-start win))
(pair (cons (window-buffer win) (window-frame win))))
(set-buffer (window-buffer win))
(cond ((null (member pair who))
(setq who (cons pair who)))
((and follow-mode (eq (point-max) start))
;; Write the same window start back, but don't
;; set the NOFORCE flag.
(set-window-start win start)))
(setq win (next-window win 'not t))
(not (eq win top)))) ;; Loop while this is true.
(set-buffer orig-buffer))))
1996-02-16 01:01:16 +00:00
;;; Pre Display Function
(defvar follow-prev-buffer nil
"The buffer current at the last call to `follow-adjust-window' or nil.
`follow-mode' is not necessarily enabled in this buffer.")
;; This function is added to `pre-display-function' and is thus called
;; before each redisplay operation. It supersedes (2018-09) the
;; former use of the post command hook, and now does the right thing
;; when a program calls `redisplay' or `sit-for'.
(defun follow-pre-redisplay-function (wins)
(if (or (eq wins t)
(null wins)
(and (listp wins)
(memq (selected-window) wins)))
(follow-post-command-hook)))
1996-02-16 01:01:16 +00:00
;;; Post Command Hook
1996-02-16 01:01:16 +00:00
;; The magic little box. This function was formerly called after every
;; command. It is now called before each redisplay operation (see
;; `follow-pre-redisplay-function' above), and at the end of several
;; search/replace commands. It retains its historical name.
;;
1996-02-16 01:01:16 +00:00
;; This is not as complicated as it seems. It is simply a list of common
;; display situations and the actions to take, plus commands for redrawing
;; the screen if it should be unaligned.
;;
;; We divide the check into two parts; whether we are at the end or not.
;; This is due to the fact that the end can actually be visible
1996-02-16 01:01:16 +00:00
;; in several window even though they are aligned.
(defun follow-post-command-hook ()
"Ensure that the windows in Follow mode are adjacent after each command."
(unless (input-pending-p)
(let ((follow-inside-post-command-hook-call t)
(win (selected-window)))
1996-02-16 01:01:16 +00:00
;; Work in the selected window, not in the current buffer.
(with-current-buffer (window-buffer win)
(unless (and (symbolp this-command)
(get this-command 'follow-mode-use-cache))
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(setq follow-windows-start-end-cache nil))
(follow-adjust-window win)))))
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; NOTE: to debug follow-mode with edebug, it is helpful to add
;; `follow-post-command-hook' to `post-command-hook' temporarily. Do
;; this locally to the target buffer with, say,:
;; M-: (add-hook 'post-command-hook 'follow-post-command-hook t t)
;; .
(defun follow-adjust-window (win)
"Adjust the window WIN and its followers."
(cl-assert (eq (window-buffer win) (current-buffer)))
;; Have we moved out of or into a follow-mode window group?
;; If so, attend to the visibility of the cursors.
(when (not (eq (current-buffer) follow-prev-buffer))
;; Do we need to switch off cursor handling in the previous buffer?
(when (buffer-live-p follow-prev-buffer)
(with-current-buffer follow-prev-buffer
(when (and follow-mode
(local-variable-p 'cursor-in-non-selected-windows))
(setq cursor-in-non-selected-windows
(default-value 'cursor-in-non-selected-windows)))))
;; Do we need to switch on cursor handling in the current buffer?
(when (and follow-mode
(local-variable-p 'cursor-in-non-selected-windows))
(setq cursor-in-non-selected-windows nil))
(when (buffer-live-p (current-buffer))
(setq follow-prev-buffer (current-buffer))))
(when (and follow-mode
(not (window-minibuffer-p win)))
(let ((windows (follow-all-followers win)))
;; If we've explicitly scrolled, align the windows first.
(when follow-fixed-window
(follow-debug-message "fixed")
(follow-redisplay windows win)
(goto-char (follow-get-scrolled-point (point) windows))
(setq follow-fixed-window nil))
(let* ((dest (point))
(win-start-end (progn
(follow-update-window-start (car windows))
(follow-windows-start-end windows)))
(aligned (follow-windows-aligned-p win-start-end))
(visible (follow-pos-visible dest win win-start-end))
selected-window-up-to-date)
(unless (and aligned visible)
(setq follow-windows-start-end-cache nil))
;; Select a window to display point.
(unless follow-internal-force-redisplay
(if (eq dest (point-max))
;; Be careful at point-max: the display can be aligned
;; while DEST can be visible in several windows.
(cond
;; Select the current window, but only when the display
;; is correct. (When inserting characters in a tail
;; window, the display is not correct, as they are
;; shown twice.)
;;
;; Never stick to the current window after a deletion.
;; Otherwise, when typing `DEL' in a window showing
;; only the end of the file, a character would be
;; removed from the window above, which is very
;; unintuitive.
((and visible
aligned
(not (memq this-command
'(backward-delete-char
delete-backward-char
backward-delete-char-untabify
kill-region))))
(follow-debug-message "Max: same"))
;; If the end is visible, and the window doesn't
;; seems like it just has been moved, select it.
((follow-select-if-end-visible win-start-end)
(follow-debug-message "Max: end visible")
(setq visible t aligned nil)
(goto-char dest))
;; Just show the end...
(t
(follow-debug-message "Max: default")
(select-window (car (last windows)))
(goto-char dest)
(setq visible nil aligned nil)))
;; We're not at the end, here life is much simpler.
(cond
;; This is the normal case!
;; It should be optimized for speed.
((and visible aligned)
(follow-debug-message "same"))
;; Pick a position in any window. If the display is ok,
;; this picks the `correct' window.
((follow-select-if-visible dest win-start-end)
(follow-debug-message "visible")
(goto-char dest)
;; Perform redisplay, in case line is partially visible.
(setq visible nil))
;; Not visible anywhere else, lets pick this one.
(visible
(follow-debug-message "visible in selected."))
;; If DEST is before the first window start, select the
;; first window.
((< dest (nth 1 (car win-start-end)))
(follow-debug-message "before first")
(select-window (car windows))
(goto-char dest)
(setq visible nil aligned nil))
;; If we can position the cursor without moving the first
;; window, do it. This is the case that catches `RET' at
;; the bottom of a window.
((follow-select-if-visible-from-first dest windows)
(follow-debug-message "Below first")
(setq visible t aligned t))
;; None of the above. Stick to the selected window.
(t
(follow-debug-message "None")
(setq visible nil aligned nil))))
;; If a new window was selected, make sure that the old is
;; not scrolled when point is outside the window.
(unless (eq win (selected-window))
(let ((p (window-point win)))
(set-window-start win (window-start win) nil)
(if (nth 2 (pos-visible-in-window-p p win t))
;; p is in a partially visible line. We can't leave
;; window-point there, because C-x o back into WIN
;; would then fail.
(with-selected-window win
(forward-line)) ; redisplay will recenter it in WIN.
(set-window-point win p)))))
(unless visible
;; If point may not be visible in the selected window,
;; perform a redisplay; this ensures scrolling.
(let ((opoint (point)))
(redisplay)
;; If this `redisplay' moved point, we got clobbered by a
;; previous call to `set-window-start'. Try again.
(when (/= (point) opoint)
(goto-char opoint)
(redisplay)))
(setq selected-window-up-to-date t)
(follow-avoid-tail-recenter)
(setq win-start-end (follow-windows-start-end windows)
follow-windows-start-end-cache nil
aligned nil))
;; Now redraw the windows around the selected window.
(unless (and (not follow-internal-force-redisplay)
(or aligned
(follow-windows-aligned-p win-start-end))
(follow-point-visible-all-windows-p win-start-end))
(setq follow-internal-force-redisplay nil)
(follow-redisplay windows (selected-window)
selected-window-up-to-date)
(setq win-start-end (follow-windows-start-end windows)
follow-windows-start-end-cache nil)
;; Point can end up in another window when DEST is at
;; the beginning of the buffer and the selected window is
;; not the first. It can also happen when long lines are
;; used and there is a big difference between the width of
;; the windows. (When scrolling one line in a wide window
;; which will cause a move larger that an entire small
;; window.)
(unless (follow-pos-visible dest win win-start-end)
(follow-select-if-visible dest win-start-end)
(goto-char dest)))
;; If the region is visible, make it look good when spanning
;; multiple windows.
(when (region-active-p)
(follow-maximize-region
(selected-window) windows win-start-end))))
;; Whether or not the buffer was in follow mode, update windows
;; displaying the tail so that Emacs won't recenter them.
(follow-avoid-tail-recenter)))
1996-02-16 01:01:16 +00:00
;;; The region
1996-02-16 01:01:16 +00:00
;; Tries to make the highlighted area representing the region look
;; good when spanning several windows.
1996-02-16 01:01:16 +00:00
;;
;; Not perfect, as point can't be placed at window end, only at
;; end-1. This will highlight a little bit in windows above
1996-02-16 01:01:16 +00:00
;; the current.
(defun follow-maximize-region (win windows win-start-end)
"Make a highlighted region stretching multiple windows look good."
1996-02-16 01:01:16 +00:00
(let* ((all (follow-split-followers windows win))
(pred (car all))
(succ (cdr all))
data)
(while pred
(setq data (assq (car pred) win-start-end))
(set-window-point (car pred) (max (nth 1 data) (- (nth 2 data) 1)))
(setq pred (cdr pred)))
(while succ
(set-window-point (car succ) (nth 1 (assq (car succ) win-start-end)))
(setq succ (cdr succ)))))
1996-02-16 01:01:16 +00:00
;;; Scroll bar
1996-02-16 01:01:16 +00:00
;;;; Scroll-bar support code.
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; This handles the case where the user drags the scroll bar of a
;; non-selected window whose buffer is in Follow mode.
(declare-function scroll-bar-toolkit-scroll "scroll-bar" (event))
(declare-function scroll-bar-drag "scroll-bar" (event))
(declare-function scroll-bar-scroll-up "scroll-bar" (event))
(declare-function scroll-bar-scroll-down "scroll-bar" (event))
(declare-function mwheel-scroll "mwheel" (event))
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(defun follow-scroll-bar-toolkit-scroll (event)
(interactive "e")
(scroll-bar-toolkit-scroll event)
(follow-redraw-after-event event))
(defun follow-scroll-bar-drag (event)
(interactive "e")
(scroll-bar-drag event)
(follow-redraw-after-event event))
(defun follow-scroll-bar-scroll-up (event)
(interactive "e")
(scroll-bar-scroll-up event)
(follow-redraw-after-event event))
(defun follow-scroll-bar-scroll-down (event)
(interactive "e")
(scroll-bar-scroll-down event)
(follow-redraw-after-event event))
(defun follow-mwheel-scroll (event)
(interactive "e")
(mwheel-scroll event)
(follow-redraw-after-event event))
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
(defun follow-redraw-after-event (event)
"Re-align the Follow mode windows affected by EVENT."
(let* ((window (nth 0 (event-end event)))
(buffer (window-buffer window))
(orig-win (selected-window)))
(when (and (buffer-local-value 'follow-mode buffer)
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; Ignore the case where we scroll the selected window;
;; that is handled by the post-command hook function.
(not (eq window (selected-window))))
(select-window window)
(follow-redisplay)
(unless (eq (window-buffer orig-win) buffer)
(select-window orig-win)))))
1996-02-16 01:01:16 +00:00
;;; Window size change
1996-02-16 01:01:16 +00:00
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; The functions in `window-size-change-functions' are called every
;; time a window in a frame changes size, most notably after the frame
;; has been resized. We call `follow-post-command-hook' for every
;; Follow mode buffer visible in any window in the resized frame.
1996-02-16 01:01:16 +00:00
;;
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; Since `follow-window-size-change' can be called indirectly from
;; `follow-post-command-hook' we have a potential infinite loop. To
;; avoid this, we simply do not do anything in this situation. The
;; variable `follow-inside-post-command-hook-call' contains
;; information about whether the execution actually is inside the
1996-02-16 01:01:16 +00:00
;; post-command-hook or not.
(defun follow-window-size-change (frame)
"Redraw all windows in FRAME, when in Follow mode."
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; Below, we call `post-command-hook'. Avoid an infloop.
(unless follow-inside-post-command-hook-call
(save-current-buffer
(let ((orig-frame (selected-frame)))
(select-frame frame)
(let ((picked-window (selected-window)) ; Note: May change below.
(seen-buffers '()))
(unwind-protect
(walk-windows
(lambda (win)
(let ((buf (window-buffer win)))
(unless (memq buf seen-buffers)
(set-buffer buf)
(when follow-mode
(let ((windows (follow-all-followers win)))
(if (not (memq picked-window windows))
(follow-redisplay windows win)
;; Make sure we're redrawing around the selected
;; window.
(select-window picked-window 'norecord)
(follow-post-command-hook)
(setq picked-window (selected-window))))
(push buf seen-buffers)))))
'no-minibuf)
(select-window picked-window 'norecord)))
(select-frame orig-frame)))))
1996-02-16 01:01:16 +00:00
(add-hook 'window-scroll-functions 'follow-avoid-tail-recenter t)
1996-02-16 01:01:16 +00:00
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
;;; Low level window start and end.
;; These routines are the Follow Mode versions of the low level
;; functions described on page "Window Start and End" of the elisp
;; manual, e.g. `window-group-start'. The aim is to be able to handle
;; Follow Mode windows by replacing `window-start' by
;; `window-group-start', etc.
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
(defun follow-after-change (_beg _end _old-len)
"After change function: set `follow-start-end-invalid'."
(setq follow-start-end-invalid t))
(defun follow-window-start (&optional window)
"Return position at which display currently starts in the
Follow Mode group of windows which includes WINDOW.
WINDOW must be a live window and defaults to the selected one.
This is updated by redisplay or by calling
`follow-set-window-start'."
(let ((windows (follow-all-followers window)))
(window-start (car windows))))
(defun follow-window-end (&optional window update)
"Return position at which display currently ends in the Follow
Mode group of windows which includes WINDOW.
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
WINDOW must be a live window and defaults to the selected one.
This is updated by redisplay, when it runs to completion.
Simply changing the buffer text or setting `window-start' does
not update this value.
Return nil if there is no recorded value. (This can happen if
the last redisplay of WINDOW was preempted, and did not
finish.) If UPDATE is non-nil, compute the up-to-date position
if it isn't already recorded."
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
(let* ((windows (follow-all-followers window))
(last (car (last windows))))
(when (and update follow-start-end-invalid)
(follow-redisplay windows (car windows)))
(window-end last update)))
(defun follow-set-window-start (window pos &optional noforce)
"Make display in the Follow Mode group of windows which includes
WINDOW start at position POS in WINDOW's buffer.
WINDOW must be a live window and defaults to the selected one. Return
POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
overriding motion of point in order to display at this exact start."
(let ((windows (follow-all-followers window)))
(setq follow-start-end-invalid t)
(set-window-start (car windows) pos noforce)))
(defun follow-pos-visible-in-window-p (&optional pos window partially)
"Return non-nil if position POS is currently on the frame in one of
the windows in the Follow Mode group which includes WINDOW.
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
WINDOW must be a live window and defaults to the selected one.
Return nil if that position is scrolled vertically out of view. If a
character is only partially visible, nil is returned, unless the
optional argument PARTIALLY is non-nil. If POS is only out of view
because of horizontal scrolling, return non-nil. If POS is t, it
specifies the position of the last visible glyph in WINDOW. POS
defaults to point in WINDOW; WINDOW defaults to the selected window.
If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
where X and Y are the pixel coordinates relative to the top left corner
of the actual window containing it. The remaining elements are
omitted if the character after POS is fully visible; otherwise, RTOP
and RBOT are the number of pixels off-window at the top and bottom of
the screen line (\"row\") containing POS, ROWH is the visible height
of that row, and VPOS is the row number \(zero-based)."
(let* ((windows (follow-all-followers window)))
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
(when follow-start-end-invalid
(follow-redisplay windows (car windows)))
(let* ((cache (follow-windows-start-end windows))
(last-elt (car (last cache)))
our-pos pertinent-elt)
(setq pertinent-elt
(if (eq pos t)
last-elt
(setq our-pos (or pos (point)))
(catch 'element
(while cache
(when (< our-pos (nth 2 (car cache)))
(throw 'element (car cache)))
(setq cache (cdr cache)))
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
last-elt)))
(pos-visible-in-window-p our-pos (car pertinent-elt) partially))))
(defun follow-move-to-window-line (arg)
"Position point relative to the Follow mode group containing the selected window.
ARG nil means position point at center of the window group.
Else, ARG specifies vertical position within the window group;
zero means top of the first window in the group, negative means
relative to bottom of the last window in the group."
(let* ((windows (follow-all-followers))
(start-end (follow-windows-start-end windows))
(rev-start-end (reverse start-end))
(lines 0)
elt count)
First commit to scratch/follow. Make Isearch work with Follow Mode, etc. doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
2015-11-11 12:02:48 +00:00
(select-window
(cond
((null arg)
(setq rev-start-end (nthcdr (/ (length windows) 2) rev-start-end))
(prog1 (car (car rev-start-end))
(while (setq rev-start-end (cdr rev-start-end))
(setq elt (car rev-start-end)
count (count-screen-lines (cadr elt) (nth 2 elt)
nil (car elt))
lines (+ lines count)))))
((>= arg 0)
(while (and (cdr start-end)
(progn
(setq elt (car start-end)
count (count-screen-lines (cadr elt) (nth 2 elt)
nil (car elt)))
(>= arg count)))
(setq arg (- arg count)
lines (+ lines count)
start-end (cdr start-end)))
(car (car start-end)))
(t ; (< arg 0)
(while (and (cadr rev-start-end)
(progn
(setq elt (car rev-start-end)
count (count-lines (cadr elt) (nth 2 elt)))
(<= arg (- count))))
(setq arg (+ arg count)
rev-start-end (cdr rev-start-end)))
(prog1 (car (car rev-start-end))
(while (setq rev-start-end (cdr rev-start-end))
(setq elt (car rev-start-end)
count (count-screen-lines (cadr elt) (nth 2 elt)
nil (car elt))
lines (+ lines count)))))))
(+ lines (move-to-window-line arg))))
;;; Profile support
1996-02-16 01:01:16 +00:00
;; The following (non-evaluated) section can be used to
;; profile this package using `elp'.
;;
;; Invalid indentation on purpose!
* lisp/follow.el: Rework, eliminating reliance on advice. (set-process-filter, process-filter, sit-for): Advice deleted. (follow-mode-off-hook): Obsolete hook removed. (follow-avoid-tail-recenter-p, follow-process-filter-alist): Vars deleted. (follow-auto): Use a :set function. (follow-mode): Rewritten. Don't advise process filters. (follow-switch-to-current-buffer-all, follow-scroll-up) (follow-scroll-down): Assume follow-mode is bound. (follow-comint-scroll-to-bottom) (follow-align-compilation-windows): New functions. (follow--window-sorter): New function. (follow-all-followers): Use it to explicitly sort windows by their positions; don't make assumptions about next-window order. (follow-windows-start-end, follow-delete-other-windows-and-split) (follow-calc-win-start): Doc fix. (follow-windows-aligned-p, follow-select-if-visible): Don't call vertical-motion unnecessarily. (follow-adjust-window): New function. (follow-post-command-hook): Use it. (follow-call-set-process-filter, follow-call-process-filter) (follow-intercept-process-output, follow-tidy-process-filter-alist) (follow-stop-intercept-process-output, follow-generic-filter): Functions deleted. (follow-scroll-bar-toolkit-scroll, follow-scroll-bar-drag) (follow-scroll-bar-scroll-up, follow-scroll-bar-scroll-down): New functions, replacing advice on scroll-bar-* commands. * lisp/comint.el (comint-adjust-point): New function. (comint-postoutput-scroll-to-bottom): Use it. Call follow-comint-scroll-to-bottom for Follow mode buffers.
2012-05-01 13:37:56 +00:00
;; (setq elp-function-list
;; '(window-end
;; vertical-motion
;; follow-mode
;; follow-all-followers
;; follow-split-followers
;; follow-redisplay
;; follow-estimate-first-window-start
;; follow-calculate-first-window-start-from-above
;; follow-calculate-first-window-start-from-below
;; follow-calc-win-end
;; follow-calc-win-start
;; follow-pos-visible
;; follow-windows-start-end
;; follow-cache-valid-p
;; follow-select-if-visible
;; follow-select-if-visible-from-first
;; follow-windows-aligned-p
;; follow-point-visible-all-windows-p
;; follow-avoid-tail-recenter
;; follow-update-window-start
;; follow-post-command-hook))
1996-02-16 01:01:16 +00:00
(provide 'follow)
;; /------------------------------------------------------------------------\
;; | "I [..] am rarely happier then when spending an entire day programming |
;; | my computer to perform automatically a task that it would otherwise |
;; | take me a good ten seconds to do by hand. Ten seconds, I tell myself, |
;; | is ten seconds. Time is valuable and ten seconds' worth of it is well |
;; | worth the investment of a day's happy activity working out a way to |
;; | save it". -- Douglas Adams, "Last Chance to See" |
;; \------------------------------------------------------------------------/
;;; follow.el ends here