Function: c-backslash-region

c-backslash-region is an interactive and byte-compiled function defined in cc-cmds.el.gz.

Signature

(c-backslash-region FROM TO DELETE-FLAG &optional LINE-MODE)

Documentation

Insert, align, or delete end-of-line backslashes on the lines in the region.

With no argument, inserts backslashes and aligns existing backslashes. With an argument, deletes the backslashes. The backslash alignment is done according to the settings in c-backslash-column, c-backslash-max-column and c-auto-align-backslashes.

This function does not modify blank lines at the start of the region. If the region ends at the start of a line and the macro doesn't continue below it, the backslash (if any) at the end of the previous line is deleted.

You can put the region around an entire macro definition and use this command to conveniently insert and align the necessary backslashes.

Probably introduced at or before Emacs version 19.20.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-cmds.el.gz
;;; This page handles insertion and removal of backslashes for C macros.

(defun c-backslash-region (from to delete-flag &optional line-mode)
  "Insert, align, or delete end-of-line backslashes on the lines in the region.
With no argument, inserts backslashes and aligns existing backslashes.
With an argument, deletes the backslashes.  The backslash alignment is
done according to the settings in `c-backslash-column',
`c-backslash-max-column' and `c-auto-align-backslashes'.

This function does not modify blank lines at the start of the region.
If the region ends at the start of a line and the macro doesn't
continue below it, the backslash (if any) at the end of the previous
line is deleted.

You can put the region around an entire macro definition and use this
command to conveniently insert and align the necessary backslashes."
  (interactive "*r\nP")
  (let ((endmark (make-marker))
	;; Keep the backslash trimming functions from changing the
	;; whitespace around point, since in this case it's only the
	;; position of point that tells the indentation of the line.
	(point-pos (if (save-excursion
			 (skip-chars-backward " \t")
			 (and (bolp) (looking-at "[ \t]*\\\\?$")))
		       (point-marker)
		     (point-min)))
	column longest-line-col bs-col-after-end)
    (save-excursion
      (goto-char to)
      (if (and (not line-mode) (bobp))
	  ;; Nothing to do if to is at bob, since we should back up
	  ;; and there's no line to back up to.
	  nil
	(when (and (not line-mode) (bolp))
	  ;; Do not back up the to line if line-mode is set, to make
	  ;; e.g. c-newline-and-indent consistent regardless whether
	  ;; the (newline) call leaves point at bol or not.
	  (backward-char)
	  (setq to (point)))
	(if delete-flag
	    (progn
	      (set-marker endmark (point))
	      (goto-char from)
	      (c-delete-backslashes-forward endmark point-pos))
	  ;; Set bs-col-after-end to the column of any backslash
	  ;; following the region, or nil if there is none.
	  (setq bs-col-after-end
		(and (progn (end-of-line)
			    (eq (char-before) ?\\))
		     (= (forward-line 1) 0)
		     (progn (end-of-line)
			    (eq (char-before) ?\\))
		     (1- (current-column))))
	  (when line-mode
	    ;; Back up the to line if line-mode is set, since the line
	    ;; after the newly inserted line break should not be
	    ;; touched in c-newline-and-indent.
	    (setq to (max from (or (c-safe (c-point 'eopl)) from)))
	    (unless bs-col-after-end
	      ;; Set bs-col-after-end to non-nil in any case, since we
	      ;; do not want to delete the backslash at the last line.
	      (setq bs-col-after-end t)))
	  (if (and line-mode
		   (not c-auto-align-backslashes))
	      (goto-char from)
	    ;; Compute the smallest column number past the ends of all
	    ;; the lines.
	    (setq longest-line-col 0)
	    (goto-char to)
	    (if bs-col-after-end
		;; Include one more line in the max column
		;; calculation, since the to line will be backslashed
		;; too.
		(forward-line 1))
	    (end-of-line)
	    (while (and (>= (point) from)
			(progn
			  (if (eq (char-before) ?\\)
			      (forward-char -1))
			  (skip-chars-backward " \t")
			  (setq longest-line-col (max longest-line-col
						      (1+ (current-column))))
			  (beginning-of-line)
			  (not (bobp))))
	      (backward-char))
	    ;; Try to align with surrounding backslashes.
	    (goto-char from)
	    (beginning-of-line)
	    (if (and (not (bobp))
		     (progn (backward-char)
			    (eq (char-before) ?\\)))
		(progn
		  (setq column (1- (current-column)))
		  (if (numberp bs-col-after-end)
		      ;; Both a preceding and a following backslash.
		      ;; Choose the greatest of them.
		      (setq column (max column bs-col-after-end)))
		  (goto-char from))
	      ;; No preceding backslash.  Try to align with one
	      ;; following the region.  Disregard the backslash at the
	      ;; to line since it's likely to be bogus (e.g. when
	      ;; called from c-newline-and-indent).
	      (if (numberp bs-col-after-end)
		  (setq column bs-col-after-end))
	      ;; Don't modify blank lines at start of region.
	      (goto-char from)
	      (while (and (< (point) to) (bolp) (eolp))
		(forward-line 1)))
	    (if (and column (< column longest-line-col))
		;; Don't try to align with surrounding backslashes if
		;; any line is too long.
		(setq column nil))
	    (unless column
	      ;; Impose minimum limit and tab width alignment only if
	      ;; we can't align with surrounding backslashes.
	      (if (> (% longest-line-col tab-width) 0)
		  (setq longest-line-col
			(* (/ (+ longest-line-col tab-width -1)
			      tab-width)
			   tab-width)))
	      (setq column (max c-backslash-column
				longest-line-col)))
	    ;; Always impose maximum limit.
	    (setq column (min column c-backslash-max-column)))
	  (if bs-col-after-end
	      ;; Add backslashes on all lines if the macro continues
	      ;; after the to line.
	      (progn
		(set-marker endmark to)
		(c-append-backslashes-forward endmark column point-pos))
	    ;; Add backslashes on all lines except the last, and
	    ;; remove any on the last line.
	    (if (save-excursion
		  (goto-char to)
		  (beginning-of-line)
		  (if (not (bobp))
		      (set-marker endmark (1- (point)))))
		(progn
		  (c-append-backslashes-forward endmark column point-pos)
		  ;; The function above leaves point on the line
		  ;; following endmark.
		  (set-marker endmark (point)))
	      (set-marker endmark to))
	    (c-delete-backslashes-forward endmark point-pos)))))
    (set-marker endmark nil)
    (if (markerp point-pos)
	(set-marker point-pos nil))))