Function: cycle-spacing
cycle-spacing is an interactive and byte-compiled function defined in
simple.el.gz.
Signature
(cycle-spacing &optional N)
Documentation
Manipulate whitespace around point in a smart way.
Repeated calls perform the actions in cycle-spacing-actions one
after the other, wrapping around after the last one.
All actions are amendable using a prefix arg N. In general, a zero or positive prefix arg allows only for deletion of tabs and spaces whereas a negative prefix arg also allows for deleting newlines.
The prefix arg given at the first invocation starting a cycle is
provided to all following actions, i.e.,
M-- (negative-argument) M-SPC (cycle-spacing) M-SPC (cycle-spacing) M-SPC (cycle-spacing)
is equivalent to
M-- (negative-argument) M-SPC (cycle-spacing) M-- (negative-argument) M-SPC (cycle-spacing) M-- (negative-argument) M-SPC (cycle-spacing).
A new sequence can be started by providing a different prefix arg
than provided at the initial invocation (except for 1), or by
doing any other command before the next M-SPC (cycle-spacing).
Probably introduced at or before Emacs version 24.4.
Key Bindings
Source Code
;; Defined in /usr/src/emacs/lisp/simple.el.gz
(defun cycle-spacing (&optional n)
"Manipulate whitespace around point in a smart way.
Repeated calls perform the actions in `cycle-spacing-actions' one
after the other, wrapping around after the last one.
All actions are amendable using a prefix arg N. In general, a
zero or positive prefix arg allows only for deletion of tabs and
spaces whereas a negative prefix arg also allows for deleting
newlines.
The prefix arg given at the first invocation starting a cycle is
provided to all following actions, i.e.,
\\[negative-argument] \\[cycle-spacing] \\[cycle-spacing] \\[cycle-spacing]
is equivalent to
\\[negative-argument] \\[cycle-spacing] \\[negative-argument] \\[cycle-spacing] \\[negative-argument] \\[cycle-spacing].
A new sequence can be started by providing a different prefix arg
than provided at the initial invocation (except for 1), or by
doing any other command before the next \\[cycle-spacing]."
(interactive "*P")
;; Initialize `cycle-spacing--context' if needed.
(when (or (not (equal last-command this-command))
(not cycle-spacing--context)
;; With M-5 M-SPC M-SPC... we pass the prefix arg 5 to
;; each action and only start a new cycle when a different
;; prefix arg is given and which is not the default value
;; 1.
(and n (not (equal (plist-get cycle-spacing--context :n)
n))))
(let ((orig-pos (point))
(skip-characters " \t\n\r"))
(save-excursion
(skip-chars-backward skip-characters)
(constrain-to-field nil orig-pos)
(let ((start (point))
(end (progn
(skip-chars-forward skip-characters)
(constrain-to-field nil orig-pos t))))
(setq cycle-spacing--context ;; Save for later.
(list :orig-pos orig-pos
:whitespace-string (buffer-substring start end)
:n n
:last-action nil))))))
;; Cycle through the actions in `cycle-spacing-actions'.
(when cycle-spacing--context
(cl-labels ((next-action ()
(let* ((l cycle-spacing-actions)
(elt (plist-get cycle-spacing--context
:last-action)))
(if (null elt)
(car cycle-spacing-actions)
(catch 'found
(while l
(cond
((null (cdr l))
(throw 'found
(when (eq elt (car l))
(car cycle-spacing-actions))))
((and (eq elt (car l))
(cdr l))
(throw 'found (cadr l)))
(t (setq l (cdr l)))))))))
(skip-chars (chars max-dist direction)
(if (eq direction 'forward)
(skip-chars-forward
chars
(and max-dist (+ (point) max-dist)))
(skip-chars-backward
chars
(and max-dist (- (point) max-dist)))))
(delete-space (n include-newlines direction)
(let ((orig-point (point))
(chars (if include-newlines
" \t\r\n"
" \t")))
(when (or (zerop n)
(= n (abs (skip-chars chars n direction))))
(let ((start (point))
(end (progn
(skip-chars chars nil direction)
(point))))
(unless (= start end)
(delete-region start end))
(goto-char (if (eq direction 'forward)
orig-point
(+ n end)))))))
(restore ()
(delete-all-space)
(insert (plist-get cycle-spacing--context
:whitespace-string))
(goto-char (plist-get cycle-spacing--context
:orig-pos))))
(let ((action (next-action)))
(atomic-change-group
(restore)
(unless (eq action 'restore)
;; action can be some-action or (some-action <arg>) where
;; arg is either an integer, the arg to be always used for
;; this action or - to use the inverted context n for this
;; action.
(let* ((actual-action (if (listp action)
(car action)
action))
(arg (when (listp action)
(nth 1 action)))
(context-n (plist-get cycle-spacing--context :n))
(actual-n (cond
((integerp arg) arg)
((eq 'inverted-arg arg)
(* -1 (prefix-numeric-value context-n)))
((eq '- arg) '-)
(t context-n)))
(numeric-n (prefix-numeric-value actual-n))
(include-newlines (or (eq actual-n '-)
(and (integerp actual-n)
(< actual-n 0)))))
(cond
((eq actual-action 'just-one-space)
(just-one-space numeric-n))
((eq actual-action 'delete-space-after)
(delete-space (if (eq actual-n '-) 0 (abs numeric-n))
include-newlines 'forward))
((eq actual-action 'delete-space-before)
(delete-space (if (eq actual-n '-) 0 (abs numeric-n))
include-newlines 'backward))
((eq actual-action 'delete-all-space)
(if include-newlines
(delete-all-space)
(delete-horizontal-space)))
((functionp actual-action)
(funcall actual-action actual-n))
(t
(error "Don't know how to handle action %S" action)))))
(setf (plist-get cycle-spacing--context :last-action)
action))))))