diff options
Diffstat (limited to 'lisp/emacs-lisp/cursor-sensor.el')
-rw-r--r-- | lisp/emacs-lisp/cursor-sensor.el | 53 |
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 |