Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mmarshall540/db04e510850703830ca114aeff33c497 to your computer and use it in GitHub Desktop.
Save mmarshall540/db04e510850703830ca114aeff33c497 to your computer and use it in GitHub Desktop.
Alternatives to 'down-list' and 'backward-up-list' with string-movement, marking, and traversal
(defun my-down-sexp-with-mark (arg)
"Like `down-list', but with some differences.
- Enter strings in addition to lists.
- Mark inner of the list or string reached.
- Traverse beyond the lowest level in a list or string and descend
into the next top-level list or string when necessary.
- Move up and select contents of the string or list reached when
prefix is negative.
With a positive numeric ARG, repeat the down-list-like movement
ARG many times and mark contents of the string or list reached.
With the '- prefix or a negative numeric prefix, travel up the
surrounding lists and/or strings by (- ARG) levels, and descend
into the last escaped list or string. Thus, invoking the command
with a '- prefix will mark the inner content of the current
string or list."
(interactive "p")
(when (< arg 0)
(up-list arg t t)
(setq arg 1))
(if (eobp)
(message "At end of buffer, no more lists to descend into.")
;; Get out of any enclosing string first.
(when (nth 3 (syntax-ppss))
(skip-syntax-forward "^\"")
(while (= (char-before) ?\\)
(forward-char)
(skip-syntax-forward "^\""))
(forward-char))
(dotimes (i (or arg 1))
(unless (eq i 0) (forward-char))
(skip-syntax-forward "^(\"")
(unless (bobp)
(while (= (char-before) ?\\)
(forward-char)
(skip-syntax-forward "^(\""))))
(let ((start (point))
(end (save-excursion
(forward-sexp)
(point))))
(set-mark (1- end))
(goto-char (1+ start)))
(activate-mark)))
(defun my-up-list-with-mark (arg)
"Like `backward-up-list', but also mark the list.
ARG has the same effect as in the original."
(interactive "p")
(backward-up-list arg t t)
(save-excursion (forward-sexp nil t)
(push-mark (point)))
(activate-mark))
@mmarshall540
Copy link
Author

mmarshall540 commented Nov 21, 2023

The my-down-sexp-with-mark command is an alternative to down-list (bound to "C-M-d") which enters strings in addition to lists. If it is already at the lowest level, it skips forward to the next list or string instead of stopping. It also marks the contents of the string or list it enters. If prefixed with a minus ('-) argument or -1, it selects the content of the list or string at point. If given an argument less than -1, it moves outward (like backward-up-list) before entering the list it reaches and selecting that list's contents.

The my-up-list-with-mark command is the same as backward-up-list (bound to "C-M-u"), except that it also marks the list or string it ascends out of.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment