emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Fix for `use-region-p' problem [was: Elisp test for whether `mouse-1'


From: Drew Adams
Subject: Fix for `use-region-p' problem [was: Elisp test for whether `mouse-1' is pressed?]
Date: Sun, 7 Nov 2021 23:26:45 +0000

I got no response to my question of how to tell
whether `mouse-1' is still pressed during a click.

But I found an answer that seems to work across
Emacs releases (24 through 27, the latest I have).

Now let me pose a different question/suggestion.
I think `use-region-p' does the wrong thing in a
particular case, and I suggest a fix for that.

Here's the problem I see.  Admittedly, most code
hasn't, and won't, run into it.

`use-region-p' is designed to let code know that
either (1) the active region is nonempty or (2)
the user has OK'd the use of an empty region
(non-nil option `use-empty-active-region').

It should return non-nil in those cases _only_.

The problem I've run into comes in #2: empty
active region that's declared to be OK to use.

I think the real motivation for "use" must be for
the user (or some code) to act on the region with
the _next_ action - in particular, a user input
action - a command.  If the region is active and
usable then you can act on it - that's the idea.

In simple user terms, in this context (being able
to act on the active region) a click of `mouse-1'
can be considered a single user action.  There's
no intention, and little ability, for a user to
act _between_ the down & up events of a click (as
opposed to a drag).

(About the only thing a user can do between the
down & up events is hit a keyboard key.)

I think a user who's OK'd acting on (aka "using")
the empty active region really expects that
action ("use") to come after the down-&-up click,
not between the down & up events.

But `use-region-p' is a general test, and it can
be used anytime - including between down & up.

The current implementation doesn't effectively
check whether the region is active and useful
for an upcoming user action.  If some code tests
between down & up, and if the result of that
test is shown to a user, then a false impression
of "usable" is given - if only momentarily (till
the up event).

This problem just hasn't been noticed, most
likely, because `use-region-p' hasn't been
invoked in between those events.

My use case is to have the active region - as
something that can be acted on by users - be
indicated in the mode-line.  When active, you
see that it's active (you see the region size
indicated also, but that's irrelevant here).

In particular, OK'ing the use of an empty
active region is helpful in this context
because you see, in the mode-line, that
you're about to act on the empty region -
something you typically don't want to do.
IOW, this is a way to _see_ ahead of time
that you're trying to use an empty region.

I use a different user option for this from
`use-empty-active-region', and its default
value is non-nil.  So this feature doesn't
interfere with whatever value you prefer for
that standard option.

But I think the solution I've found (after I
posed the question looking for one) should
be considered as a fix for the problem in
`use-region-p' itself.  Why not fix this
corner case, even though people aren't very
likely to run into it?

Here's the code I'd propose:

---

(defun use-region-p ()
  "Return non-nil if it is appropriate to act on the region.
This is used by commands that act specially on the region when
Transient Mark mode is enabled.

The return value is non-nil if the region is active and either of the
following conditions is true; otherwise, the return value is nil.
 * The region is nonempty.
 * Option `use-empty-active-region' is non-nil, and the last input did
   not use `mouse-1' to set or adjust the region.

For some commands, it might be appropriate to ignore the value of
`use-empty-active-region'; in that case, use `region-active-p'."
  (ignore-errors
    (and (region-active-p)
         (or (> (region-end) (region-beginning))
             (and use-empty-active-region
                  (not (eq 'down-mouse-1
                           (car-safe last-input-event)))
                  (not (mouse-movement-p
                         last-input-event)))))))
---

(The fix ANDs those two mouse conditions to
`use-empty-active-region'.)

I'm no expert on events, mouse or otherwise,
so if someone sees a better implementation,
great.  (I'm not sure the `ignore-errors' is
needed, for example.)

The question is really whether preventing
`use-region-p' from returning true between
the down-&-up events of a click makes sense,
and if so, how best to do that.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]