I made some minor changes below. Alongside my suggestions are explanations as to why. This is a hard command to describe! > (defun mark-sexp (&optional arg allow-extend) > "Set mark ARG sexps from point or move mark ARG sexps. Mark can be moved ARG steps. Press C-M-@ C-M-@ C-u 3 C-M-@. There will be five total sexps marked. I'm hoping this explains that case as well, and giving an intuition for what this command does ("move mark ARG steps"). > When invoked interactively without a prefix argument and no active > region, mark moves one sexp forward. I moved this first, both because I suspect it's the most common use case, but also because it's the the simplest to understand. > When invoked interactively without a prefix argument, and region > is active, mark moves one sexp away from point (i.e., forward > if mark is at or after point, back if mark is before point), thus > extending the region by one sexp. > With ALLOW-EXTEND non-nil (interactively, with prefix argument), > the place mark goes is the same place \\[forward-sexp] would move > with the same value of ARG; if the mark is active, it moves ARG > sexps from its current position, otherwise it is set ARG sexps > from point. Moved this earlier to keep the entire interactive block together. > When the region is active, the direction the region is extended > depends on the relative position of mark and point. This means the > direction can be changed by pressing \\[exchange-point-and-mark] > before this command.. I moved this to a separate section to simplify the earlier parts, and to call out that this is possible whenever the region is active. > When called from Lisp with ALLOW-EXTEND omitted or nil, mark is > set ARG (defaulting to 1) sexps from point. Removed extra m from "omitted". > This command assumes point is not in a string or comment." Altogether, the docstring with my suggestions looks like: > (defun mark-sexp (&optional arg allow-extend) > "Set mark ARG sexps from point or move mark ARG sexps. > When invoked interactively without a prefix argument and no active > region, mark moves one sexp forward. > When invoked interactively without a prefix argument, and region > is active, mark moves one sexp away from point (i.e., forward > if mark is at or after point, back if mark is before point), thus > extending the region by one sexp. > With ALLOW-EXTEND non-nil (interactively, with prefix argument), > the place mark goes is the same place \\[forward-sexp] would move > with the same value of ARG; if the mark is active, it moves ARG > sexps from its current position, otherwise it is set ARG sexps > from point. > When the region is active, the direction the region is extended > depends on the relative position of mark and point. This means the > direction can be changed by pressing \\[exchange-point-and-mark] > before this command. > When called from Lisp with ALLOW-EXTEND omitted or nil, mark is > set ARG (defaulting to 1) sexps from point. > This command assumes point is not in a string or comment." This is a complicated command, for sure -- which is partially why I want simple functions to mark sexps forward and backward: to not have to think about different cases. Can we fork off a discussion about those functions? Having simple functions allows the user to do what they want without having to learn complex nuance. On Thu, Apr 27, 2023 at 2:14 PM Juri Linkov wrote: > > I tried to describe the behavior in the doc string as follows: > > > > (defun mark-sexp (&optional arg allow-extend) > > "Set mark ARG sexps from point or move mark one sexp. > > When called from Lisp with ALLOW-EXTEND ommitted or nil, mark is > > set ARG sexps from point; ARG defaults to 1. > > With ALLOW-EXTEND non-nil (interactively, with prefix argument), > > the place mark goes is the same place \\[forward-sexp] would move > > with the same value of ARG; if the mark is active, it moves ARG > > sexps from its current position, otherwise it is set ARG sexps > > from point; ARG defaults to 1. > > When invoked interactively without a prefix argument and no active > > region, mark moves one sexp forward. > > When invoked interactively without a prefix argument, and region > > is active, mark moves one sexp away of point (i.e., forward > > if mark is at or after point, back if mark is before point), thus > > extending the region by one sexp. Since the direction of region > > extension depends on the relative position of mark and point, you > > can change the direction by \\[exchange-point-and-mark]. > > This command assumes point is not in a string or comment." > > > > It is still somewhat complicated and confusing, but at least it's > > accurate, I think. > > mark-sexp has a counterpart mark-word that has almost the same > implementation and docstring. So this could be fixed in both places. >