;;; cc-cmds.el --- user level commands for CC Mode
-;; Copyright (C) 1985,1987,1992-2003 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2003, 2004, 2005, 2006 Free Software
+;; Foundation, Inc.
;; Authors: 1998- Martin Stjernholm
;; 1992-1999 Barry A. Warsaw
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
(cc-require 'cc-engine)
;; Silence the compiler.
-(cc-bytecomp-defvar delete-key-deletes-forward) ; XEmacs 20+
-(cc-bytecomp-defun delete-forward-p) ; XEmacs 21+
-(cc-bytecomp-obsolete-fun insert-and-inherit) ; Marked obsolete in XEmacs 19
+(cc-bytecomp-defun delete-forward-p) ; XEmacs
(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge
; which looks at this.
-
+(cc-bytecomp-defun c-forward-subword)
+(cc-bytecomp-defun c-backward-subword)
\f
(defvar c-fix-backslashes t)
-(defun c-shift-line-indentation (shift-amt)
- ;; This function does not do any hidden buffer changes.
- (let ((pos (- (point-max) (point)))
- (c-macro-start c-macro-start)
- tmp-char-inserted)
- (if (zerop shift-amt)
- nil
- (when (and (c-query-and-set-macro-start)
- (looking-at "[ \t]*\\\\$")
- (save-excursion
- (skip-chars-backward " \t")
- (bolp)))
- (insert ?x)
- (backward-char)
- (setq tmp-char-inserted t))
- (unwind-protect
- (let ((col (current-indentation)))
- (delete-region (c-point 'bol) (c-point 'boi))
- (beginning-of-line)
- (indent-to (+ col shift-amt)))
- (when tmp-char-inserted
- (delete-char 1))))
- ;; If initial point was within line's indentation and we're not on
- ;; a line with a line continuation in a macro, position after the
- ;; indentation. Else stay at same point in text.
- (if (and (< (point) (c-point 'boi))
- (not tmp-char-inserted))
- (back-to-indentation)
- (if (> (- (point-max) pos) (point))
- (goto-char (- (point-max) pos))))))
-
(defun c-indent-line (&optional syntax quiet ignore-point-pos)
"Indent the current line according to the syntactic context,
if `c-syntactic-indentation' is non-nil. Optional SYNTAX is the
is otherwise empty \(ignoring any line continuation backslash), but
that's not done if IGNORE-POINT-POS is non-nil. Returns the amount of
indentation change \(in columns)."
- ;;
- ;; This function does not do any hidden buffer changes.
(let ((line-cont-backslash (save-excursion
(end-of-line)
shift-amt))
(defun c-newline-and-indent (&optional newline-arg)
- "Inserts a newline and indents the new line.
+ "Insert a newline and indent the new line.
This function fixes line continuation backslashes if inside a macro,
and takes care to set the indentation before calling
`indent-according-to-mode', so that lineup functions like
`c-lineup-dont-change' works better."
- ;;
- ;; This function does not do any hidden buffer changes.
;; TODO: Backslashes before eol in comments and literals aren't
;; kept intact.
(c-save-buffer-state nil
(c-guess-basic-syntax)))))
(if (not (consp arg))
- (message "syntactic analysis: %s" syntax)
+ (let (elem pos ols)
+ (message "Syntactic analysis: %s" syntax)
+ (unwind-protect
+ (progn
+ (while syntax
+ (setq elem (pop syntax))
+ (when (setq pos (c-langelem-pos elem))
+ (push (c-put-overlay pos (1+ pos)
+ 'face 'highlight)
+ ols))
+ (when (setq pos (c-langelem-2nd-pos elem))
+ (push (c-put-overlay pos (1+ pos)
+ 'face 'secondary-selection)
+ ols)))
+ (sit-for 10))
+ (while ols
+ (c-delete-overlay (pop ols)))))
(indent-for-comment)
(insert-and-inherit (format "%s" syntax))
))
(c-keep-region-active))
(defun c-syntactic-information-on-region (from to)
- "Inserts a comment with the syntactic analysis on every line in the region."
+ "Insert a comment with the syntactic analysis on every line in the region."
(interactive "*r")
(save-excursion
(save-restriction
(forward-line)))))
\f
+(defun c-update-modeline ()
+ (let ((fmt (format "/%s%s%s%s"
+ (if c-electric-flag "l" "")
+ (if (and c-electric-flag c-auto-newline)
+ "a" "")
+ (if c-hungry-delete-key "h" "")
+ (if (and
+ ;; cc-subword might not be loaded.
+ (boundp 'c-subword-mode)
+ (symbol-value 'c-subword-mode))
+ "w"
+ "")))
+ (bare-mode-name (if (string-match "\\(^[^/]*\\)/" mode-name)
+ (substring mode-name (match-beginning 1) (match-end 1))
+ mode-name)))
+;; (setq c-submode-indicators
+;; (if (> (length fmt) 1)
+;; fmt))
+ (setq mode-name
+ (if (> (length fmt) 1)
+ (concat bare-mode-name fmt)
+ bare-mode-name))
+ (force-mode-line-update)))
+
(defun c-toggle-syntactic-indentation (&optional arg)
"Toggle syntactic indentation.
Optional numeric ARG, if supplied, turns on syntactic indentation when
functions and the electric keys indent according to the syntactic
context keys, when applicable.
-When it's turned off, the electric keys does no reindentation, the
-indentation functions indents every new line to the same level as the
-previous nonempty line, and \\[c-indent-command] adjusts the
-indentation in seps specified `c-basic-offset'. The indentation style
-has no effect in this mode, nor any of the indentation associated
-variables, e.g. `c-special-indent-hook'.
+When it's turned off, the electric keys don't reindent, the indentation
+functions indents every new line to the same level as the previous
+nonempty line, and \\[c-indent-command] adjusts the indentation in steps
+specified by `c-basic-offset'. The indentation style has no effect in
+this mode, nor any of the indentation associated variables,
+e.g. `c-special-indent-hook'.
This command sets the variable `c-syntactic-indentation'."
(interactive "P")
(c-calculate-state arg c-syntactic-indentation))
(c-keep-region-active))
-(defun c-toggle-auto-state (&optional arg)
+(defun c-toggle-auto-newline (&optional arg)
"Toggle auto-newline feature.
Optional numeric ARG, if supplied, turns on auto-newline when
positive, turns it off when negative, and just toggles it when zero or
left out.
-When the auto-newline feature is enabled (as evidenced by the `/a' or
-`/ah' on the modeline after the mode name) newlines are automatically
-inserted after special characters such as brace, comma, semi-colon,
-and colon."
+Turning on auto-newline automatically enables electric indentation.
+
+When the auto-newline feature is enabled (indicated by \"/la\" on the
+modeline after the mode name) newlines are automatically inserted
+after special characters such as brace, comma, semi-colon, and colon."
(interactive "P")
- (setq c-auto-newline (c-calculate-state arg c-auto-newline))
+ (setq c-auto-newline
+ (c-calculate-state arg (and c-auto-newline c-electric-flag)))
+ (if c-auto-newline (setq c-electric-flag t))
(c-update-modeline)
(c-keep-region-active))
+(defalias 'c-toggle-auto-state 'c-toggle-auto-newline)
+(make-obsolete 'c-toggle-auto-state 'c-toggle-auto-newline)
+
(defun c-toggle-hungry-state (&optional arg)
"Toggle hungry-delete-key feature.
Optional numeric ARG, if supplied, turns on hungry-delete when
positive, turns it off when negative, and just toggles it when zero or
left out.
-When the hungry-delete-key feature is enabled (as evidenced by the
-`/h' or `/ah' on the modeline after the mode name) the delete key
-gobbles all preceding whitespace in one fell swoop."
+When the hungry-delete-key feature is enabled (indicated by \"/h\" on
+the modeline after the mode name) the delete key gobbles all preceding
+whitespace in one fell swoop."
(interactive "P")
(setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
(c-update-modeline)
hungry-delete when positive, turns them off when negative, and just
toggles them when zero or left out.
-See `c-toggle-auto-state' and `c-toggle-hungry-state' for details."
+See `c-toggle-auto-newline' and `c-toggle-hungry-state' for details."
(interactive "P")
(setq c-auto-newline (c-calculate-state arg c-auto-newline))
(setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
(c-update-modeline)
(c-keep-region-active))
+(defun c-toggle-electric-state (&optional arg)
+ "Toggle the electric indentation feature.
+Optional numeric ARG, if supplied, turns on electric indentation when
+positive, turns it off when negative, and just toggles it when zero or
+left out."
+ (interactive "P")
+ (setq c-electric-flag (c-calculate-state arg c-electric-flag))
+ (c-update-modeline)
+ (c-keep-region-active))
+
\f
;; Electric keys
(defun c-electric-backspace (arg)
"Delete the preceding character or whitespace.
-If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or
-\"/ah\" string on the mode line, then all preceding whitespace is
-consumed. If however a prefix argument is supplied, or
-`c-hungry-delete-key' is nil, or point is inside a literal then the
-function in the variable `c-backspace-function' is called."
+If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode
+line) then all preceding whitespace is consumed. If however a prefix
+argument is supplied, or `c-hungry-delete-key' is nil, or point is
+inside a literal then the function in the variable
+`c-backspace-function' is called."
(interactive "*P")
- (if (or (not c-hungry-delete-key)
- arg
- (c-in-literal))
+ (if (c-save-buffer-state ()
+ (or (not c-hungry-delete-key)
+ arg
+ (c-in-literal)))
(funcall c-backspace-function (prefix-numeric-value arg))
- (c-hungry-backspace)))
+ (c-hungry-delete-backwards)))
-(defun c-hungry-backspace ()
+(defun c-hungry-delete-backwards ()
"Delete the preceding character or all preceding whitespace
back to the previous non-whitespace character.
See also \\[c-hungry-delete-forward]."
(delete-region (point) here)
(funcall c-backspace-function 1))))
+(defalias 'c-hungry-backspace 'c-hungry-delete-backwards)
+
(defun c-electric-delete-forward (arg)
"Delete the following character or whitespace.
-If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or
-\"/ah\" string on the mode line, then all following whitespace is
-consumed. If however a prefix argument is supplied, or
-`c-hungry-delete-key' is nil, or point is inside a literal then the
-function in the variable `c-delete-function' is called."
+If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode
+line) then all following whitespace is consumed. If however a prefix
+argument is supplied, or `c-hungry-delete-key' is nil, or point is
+inside a literal then the function in the variable `c-delete-function'
+is called."
(interactive "*P")
- (if (or (not c-hungry-delete-key)
- arg
- (c-in-literal))
+ (if (c-save-buffer-state ()
+ (or (not c-hungry-delete-key)
+ arg
+ (c-in-literal)))
(funcall c-delete-function (prefix-numeric-value arg))
(c-hungry-delete-forward)))
(defun c-hungry-delete-forward ()
"Delete the following character or all following whitespace
up to the next non-whitespace character.
-See also \\[c-hungry-backspace]."
+See also \\[c-hungry-delete-backwards]."
(interactive)
(let ((here (point)))
(c-skip-ws-forward)
(defun c-electric-delete (arg)
"Deletes preceding or following character or whitespace.
This function either deletes forward as `c-electric-delete-forward' or
-backward as `c-electric-backspace', depending on the configuration:
-
-If the function `delete-forward-p' is defined (XEmacs 21) and returns
-non-nil, it deletes forward. Else, if the variable
-`delete-key-deletes-forward' is defined (XEmacs 20) and is set to
-non-nil, it deletes forward. Otherwise it deletes backward.
-
-Note: This is the way in XEmacs 20 and later to choose the correct
-action for the [delete] key, whichever key that means. In other
-flavors this function isn't used, instead it's left to the user to
-bind [delete] to either \\[c-electric-delete-forward] or \\[c-electric-backspace] as appropriate
-\(the keymap `function-key-map' is useful for that). Emacs 21 handles
-that automatically, though."
+backward as `c-electric-backspace', depending on the configuration: If
+the function `delete-forward-p' is defined and returns non-nil, it
+deletes forward. Otherwise it deletes backward.
+
+Note: This is the way in XEmacs to choose the correct action for the
+\[delete] key, whichever key that means. Other flavors don't use this
+function to control that."
(interactive "*P")
- (if (or (and (fboundp 'delete-forward-p) ;XEmacs 21
- (delete-forward-p))
- (and (boundp 'delete-key-deletes-forward) ;XEmacs 20
- delete-key-deletes-forward))
+ (if (and (fboundp 'delete-forward-p)
+ (delete-forward-p))
(c-electric-delete-forward arg)
(c-electric-backspace arg)))
+;; This function is only used in XEmacs.
+(defun c-hungry-delete ()
+ "Delete a non-whitespace char, or all whitespace up to the next non-whitespace char.
+The direction of deletion depends on the configuration: If the
+function `delete-forward-p' is defined and returns non-nil, it deletes
+forward using `c-hungry-delete-forward'. Otherwise it deletes
+backward using `c-hungry-backspace'.
+
+Note: This is the way in XEmacs to choose the correct action for the
+\[delete] key, whichever key that means. Other flavors don't use this
+function to control that."
+ (interactive)
+ (if (and (fboundp 'delete-forward-p)
+ (delete-forward-p))
+ (c-hungry-delete-forward)
+ (c-hungry-delete-backwards)))
+
(defun c-electric-pound (arg)
- "Electric pound (`#') insertion.
-Inserts a `#' character specially depending on the variable
-`c-electric-pound-behavior'. If a numeric ARG is supplied, or if
-point is inside a literal or a macro, nothing special happens."
+ "Insert a \"#\".
+If `c-electric-flag' is set, handle it specially according to the variable
+`c-electric-pound-behavior'. If a numeric ARG is supplied, or if point is
+inside a literal or a macro, nothing special happens."
(interactive "*P")
- (if (or arg
- (not (memq 'alignleft c-electric-pound-behavior))
- (save-excursion
- (skip-chars-backward " \t")
- (not (bolp)))
- (save-excursion
- (and (= (forward-line -1) 0)
- (progn (end-of-line)
- (eq (char-before) ?\\))))
- (c-in-literal))
+ (if (c-save-buffer-state ()
+ (or arg
+ (not c-electric-flag)
+ (not (memq 'alignleft c-electric-pound-behavior))
+ (save-excursion
+ (skip-chars-backward " \t")
+ (not (bolp)))
+ (save-excursion
+ (and (= (forward-line -1) 0)
+ (progn (end-of-line)
+ (eq (char-before) ?\\))))
+ (c-in-literal)))
;; do nothing special
(self-insert-command (prefix-numeric-value arg))
;; place the pound character at the left edge
(goto-char (- (point-max) pos)))
)))
+(defun c-point-syntax ()
+ ;; Return the syntactic context of the construct at point. (This is NOT
+ ;; nec. the same as the s.c. of the line point is on). N.B. This won't work
+ ;; between the `#' of a cpp thing and what follows (see c-opt-cpp-prefix).
+ (c-save-buffer-state (;; shut this up too
+ (c-echo-syntactic-information-p nil)
+ syntax)
+ (c-tentative-buffer-changes
+ ;; insert a newline to isolate the construct at point for syntactic
+ ;; analysis.
+ (insert-char ?\n 1)
+ ;; In AWK (etc.) or in a macro, make sure this CR hasn't changed
+ ;; the syntax. (There might already be an escaped NL there.)
+ (when (or (c-at-vsemi-p (1- (point)))
+ (let ((pt (point)))
+ (save-excursion
+ (backward-char)
+ (and (c-beginning-of-macro)
+ (progn (c-end-of-macro)
+ (< (point) pt))))))
+ (backward-char)
+ (insert-char ?\\ 1)
+ (forward-char))
+ (let ((c-syntactic-indentation-in-macros t)
+ (c-auto-newline-analysis t))
+ ;; Turn on syntactic macro analysis to help with auto
+ ;; newlines only.
+ (setq syntax (c-guess-basic-syntax))
+ nil))
+ syntax))
+
+(defun c-brace-newlines (syntax)
+ ;; A brace stands at point. SYNTAX is the syntactic context of this brace
+ ;; (not necessarily the same as the S.C. of the line it is on). Return
+ ;; NEWLINES, the list containing some combination of the symbols `before'
+ ;; and `after' saying where newlines should be inserted.
+ (c-save-buffer-state
+ ((syms
+ ;; This is the list of brace syntactic symbols that can hang.
+ ;; If any new ones are added to c-offsets-alist, they should be
+ ;; added here as well.
+ '(class-open class-close defun-open defun-close
+ inline-open inline-close
+ brace-list-open brace-list-close
+ brace-list-intro brace-entry-open
+ block-open block-close
+ substatement-open statement-case-open
+ extern-lang-open extern-lang-close
+ namespace-open namespace-close
+ module-open module-close
+ composition-open composition-close
+ inexpr-class-open inexpr-class-close
+ ;; `statement-cont' is here for the case with a brace
+ ;; list opener inside a statement. C.f. CASE B.2 in
+ ;; `c-guess-continued-construct'.
+ statement-cont))
+ ;; shut this up too
+ (c-echo-syntactic-information-p nil)
+ symb-newlines) ; e.g. (substatement-open . (after))
+
+ (setq symb-newlines
+ ;; Do not try to insert newlines around a special
+ ;; (Pike-style) brace list.
+ (if (and c-special-brace-lists
+ (save-excursion
+ (c-safe (if (= (char-before) ?{)
+ (forward-char -1)
+ (c-forward-sexp -1))
+ (c-looking-at-special-brace-list))))
+ nil
+ ;; Seek the matching entry in c-hanging-braces-alist.
+ (or (c-lookup-lists
+ syms
+ ;; Substitute inexpr-class and class-open or
+ ;; class-close with inexpr-class-open or
+ ;; inexpr-class-close.
+ (if (assq 'inexpr-class syntax)
+ (cond ((assq 'class-open syntax)
+ '((inexpr-class-open)))
+ ((assq 'class-close syntax)
+ '((inexpr-class-close)))
+ (t syntax))
+ syntax)
+ c-hanging-braces-alist)
+ '(ignore before after)))) ; Default, when not in c-h-b-l.
+
+ ;; If syntax is a function symbol, then call it using the
+ ;; defined semantics.
+ (if (and (not (consp (cdr symb-newlines)))
+ (functionp (cdr symb-newlines)))
+ (let ((c-syntactic-context syntax))
+ (funcall (cdr symb-newlines)
+ (car symb-newlines)
+ (point)))
+ (cdr symb-newlines))))
+
+(defun c-try-one-liner ()
+ ;; Point is just after a newly inserted }. If the non-whitespace
+ ;; content of the braces is a single line of code, compact the whole
+ ;; construct to a single line, if this line isn't too long. The Right
+ ;; Thing is done with comments.
+ ;;
+ ;; Point will be left after the }, regardless of whether the clean-up is
+ ;; done. Return NON-NIL if the clean-up happened, NIL if it didn't.
+
+ (let ((here (point))
+ (pos (- (point-max) (point)))
+ mbeg1 mend1 mbeg4 mend4
+ eol-col cmnt-pos cmnt-col cmnt-gap)
+
+ (when
+ (save-excursion
+ (save-restriction
+ ;; Avoid backtracking over a very large block. The one we
+ ;; deal with here can never be more than three lines.
+ (narrow-to-region (save-excursion
+ (forward-line -2)
+ (point))
+ (point))
+ (and (c-safe (c-backward-sexp))
+ (progn
+ (forward-char)
+ (narrow-to-region (point) (1- here)) ; innards of {.}
+ (looking-at
+ (cc-eval-when-compile
+ (concat
+ "\\(" ; (match-beginning 1)
+ "[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL
+ "\\)" ; (match-end 1)
+ "[^ \t\r\n]+\\([ \t]+[^ \t\r\n]+\\)*" ; non-WS
+ "\\(" ; (match-beginning 4)
+ "[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL
+ "\\)\\'"))))))) ; (match-end 4) at EOB.
+
+ (if (c-tentative-buffer-changes
+ (setq mbeg1 (match-beginning 1) mend1 (match-end 1)
+ mbeg4 (match-beginning 4) mend4 (match-end 4))
+ (backward-char) ; back over the `}'
+ (save-excursion
+ (setq cmnt-pos (and (c-backward-single-comment)
+ (- (point) (- mend1 mbeg1)))))
+ (delete-region mbeg4 mend4)
+ (delete-region mbeg1 mend1)
+ (setq eol-col (save-excursion (end-of-line) (current-column)))
+
+ ;; Necessary to put the closing brace before any line
+ ;; oriented comment to keep it syntactically significant.
+ ;; This isn't necessary for block comments, but the result
+ ;; looks nicer anyway.
+ (when cmnt-pos
+ (delete-char 1) ; the `}' has blundered into a comment
+ (goto-char cmnt-pos)
+ (setq cmnt-col (1+ (current-column)))
+ (setq cmnt-pos (1+ cmnt-pos)) ; we're inserting a `}'
+ (c-skip-ws-backward)
+ (insert-char ?\} 1) ; reinsert the `}' before the comment.
+ (setq cmnt-gap (- cmnt-col (current-column)))
+ (when (zerop cmnt-gap)
+ (insert-char ?\ 1) ; Put a space before a bare comment.
+ (setq cmnt-gap 1)))
+
+ (or (null c-max-one-liner-length)
+ (zerop c-max-one-liner-length)
+ (<= eol-col c-max-one-liner-length)
+ ;; Can we trim space before comment to make the line fit?
+ (and cmnt-gap
+ (< (- eol-col cmnt-gap) c-max-one-liner-length)
+ (progn (goto-char cmnt-pos)
+ (backward-delete-char-untabify
+ (- eol-col c-max-one-liner-length))
+ t))))
+ (goto-char (- (point-max) pos))))))
+
(defun c-electric-brace (arg)
"Insert a brace.
-If the auto-newline feature is turned on, as evidenced by the \"/a\"
-or \"/ah\" string on the mode line, newlines are inserted before and
-after braces based on the value of `c-hanging-braces-alist'.
+If `c-electric-flag' is non-nil, the brace is not inside a literal and a
+numeric ARG hasn't been supplied, the command performs several electric
+actions:
-Also, the line is re-indented unless a numeric ARG is supplied, the
-brace is inserted inside a literal, or `c-syntactic-indentation' is
-nil.
+\(a) If the auto-newline feature is turned on (indicated by \"/la\" on
+the mode line) newlines are inserted before and after the brace as
+directed by the settings in `c-hanging-braces-alist'.
+
+\(b) Any auto-newlines are indented. The original line is also
+reindented unless `c-syntactic-indentation' is nil.
+
+\(c) If auto-newline is turned on, various newline cleanups based on the
+settings of `c-cleanup-list' are done."
-This function does various newline cleanups based on the value of
-`c-cleanup-list'."
(interactive "*P")
- (let* ((safepos (c-safe-position (point) (c-parse-state)))
- (literal (c-in-literal safepos))
- ;; We want to inhibit blinking the paren since this will be
- ;; most disruptive. We'll blink it ourselves later on.
- (old-blink-paren blink-paren-function)
- blink-paren-function)
- (cond
- ((or literal arg)
- (self-insert-command (prefix-numeric-value arg)))
- ((not (looking-at "[ \t]*\\\\?$"))
- (self-insert-command (prefix-numeric-value arg))
- (if c-syntactic-indentation
- (indent-according-to-mode)))
- (t
- (let* ((syms
- ;; This is the list of brace syntactic symbols that can
- ;; hang. If any new ones are added to c-offsets-alist,
- ;; they should be added here as well.
- '(class-open class-close defun-open defun-close
- inline-open inline-close
- brace-list-open brace-list-close
- brace-list-intro brace-entry-open
- block-open block-close
- substatement-open statement-case-open
- extern-lang-open extern-lang-close
- namespace-open namespace-close
- module-open module-close
- composition-open composition-close
- inexpr-class-open inexpr-class-close
- ;; `statement-cont' is here for the case with a brace
- ;; list opener inside a statement. C.f. CASE B.2 in
- ;; `c-guess-continued-construct'.
- statement-cont))
- (insertion-point (point))
- (preserve-p (and (not (bobp))
- (eq ?\ (char-syntax (char-before)))))
- ;; shut this up too
- (c-echo-syntactic-information-p nil)
- delete-temp-newline syntax newlines)
- ;; only insert a newline if there is non-whitespace behind us
- (when (save-excursion
- (skip-chars-backward " \t")
- (not (bolp)))
- (c-newline-and-indent)
- ;; Set markers around the newline and indention inserted
- ;; above. We insert the start marker here and not before
- ;; the call to kludge around a misfeature in expand-abbrev:
- ;; If the line contains e.g. "else" then expand-abbrev will
- ;; be called when c-newline-and-indent inserts the newline.
- ;; That function first removes the abbrev "else" and then
- ;; inserts the expansion, which is an identical "else" in
- ;; this case. So the marker that we put after "else" would
- ;; end up before it.
- (setq delete-temp-newline
- (cons (copy-marker (c-point 'eopl) t)
- (point-marker))))
- (unwind-protect
- (progn
- (if (eq last-command-char ?{)
- (setq c-state-cache (cons (point) c-state-cache)))
- (self-insert-command (prefix-numeric-value arg))
- (c-save-buffer-state ((c-syntactic-indentation-in-macros t)
- (c-auto-newline-analysis t))
- ;; Turn on syntactic macro analysis to help with auto
- ;; newlines only.
- (setq syntax (c-guess-basic-syntax)))
- (setq newlines
- (and
- c-auto-newline
- (or (c-lookup-lists
- syms
- ;; Substitute inexpr-class and class-open or
- ;; class-close with inexpr-class-open or
- ;; inexpr-class-close.
- (if (assq 'inexpr-class syntax)
- (cond ((assq 'class-open syntax)
- '((inexpr-class-open)))
- ((assq 'class-close syntax)
- '((inexpr-class-close)))
- (t syntax))
- syntax)
- c-hanging-braces-alist)
- '(ignore before after))))
- ;; Do not try to insert newlines around a special
- ;; (Pike-style) brace list.
- (if (and c-special-brace-lists
- (save-excursion
- (c-save-buffer-state nil
- (c-safe (if (= (char-before) ?{)
- (forward-char -1)
- (c-forward-sexp -1))
- (c-looking-at-special-brace-list)))))
- (setq newlines nil))
- ;; If syntax is a function symbol, then call it using the
- ;; defined semantics.
- (if (and (not (consp (cdr newlines)))
- (functionp (cdr newlines)))
- (let ((c-syntactic-context syntax))
- (setq newlines
- (funcall (cdr newlines)
- (car newlines)
- insertion-point))))
- ;; does a newline go before the open brace?
- (when (memq 'before newlines)
- ;; we leave the newline we've put in there before,
- ;; but we need to re-indent the line above
- (when delete-temp-newline
- (set-marker (car delete-temp-newline) nil)
- (set-marker (cdr delete-temp-newline) nil)
- (setq delete-temp-newline nil))
- (when c-syntactic-indentation
- (let ((pos (- (point-max) (point)))
- (here (point)))
- (forward-line -1)
- (indent-according-to-mode)
- (goto-char (- (point-max) pos))
- ;; if the buffer has changed due to the
- ;; indentation, we need to recalculate syntax for
- ;; the current line.
- (if (/= (point) here)
- (c-save-buffer-state
- ((c-syntactic-indentation-in-macros t)
- (c-auto-newline-analysis t))
- ;; Turn on syntactic macro analysis to help
- ;; with auto newlines only.
- (setq syntax (c-guess-basic-syntax))))))))
- ;; must remove the newline we just stuck in (if we really did it)
- (when delete-temp-newline
- (save-excursion
- (delete-region (car delete-temp-newline)
- (cdr delete-temp-newline))
- (goto-char (car delete-temp-newline))
- (set-marker (car delete-temp-newline) nil)
- (set-marker (cdr delete-temp-newline) nil)
- ;; if there is whitespace before point, then preserve
- ;; at least one space.
- (just-one-space)
- (if (not preserve-p)
- (delete-char -1)))))
- (if (not (memq 'before newlines))
- ;; since we're hanging the brace, we need to recalculate
- ;; syntax.
- (c-save-buffer-state ((c-syntactic-indentation-in-macros t)
- (c-auto-newline-analysis t))
- ;; Turn on syntactic macro analysis to help with auto
- ;; newlines only.
- (setq syntax (c-guess-basic-syntax))))
- (when c-syntactic-indentation
- ;; Now adjust the line's indentation. Don't update the state
- ;; cache since c-guess-basic-syntax isn't called when
- ;; c-syntactic-context is set.
- (let* ((c-syntactic-context syntax))
- (indent-according-to-mode)))
- ;; Do all appropriate clean ups
- (let ((here (point))
- (pos (- (point-max) (point)))
- mbeg mend tmp)
- ;; clean up empty defun braces
- (if (and c-auto-newline
- (memq 'empty-defun-braces c-cleanup-list)
- (eq last-command-char ?\})
- (c-intersect-lists '(defun-close class-close inline-close)
- syntax)
- (progn
- (forward-char -1)
- (c-skip-ws-backward)
- (eq (char-before) ?\{))
- ;; make sure matching open brace isn't in a comment
- (not (c-in-literal)))
- (delete-region (point) (1- here)))
- ;; clean up brace-else-brace and brace-elseif-brace
- (when (and c-auto-newline
- (eq last-command-char ?\{))
- (cond
- ((and (memq 'brace-else-brace c-cleanup-list)
- (re-search-backward
- (concat "}"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "else"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "{")
- nil t)
- (progn
- (setq mbeg (match-beginning 0)
- mend (match-end 0))
- (eq (match-end 0) here)))
- (delete-region mbeg mend)
- (insert-and-inherit "} else {"))
- ((and (memq 'brace-elseif-brace c-cleanup-list)
- (progn
- (goto-char (1- here))
- (setq mend (point))
- (c-skip-ws-backward)
- (setq mbeg (point))
- (eq (char-before) ?\)))
- (zerop (c-save-buffer-state nil (c-backward-token-2 1 t)))
- (eq (char-after) ?\()
- (progn
- (setq tmp (point))
- (re-search-backward
- (concat "}"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "else"
- "\\([ \t\n]\\|\\\\\n\\)+"
- "if"
- "\\([ \t\n]\\|\\\\\n\\)*")
- nil t))
- (eq (match-end 0) tmp))
- (delete-region mbeg mend)
- (goto-char mbeg)
- (insert ?\ ))))
- (goto-char (- (point-max) pos))
- )
- ;; does a newline go after the brace?
- (if (memq 'after newlines)
- (c-newline-and-indent))
- )))
+ (let (safepos literal
+ ;; We want to inhibit blinking the paren since this would be
+ ;; most disruptive. We'll blink it ourselves later on.
+ (old-blink-paren blink-paren-function)
+ blink-paren-function)
+
+ (c-save-buffer-state ()
+ (setq safepos (c-safe-position (point) (c-parse-state))
+ literal (c-in-literal safepos)))
+
+ ;; Insert the brace. Note that expand-abbrev might reindent
+ ;; the line here if there's a preceding "else" or something.
+ (self-insert-command (prefix-numeric-value arg))
+
+ (when (and c-electric-flag (not literal) (not arg))
+ (if (not (looking-at "[ \t]*\\\\?$"))
+ (if c-syntactic-indentation
+ (indent-according-to-mode))
+
+ (let ( ;; shut this up too
+ (c-echo-syntactic-information-p nil)
+ newlines
+ ln-syntax br-syntax syntax) ; Syntactic context of the original line,
+ ; of the brace itself, of the line the brace ends up on.
+ (c-save-buffer-state ((c-syntactic-indentation-in-macros t)
+ (c-auto-newline-analysis t))
+ (setq ln-syntax (c-guess-basic-syntax)))
+ (if c-syntactic-indentation
+ (c-indent-line ln-syntax))
+
+ (when c-auto-newline
+ (backward-char)
+ (setq br-syntax (c-point-syntax)
+ newlines (c-brace-newlines br-syntax))
+
+ ;; Insert the BEFORE newline, if wanted, and reindent the newline.
+ (if (and (memq 'before newlines)
+ (> (current-column) (current-indentation)))
+ (if c-syntactic-indentation
+ ;; Only a plain newline for now - it's indented
+ ;; after the cleanups when the line has its final
+ ;; appearance.
+ (newline)
+ (c-newline-and-indent)))
+ (forward-char)
+
+ ;; `syntax' is the syntactic context of the line which ends up
+ ;; with the brace on it.
+ (setq syntax (if (memq 'before newlines) br-syntax ln-syntax))
+
+ ;; Do all appropriate clean ups
+ (let ((here (point))
+ (pos (- (point-max) (point)))
+ mbeg mend
+ )
+
+ ;; `}': clean up empty defun braces
+ (when (c-save-buffer-state ()
+ (and (memq 'empty-defun-braces c-cleanup-list)
+ (eq last-command-char ?\})
+ (c-intersect-lists '(defun-close class-close inline-close)
+ syntax)
+ (progn
+ (forward-char -1)
+ (c-skip-ws-backward)
+ (eq (char-before) ?\{))
+ ;; make sure matching open brace isn't in a comment
+ (not (c-in-literal))))
+ (delete-region (point) (1- here))
+ (setq here (- (point-max) pos)))
+ (goto-char here)
+
+ ;; `}': compact to a one-liner defun?
+ (save-match-data
+ (when
+ (and (eq last-command-char ?\})
+ (memq 'one-liner-defun c-cleanup-list)
+ (c-intersect-lists '(defun-close) syntax)
+ (c-try-one-liner))
+ (setq here (- (point-max) pos))))
+
+ ;; `{': clean up brace-else-brace and brace-elseif-brace
+ (when (eq last-command-char ?\{)
+ (cond
+ ((and (memq 'brace-else-brace c-cleanup-list)
+ (re-search-backward
+ (concat "}"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "else"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "{"
+ "\\=")
+ nil t))
+ (delete-region (match-beginning 0) (match-end 0))
+ (insert-and-inherit "} else {"))
+ ((and (memq 'brace-elseif-brace c-cleanup-list)
+ (progn
+ (goto-char (1- here))
+ (setq mend (point))
+ (c-skip-ws-backward)
+ (setq mbeg (point))
+ (eq (char-before) ?\)))
+ (zerop (c-save-buffer-state nil (c-backward-token-2 1 t)))
+ (eq (char-after) ?\()
+ ; (progn
+ ; (setq tmp (point))
+ (re-search-backward
+ (concat "}"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "else"
+ "\\([ \t\n]\\|\\\\\n\\)+"
+ "if"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "\\=")
+ nil t);)
+ ;(eq (match-end 0) tmp);
+ )
+ (delete-region mbeg mend)
+ (goto-char mbeg)
+ (insert ?\ ))))
+
+ (goto-char (- (point-max) pos))
+
+ ;; Indent the line after the cleanups since it might
+ ;; very well indent differently due to them, e.g. if
+ ;; c-indent-one-line-block is used together with the
+ ;; one-liner-defun cleanup.
+ (when c-syntactic-indentation
+ (c-indent-line)))
+
+ ;; does a newline go after the brace?
+ (if (memq 'after newlines)
+ (c-newline-and-indent))
+ ))))
+
;; blink the paren
(and (eq last-command-char ?\})
(not executing-kbd-macro)
(defun c-electric-slash (arg)
"Insert a slash character.
+If the slash is inserted immediately after the comment prefix in a c-style
+comment, the comment might get closed by removing whitespace and possibly
+inserting a \"*\". See the variable `c-cleanup-list'.
+
Indent the line as a comment, if:
- 1. The slash is second of a `//' line oriented comment introducing
+ 1. The slash is second of a \"//\" line oriented comment introducing
token and we are on a comment-only-line, or
- 2. The slash is part of a `*/' token that closes a block oriented
+ 2. The slash is part of a \"*/\" token that closes a block oriented
comment.
If a numeric ARG is supplied, point is inside a literal, or
-`c-syntactic-indentation' is nil, indentation is inhibited."
+`c-syntactic-indentation' is nil or `c-electric-flag' is nil, indentation
+is inhibited."
(interactive "*P")
- (let* ((ch (char-before))
- (literal (c-in-literal))
- (indentp (and c-syntactic-indentation
- (not arg)
+ (let ((literal (c-save-buffer-state () (c-in-literal)))
+ indentp
+ ;; shut this up
+ (c-echo-syntactic-information-p nil))
+
+ ;; comment-close-slash cleanup? This DOESN'T need `c-electric-flag' or
+ ;; `c-syntactic-indentation' set.
+ (when (and (not arg)
+ (eq literal 'c)
+ (memq 'comment-close-slash c-cleanup-list)
+ (eq last-command-char ?/)
+ ; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */
+ (save-excursion
+ (back-to-indentation)
+ (looking-at (concat c-current-comment-prefix "[ \t]*$"))))
+ (end-of-line)
+ (delete-horizontal-space)
+ (or (eq (char-before) ?*) (insert-char ?* 1))) ; Do I need a t (retain sticky properties) here?
+
+ (setq indentp (and (not arg)
+ c-syntactic-indentation
+ c-electric-flag
(eq last-command-char ?/)
- (or (and (eq ch ?/)
- (not literal))
- (and (eq ch ?*)
- literal))
- ))
- ;; shut this up
- (c-echo-syntactic-information-p nil))
+ (eq (char-before) (if literal ?* ?/))))
(self-insert-command (prefix-numeric-value arg))
(if indentp
(indent-according-to-mode))))
(defun c-electric-star (arg)
"Insert a star character.
-If the star is the second character of a C style comment introducing
-construct, and we are on a comment-only-line, indent line as comment.
-If a numeric ARG is supplied, point is inside a literal, or
-`c-syntactic-indentation' is nil, indentation is inhibited."
+If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, and
+the star is the second character of a C style comment starter on a
+comment-only-line, indent the line as a comment. If a numeric ARG is
+supplied, point is inside a literal, or `c-syntactic-indentation' is nil,
+this indentation is inhibited."
+
(interactive "*P")
(self-insert-command (prefix-numeric-value arg))
- ;; if we are in a literal, or if arg is given do not re-indent the
+ ;; if we are in a literal, or if arg is given do not reindent the
;; current line, unless this star introduces a comment-only line.
- (if (and c-syntactic-indentation
- (not arg)
- (eq (c-in-literal) 'c)
- (eq (char-before) ?*)
- (save-excursion
- (forward-char -1)
- (skip-chars-backward "*")
- (if (eq (char-before) ?/)
- (forward-char -1))
- (skip-chars-backward " \t")
- (bolp)))
+ (if (c-save-buffer-state ()
+ (and c-syntactic-indentation
+ c-electric-flag
+ (not arg)
+ (eq (c-in-literal) 'c)
+ (eq (char-before) ?*)
+ (save-excursion
+ (forward-char -1)
+ (skip-chars-backward "*")
+ (if (eq (char-before) ?/)
+ (forward-char -1))
+ (skip-chars-backward " \t")
+ (bolp))))
(let (c-echo-syntactic-information-p) ; shut this up
(indent-according-to-mode))
))
(defun c-electric-semi&comma (arg)
"Insert a comma or semicolon.
-When the auto-newline feature is turned on, as evidenced by the \"/a\"
-or \"/ah\" string on the mode line, a newline might be inserted. See
-the variable `c-hanging-semi&comma-criteria' for how newline insertion
-is determined.
-When a semicolon is inserted, the line is re-indented unless a numeric
-arg is supplied, point is inside a literal, or
-`c-syntactic-indentation' is nil.
+If `c-electric-flag' is non-nil, point isn't inside a literal and a
+numeric ARG hasn't been supplied, the command performs several electric
+actions:
+
+\(a) When the auto-newline feature is turned on (indicated by \"/la\" on
+the mode line) a newline might be inserted. See the variable
+`c-hanging-semi&comma-criteria' for how newline insertion is determined.
+
+\(b) Any auto-newlines are indented. The original line is also
+reindented unless `c-syntactic-indentation' is nil.
-Based on the value of `c-cleanup-list', this function cleans up commas
-following brace lists and semicolons following defuns."
+\(c) If auto-newline is turned on, a comma following a brace list or a
+semicolon following a defun might be cleaned up, depending on the
+settings of `c-cleanup-list'."
(interactive "*P")
- (let* ((lim (c-most-enclosing-brace (c-parse-state)))
- (literal (c-in-literal lim))
+ (let* (lim literal c-syntactic-context
(here (point))
;; shut this up
(c-echo-syntactic-information-p nil))
- (if (or literal arg)
- (self-insert-command (prefix-numeric-value arg))
- ;; do some special stuff with the character
- (self-insert-command (prefix-numeric-value arg))
- ;; do all cleanups and newline insertions if c-auto-newline is
- ;; turned on
- (if (or (not c-auto-newline)
- (not (looking-at "[ \t]*\\\\?$")))
- (if c-syntactic-indentation
- (indent-according-to-mode))
- ;; clean ups
- (let ((pos (- (point-max) (point))))
- (if (and (or (and
- (eq last-command-char ?,)
- (memq 'list-close-comma c-cleanup-list))
- (and
- (eq last-command-char ?\;)
- (memq 'defun-close-semi c-cleanup-list)))
- (progn
- (forward-char -1)
- (c-skip-ws-backward)
- (eq (char-before) ?}))
- ;; make sure matching open brace isn't in a comment
- (not (c-in-literal lim)))
- (delete-region (point) here))
- (goto-char (- (point-max) pos)))
- ;; re-indent line
- (if c-syntactic-indentation
- (indent-according-to-mode))
- ;; check to see if a newline should be added
- (let ((criteria c-hanging-semi&comma-criteria)
- answer add-newline-p)
- (while criteria
- (setq answer (funcall (car criteria)))
- ;; only nil value means continue checking
- (if (not answer)
- (setq criteria (cdr criteria))
- (setq criteria nil)
- ;; only 'stop specifically says do not add a newline
- (setq add-newline-p (not (eq answer 'stop)))
- ))
- (if add-newline-p
- (c-newline-and-indent))
- )))))
+
+ (c-save-buffer-state ()
+ (setq lim (c-most-enclosing-brace (c-parse-state))
+ literal (c-in-literal lim)))
+
+ (self-insert-command (prefix-numeric-value arg))
+
+ (if (and c-electric-flag (not literal) (not arg))
+ ;; do all cleanups and newline insertions if c-auto-newline is on.
+ (if (or (not c-auto-newline)
+ (not (looking-at "[ \t]*\\\\?$")))
+ (if c-syntactic-indentation
+ (c-indent-line))
+ ;; clean ups: list-close-comma or defun-close-semi
+ (let ((pos (- (point-max) (point))))
+ (if (c-save-buffer-state ()
+ (and (or (and
+ (eq last-command-char ?,)
+ (memq 'list-close-comma c-cleanup-list))
+ (and
+ (eq last-command-char ?\;)
+ (memq 'defun-close-semi c-cleanup-list)))
+ (progn
+ (forward-char -1)
+ (c-skip-ws-backward)
+ (eq (char-before) ?}))
+ ;; make sure matching open brace isn't in a comment
+ (not (c-in-literal lim))))
+ (delete-region (point) here))
+ (goto-char (- (point-max) pos)))
+ ;; reindent line
+ (when c-syntactic-indentation
+ (setq c-syntactic-context (c-guess-basic-syntax))
+ (c-indent-line c-syntactic-context))
+ ;; check to see if a newline should be added
+ (let ((criteria c-hanging-semi&comma-criteria)
+ answer add-newline-p)
+ (while criteria
+ (setq answer (funcall (car criteria)))
+ ;; only nil value means continue checking
+ (if (not answer)
+ (setq criteria (cdr criteria))
+ (setq criteria nil)
+ ;; only 'stop specifically says do not add a newline
+ (setq add-newline-p (not (eq answer 'stop)))
+ ))
+ (if add-newline-p
+ (c-newline-and-indent))
+ )))))
(defun c-electric-colon (arg)
"Insert a colon.
-If the auto-newline feature is turned on, as evidenced by the \"/a\"
-or \"/ah\" string on the mode line, newlines are inserted before and
-after colons based on the value of `c-hanging-colons-alist'.
+If `c-electric-flag' is non-nil, the colon is not inside a literal and a
+numeric ARG hasn't been supplied, the command performs several electric
+actions:
+
+\(a) If the auto-newline feature is turned on (indicated by \"/la\" on
+the mode line) newlines are inserted before and after the colon based on
+the settings in `c-hanging-colons-alist'.
-Also, the line is re-indented unless a numeric ARG is supplied, the
-colon is inserted inside a literal, or `c-syntactic-indentation' is
-nil.
+\(b) Any auto-newlines are indented. The original line is also
+reindented unless `c-syntactic-indentation' is nil.
+
+\(c) If auto-newline is turned on, whitespace between two colons will be
+\"cleaned up\" leaving a scope operator, if this action is set in
+`c-cleanup-list'."
-This function cleans up double colon scope operators based on the
-value of `c-cleanup-list'."
(interactive "*P")
(let* ((bod (c-point 'bod))
- (literal (c-in-literal bod))
+ (literal (c-save-buffer-state () (c-in-literal bod)))
newlines is-scope-op
;; shut this up
(c-echo-syntactic-information-p nil))
- (cond
- ((or literal arg)
- (self-insert-command (prefix-numeric-value arg)))
- ((not (looking-at "[ \t]*\\\\?$"))
- (self-insert-command (prefix-numeric-value arg))
- (if c-syntactic-indentation
- (indent-according-to-mode)))
- (t
- ;; insert the colon, then do any specified cleanups
- (self-insert-command (prefix-numeric-value arg))
- (let ((pos (- (point-max) (point)))
- (here (point)))
- (if (and c-auto-newline
- (memq 'scope-operator c-cleanup-list)
- (eq (char-before) ?:)
- (progn
- (forward-char -1)
- (c-skip-ws-backward)
- (eq (char-before) ?:))
- (not (c-in-literal))
- (not (eq (char-after (- (point) 2)) ?:)))
- (progn
- (delete-region (point) (1- here))
- (setq is-scope-op t)))
- (goto-char (- (point-max) pos)))
- ;; indent the current line if it's done syntactically.
- (if c-syntactic-indentation
- ;; Cannot use the same syntax analysis as we find below,
- ;; since that's made with c-syntactic-indentation-in-macros
- ;; always set to t.
- (indent-according-to-mode))
- (c-save-buffer-state
- ((c-syntactic-indentation-in-macros t)
- (c-auto-newline-analysis t)
- ;; Turn on syntactic macro analysis to help with auto newlines
- ;; only.
- (syntax (c-guess-basic-syntax))
- (elem syntax))
- ;; Translate substatement-label to label for this operation.
- (while elem
- (if (eq (car (car elem)) 'substatement-label)
- (setcar (car elem) 'label))
- (setq elem (cdr elem)))
- ;; some language elements can only be determined by checking
- ;; the following line. Lets first look for ones that can be
- ;; found when looking on the line with the colon
- (setq newlines
- (and c-auto-newline
- (or (c-lookup-lists '(case-label label access-label)
- syntax c-hanging-colons-alist)
- (c-lookup-lists '(member-init-intro inher-intro)
- (progn
- (insert ?\n)
- (unwind-protect
- (c-guess-basic-syntax)
- (delete-char -1)))
- c-hanging-colons-alist)))))
- ;; does a newline go before the colon? Watch out for already
- ;; non-hung colons. However, we don't unhang them because that
- ;; would be a cleanup (and anti-social).
- (if (and (memq 'before newlines)
- (not is-scope-op)
- (save-excursion
- (skip-chars-backward ": \t")
- (not (bolp))))
- (let ((pos (- (point-max) (point))))
- (forward-char -1)
- (c-newline-and-indent)
- (goto-char (- (point-max) pos))))
- ;; does a newline go after the colon?
- (if (and (memq 'after (cdr-safe newlines))
- (not is-scope-op))
- (c-newline-and-indent))
- ))))
+ (self-insert-command (prefix-numeric-value arg))
+ ;; Any electric action?
+ (if (and c-electric-flag (not literal) (not arg))
+ ;; Unless we're at EOL, only re-indentation happens.
+ (if (not (looking-at "[ \t]*\\\\?$"))
+ (if c-syntactic-indentation
+ (indent-according-to-mode))
+
+ ;; scope-operator clean-up?
+ (let ((pos (- (point-max) (point)))
+ (here (point)))
+ (if (c-save-buffer-state () ; Why do we need this? [ACM, 2003-03-12]
+ (and c-auto-newline
+ (memq 'scope-operator c-cleanup-list)
+ (eq (char-before) ?:)
+ (progn
+ (forward-char -1)
+ (c-skip-ws-backward)
+ (eq (char-before) ?:))
+ (not (c-in-literal))
+ (not (eq (char-after (- (point) 2)) ?:))))
+ (progn
+ (delete-region (point) (1- here))
+ (setq is-scope-op t)))
+ (goto-char (- (point-max) pos)))
+
+ ;; indent the current line if it's done syntactically.
+ (if c-syntactic-indentation
+ ;; Cannot use the same syntax analysis as we find below,
+ ;; since that's made with c-syntactic-indentation-in-macros
+ ;; always set to t.
+ (indent-according-to-mode))
+
+ ;; Calculate where, if anywhere, we want newlines.
+ (c-save-buffer-state
+ ((c-syntactic-indentation-in-macros t)
+ (c-auto-newline-analysis t)
+ ;; Turn on syntactic macro analysis to help with auto newlines
+ ;; only.
+ (syntax (c-guess-basic-syntax))
+ (elem syntax))
+ ;; Translate substatement-label to label for this operation.
+ (while elem
+ (if (eq (car (car elem)) 'substatement-label)
+ (setcar (car elem) 'label))
+ (setq elem (cdr elem)))
+ ;; some language elements can only be determined by checking
+ ;; the following line. Lets first look for ones that can be
+ ;; found when looking on the line with the colon
+ (setq newlines
+ (and c-auto-newline
+ (or (c-lookup-lists '(case-label label access-label)
+ syntax c-hanging-colons-alist)
+ (c-lookup-lists '(member-init-intro inher-intro)
+ (progn
+ (insert ?\n)
+ (unwind-protect
+ (c-guess-basic-syntax)
+ (delete-char -1)))
+ c-hanging-colons-alist)))))
+ ;; does a newline go before the colon? Watch out for already
+ ;; non-hung colons. However, we don't unhang them because that
+ ;; would be a cleanup (and anti-social).
+ (if (and (memq 'before newlines)
+ (not is-scope-op)
+ (save-excursion
+ (skip-chars-backward ": \t")
+ (not (bolp))))
+ (let ((pos (- (point-max) (point))))
+ (forward-char -1)
+ (c-newline-and-indent)
+ (goto-char (- (point-max) pos))))
+ ;; does a newline go after the colon?
+ (if (and (memq 'after (cdr-safe newlines))
+ (not is-scope-op))
+ (c-newline-and-indent))
+ ))))
(defun c-electric-lt-gt (arg)
- "Insert a less-than, or greater-than character.
-The line will be re-indented if the character inserted is the second
-of a C++ style stream operator and the buffer is in C++ mode.
-Exceptions are when a numeric argument is supplied, point is inside a
-literal, or `c-syntactic-indentation' is nil, in which case the line
-will not be re-indented."
+ "Insert a \"<\" or \">\" character.
+If the current language uses angle bracket parens (e.g. template
+arguments in C++), try to find out if the inserted character is a
+paren and give it paren syntax if appropriate.
+
+If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, the
+line will be reindented if the inserted character is a paren or if it
+finishes a C++ style stream operator in C++ mode. Exceptions are when a
+numeric argument is supplied, or the point is inside a literal."
+
(interactive "*P")
- (let ((indentp (and c-syntactic-indentation
- (not arg)
- (eq (char-before) last-command-char)
- (not (c-in-literal))))
- ;; shut this up
- (c-echo-syntactic-information-p nil))
+ (let ((c-echo-syntactic-information-p nil)
+ final-pos close-paren-inserted)
+
(self-insert-command (prefix-numeric-value arg))
- (if indentp
- (indent-according-to-mode))))
+ (setq final-pos (point))
+
+ (c-save-buffer-state (c-parse-and-markup-<>-arglists
+ c-restricted-<>-arglists
+ <-pos)
+
+ (when c-recognize-<>-arglists
+ (if (eq last-command-char ?<)
+ (when (and (progn
+ (backward-char)
+ (= (point)
+ (progn
+ (c-beginning-of-current-token)
+ (point))))
+ (progn
+ (c-backward-token-2)
+ (looking-at c-opt-<>-sexp-key)))
+ (c-mark-<-as-paren (1- final-pos)))
+
+ ;; It's a ">". Check if there's an earlier "<" which either has
+ ;; open paren syntax already or that can be recognized as an arglist
+ ;; together with this ">". Note that this won't work in cases like
+ ;; "template <x, a < b, y>" but they ought to be rare.
+
+ (save-restriction
+ ;; Narrow to avoid that `c-forward-<>-arglist' below searches past
+ ;; our position.
+ (narrow-to-region (point-min) final-pos)
+
+ (while (and
+ (progn
+ (goto-char final-pos)
+ (c-syntactic-skip-backward "^<;}" nil t)
+ (eq (char-before) ?<))
+ (progn
+ (backward-char)
+ ;; If the "<" already got open paren syntax we know we
+ ;; have the matching closer. Handle it and exit the
+ ;; loop.
+ (if (looking-at "\\s\(")
+ (progn
+ (c-mark->-as-paren (1- final-pos))
+ (setq close-paren-inserted t)
+ nil)
+ t))
+
+ (progn
+ (setq <-pos (point))
+ (c-backward-syntactic-ws)
+ (c-simple-skip-symbol-backward))
+ (or (looking-at c-opt-<>-sexp-key)
+ (not (looking-at c-keywords-regexp)))
+
+ (let ((c-parse-and-markup-<>-arglists t)
+ c-restricted-<>-arglists
+ (containing-sexp
+ (c-most-enclosing-brace (c-parse-state))))
+ (when (and containing-sexp
+ (progn (goto-char containing-sexp)
+ (eq (char-after) ?\())
+ (not (eq (get-text-property (point) 'c-type)
+ 'c-decl-arg-start)))
+ (setq c-restricted-<>-arglists t))
+ (goto-char <-pos)
+ (c-forward-<>-arglist nil))
+
+ ;; Loop here if the "<" we found above belongs to a nested
+ ;; angle bracket sexp. When we start over we'll find the
+ ;; previous or surrounding sexp.
+ (if (< (point) final-pos)
+ t
+ (setq close-paren-inserted t)
+ nil)))))))
+ (goto-char final-pos)
+
+ ;; Indent the line if appropriate.
+ (when (and c-electric-flag c-syntactic-indentation)
+ (backward-char)
+ (when (prog1 (or (looking-at "\\s\(\\|\\s\)")
+ (and (c-major-mode-is 'c++-mode)
+ (progn
+ (c-beginning-of-current-token)
+ (looking-at "<<\\|>>"))
+ (= (match-end 0) final-pos)))
+ (goto-char final-pos))
+ (indent-according-to-mode)))
+
+ (when (and close-paren-inserted
+ (not executing-kbd-macro)
+ blink-paren-function)
+ ;; Note: Most paren blink functions, such as the standard
+ ;; `blink-matching-open', currently doesn't handle paren chars
+ ;; marked with text properties very well. Maybe we should avoid
+ ;; this call for the time being?
+ (funcall blink-paren-function))))
(defun c-electric-paren (arg)
"Insert a parenthesis.
-Some newline cleanups are done if appropriate; see the variable
-`c-cleanup-list'.
+If `c-syntactic-indentation' and `c-electric-flag' are both non-nil, the
+line is reindented unless a numeric ARG is supplied, or the parenthesis
+is inserted inside a literal.
+
+Whitespace between a function name and the parenthesis may get added or
+removed; see the variable `c-cleanup-list'.
-Also, the line is re-indented unless a numeric ARG is supplied, the
-parenthesis is inserted inside a literal, or `c-syntactic-indentation'
-is nil."
+Also, if `c-electric-flag' and `c-auto-newline' are both non-nil, some
+newline cleanups are done if appropriate; see the variable `c-cleanup-list'."
(interactive "*P")
- (let ((literal (c-in-literal (c-point 'bod)))
+ (let ((literal (c-save-buffer-state () (c-in-literal)))
;; shut this up
(c-echo-syntactic-information-p nil))
- (if (or arg literal)
- (self-insert-command (prefix-numeric-value arg))
- ;; do some special stuff with the character
- (let* (;; We want to inhibit blinking the paren since this will
- ;; be most disruptive. We'll blink it ourselves
- ;; afterwards.
- (old-blink-paren blink-paren-function)
- blink-paren-function)
- (self-insert-command (prefix-numeric-value arg))
- (if c-syntactic-indentation
- (indent-according-to-mode))
- (when (looking-at "[ \t]*\\\\?$")
- (when c-auto-newline
- ;; Do all appropriate clean ups
- (let ((here (point))
- (pos (- (point-max) (point)))
- mbeg mend)
- ;; clean up brace-elseif-brace
- (if (and (memq 'brace-elseif-brace c-cleanup-list)
- (eq last-command-char ?\()
- (re-search-backward
- (concat "}"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "else"
- "\\([ \t\n]\\|\\\\\n\\)+"
- "if"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "(")
- nil t)
- (save-excursion
- (setq mbeg (match-beginning 0)
- mend (match-end 0))
- (= mend here))
- (not (c-in-literal)))
- (progn
- (delete-region mbeg mend)
- (insert-and-inherit "} else if ("))
- ;; clean up brace-catch-brace
- (goto-char here)
- (if (and (memq 'brace-catch-brace c-cleanup-list)
- (eq last-command-char ?\()
- (re-search-backward
- (concat "}"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "catch"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "(")
- nil t)
- (save-excursion
- (setq mbeg (match-beginning 0)
- mend (match-end 0))
- (= mend here))
- (not (c-in-literal)))
- (progn
- (delete-region mbeg mend)
- (insert-and-inherit "} catch ("))))
- (goto-char (- (point-max) pos))
- )))
- (let (beg (end (1- (point))))
- (cond ((and (memq 'space-before-funcall c-cleanup-list)
- (eq last-command-char ?\()
- (save-excursion
- (backward-char)
- (skip-chars-backward " \t")
- (setq beg (point))
- (c-on-identifier)))
- (save-excursion
- (delete-region beg end)
- (goto-char beg)
- (insert ?\ )))
- ((and (memq 'compact-empty-funcall c-cleanup-list)
- (eq last-command-char ?\))
- (save-excursion
- (c-safe (backward-char 2))
- (when (looking-at "()")
- (setq end (point))
- (skip-chars-backward " \t")
- (setq beg (point))
- (c-on-identifier))))
- (delete-region beg end))))
- (and (not executing-kbd-macro)
- old-blink-paren
- (funcall old-blink-paren))))))
+ (self-insert-command (prefix-numeric-value arg))
+
+ (if (and (not arg) (not literal))
+ (let* ( ;; We want to inhibit blinking the paren since this will
+ ;; be most disruptive. We'll blink it ourselves
+ ;; afterwards.
+ (old-blink-paren blink-paren-function)
+ blink-paren-function)
+ (if (and c-syntactic-indentation c-electric-flag)
+ (indent-according-to-mode))
+
+ ;; If we're at EOL, check for new-line clean-ups.
+ (when (and c-electric-flag c-auto-newline
+ (looking-at "[ \t]*\\\\?$"))
+
+ ;; clean up brace-elseif-brace
+ (when
+ (and (memq 'brace-elseif-brace c-cleanup-list)
+ (eq last-command-char ?\()
+ (re-search-backward
+ (concat "}"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "else"
+ "\\([ \t\n]\\|\\\\\n\\)+"
+ "if"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "("
+ "\\=")
+ nil t)
+ (not (c-save-buffer-state () (c-in-literal))))
+ (delete-region (match-beginning 0) (match-end 0))
+ (insert-and-inherit "} else if ("))
+
+ ;; clean up brace-catch-brace
+ (when
+ (and (memq 'brace-catch-brace c-cleanup-list)
+ (eq last-command-char ?\()
+ (re-search-backward
+ (concat "}"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "catch"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "("
+ "\\=")
+ nil t)
+ (not (c-save-buffer-state () (c-in-literal))))
+ (delete-region (match-beginning 0) (match-end 0))
+ (insert-and-inherit "} catch (")))
+
+ ;; Check for clean-ups at function calls. These two DON'T need
+ ;; `c-electric-flag' or `c-syntactic-indentation' set.
+ ;; Point is currently just after the inserted paren.
+ (let (beg (end (1- (point))))
+ (cond
+
+ ;; space-before-funcall clean-up?
+ ((and (memq 'space-before-funcall c-cleanup-list)
+ (eq last-command-char ?\()
+ (save-excursion
+ (backward-char)
+ (skip-chars-backward " \t")
+ (setq beg (point))
+ (c-save-buffer-state () (c-on-identifier))))
+ (save-excursion
+ (delete-region beg end)
+ (goto-char beg)
+ (insert ?\ )))
+
+ ;; compact-empty-funcall clean-up?
+ ((c-save-buffer-state ()
+ (and (memq 'compact-empty-funcall c-cleanup-list)
+ (eq last-command-char ?\))
+ (save-excursion
+ (c-safe (backward-char 2))
+ (when (looking-at "()")
+ (setq end (point))
+ (skip-chars-backward " \t")
+ (setq beg (point))
+ (c-on-identifier)))))
+ (delete-region beg end))))
+ (and (eq last-input-event ?\))
+ (not executing-kbd-macro)
+ old-blink-paren
+ (funcall old-blink-paren))))))
(defun c-electric-continued-statement ()
"Reindent the current line if appropriate.
The line is reindented if there is nothing but whitespace before the
keyword on the line, the keyword is not inserted inside a literal, and
-`c-syntactic-indentation' is non-nil."
+`c-electric-flag' and `c-syntactic-indentation' are both non-nil."
(let (;; shut this up
(c-echo-syntactic-information-p nil))
- (when (and c-syntactic-indentation
- (not (eq last-command-char ?_))
- (= (save-excursion
- (skip-syntax-backward "w")
- (point))
- (c-point 'boi))
- (not (c-in-literal (c-point 'bod))))
+ (when (c-save-buffer-state ()
+ (and c-electric-flag
+ c-syntactic-indentation
+ (not (eq last-command-char ?_))
+ (= (save-excursion
+ (skip-syntax-backward "w")
+ (point))
+ (c-point 'boi))
+ (not (c-in-literal (c-point 'bod)))))
;; Have to temporarily insert a space so that
;; c-guess-basic-syntax recognizes the keyword. Follow the
;; space with a nonspace to avoid messing up any whitespace
(delete-char -2)))))
\f
-;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus
-;; originally contributed by Terry_Glanfield.Southern@rxuk.xerox.com
(defun c-forward-into-nomenclature (&optional arg)
- "Move forward to end of a nomenclature section or word.
-With arg, do it arg times."
+ "Compatibility alias for `c-forward-subword'."
(interactive "p")
- (let ((case-fold-search nil))
- (if (> arg 0)
- (re-search-forward
- (cc-eval-when-compile
- (concat "\\W*\\([" c-upper "]*[" c-lower c-digit "]*\\)"))
- (point-max) t arg)
- (while (and (< arg 0)
- (re-search-backward
- (cc-eval-when-compile
- (concat
- "\\(\\(\\W\\|[" c-lower c-digit "]\\)[" c-upper "]+"
- "\\|\\W\\w+\\)"))
- (point-min) 0))
- (forward-char 1)
- (setq arg (1+ arg)))))
- (c-keep-region-active))
+ (require 'cc-subword)
+ (c-forward-subword arg))
+(make-obsolete 'c-forward-into-nomenclature 'c-forward-subword)
(defun c-backward-into-nomenclature (&optional arg)
- "Move backward to beginning of a nomenclature section or word.
-With optional ARG, move that many times. If ARG is negative, move
-forward."
+ "Compatibility alias for `c-backward-subword'."
(interactive "p")
- (c-forward-into-nomenclature (- arg))
- (c-keep-region-active))
+ (require 'cc-subword)
+ (c-backward-subword arg))
+(make-obsolete 'c-backward-into-nomenclature 'c-backward-subword)
(defun c-scope-operator ()
"Insert a double colon scope operator at point.
;; following one is chosen instead (if there is any). The end
;; position is at the next line, providing there is one before the
;; declaration.
+ ;;
+ ;; This function might do hidden buffer changes.
(save-excursion
;; Note: Some code duplication in `c-beginning-of-defun' and
(push-mark (cdr decl-limits) nil t))))
\f
+(defun c-in-comment-line-prefix-p ()
+ ;; Point is within a comment. Is it also within a comment-prefix?
+ ;; Space at BOL which precedes a comment-prefix counts as part of it.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (let ((here (point)))
+ (save-excursion
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (and (looking-at c-current-comment-prefix)
+ (/= (match-beginning 0) (match-end 0))
+ (< here (match-end 0))))))
+
+(defun c-narrow-to-comment-innards (range)
+ ;; Narrow to the "inside" of the comment (block) defined by range, as
+ ;; follows:
+ ;;
+ ;; A c-style block comment has its opening "/*" and its closing "*/" (if
+ ;; present) removed. A c++-style line comment retains its opening "//" but
+ ;; has any final NL removed. If POINT is currently outwith these innards,
+ ;; move it to the appropriate boundary.
+ ;;
+ ;; This narrowing simplifies the sentence movement functions, since it
+ ;; eliminates awkward things at the boundaries of the comment (block).
+ ;;
+ ;; This function might do hidden buffer changes.
+ (let* ((lit-type (c-literal-type range))
+ (beg (if (eq lit-type 'c) (+ (car range) 2) (car range)))
+ (end (if (eq lit-type 'c)
+ (if (and (eq (char-before (cdr range)) ?/)
+ (eq (char-before (1- (cdr range))) ?*))
+ (- (cdr range) 2)
+ (point-max))
+ (if (eq (cdr range) (point-max))
+ (point-max)
+ (- (cdr range) 1)))))
+ (if (> (point) end)
+ (goto-char end)) ; This would be done automatically by ...
+ (if (< (point) beg)
+ (goto-char beg)) ; ... narrow-to-region but is not documented.
+ (narrow-to-region beg end)))
+
+(defun c-beginning-of-sentence-in-comment (range)
+ ;; Move backwards to the "beginning of a sentence" within the comment
+ ;; defined by RANGE, a cons of its starting and ending positions. If we
+ ;; find a BOS, return NIL. Otherwise, move point to just before the start
+ ;; of the comment and return T.
+ ;;
+ ;; The BOS is either text which follows a regexp match of sentence-end,
+ ;; or text which is a beginning of "paragraph".
+ ;; Comment-prefixes are treated like WS when calculating BOSes or BOPs.
+ ;;
+ ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+ ;; It is not a general function, but is intended only for calling from
+ ;; c-move-over-sentence. Not all preconditions have been explicitly stated.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (save-match-data
+ (let ((start-point (point)))
+ (save-restriction
+ (c-narrow-to-comment-innards range) ; This may move point back.
+ (let* ((here (point))
+ last
+ (here-filler ; matches WS and comment-prefices at point.
+ (concat "\\=\\(^[ \t]*\\(" c-current-comment-prefix "\\)"
+ "\\|[ \t\n\r\f]\\)*"))
+ (prefix-at-bol-here ; matches WS and prefix at BOL, just before point
+ (concat "^[ \t]*\\(" c-current-comment-prefix "\\)[ \t\n\r\f]*\\="))
+ ;; First, find the previous paragraph start, if any.
+ (par-beg ; point where non-WS/non-prefix text of paragraph starts.
+ (save-excursion
+ (forward-paragraph -1) ; uses cc-mode values of
+ ; paragraph-\(start\|separate\)
+ (if (> (re-search-forward here-filler nil t) here)
+ (goto-char here))
+ (when (>= (point) here)
+ (forward-paragraph -2)
+ (if (> (re-search-forward here-filler nil t) here)
+ (goto-char here)))
+ (point))))
+
+ ;; Now seek successively earlier sentence ends between PAR-BEG and
+ ;; HERE, until the "start of sentence" following it is earlier than
+ ;; HERE, or we hit PAR-BEG. Beware of comment prefices!
+ (while (and (re-search-backward (c-sentence-end) par-beg 'limit)
+ (setq last (point))
+ (goto-char (match-end 0)) ; tentative beginning of sentence
+ (or (>= (point) here)
+ (and (not (bolp)) ; Found a non-blank comment-prefix?
+ (save-excursion
+ (if (re-search-backward prefix-at-bol-here nil t)
+ (/= (match-beginning 1) (match-end 1)))))
+ (progn ; Skip the crud to find a real b-o-s.
+ (if (c-in-comment-line-prefix-p)
+ (beginning-of-line))
+ (re-search-forward here-filler) ; always succeeds.
+ (>= (point) here))))
+ (goto-char last))
+ (re-search-forward here-filler)))
+
+ (if (< (point) start-point)
+ nil
+ (goto-char (car range))
+ t))))
+
+(defun c-end-of-sentence-in-comment (range)
+ ;; Move forward to the "end of a sentence" within the comment defined by
+ ;; RANGE, a cons of its starting and ending positions (enclosing the opening
+ ;; comment delimiter and the terminating */ or newline). If we find an EOS,
+ ;; return NIL. Otherwise, move point to just after the end of the comment
+ ;; and return T.
+ ;;
+ ;; The EOS is just after the non-WS part of the next match of the regexp
+ ;; sentence-end. Typically, this is just after one of [.!?]. If there is
+ ;; no sentence-end match following point, any WS before the end of the
+ ;; comment will count as EOS, providing we're not already in it.
+ ;;
+ ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+ ;; It is not a general function, but is intended only for calling from
+ ;; c-move-over-sentence.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (save-match-data
+ (let ((start-point (point))
+ ;; (lit-type (c-literal-type range)) ; Commented out, 2005/11/23, ACM
+ )
+ (save-restriction
+ (c-narrow-to-comment-innards range) ; This might move point forwards.
+ (let* ((here (point))
+ (par-end ; EOL position of last text in current/next paragraph.
+ (save-excursion
+ ;; The cc-mode values of paragraph-\(start\|separate\), set
+ ;; in c-setup-paragraph-variables, are used in the
+ ;; following.
+ (forward-paragraph 1)
+ (if (eq (preceding-char) ?\n) (forward-char -1))
+ (when (<= (point) here) ; can happen, e.g., when HERE is at EOL.
+ (goto-char here)
+ (forward-paragraph 2)
+ (if (eq (preceding-char) ?\n) (forward-char -1)))
+ (point)))
+
+ last
+ (prefix-at-bol-here
+ (concat "^[ \t]*\\(" c-current-comment-prefix "\\)\\=")))
+ ;; Go forward one "comment-prefix which looks like sentence-end"
+ ;; each time round the following:
+ (while (and (re-search-forward (c-sentence-end) par-end 'limit)
+ (progn
+ (setq last (point))
+ (skip-chars-backward " \t\n")
+ (or (and (not (bolp))
+ (re-search-backward prefix-at-bol-here nil t)
+ (/= (match-beginning 1) (match-end 1)))
+ (<= (point) here))))
+ (goto-char last))
+
+ ;; Take special action if we're up against the end of a comment (of
+ ;; either sort): Leave point just after the last non-ws text.
+ (if (eq (point) (point-max))
+ (while (or (/= (skip-chars-backward " \t\n") 0)
+ (and (re-search-backward prefix-at-bol-here nil t)
+ (/= (match-beginning 1) (match-end 1))))))))
+
+ (if (> (point) start-point)
+ nil
+ (goto-char (cdr range))
+ t))))
+
+(defun c-beginning-of-sentence-in-string (range)
+ ;; Move backwards to the "beginning of a sentence" within the string defined
+ ;; by RANGE, a cons of its starting and ending positions (enclosing the
+ ;; string quotes). If we find a BOS, return NIL. Otherwise, move point to
+ ;; just before the start of the string and return T.
+ ;;
+ ;; The BOS is either the text which follows a regexp match of sentence-end
+ ;; or text which is a beginning of "paragraph". For the purposes of
+ ;; determining paragraph boundaries, escaped newlines are treated as
+ ;; ordinary newlines.
+ ;;
+ ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+ ;; It is not a general function, but is intended only for calling from
+ ;; c-move-over-sentence.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (save-match-data
+ (let* ((here (point)) last
+ (end (1- (cdr range)))
+ (here-filler ; matches WS and escaped newlines at point.
+ "\\=\\([ \t\n\r\f]\\|\\\\[\n\r]\\)*")
+ ;; Enhance paragraph-start and paragraph-separate also to recognise
+ ;; blank lines terminated by escaped EOLs. IT MAY WELL BE that
+ ;; these values should be customizable user options, or something.
+ (paragraph-start c-string-par-start)
+ (paragraph-separate c-string-par-separate)
+
+ (par-beg ; beginning of current (or previous) paragraph.
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (1+ (car range)) end)
+ (forward-paragraph -1) ; uses above values of
+ ; paragraph-\(start\|separate\)
+ (if (> (re-search-forward here-filler nil t) here)
+ (goto-char here))
+ (when (>= (point) here)
+ (forward-paragraph -2)
+ (if (> (re-search-forward here-filler nil t) here)
+ (goto-char here)))
+ (point)))))
+ ;; Now see if we can find a sentence end after PAR-BEG.
+ (while (and (re-search-backward c-sentence-end-with-esc-eol par-beg 'limit)
+ (setq last (point))
+ (goto-char (match-end 0))
+ (or (> (point) end)
+ (progn
+ (re-search-forward
+ here-filler end t) ; always succeeds. Use end rather
+ ; than here, in case point starts
+ ; beyond the closing quote.
+ (>= (point) here))))
+ (goto-char last))
+ (re-search-forward here-filler here t)
+ (if (< (point) here)
+ nil
+ (goto-char (car range))
+ t))))
+
+(defun c-end-of-sentence-in-string (range)
+ ;; Move forward to the "end of a sentence" within the string defined by
+ ;; RANGE, a cons of its starting and ending positions. If we find an EOS,
+ ;; return NIL. Otherwise, move point to just after the end of the string
+ ;; and return T.
+ ;;
+ ;; The EOS is just after the non-WS part of the next match of the regexp
+ ;; sentence-end. Typically, this is just after one of [.!?]. If there is
+ ;; no sentence-end match following point, any WS before the end of the
+ ;; string will count as EOS, providing we're not already in it.
+ ;;
+ ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+ ;; It is not a general function, but is intended only for calling from
+ ;; c-move-over-sentence.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (save-match-data
+ (let* ((here (point))
+ last
+ ;; Enhance paragraph-start and paragraph-separate to recognise
+ ;; blank lines terminated by escaped EOLs.
+ (paragraph-start c-string-par-start)
+ (paragraph-separate c-string-par-separate)
+
+ (par-end ; EOL position of last text in current/next paragraph.
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (car range) (1- (cdr range)))
+ ;; The above values of paragraph-\(start\|separate\) are used
+ ;; in the following.
+ (forward-paragraph 1)
+ (setq last (point))
+ ;; (re-search-backward filler-here nil t) would find an empty
+ ;; string. Therefore we simulate it by the following:
+ (while (or (/= (skip-chars-backward " \t\n\r\f") 0)
+ (re-search-backward "\\\\\\($\\)\\=" nil t)))
+ (unless (> (point) here)
+ (goto-char last)
+ (forward-paragraph 1)
+ (while (or (/= (skip-chars-backward " \t\n\r\f") 0)
+ (re-search-backward "\\\\\\($\\)\\=" nil t))))
+ (point)))))
+ ;; Try to go forward a sentence.
+ (when (re-search-forward c-sentence-end-with-esc-eol par-end 'limit)
+ (setq last (point))
+ (while (or (/= (skip-chars-backward " \t\n") 0)
+ (re-search-backward "\\\\\\($\\)\\=" nil t))))
+ ;; Did we move a sentence, or did we hit the end of the string?
+ (if (> (point) here)
+ nil
+ (goto-char (cdr range))
+ t))))
+
+(defun c-ascertain-preceding-literal ()
+ ;; Point is not in a literal (i.e. comment or string (include AWK regexp)).
+ ;; If a literal is the next thing (aside from whitespace) to be found before
+ ;; point, return a cons of its start.end positions (enclosing the
+ ;; delimiters). Otherwise return NIL.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (save-excursion
+ (c-collect-line-comments
+ (let ((here (point))
+ pos)
+ (if (c-backward-single-comment)
+ (cons (point) (progn (c-forward-single-comment) (point)))
+ (save-restriction
+ ;; to prevent `looking-at' seeing a " at point.
+ (narrow-to-region (point-min) here)
+ (when
+ (or
+ ;; An EOL can act as an "open string" terminator in AWK.
+ (looking-at c-ws*-string-limit-regexp)
+ (and (not (bobp))
+ (progn (backward-char)
+ (looking-at c-string-limit-regexp))))
+ (goto-char (match-end 0)) ; just after the string terminator.
+ (setq pos (point))
+ (c-safe (c-backward-sexp 1) ; move back over the string.
+ (cons (point) pos)))))))))
+
+(defun c-ascertain-following-literal ()
+ ;; Point is not in a literal (i.e. comment or string (include AWK regexp)).
+ ;; If a literal is the next thing (aside from whitespace) following point,
+ ;; return a cons of its start.end positions (enclosing the delimiters).
+ ;; Otherwise return NIL.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (save-excursion
+ (c-collect-line-comments
+ (let (pos)
+ (c-skip-ws-forward)
+ (if (looking-at c-string-limit-regexp) ; string-delimiter.
+ (cons (point) (or (c-safe (progn (c-forward-sexp 1) (point)))
+ (point-max)))
+ (setq pos (point))
+ (if (c-forward-single-comment)
+ (cons pos (point))))))))
+
+(defun c-after-statement-terminator-p () ; Should we pass in LIM here?
+ ;; Does point immediately follow a statement "terminator"? A virtual
+ ;; semicolon is regarded here as such. So is a an opening brace ;-)
+ ;;
+ ;; This function might do hidden buffer changes.
+ (or (save-excursion
+ (backward-char)
+ (and (looking-at "[;{}]")
+ (not (and c-special-brace-lists ; Pike special brace lists.
+ (eq (char-after) ?{)
+ (c-looking-at-special-brace-list)))))
+ (c-at-vsemi-p)
+ ;; The following (for macros) is not strict about exactly where we are
+ ;; wrt white space at the end of the macro. Doesn't seem to matter too
+ ;; much. ACM 2004/3/29.
+ (let (eom)
+ (save-excursion
+ (if (c-beginning-of-macro)
+ (setq eom (progn (c-end-of-macro)
+ (point)))))
+ (when eom
+ (save-excursion
+ (c-forward-comments)
+ (>= (point) eom))))))
+
+(defun c-back-over-illiterals (macro-start)
+ ;; Move backwards over code which isn't a literal (i.e. comment or string),
+ ;; stopping before reaching BOB or a literal or the boundary of a
+ ;; preprocessor statement or the "beginning of a statement". MACRO-START is
+ ;; the position of the '#' beginning the current preprocessor directive, or
+ ;; NIL if we're not in such.
+ ;;
+ ;; Return a cons (A.B), where
+ ;; A is NIL if we moved back to a BOS (and know it), T otherwise (we
+ ;; didn't move, or we hit a literal, or we're not sure about BOS).
+ ;; B is MACRO-BOUNDARY if we are about to cross the boundary out of or
+ ;; into a macro, otherwise LITERAL if we've hit a literal, otherwise NIL
+ ;;
+ ;; The total collection of returned values is as follows:
+ ;; (nil . nil): Found a BOS whilst remaining inside the illiterals.
+ ;; (t . literal): No BOS found: only a comment/string. We _might_ be at
+ ;; a BOS - the caller must check this.
+ ;; (nil . macro-boundary): only happens with non-nil macro-start. We've
+ ;; moved and reached the opening # of the macro.
+ ;; (t . macro-boundary): Every other circumstance in which we're at a
+ ;; macro-boundary. We might be at a BOS.
+ ;;
+ ;; Point is left either at the beginning-of-statement, or at the last non-ws
+ ;; code before encountering the literal/BOB or macro-boundary.
+ ;;
+ ;; Note that this function moves within either preprocessor commands
+ ;; (macros) or normal code, but will not cross a boundary between the two,
+ ;; or between two distinct preprocessor commands.
+ ;;
+ ;; Stop before `{' and after `;', `{', `}' and `};' when not followed by `}'
+ ;; or `)', but on the other side of the syntactic ws. Move by sexps and
+ ;; move into parens. Also stop before `#' when it's at boi on a line.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (save-match-data
+ (let ((here (point))
+ last) ; marks the position of non-ws code, what'll be BOS if, say, a
+ ; semicolon precedes it.
+ (catch 'done
+ (while t ;; We go back one "token" each iteration of the loop.
+ (setq last (point))
+ (cond
+ ;; Stop at the token after a comment.
+ ((c-backward-single-comment) ; Also functions as backwards-ws.
+ (goto-char last)
+ (throw 'done '(t . literal)))
+
+ ;; If we've gone back over a LF, we might have moved into or out of
+ ;; a preprocessor line.
+ ((and (save-excursion
+ (beginning-of-line)
+ (re-search-forward "\\(^\\|[^\\]\\)[\n\r]" last t))
+ (if macro-start
+ (< (point) macro-start)
+ (c-beginning-of-macro)))
+ (goto-char last)
+ ;; Return a car of NIL ONLY if we've hit the opening # of a macro.
+ (throw 'done (cons (or (eq (point) here)
+ (not macro-start))
+ 'macro-boundary)))
+
+ ;; Have we found a virtual semicolon? If so, stop, unless the next
+ ;; statement is where we started from.
+ ((and (c-at-vsemi-p)
+ (< last here)
+ (not (memq (char-after last) '(?\) ?})))) ; we've moved back from ) or }
+ (goto-char last)
+ (throw 'done '(nil . nil)))
+
+ ;; Hit the beginning of the buffer/region?
+ ((bobp)
+ (if (/= here last)
+ (goto-char last))
+ (throw 'done '(nil . nil)))
+
+ ;; Move back a character.
+ ((progn (backward-char) nil))
+
+ ;; Stop at "{" (unless it's a PIKE special brace list.)
+ ((eq (char-after) ?\{)
+ (if (and c-special-brace-lists
+ (c-looking-at-special-brace-list))
+ (skip-syntax-backward "w_") ; Speedup only.
+ (if (/= here last)
+ (goto-char last))
+ (throw 'done '(nil . nil))))
+
+ ;; Have we reached the start of a macro? This always counts as
+ ;; BOS. (N.B. I don't think (eq (point) here) can ever be true
+ ;; here. FIXME!!! ACM 2004/3/29)
+ ((and macro-start (eq (point) macro-start))
+ (throw 'done (cons (eq (point) here) 'macro-boundary)))
+
+ ;; Stop at token just after "}" or ";".
+ ((looking-at "[;}]")
+ ;; If we've gone back over ;, {, or }, we're done.
+ (if (or (= here last)
+ (memq (char-after last) '(?\) ?}))) ; we've moved back from ) or }
+ (if (and (eq (char-before) ?}) ; If };, treat them as a unit.
+ (eq (char-after) ?\;))
+ (backward-char))
+ (goto-char last) ; To the statement starting after the ; or }.
+ (throw 'done '(nil . nil))))
+
+ ;; Stop at the token after a string.
+ ((looking-at c-string-limit-regexp) ; Just gone back over a string terminator?
+ (goto-char last)
+ (throw 'done '(t . literal)))
+
+ ;; Nothing special: go back word characters.
+ (t (skip-syntax-backward "w_")) ; Speedup only.
+ ))))))
+
+(defun c-forward-over-illiterals (macro-end allow-early-stop)
+ ;; Move forwards over code, stopping before reaching EOB or a literal
+ ;; (i.e. a comment/string) or the boundary of a preprocessor statement or
+ ;; the "end of a statement". MACRO-END is the position of the EOL/EOB which
+ ;; terminates the current preprocessor directive, or NIL if we're not in
+ ;; such.
+ ;;
+ ;; ALLOW-EARLY-STOP is non-nil if it is permissible to return without moving
+ ;; forward at all, should we encounter a `{'. This is an ugly kludge, but
+ ;; seems unavoidable. Depending on the context this function is called
+ ;; from, we _sometimes_ need to stop there. Currently (2004/4/3),
+ ;; ALLOW-EARLY-STOP is applied only to open braces, not to virtual
+ ;; semicolons, or anything else.
+ ;;
+ ;; Return a cons (A.B), where
+ ;; A is NIL if we moved forward to an EOS, or stay at one (when
+ ;; ALLOW-EARLY-STOP is set), T otherwise (we hit a literal).
+ ;; B is 'MACRO-BOUNDARY if we are about to cross the boundary out of or
+ ;; into a macro, otherwise 'LITERAL if we've hit a literal, otherwise NIL
+ ;;
+ ;; Point is left either after the end-of-statement, or at the last non-ws
+ ;; code before encountering the literal, or the # of the preprocessor
+ ;; statement, or at EOB [or just after last non-WS stuff??].
+ ;;
+ ;; As a clarification of "after the end-of-statement", if a comment or
+ ;; whitespace follows a completed AWK statement, that statement is treated
+ ;; as ending just after the last non-ws character before the comment.
+ ;;
+ ;; Note that this function moves within either preprocessor commands
+ ;; (macros) or normal code, but not both within the same invocation.
+ ;;
+ ;; Stop before `{', `}', and `#' when it's at boi on a line, but on the
+ ;; other side of the syntactic ws, and after `;', `}' and `};'. Only
+ ;; stop before `{' if at top level or inside braces, though. Move by
+ ;; sexps and move into parens. Also stop at eol of lines with `#' at
+ ;; the boi.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (let ((here (point))
+ last)
+ (catch 'done
+ (while t ;; We go one "token" forward each time round this loop.
+ (setq last (point))
+
+ ;; If we've moved forward to a virtual semicolon, we're done.
+ (if (and (> last here) ; Should we check ALLOW-EARLY-STOP, here? 2004/4/3
+ (c-at-vsemi-p))
+ (throw 'done '(nil . nil)))
+
+ (c-skip-ws-forward)
+ (cond
+ ;; Gone past the end of a macro?
+ ((and macro-end (> (point) macro-end))
+ (goto-char last)
+ (throw 'done (cons (eq (point) here) 'macro-boundary)))
+
+ ;; About to hit a comment?
+ ((save-excursion (c-forward-single-comment))
+ (goto-char last)
+ (throw 'done '(t . literal)))
+
+ ;; End of buffer?
+ ((eobp)
+ (if (/= here last)
+ (goto-char last))
+ (throw 'done '(nil . nil)))
+
+ ;; If we encounter a '{', stop just after the previous token.
+ ((and (eq (char-after) ?{)
+ (not (and c-special-brace-lists
+ (c-looking-at-special-brace-list)))
+ (or allow-early-stop (/= here last))
+ (save-excursion ; Is this a check that we're NOT at top level?
+;;;; NO! This seems to check that (i) EITHER we're at the top level; OR (ii) The next enclosing
+;;;; level of bracketing is a '{'. HMM. Doesn't seem to make sense.
+;;;; 2003/8/8 This might have something to do with the GCC extension "Statement Expressions", e.g.
+;;;; while ({stmt1 ; stmt2 ; exp ;}). This form excludes such Statement Expressions.
+ (or (not (c-safe (up-list -1) t))
+ (= (char-after) ?{))))
+ (goto-char last)
+ (throw 'done '(nil . nil)))
+
+ ;; End of a PIKE special brace list? If so, step over it and continue.
+ ((and c-special-brace-lists
+ (eq (char-after) ?})
+ (save-excursion
+ (and (c-safe (up-list -1) t)
+ (c-looking-at-special-brace-list))))
+ (forward-char)
+ (skip-syntax-forward "w_")) ; Speedup only.
+
+ ;; Have we got a '}' after having moved? If so, stop after the
+ ;; previous token.
+ ((and (eq (char-after) ?})
+ (/= here last))
+ (goto-char last)
+ (throw 'done '(nil . nil)))
+
+ ;; Stop if we encounter a preprocessor line.
+ ((and (not macro-end)
+ (eq (char-after) ?#)
+ (= (point) (c-point 'boi)))
+ (goto-char last)
+ ;(throw 'done (cons (eq (point) here) 'macro-boundary))) ; Changed 2003/3/26
+ (throw 'done '(t . macro-boundary)))
+
+ ;; Stop after a ';', '}', or "};"
+ ((looking-at ";\\|};?")
+ (goto-char (match-end 0))
+ (throw 'done '(nil . nil)))
+
+ ;; Found a string (this subsumes AWK regexps)?
+ ((looking-at c-string-limit-regexp)
+ (goto-char last)
+ (throw 'done '(t . literal)))
+
+ (t
+ (forward-char) ; Can't fail - we checked (eobp) earlier on.
+ (skip-syntax-forward "w_") ; Speedup only.
+ (when (and macro-end (> (point) macro-end))
+ (goto-char last)
+ (throw 'done (cons (eq (point) here) 'macro-boundary))))
+ )))))
+
+(defun c-one-line-string-p (range)
+ ;; Is the literal defined by RANGE a string contained in a single line?
+ ;;
+ ;; This function might do hidden buffer changes.
+ (save-excursion
+ (goto-char (car range))
+ (and (looking-at c-string-limit-regexp)
+ (progn (skip-chars-forward "^\n" (cdr range))
+ (eq (point) (cdr range))))))
+
(defun c-beginning-of-statement (&optional count lim sentence-flag)
"Go to the beginning of the innermost C statement.
With prefix arg, go back N - 1 statements. If already at the
to search for the syntactic context, and a flag saying whether to do
sentence motion in or near comments and multiline strings.
-Note that `c-beginning-of-statement-1' is usually better to use from
-programs. It has much more well defined semantics than this one,
-which is intended for interactive use and might therefore change to be
-more \"DWIM:ey\"."
+Note that for use in programs, `c-beginning-of-statement-1' is
+usually better. It has much better defined semantics than this one,
+which is intended for interactive use, and might therefore change to
+be more \"DWIM:ey\"."
(interactive (list (prefix-numeric-value current-prefix-arg)
nil t))
- (c-save-buffer-state
- ((count (or count 1))
- here
- (range (c-collect-line-comments (c-literal-limits lim))))
- (while (and (/= count 0)
- (or (not lim) (> (point) lim)))
- (setq here (point))
- (if (and (not range) sentence-flag)
- (save-excursion
- ;; Find the comment next to point if we're not in one.
- (if (> count 0)
- (if (c-backward-single-comment)
- (setq range (cons (point)
- (progn (c-forward-single-comment)
- (point))))
- (c-skip-ws-backward)
- (setq range (point))
- (setq range
- (if (eq (char-before) ?\")
- (c-safe (c-backward-sexp 1)
- (cons (point) range)))))
- (c-skip-ws-forward)
- (if (eq (char-after) ?\")
- (setq range (cons (point)
- (progn
- (c-forward-sexp 1)
- (point))))
- (setq range (point))
- (setq range (if (c-forward-single-comment)
- (cons range (point))
- nil))))
- (setq range (c-collect-line-comments range))))
- (if (and (< count 0) (= here (point-max)))
- ;; Special case because eob might be in a literal.
- (setq range nil))
- (if range
- (if (and sentence-flag
- (or (/= (char-syntax (char-after (car range))) ?\")
- ;; Only visit a string if it spans more than one line.
- (save-excursion
- (goto-char (car range))
- (skip-chars-forward "^\n" (cdr range))
- (< (point) (cdr range)))))
- (let* ((lit-type (c-literal-type range))
- (line-prefix (concat "[ \t]*\\("
- c-current-comment-prefix
- "\\)[ \t]*"))
- (beg (if (eq lit-type 'string)
- (1+ (car range))
- (save-excursion
- (goto-char (car range))
- (max (progn
- (looking-at comment-start-skip)
- (match-end 0))
- (progn
- (looking-at line-prefix)
- (match-end 0))))))
- (end (- (cdr range) (if (eq lit-type 'c) 2 1)))
- (beg-of-para (if (eq lit-type 'string)
- (lambda ())
- (lambda ()
- (beginning-of-line)
- (if (looking-at line-prefix)
- (goto-char (match-end 0)))))))
- (save-restriction
- ;; Move by sentence, but not past the limit of the
- ;; literal, narrowed to the appropriate
- ;; paragraph(s).
- (narrow-to-region (save-excursion
- (let ((pos (min here end)))
- (goto-char pos)
- (forward-paragraph -1)
- (if (looking-at paragraph-separate)
- (forward-line))
- (when (> (point) beg)
- (funcall beg-of-para)
- (when (>= (point) pos)
- (forward-paragraph -2)
- (funcall beg-of-para)))
- (max (point) beg)))
- end)
- (c-safe (forward-sentence (if (< count 0) 1 -1)))
- (if (and (memq lit-type '(c c++))
- ;; Check if we stopped due to a comment
- ;; prefix and not a sentence end.
- (/= (point) (point-min))
- (/= (point) (point-max))
- (save-excursion
- (beginning-of-line)
- (looking-at line-prefix))
- (>= (point) (match-beginning 0))
- (/= (match-beginning 1) (match-end 1))
- (or (< (point) (match-end 0))
- (and
- (= (point) (match-end 0))
- ;; The comment prefix may contain
- ;; characters that is regarded as end
- ;; of sentence.
- (or (eolp)
- (and
- (save-excursion
- (forward-paragraph -1)
- (< (point) (match-beginning 0)))
- (save-excursion
- (beginning-of-line)
- (or (not (re-search-backward
- sentence-end
- (c-point 'bopl)
- t))
- (< (match-end 0)
- (c-point 'eol)))))))))
- (setq count (+ count (if (< count 0) -1 1)))
- (if (< count 0)
- (progn
- ;; In block comments, if there's only
- ;; horizontal ws between the text and the
- ;; comment ender, stop before it. Stop after
- ;; the ender if there's either nothing or
- ;; newlines between.
- (when (and (eq lit-type 'c)
- (eq (point) (point-max)))
- (widen)
- (when (or (= (skip-chars-backward " \t") 0)
- (eq (point) (point-max))
- (bolp))
- (goto-char (cdr range)))))
- (when (and (eq (point) (point-min))
- (looking-at "[ \t]*\\\\?$"))
- ;; Stop before instead of after the comment
- ;; starter if nothing follows it.
- (widen)
- (goto-char (car range))
- (if (and (eq lit-type 'string) (/= (point) here))
- (setq count (1+ count)
- range nil))))))
- ;; See if we should escape the literal.
- (if (> count 0)
- (if (< (point) here)
- (setq count (1- count))
- (goto-char (car range))
- (setq range nil))
- (if (> (point) here)
- (setq count (1+ count))
- (goto-char (cdr range))
- (setq range nil))))
- (goto-char (if (> count 0) (car range) (cdr range)))
- (setq range nil))
- (goto-char here)
- (if (> count 0)
- (condition-case nil
- ;; Stop before `{' and after `;', `{', `}' and `};'
- ;; when not followed by `}' or `)', but on the other
- ;; side of the syntactic ws. Move by sexps and move
- ;; into parens. Also stop before `#' when it's at boi
- ;; on a line.
- (let ((literal-pos (not sentence-flag))
- last last-below-line)
- (catch 'done
- (while t
- (setq last (point))
- (when (and (or (eq (char-after) ?\{)
- (and (eq (char-after) ?#)
- (eq (point) (c-point 'boi)))
- )
- (/= here last))
- (unless (and c-special-brace-lists
- (eq (char-after) ?{)
- (c-looking-at-special-brace-list))
- (if (and (eq (char-after) ?#)
- (numberp last-below-line)
- (not (eq last-below-line here)))
- (goto-char last-below-line))
- (throw 'done t)))
- ;; Don't know why I added the following, but it
- ;; doesn't work when point is preceded by a line
- ;; style comment. /mast
- ;;(c-skip-ws-backward)
- (if literal-pos
- (c-backward-comments)
- (when (c-backward-single-comment)
- ;; Record position of first comment.
- (save-excursion
- (c-forward-single-comment)
- (setq literal-pos (point)))
- (c-backward-comments)))
- (unless last-below-line
- (if (save-excursion
- (re-search-forward "\\(^\\|[^\\]\\)$" last t))
- (setq last-below-line last)))
- (cond ((bobp) ; Must handle bob specially.
- (if (= here last)
- (throw 'done t)
- (goto-char last)
- (throw 'done t)))
- ((progn (backward-char)
- (looking-at "[;{}]"))
- (if (and c-special-brace-lists
- (eq (char-after) ?{)
- (c-looking-at-special-brace-list))
- (skip-syntax-backward "w_") ; Speedup only.
- (if (or (= here last)
- (memq (char-after last) '(?\) ?})))
- (if (and (eq (char-before) ?})
- (eq (char-after) ?\;))
- (backward-char))
- (goto-char last)
- (throw 'done t))))
- ((= (char-syntax (char-after)) ?\")
- (let ((end (point)))
- (forward-char)
- (c-backward-sexp)
- (save-excursion
- (skip-chars-forward "^\n" end)
- (when (< (point) end)
- ;; Break at multiline string.
- (setq literal-pos (1+ end))
- (throw 'done t)))))
- (t (skip-syntax-backward "w_")) ; Speedup only.
- )))
- (if (and (numberp literal-pos)
- (< (point) literal-pos))
- ;; We jumped over a comment or string that
- ;; should be investigated.
- (goto-char literal-pos)
- (setq count (1- count))))
- (error
- (goto-char (point-min))
- (setq count 0)))
- (condition-case nil
- ;; Stop before `{', `}', and `#' when it's at boi on a
- ;; line, but on the other side of the syntactic ws, and
- ;; after `;', `}' and `};'. Only stop before `{' if at
- ;; top level or inside braces, though. Move by sexps
- ;; and move into parens. Also stop at eol of lines
- ;; with `#' at the boi.
- (let ((literal-pos (not sentence-flag))
- last)
- (catch 'done
- (while t
- (setq last (point))
- (if literal-pos
- (c-forward-comments)
- (if (progn
- (c-skip-ws-forward)
- ;; Record position of first comment.
- (setq literal-pos (point))
- (c-forward-single-comment))
- (c-forward-comments)
- (setq literal-pos nil)))
- (cond ((and (eq (char-after) ?{)
- (not (and c-special-brace-lists
- (c-looking-at-special-brace-list)))
- (/= here last)
- (save-excursion
- (or (not (c-safe (up-list -1) t))
- (= (char-after) ?{))))
- (goto-char last)
- (throw 'done t))
- ((and c-special-brace-lists
- (eq (char-after) ?})
- (save-excursion
- (and (c-safe (up-list -1) t)
- (c-looking-at-special-brace-list))))
- (forward-char 1)
- (skip-syntax-forward "w_")) ; Speedup only.
- ((and (eq (char-after) ?})
- (/= here last))
- (goto-char last)
- (throw 'done t))
-; ((and (eq (char-after) ?#)
-; (= (point) (c-point 'boi)))
-; (if (= here last)
-; (or (re-search-forward "\\(^\\|[^\\]\\)$" nil t)
-; (goto-char (point-max)))
-; (goto-char last))
-; (throw 'done t))
- ((looking-at ";\\|};?")
- (goto-char (match-end 0))
- (throw 'done t))
- ((= (char-syntax (char-after)) ?\")
- (let ((beg (point)))
- (c-forward-sexp)
- (save-excursion
- (skip-chars-backward "^\n" beg)
- (when (> (point) beg)
- ;; Break at multiline string.
- (setq literal-pos beg)
- (throw 'done t)))))
- (t
- (forward-char 1)
- (skip-syntax-forward "w_")) ; Speedup only.
- )))
- (if (and (numberp literal-pos)
- (> (point) literal-pos))
- ;; We jumped over a comment that should be investigated.
- (goto-char literal-pos)
- (setq count (1+ count))))
- (error
- (goto-char (point-max))
- (setq count 0)))
- ))
- ;; If we haven't moved we're near a buffer limit.
- (when (and (not (zerop count)) (= (point) here))
- (goto-char (if (> count 0) (point-min) (point-max)))
- (setq count 0))))
- (c-keep-region-active))
+ (if (< count 0)
+ (c-end-of-statement (- count) lim sentence-flag)
+ (c-save-buffer-state
+ ((count (or count 1))
+ last ; start point for going back ONE chunk. Updated each chunk movement.
+ (macro-fence
+ (save-excursion (and (not (bobp)) (c-beginning-of-macro) (point))))
+ res ; result from sub-function call
+ not-bos ; "not beginning-of-statement"
+ (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL
+
+ ;; Go back one statement at each iteration of the following loop.
+ (while (and (/= count 0)
+ (or (not lim) (> (point) lim)))
+ ;; Go back one "chunk" each time round the following loop, stopping
+ ;; when we reach a statement boundary, etc.
+ (setq last (point))
+ (while
+ (cond ; Each arm of this cond returns NIL on reaching a desired
+ ; statement boundary, non-NIL otherwise.
+ ((bobp)
+ (setq count 0)
+ nil)
+
+ (range ; point is within or approaching a literal.
+ (cond
+ ;; Single line string or sentence-flag is null => skip the
+ ;; entire literal.
+ ((or (null sentence-flag)
+ (c-one-line-string-p range))
+ (goto-char (car range))
+ (setq range (c-ascertain-preceding-literal))
+ ;; N.B. The following is essentially testing for an AWK regexp
+ ;; at BOS:
+ ;; Was the previous non-ws thing an end of statement?
+ (save-excursion
+ (if macro-fence
+ (c-backward-comments)
+ (c-backward-syntactic-ws))
+ (not (or (bobp) (c-after-statement-terminator-p)))))
+
+ ;; Comment inside a statement or a multi-line string.
+ (t (when (setq res ; returns non-nil when we go out of the literal
+ (if (eq (c-literal-type range) 'string)
+ (c-beginning-of-sentence-in-string range)
+ (c-beginning-of-sentence-in-comment range)))
+ (setq range (c-ascertain-preceding-literal)))
+ res)))
+
+ ;; Non-literal code.
+ (t (setq res (c-back-over-illiterals macro-fence))
+ (setq not-bos ; "not reached beginning-of-statement".
+ (or (= (point) last)
+ (memq (char-after) '(?\) ?\}))
+ (and
+ (car res)
+ ;; We're at a tentative BOS. The next form goes
+ ;; back over WS looking for an end of previous
+ ;; statement.
+ (not (save-excursion
+ (if macro-fence
+ (c-backward-comments)
+ (c-backward-syntactic-ws))
+ (or (bobp) (c-after-statement-terminator-p)))))))
+ ;; Are we about to move backwards into or out of a
+ ;; preprocessor command? If so, locate it's beginning.
+ (when (eq (cdr res) 'macro-boundary)
+ (save-excursion
+ (beginning-of-line)
+ (setq macro-fence
+ (and (not (bobp))
+ (progn (c-skip-ws-backward) (c-beginning-of-macro))
+ (point)))))
+ ;; Are we about to move backwards into a literal?
+ (when (memq (cdr res) '(macro-boundary literal))
+ (setq range (c-ascertain-preceding-literal)))
+ not-bos))
+ (setq last (point)))
+
+ (if (/= count 0) (setq count (1- count))))
+ (c-keep-region-active))))
(defun c-end-of-statement (&optional count lim sentence-flag)
"Go to the end of the innermost C statement.
sentence motion in or near comments and multiline strings."
(interactive (list (prefix-numeric-value current-prefix-arg)
nil t))
- (c-beginning-of-statement (- (or count 1)) lim sentence-flag)
- (c-keep-region-active))
+ (setq count (or count 1))
+ (if (< count 0) (c-beginning-of-statement (- count) lim sentence-flag)
+
+ (c-save-buffer-state
+ (here ; start point for going forward ONE statement. Updated each statement.
+ (macro-fence
+ (save-excursion
+ (and (not (eobp)) (c-beginning-of-macro)
+ (progn (c-end-of-macro) (point)))))
+ res
+ (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL
+
+ ;; Go back/forward one statement at each iteration of the following loop.
+ (while (and (/= count 0)
+ (or (not lim) (< (point) lim)))
+ (setq here (point)) ; ONLY HERE is HERE updated
+
+ ;; Go forward one "chunk" each time round the following loop, stopping
+ ;; when we reach a statement boundary, etc.
+ (while
+ (cond ; Each arm of this cond returns NIL on reaching a desired
+ ; statement boundary, non-NIL otherwise.
+ ((eobp)
+ (setq count 0)
+ nil)
+
+ (range ; point is within a literal.
+ (cond
+ ;; sentence-flag is null => skip the entire literal.
+ ;; or a Single line string.
+ ((or (null sentence-flag)
+ (c-one-line-string-p range))
+ (goto-char (cdr range))
+ (setq range (c-ascertain-following-literal))
+ ;; Is there a virtual semicolon here (e.g. for AWK)?
+ (not (c-at-vsemi-p)))
+
+ ;; Comment or multi-line string.
+ (t (when (setq res ; gets non-nil when we go out of the literal
+ (if (eq (c-literal-type range) 'string)
+ (c-end-of-sentence-in-string range)
+ (c-end-of-sentence-in-comment range)))
+ (setq range (c-ascertain-following-literal)))
+ ;; If we've just come forward out of a literal, check for
+ ;; vsemi. (N.B. AWK can't have a vsemi after a comment, but
+ ;; some other language may do in the future)
+ (and res
+ (not (c-at-vsemi-p))))))
+
+ ;; Non-literal code.
+ (t (setq res (c-forward-over-illiterals macro-fence
+ (> (point) here)))
+ ;; Are we about to move forward into or out of a
+ ;; preprocessor command?
+ (when (eq (cdr res) 'macro-boundary)
+ (save-excursion
+ (end-of-line)
+ (setq macro-fence
+ (and (not (eobp))
+ (progn (c-skip-ws-forward)
+ (c-beginning-of-macro))
+ (progn (c-end-of-macro)
+ (point))))))
+ ;; Are we about to move forward into a literal?
+ (when (memq (cdr res) '(macro-boundary literal))
+ (setq range (c-ascertain-following-literal)))
+ (car res))))
+
+ (if (/= count 0) (setq count (1- count))))
+ (c-keep-region-active))))
+
\f
;; set up electric character functions to work with pending-del,
\f
(defun c-calc-comment-indent (entry)
+ ;; This function might do hidden buffer changes.
(if (symbolp entry)
(setq entry (or (assq entry c-indent-comment-alist)
(assq 'other c-indent-comment-alist)
(let ((lim (c-literal-limits (c-point 'bol) t)))
(when (consp lim)
(goto-char (car lim))
- (when (looking-at "/[/*]")
+ (when (looking-at "/[/*]") ; FIXME!!! Adapt for AWK! (ACM, 2005/11/18)
;; Found comment to align with.
(if (bolp)
;; Do not pad with one space if we're at bol.
A prefix argument acts as a repeat count. With a negative argument,
move forward to the end of the containing preprocessor conditional.
-`#elif' is treated like `#else' followed by `#if', so the function
-stops at them when going backward, but not when going forward."
+\"#elif\" is treated like \"#else\" followed by \"#if\", so the
+function stops at them when going backward, but not when going
+forward."
(interactive "p")
(c-forward-conditional (- count) -1)
(c-keep-region-active))
(defun c-up-conditional-with-else (count)
- "Move back to the containing preprocessor conditional, including `#else'.
-Just like `c-up-conditional', except it also stops at `#else'
+ "Move back to the containing preprocessor conditional, including \"#else\".
+Just like `c-up-conditional', except it also stops at \"#else\"
directives."
(interactive "p")
(c-forward-conditional (- count) -1 t)
A prefix argument acts as a repeat count. With a negative argument,
move backward into the previous preprocessor conditional.
-`#elif' is treated like `#else' followed by `#if', so the function
-stops at them when going forward, but not when going backward."
+\"#elif\" is treated like \"#else\" followed by \"#if\", so the
+function stops at them when going forward, but not when going
+backward."
(interactive "p")
(c-forward-conditional count 1)
(c-keep-region-active))
(defun c-down-conditional-with-else (count)
- "Move forward into the next preprocessor conditional, including `#else'.
-Just like `c-down-conditional', except it also stops at `#else'
+ "Move forward into the next preprocessor conditional, including \"#else\".
+Just like `c-down-conditional', except it also stops at \"#else\"
directives."
(interactive "p")
(c-forward-conditional count 1 t)
A prefix argument acts as a repeat count. With a negative argument,
move backward across a preprocessor conditional.
-`#elif' is treated like `#else' followed by `#if', except that the
-nesting level isn't changed when tracking subconditionals.
+\"#elif\" is treated like \"#else\" followed by \"#if\", except that
+the nesting level isn't changed when tracking subconditionals.
The optional argument TARGET-DEPTH specifies the wanted nesting depth
after each scan. I.e. if TARGET-DEPTH is -1, the function will move
out of the enclosing conditional. A non-integer non-nil TARGET-DEPTH
counts as -1.
-If the optional argument WITH-ELSE is non-nil, `#else' directives are
-treated as conditional clause limits. Normally they are ignored."
+If the optional argument WITH-ELSE is non-nil, \"#else\" directives
+are treated as conditional clause limits. Normally they are ignored."
(interactive "p")
(let* ((forward (> count 0))
(increment (if forward -1 1))
If nil, indent the current line only if point is at the left margin or
in the line's indentation; otherwise insert some whitespace[*]. If
other than nil or t, then some whitespace[*] is inserted only within
-literals (comments and strings) and inside preprocessor directives,
-but the line is always reindented.
+literals (comments and strings), but the line is always reindented.
If `c-syntactic-indentation' is t, indentation is done according to
the syntactic context. A numeric argument, regardless of its value,
just inserts a tab character, or the equivalent number of spaces,
depending on the variable `indent-tabs-mode'."
- (interactive "p")
+ (interactive "P")
(let ((indent-function
(if c-syntactic-indentation
(symbol-function 'indent-according-to-mode)
(lambda ()
(let ((c-macro-start c-macro-start)
- (steps (cond ((not current-prefix-arg) 1)
- ((equal current-prefix-arg '(4)) -1)
- (t arg))))
+ (steps (if (equal arg '(4))
+ -1
+ (prefix-numeric-value arg))))
(c-shift-line-indentation (* steps c-basic-offset))
(when (and c-auto-align-backslashes
(save-excursion
;; Realign the line continuation backslash if inside a macro.
(c-backslash-region (point) (point) nil t)))
))))
- (if (and c-syntactic-indentation current-prefix-arg)
+ (if (and c-syntactic-indentation arg)
;; If c-syntactic-indentation and got arg, always indent this
;; line as C and shift remaining lines of expression the same
;; amount.
shift-amt))
(save-excursion
(if (eq c-tab-always-indent t)
- (beginning-of-line))
+ (beginning-of-line)) ; FIXME!!! What is this here for? ACM 2005/10/31
(setq beg (point))
(c-forward-sexp 1)
(setq end (point))
(indent-code-rigidly beg end shift-amt "#")))
;; Else use c-tab-always-indent to determine behavior.
(cond
- ;; CASE 1: indent when at column zero or in lines indentation,
+ ;; CASE 1: indent when at column zero or in line's indentation,
;; otherwise insert a tab
((not c-tab-always-indent)
(if (save-excursion
;; CASE 3: if in a literal, insert a tab, but always indent the
;; line
(t
- (if (c-in-literal)
+ (if (c-save-buffer-state () (c-in-literal))
(funcall c-insert-tab-function))
(funcall indent-function)
)))))
;; shut up any echo msgs on indiv lines
(c-echo-syntactic-information-p nil)
(in-macro (and c-auto-align-backslashes
- (save-excursion (c-beginning-of-macro))
+ (c-save-buffer-state ()
+ (save-excursion (c-beginning-of-macro)))
start))
(c-fix-backslashes nil)
syntax)
(defun c-fn-region-is-active-p ()
;; Function version of the macro for use in places that aren't
;; compiled, e.g. in the menus.
- ;;
- ;; This function does not do any hidden buffer changes.
(c-region-is-active-p))
(defun c-indent-line-or-region ()
(defvar c-progress-info nil)
(defun c-progress-init (start end context)
- ;; This function does not do any hidden buffer changes.
(cond
;; Be silent
((not c-progress-interval))
))
(defun c-progress-update ()
- ;; This function does not do any hidden buffer changes.
(if (not (and c-progress-info c-progress-interval))
nil
(let ((now (nth 1 (current-time)))
)))
(defun c-progress-fini (context)
- ;; This function does not do any hidden buffer changes.
(if (not c-progress-interval)
nil
(if (or (eq context (aref c-progress-info 3))
(set-marker point-pos nil))))
(defun c-append-backslashes-forward (to-mark column point-pos)
- ;; This function does not do any hidden buffer changes.
(let ((state (parse-partial-sexp (c-point 'bol) (point))))
(if column
(while
(delete-region (point) end)
(indent-to column 1)))
- (= (forward-line 1) 0))))
+ (zerop (forward-line 1)))
+ (bolp))) ; forward-line has funny behavior at eob.
;; Make sure there are backslashes with at least one space in
;; front of them.
(insert ?\\)
(insert ?\ ?\\)))
- (= (forward-line 1) 0)))))))
+ (zerop (forward-line 1)))
+ (bolp)))))) ; forward-line has funny behavior at eob.
(defun c-delete-backslashes-forward (to-mark point-pos)
- ;; This function does not do any hidden buffer changes.
(while
(and (<= (point) to-mark)
(progn
(skip-chars-backward " \t" (if (>= (point) point-pos)
point-pos))
(point))))
- (= (forward-line 1) 0)))))
+ (zerop (forward-line 1)))
+ (bolp)))) ; forward-line has funny behavior at eob.
\f
;; comment. Return a cons of the prefix string and the column where
;; it ends. If fill-prefix is set, it'll override. Note that this
;; function also uses the value of point in some heuristics.
+ ;;
+ ;; This function might do hidden buffer changes.
(let* ((here (point))
(prefix-regexp (concat "[ \t]*\\("
;; There's no nonempty prefix on the line after the
;; comment opener. If the line is empty, or if the
- ;; text on has less or equal indentation than the
+ ;; text on it has less or equal indentation than the
;; comment starter we assume it's an unclosed
;; comment starter, i.e. that
;; `c-block-comment-prefix' should be used.
;; If APPLY-OUTSIDE-LITERAL is nil then the function will be called
;; only if the point turns out to be inside a comment or a string.
;;
- ;; This function does not do any hidden buffer changes.
+ ;; Note that this function does not do any hidden buffer changes.
(let (fill
;; beg and end limits the region to narrow. end is a marker.
;; hanging. In that case it's set to the number of spaces
;; that should be between the text and the ender.
hang-ender-stuck
+ ;; auto-fill-spaces is the exact sequence of whitespace between a
+ ;; comment's last word and the comment ender, temporarily replaced
+ ;; with 'x's before calling FUN when FILL-PARAGRAPH is nil.
+ auto-fill-spaces
(here (point))
(c-lit-limits c-lit-limits)
(c-lit-type c-lit-type))
(if (and buffer-undo-list (not (eq buffer-undo-list t)))
(setq buffer-undo-list (cons (point) buffer-undo-list)))
- (save-restriction
- ;; Widen to catch comment limits correctly.
- (widen)
- (unless c-lit-limits
- (setq c-lit-limits (c-literal-limits nil fill-paragraph)))
- (setq c-lit-limits (c-collect-line-comments c-lit-limits))
- (unless c-lit-type
- (setq c-lit-type (c-literal-type c-lit-limits))))
+ (c-save-buffer-state ()
+ (save-restriction
+ ;; Widen to catch comment limits correctly.
+ (widen)
+ (unless c-lit-limits
+ (setq c-lit-limits (c-literal-limits nil fill-paragraph)))
+ (setq c-lit-limits (c-collect-line-comments c-lit-limits))
+ (unless c-lit-type
+ (setq c-lit-type (c-literal-type c-lit-limits))))
- (save-excursion
- (unless (c-safe (backward-char)
- (forward-paragraph)
- (>= (point) here))
- (goto-char here)
- (forward-paragraph))
- (setq end (point-marker)))
- (save-excursion
- (unless (c-safe (forward-char)
- (backward-paragraph)
- (<= (point) here))
- (goto-char here)
- (backward-paragraph))
- (setq beg (point)))
+ (save-excursion
+ (unless (c-safe (backward-char)
+ (forward-paragraph)
+ (>= (point) here))
+ (goto-char here)
+ (forward-paragraph))
+ (setq end (point-marker)))
+ (save-excursion
+ (unless (c-safe (forward-char)
+ (backward-paragraph)
+ (<= (point) here))
+ (goto-char here)
+ (backward-paragraph))
+ (setq beg (point))))
(unwind-protect
(progn
;; own. Keep it that way.
(set-marker end (point))))
- (if fill-paragraph
- ;; The comment ender should hang. Replace all
- ;; cruft between it and the last word with one or
- ;; two 'x' and include it in the region. We'll
- ;; change them back to spaces afterwards. This
- ;; isn't done when auto filling, since that'd
- ;; effectively make it impossible to insert extra
- ;; spaces before the comment ender.
- (let* ((ender-start (save-excursion
- (goto-char (cdr c-lit-limits))
- (skip-syntax-backward "^w ")
- (point)))
- (point-rel (- ender-start here))
- spaces)
-
- (save-excursion
- (goto-char (cdr c-lit-limits))
- (setq tmp-post (point-marker))
- (insert ?\n)
- (set-marker end (point))
- (forward-line -1)
- (if (and (looking-at (concat "[ \t]*\\(\\("
- c-current-comment-prefix
- "\\)[ \t]*\\)"))
- (eq ender-start (match-end 0)))
- ;; The comment ender is prefixed by nothing
- ;; but a comment line prefix. Remove it
- ;; along with surrounding ws.
- (setq spaces (- (match-end 1) (match-end 2)))
- (goto-char ender-start))
- (skip-chars-backward " \t\r\n")
-
- (if (/= (point) ender-start)
- (progn
- (if (<= here (point))
- ;; Don't adjust point below if it's
- ;; before the string we replace.
- (setq point-rel -1))
- ;; Keep one or two spaces between the
- ;; text and the ender, depending on how
- ;; many there are now.
- (unless spaces
- (setq spaces (- ender-start (point))))
+ ;; The comment ender should hang. Replace all space between
+ ;; it and the last word either by one or two 'x's (when
+ ;; FILL-PARAGRAPH is non-nil), or a row of x's the same width
+ ;; as the whitespace (when auto filling), and include it in
+ ;; the region. We'll change them back to whitespace
+ ;; afterwards. The effect of this is to glue the comment
+ ;; ender to the last word in the comment during filling.
+ (let* ((ender-start (save-excursion
+ (goto-char (cdr c-lit-limits))
+ (skip-syntax-backward "^w ")
+ (point)))
+ (ender-column (save-excursion
+ (goto-char ender-start)
+ (current-column)))
+ (point-rel (- ender-start here))
+ spaces)
+
+ (save-excursion
+ (goto-char (cdr c-lit-limits))
+ (setq tmp-post (point-marker))
+ (insert ?\n)
+ (set-marker end (point))
+ (forward-line -1) ; last line of the comment
+ (if (and (looking-at (concat "[ \t]*\\(\\("
+ c-current-comment-prefix
+ "\\)[ \t]*\\)"))
+ (eq ender-start (match-end 0)))
+ ;; The comment ender is prefixed by nothing
+ ;; but a comment line prefix. Remove it
+ ;; along with surrounding ws.
+ (setq spaces (- (match-end 1) (match-end 2)))
+ (goto-char ender-start))
+ (skip-chars-backward " \t\r\n") ; Surely this can be
+ ; " \t"? "*/" is NOT alone on the line (ACM, 2005/8/18)
+
+ (if (/= (point) ender-start)
+ (progn
+ (if (<= here (point))
+ ;; Don't adjust point below if it's
+ ;; before the string we replace.
+ (setq point-rel -1))
+ ;; Keep one or two spaces between the
+ ;; text and the ender, depending on how
+ ;; many there are now.
+ (unless spaces
+ (setq spaces (- ender-column (current-column))))
+ (setq auto-fill-spaces (c-delete-and-extract-region
+ (point) ender-start))
+ ;; paragraph filling condenses multiple spaces to
+ ;; single or double spaces. auto-fill doesn't.
+ (if fill-paragraph
(setq spaces
(max
(min spaces
(if sentence-end-double-space 2 1))
- 1))
- ;; Insert the filler first to keep marks right.
- (insert-char ?x spaces t)
- (delete-region (point) (+ ender-start spaces))
- (setq hang-ender-stuck spaces)
- (setq point-rel
- (and (>= point-rel 0)
- (- (point) (min point-rel spaces)))))
- (setq point-rel nil)))
-
- (if point-rel
- ;; Point was in the middle of the string we
- ;; replaced above, so put it back in the same
- ;; relative position, counting from the end.
- (goto-char point-rel)))
-
- ;; We're doing auto filling. Just move the marker
- ;; to the comment end to ignore any code after the
- ;; comment.
- (move-marker end (cdr c-lit-limits)))))
+ 1)))
+ ;; Insert the filler first to keep marks right.
+ (insert-char ?x spaces t)
+ (setq hang-ender-stuck spaces)
+ (setq point-rel
+ (and (>= point-rel 0)
+ (- (point) (min point-rel spaces)))))
+ (setq point-rel nil)))
+
+ (if point-rel
+ ;; Point was in the middle of the string we
+ ;; replaced above, so put it back in the same
+ ;; relative position, counting from the end.
+ (goto-char point-rel)))
+ ))
(when (<= beg (car c-lit-limits))
;; The region includes the comment starter.
;; inside macros is bogus to begin with since the line
;; continuation backslashes aren't handled).
(save-excursion
- (c-beginning-of-macro)
- (beginning-of-line)
- (if (> (point) beg)
- (setq beg (point)))
- (c-end-of-macro)
- (forward-line)
- (if (< (point) end)
- (set-marker end (point)))))
+ (c-save-buffer-state ()
+ (c-beginning-of-macro)
+ (beginning-of-line)
+ (if (> (point) beg)
+ (setq beg (point)))
+ (c-end-of-macro)
+ (forward-line)
+ (if (< (point) end)
+ (set-marker end (point))))))
(t ; Other code.
;; Try to avoid comments and macros in the paragraph to
(goto-char tmp-post)
(skip-syntax-backward "^w ")
(forward-char (- hang-ender-stuck))
- (insert-char ?\ hang-ender-stuck t)
+ (if (or fill-paragraph (not auto-fill-spaces))
+ (insert-char ?\ hang-ender-stuck t)
+ (insert auto-fill-spaces)
+ (setq here (- here (- hang-ender-stuck (length auto-fill-spaces)))))
(delete-char hang-ender-stuck)
(goto-char here))
(set-marker tmp-post nil))
(defun c-do-auto-fill ()
;; Do automatic filling if not inside a context where it should be
;; ignored.
- ;;
- ;; This function does not do any hidden buffer changes.
(let ((c-auto-fill-prefix
;; The decision whether the line should be broken is actually
;; done in c-indent-new-comment-line, which do-auto-fill
(c-lit-limits c-lit-limits)
(c-lit-type c-lit-type)
(c-macro-start c-macro-start))
- (when (not (eq c-auto-fill-prefix t))
- ;; Called from do-auto-fill.
- (unless c-lit-limits
- (setq c-lit-limits (c-literal-limits nil nil t)))
- (unless c-lit-type
- (setq c-lit-type (c-literal-type c-lit-limits)))
- (if (memq (cond ((c-query-and-set-macro-start) 'cpp)
- ((null c-lit-type) 'code)
- (t c-lit-type))
- c-ignore-auto-fill)
- (setq fill-prefix t) ; Used as flag in the cond.
- (if (and (null c-auto-fill-prefix)
- (eq c-lit-type 'c)
- (<= (c-point 'bol) (car c-lit-limits)))
- ;; The adaptive fill function has generated a prefix, but
- ;; we're on the first line in a block comment so it'll be
- ;; wrong. Ignore it to guess a better one below.
- (setq fill-prefix nil)
- (when (and (eq c-lit-type 'c++)
- (not (string-match "\\`[ \t]*//" (or fill-prefix ""))))
- ;; Kludge: If the function that adapted the fill prefix
- ;; doesn't produce the required comment starter for line
- ;; comments, then we ignore it.
- (setq fill-prefix nil)))
- ))
+
+ (c-save-buffer-state ()
+ (when (not (eq c-auto-fill-prefix t))
+ ;; Called from do-auto-fill.
+ (unless c-lit-limits
+ (setq c-lit-limits (c-literal-limits nil nil t)))
+ (unless c-lit-type
+ (setq c-lit-type (c-literal-type c-lit-limits)))
+ (if (memq (cond ((c-query-and-set-macro-start) 'cpp)
+ ((null c-lit-type) 'code)
+ (t c-lit-type))
+ c-ignore-auto-fill)
+ (setq fill-prefix t) ; Used as flag in the cond.
+ (if (and (null c-auto-fill-prefix)
+ (eq c-lit-type 'c)
+ (<= (c-point 'bol) (car c-lit-limits)))
+ ;; The adaptive fill function has generated a prefix, but
+ ;; we're on the first line in a block comment so it'll be
+ ;; wrong. Ignore it to guess a better one below.
+ (setq fill-prefix nil)
+ (when (and (eq c-lit-type 'c++)
+ (not (string-match (concat "\\`[ \t]*"
+ c-line-comment-starter)
+ (or fill-prefix ""))))
+ ;; Kludge: If the function that adapted the fill prefix
+ ;; doesn't produce the required comment starter for line
+ ;; comments, then we ignore it.
+ (setq fill-prefix nil)))
+ )))
+
(cond ((eq fill-prefix t)
;; A call from do-auto-fill which should be ignored.
)
;; A fill-prefix overrides anything.
(funcall do-line-break)
(insert-and-inherit fill-prefix))
- ((progn
+ ((c-save-buffer-state ()
(unless c-lit-limits
(setq c-lit-limits (c-literal-limits)))
(unless c-lit-type
comment prefix (see the `c-comment-prefix-regexp' and
`c-block-comment-prefix' variables for details). The end of a
C++-style line comment doesn't count as inside it."
+
(interactive "*")
- (let* ((c-lit-limits (c-literal-limits nil nil t))
- (c-lit-type (c-literal-type c-lit-limits))
+ (let* (c-lit-limits c-lit-type
(c-macro-start c-macro-start))
- (if (or (eq c-lit-type 'c)
- (and (eq c-lit-type 'c++)
- (< (save-excursion
- (skip-chars-forward " \t")
- (point))
- (1- (cdr (setq c-lit-limits
- (c-collect-line-comments c-lit-limits))))))
- (and (or (not (looking-at "\\s *$"))
- (eq (char-before) ?\\))
- (c-query-and-set-macro-start)
- (<= (save-excursion
- (goto-char c-macro-start)
- (if (looking-at c-opt-cpp-start)
- (goto-char (match-end 0)))
- (point))
- (point))))
+
+ (if (c-save-buffer-state ()
+ (setq c-lit-limits (c-literal-limits nil nil t)
+ c-lit-type (c-literal-type c-lit-limits))
+ (or (eq c-lit-type 'c)
+ (and (eq c-lit-type 'c++)
+ (< (save-excursion
+ (skip-chars-forward " \t")
+ (point))
+ (1- (cdr (setq c-lit-limits (c-collect-line-comments
+ c-lit-limits))))))
+ (and (or (not (looking-at "\\s *$"))
+ (eq (char-before) ?\\))
+ (c-query-and-set-macro-start)
+ (<= (save-excursion
+ (goto-char c-macro-start)
+ (if (looking-at c-opt-cpp-start)
+ (goto-char (match-end 0)))
+ (point))
+ (point)))))
+
(let ((comment-multi-line t)
(fill-prefix nil))
(c-indent-new-comment-line nil t))
+
(delete-horizontal-space)
(newline)
+
;; c-indent-line may look at the current indentation, so let's
;; start out with the same indentation as the previous line.
(let ((col (save-excursion
(= (forward-line -1) 0)))
(current-indentation))))
(indent-to col))
+
(indent-according-to-mode))))
(defun c-context-open-line ()
\f
(cc-provide 'cc-cmds)
+;;; arch-tag: bf0611dc-d1f4-449e-9e45-4ec7c6936677
;;; cc-cmds.el ends here