summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/cursor-sensor.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/cursor-sensor.el')
-rw-r--r--lisp/emacs-lisp/cursor-sensor.el53
1 files changed, 43 insertions, 10 deletions
diff --git a/lisp/emacs-lisp/cursor-sensor.el b/lisp/emacs-lisp/cursor-sensor.el
index 7e3088dd91e..66b940f7fb3 100644
--- a/lisp/emacs-lisp/cursor-sensor.el
+++ b/lisp/emacs-lisp/cursor-sensor.el
@@ -1,6 +1,6 @@
;;; cursor-sensor.el --- React to cursor movement -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2018 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2019 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
@@ -22,17 +22,50 @@
;;; Commentary:
-;; This package implements the `cursor-intangible' property, which is
-;; meant to replace the old `intangible' property. To use it, just enable the
-;; `cursor-intangible-mode', after which this package will move point away from
-;; any position that has a non-nil `cursor-intangible' property. This is only
-;; done just before redisplay happens, contrary to the old `intangible'
-;; property which was done at a much lower level.
+;; This package implements the `cursor-intangible' and
+;; `cursor-sensor-functions' properties, which are meant to replace
+;; the old `intangible', `point-entered', and `point-left' properties.
+
+;; To use `cursor-intangible', just enable the
+;; `cursor-intangible-mode' minor mode, after which this package will
+;; move point away from any position that has a non-nil
+;; `cursor-intangible' property. This is only done just before
+;; redisplay happens, contrary to the old `intangible' property which
+;; was done at a much lower level.
+
+;; To use `cursor-sensor-functions', enable the `cursor-sensor-mode'
+;; minor mode, after which the `cursor-sensor-functions' will be
+;; called just before redisplay happens, according to the movement of
+;; the cursor since the last redisplay.
+
+;;;; Motivation
+
+;; The old properties were very problematic in practice because they
+;; operate at a much lower level and hence affect all motion
+;; *functions* like goto-char, forward-char, ... hence breaking
+;; invariants like:
+;;
+;; (forward-char N) == (progn (forward-char N1) (forward-char (- N N1)))
+;; (point) == (progn (forward-char N) (forward-char -N) (point))
+;; (+ N (point)) == (progn (forward-char N) (point))
+;;
+;; The problems would usually show up due to interaction between
+;; unrelated code working in the same buffer, where one code used those
+;; properties and the other (unknowingly) assumed those aren't used.
+;; In practice a *lot* of code assumes there's no such funny business.
+;;
+;; Worse: all(?) packages using those properties don't actually want those
+;; properties to affect motion at such a low-level, they only want to
+;; affect the overall effect of commands, but not the effect of every
+;; single point-motion that a given command happened to use internally.
;;; Code:
;;;###autoload
-(defvar cursor-sensor-inhibit nil)
+(defvar cursor-sensor-inhibit nil
+ "When non-nil, suspend `cursor-sensor-mode' and `cursor-intangible-mode'.
+By convention, this is a list of symbols where each symbol stands for the
+\"cause\" of the suspension.")
(defun cursor-sensor--intangible-p (pos)
(let ((p (get-pos-property pos 'cursor-intangible)))
@@ -127,7 +160,7 @@
(setcdr old nil))
(if (or (and (null new) (null (cdr old)))
(and (eq new (cdr old))
- (eq (next-single-property-change
+ (eq (next-single-char-property-change
start 'cursor-sensor-functions nil end)
end)))
;; Clearly nothing to do.
@@ -139,7 +172,7 @@
(let ((pos start)
(missing nil))
(while (< pos end)
- (setq pos (next-single-property-change
+ (setq pos (next-single-char-property-change
pos 'cursor-sensor-functions
nil end))
(unless (memq f (get-char-property