Subject: bug#62892: proposal to extend mark-sexp to go forward and backward on command

From: Zachary Kanfer <[email-masked]>
Date: Wed, 26 Apr 2023 22:37:58 -0400

> > Worse still is the next part:
> >
> > > Interactively, if this command is repeated
> > > or (in Transient Mark mode) if the mark is active,
> > > it marks the next ARG sexps after the ones already marked.
> >
> > This says it marks sexps *after* the ones already marked. This is
incorrect; if point is *after* mark, and
> > mark is active, this function marks sexps *before* the ones already
marked.
>
> I cannot reproduce this behavior, if I understand your description
> correctly.  Please show a recipe, starting from "emacs -Q", to
> reproduce.

Open Emacs with:

emacs -Q --eval '(progn (insert "foo bar baz") (goto-char 8) (set-mark 5))'

It will insert "foo bar baz", put point after "bar", and mark before "bar".
Region contains "bar".

Then when we run mark-sexp, we expect to mark some sexps "after the ones
already marked". That's what the docstring says.

After running the command above to open emacs, press C-M-@ to run
mark-sexp. We should see sexps marked "after the ones already marked"; that
is, we should see "bar baz" marked. But we don't. Instead, we see that "foo
bar" is highlighted. That is, we have marked sexps *before* the ones
already marked.

> > The documentation for mark-sexp says:
> >
> > > Set mark ARG sexps from point.
> > > The place mark goes is the same place C-M-<right> would
> > > move to with the same argument.
> >
> > This is correct but misleading.
>
> Please elaborate: how could it mislead?

"The same argument" is the misleading part. If I call mark-sexp with no
argument, sometimes that code passes -1 to forward-sexp. So while I think
I'm effectively passing a "1" to mark-sexp, instead -1 is passed to
forward-sexp. This is somewhat explained by the next part of the docstring,
but not entirely. Read with the rest of the docstring, it reinforces the
belief that the command only marks sexps *after* point.

> > > In my opinion, the description of that feature should not be part of
the
> > > mark-sexp command documentation, because the feature is actually
> > > provided by C-x C-x (exchange-point-and-mark).
> >
> > One way for this situation to occur is by using C-x C-x, yes, but it's
not the only way. You can set point,
> > move forward sexps, and then calling mark-sexp will mark sexps
backwards.
> >
> > There is specific code in mark-sexp to check which direction to move;
it should be documented as
> > such.
>
> Please also demonstrate this behavior and point to that code, so we
> will know what you are alluding to.

Here is the line of code:
https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/emacs-lisp/lisp.el#n107.
When the region is active, and no prefix arg is given to mark-sexp, the
function resets `arg` as follows:

(setq arg (if arg (prefix-numeric-value arg)
              (if (< (mark) (point)) -1 1)))

When no prefix arg is given, when the region is active, it sets arg to
either 1 or -1, depending on the relative positions of point and mark.

The behavior can be seen in the instructions above, but here's a simpler
way to see it:

1. `emacs -Q --eval '(progn (insert "foo bar baz") (goto-char 5))`
2. C-space. (Set mark)
3. M-f. (forward word). We have now set up the situation I was referring to
-- point is set after mark, and mark is active.
4. C-M-@. Here, we see mark-sexp extend region backwards without ever using
C-x C-x (exchange-point-and-mark). The feature of extending the region
backwards cannot be provided by exchange-point-and-mark.

On Wed, Apr 26, 2023 at 2:28 AM Eli Zaretskii <[email-masked]> wrote:

> > Cc: Ruijie Yu <[email-masked]>, Stefan Monnier <
> [email-masked]>,
> >  [email-masked]
> > From: Zachary Kanfer <[email-masked]>
> > Date: Wed, 26 Apr 2023 00:41:45 -0400
> >
> > The documentation for mark-sexp says:
> >
> > > Set mark ARG sexps from point.
> > > The place mark goes is the same place C-M-<right> would
> > > move to with the same argument.
> >
> > This is correct but misleading.
>
> Please elaborate: how could it mislead?
>
> > Worse still is the next part:
> >
> > > Interactively, if this command is repeated
> > > or (in Transient Mark mode) if the mark is active,
> > > it marks the next ARG sexps after the ones already marked.
> >
> > This says it marks sexps *after* the ones already marked. This is
> incorrect; if point is *after* mark, and
> > mark is active, this function marks sexps *before* the ones already
> marked.
>
> I cannot reproduce this behavior, if I understand your description
> correctly.  Please show a recipe, starting from "emacs -Q", to
> reproduce.
>
> > > In my opinion, the description of that feature should not be part of
> the
> > > mark-sexp command documentation, because the feature is actually
> > > provided by C-x C-x (exchange-point-and-mark).
> >
> > One way for this situation to occur is by using C-x C-x, yes, but it's
> not the only way. You can set point,
> > move forward sexps, and then calling mark-sexp will mark sexps backwards.
> >
> > There is specific code in mark-sexp to check which direction to move; it
> should be documented as
> > such.
>
> Please also demonstrate this behavior and point to that code, so we
> will know what you are alluding to.
>
> Thanks.
>