Attached is a patch with a few updates:

1. Added documentation in doc/emacs/mark.texi, under the mark-sexp section. I'm unfamiliar with standards for how the manuals are written, but am happy to update further as needed.
2. Extracted a new helper function mark--helper. This takes two arguments -- a move function, and a number of how many things to move.

The helper function is able to be used for all mark-*-forward and mark-*-backward functions; I think this should handle at least some of your concerns about the composability of the design -- different mark functions can be made by passing a different move function. For example, mark-word-forward and mark-word-backward would be defined this way:

(defun mark-word-forward (&optional number-of-words)
  "Mark NUMBER-OF-WORDS words forward.

 Repeated calls to this mark more words."
  (interactive "p")
  (mark--helper #'forward-word (or number-of-words 1)))

(defun mark-word-backward (&optional number-of-words)
  "Mark NUMBER-OF-WORDS words backward.

 Repeated calls to this mark more words."
  (interactive "p")
  (mark--helper #'forward-word (- (or number-of-words 1))))

I'm not exactly sure of the best place to put the helper function, nor exactly how the different lisp files in Emacs work together. There's no provide statement; are all the files in lisp/emacs-lisp loaded at the same time? If so, I'll make the other relevant functions (for marking word, defun, page, paragraph, line, and char).

Also, whatever the outcome of this patch, I think it would be advisable to explain somewhere how mark-sexp extends region by the end of region opposite point; this is not in the docstring or any other documentation I've seen.

On Fri, Apr 21, 2023 at 9:10 AM Stefan Monnier <monnier@iro.umontreal.ca> wrote:
> If this is to be accepted, why not extend it to all like mark functions,
> listed below?  Implementing them should be pretty similar, and you might
> even be able to reuse the same helper for all these variants.  Also, the
> helper function might need to contain a double-dash in its name because
> this is inherently a private function.
>
> - `mark-defun'
> - `mark-page'
> - `mark-paragraph'
> - `mark-word'

Agreed: we should move towards a more orthogonal/composable design,
where the granularity of the operation (char, word, line, sexp,
paragraph, page, defun, ...) and the operation itself (move, mark) and
the direction and all independent such that we can use any combination
of them.

Both at the ELisp level and at the key-binding level.


        Stefan