📄 c-mode.el
字号:
;; If initial point was within line's indentation, ;; position after the indentation. Else stay at same point in text. (if (> (- (point-max) pos) (point)) (goto-char (- (point-max) pos)))) shift-amt))(defun calculate-c-indent (&optional parse-start) "Return appropriate indentation for current line as C code.In usual case returns an integer: the column to indent to.Returns nil if line starts inside a string, t if in a comment." (save-excursion (beginning-of-line) (let ((indent-point (point)) (case-fold-search nil) state containing-sexp) (if parse-start (goto-char parse-start) (beginning-of-defun)) (while (< (point) indent-point) (setq parse-start (point)) (setq state (parse-partial-sexp (point) indent-point 0)) (setq containing-sexp (car (cdr state)))) (cond ((or (nth 3 state) (nth 4 state)) ;; return nil or t if should not change this line (nth 4 state)) ((null containing-sexp) ;; Line is at top level. May be data or function definition, ;; or may be function argument declaration. ;; Indent like the previous top level line ;; unless that ends in a closeparen without semicolon, ;; in which case this line is the first argument decl. (goto-char indent-point) (skip-chars-forward " \t") (if (= (following-char) ?{) 0 ; Unless it starts a function body (c-backward-to-noncomment (or parse-start (point-min))) ;; Look at previous line that's at column 0 ;; to determine whether we are in top-level decls ;; or function's arg decls. Set basic-indent accordinglu. (let ((basic-indent (save-excursion (re-search-backward "^[^ \^L\t\n#]" nil 'move) (if (and (looking-at "\\sw\\|\\s_") (looking-at ".*(") (progn (goto-char (1- (match-end 0))) (forward-sexp 1) (and (< (point) indent-point) (not (memq (following-char) '(?\, ?\;)))))) c-argdecl-indent 0)))) ;; Now add a little if this is a continuation line. (+ basic-indent (if (or (bobp) (memq (preceding-char) '(?\) ?\; ?\}))) 0 c-continued-statement-offset))))) ((/= (char-after containing-sexp) ?{) ;; line is expression, not statement: ;; indent to just after the surrounding open. (goto-char (1+ containing-sexp)) (current-column)) (t ;; Statement level. Is it a continuation or a new statement? ;; Find previous non-comment character. (goto-char indent-point) (c-backward-to-noncomment containing-sexp) ;; Back up over label lines, since they don't ;; affect whether our line is a continuation. (while (or (eq (preceding-char) ?\,) (and (eq (preceding-char) ?:) (or (eq (char-after (- (point) 2)) ?\') (memq (char-syntax (char-after (- (point) 2))) '(?w ?_))))) (if (eq (preceding-char) ?\,) (c-backward-to-start-of-continued-exp containing-sexp)) (beginning-of-line) (c-backward-to-noncomment containing-sexp)) ;; Now we get the answer. (if (not (memq (preceding-char) '(nil ?\, ?\; ?\} ?\{))) ;; This line is continuation of preceding line's statement; ;; indent c-continued-statement-offset more than the ;; previous line of the statement. (progn (c-backward-to-start-of-continued-exp containing-sexp) (+ c-continued-statement-offset (current-column) (if (save-excursion (goto-char indent-point) (skip-chars-forward " \t") (eq (following-char) ?{)) c-continued-brace-offset 0))) ;; This line starts a new statement. ;; Position following last unclosed open. (goto-char containing-sexp) ;; Is line first statement after an open-brace? (or ;; If no, find that first statement and indent like it. (save-excursion (forward-char 1) (let ((colon-line-end 0)) (while (progn (skip-chars-forward " \t\n") (looking-at "#\\|/\\*\\|case[ \t\n].*:\\|[a-zA-Z0-9_$]*:")) ;; Skip over comments and labels following openbrace. (cond ((= (following-char) ?\#) (forward-line 1)) ((= (following-char) ?\/) (forward-char 2) (search-forward "*/" nil 'move)) ;; case or label: (t (save-excursion (end-of-line) (setq colon-line-end (point))) (search-forward ":")))) ;; The first following code counts ;; if it is before the line we want to indent. (and (< (point) indent-point) (if (> colon-line-end (point)) (- (current-indentation) c-label-offset) (current-column))))) ;; If no previous statement, ;; indent it relative to line brace is on. ;; For open brace in column zero, don't let statement ;; start there too. If c-indent-level is zero, ;; use c-brace-offset + c-continued-statement-offset instead. ;; For open-braces not the first thing in a line, ;; add in c-brace-imaginary-offset. (+ (if (and (bolp) (zerop c-indent-level)) (+ c-brace-offset c-continued-statement-offset) c-indent-level) ;; Move back over whitespace before the openbrace. ;; If openbrace is not first nonwhite thing on the line, ;; add the c-brace-imaginary-offset. (progn (skip-chars-backward " \t") (if (bolp) 0 c-brace-imaginary-offset)) ;; If the openbrace is preceded by a parenthesized exp, ;; move to the beginning of that; ;; possibly a different line (progn (if (eq (preceding-char) ?\)) (forward-sexp -1)) ;; Get initial indentation of the line we are on. (current-indentation))))))))))(defun calculate-c-indent-within-comment () "Return the indentation amount for line, assuming thatthe current line is to be regarded as part of a block comment." (let (end star-start) (save-excursion (beginning-of-line) (skip-chars-forward " \t") (setq star-start (= (following-char) ?\*)) (skip-chars-backward " \t\n") (setq end (point)) (beginning-of-line) (skip-chars-forward " \t") (and (re-search-forward "/\\*[ \t]*" end t) star-start (goto-char (1+ (match-beginning 0)))) (current-column))))(defun c-backward-to-noncomment (lim) (let (opoint stop) (while (not stop) (skip-chars-backward " \t\n\f" lim) (setq opoint (point)) (if (and (>= (point) (+ 2 lim)) (save-excursion (forward-char -2) (looking-at "\\*/"))) (search-backward "/*" lim 'move) (setq stop (or (<= (point) lim) (save-excursion (beginning-of-line) (skip-chars-forward " \t") (not (looking-at "#"))))) (or stop (beginning-of-line))))))(defun c-backward-to-start-of-continued-exp (lim) (if (= (preceding-char) ?\)) (forward-sexp -1)) (beginning-of-line) (if (<= (point) lim) (goto-char (1+ lim))) (skip-chars-forward " \t"))(defun c-backward-to-start-of-if (&optional limit) "Move to the start of the last ``unbalanced'' if." (or limit (setq limit (save-excursion (beginning-of-defun) (point)))) (let ((if-level 1) (case-fold-search nil)) (while (not (zerop if-level)) (backward-sexp 1) (cond ((looking-at "else\\b") (setq if-level (1+ if-level))) ((looking-at "if\\b") (setq if-level (1- if-level))) ((< (point) limit) (setq if-level 0) (goto-char limit))))))(defun mark-c-function () "Put mark at end of C function, point at beginning." (interactive) (push-mark (point)) (end-of-defun) (push-mark (point)) (beginning-of-defun) (backward-paragraph))(defun indent-c-exp () "Indent each line of the C grouping following point." (interactive) (let ((indent-stack (list nil)) (contain-stack (list (point))) (case-fold-search nil) restart outer-loop-done inner-loop-done state ostate this-indent last-sexp at-else at-brace (opoint (point)) (next-depth 0)) (save-excursion (forward-sexp 1)) (save-excursion (setq outer-loop-done nil) (while (and (not (eobp)) (not outer-loop-done)) (setq last-depth next-depth) ;; Compute how depth changes over this line ;; plus enough other lines to get to one that ;; does not end inside a comment or string. ;; Meanwhile, do appropriate indentation on comment lines. (setq inner-loop-done nil) (while (and (not inner-loop-done) (not (and (eobp) (setq outer-loop-done t)))) (setq ostate state) (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) nil nil state)) (setq next-depth (car state)) (if (and (car (cdr (cdr state))) (>= (car (cdr (cdr state))) 0)) (setq last-sexp (car (cdr (cdr state))))) (if (or (nth 4 ostate)) (c-indent-line)) (if (or (nth 3 state)) (forward-line 1) (setq inner-loop-done t))) (if (<= next-depth 0) (setq outer-loop-done t)) (if outer-loop-done nil ;; If this line had ..))) (((.. in it, pop out of the levels ;; that ended anywhere in this line, even if the final depth ;; doesn't indicate that they ended. (while (> last-depth (nth 6 state)) (setq indent-stack (cdr indent-stack) contain-stack (cdr contain-stack) last-depth (1- last-depth))) (if (/= last-depth next-depth) (setq last-sexp nil)) ;; Add levels for any parens that were started in this line. (while (< last-depth next-depth) (setq indent-stack (cons nil indent-stack) contain-stack (cons nil contain-stack) last-depth (1+ last-depth))) (if (null (car contain-stack)) (setcar contain-stack (or (car (cdr state)) (save-excursion (forward-sexp -1) (point))))) (forward-line 1) (skip-chars-forward " \t") (if (eolp) nil (if (and (car indent-stack) (>= (car indent-stack) 0)) ;; Line is on an existing nesting level. ;; Lines inside parens are handled specially. (if (/= (char-after (car contain-stack)) ?{) (setq this-indent (car indent-stack)) ;; Line is at statement level. ;; Is it a new statement? Is it an else? ;; Find last non-comment character before this line (save-excursion (setq at-else (looking-at "else\\W")) (setq at-brace (= (following-char) ?{)) (c-backward-to-noncomment opoint) (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{))) ;; Preceding line did not end in comma or semi; ;; indent this line c-continued-statement-offset ;; more than previous. (progn (c-backward-to-start-of-continued-exp (car contain-stack)) (setq this-indent (+ c-continued-statement-offset (current-column) (if at-brace c-continued-brace-offset 0)))) ;; Preceding line ended in comma or semi; ;; use the standard indent for this level. (if at-else (progn (c-backward-to-start-of-if opoint) (setq this-indent (current-indentation))) (setq this-indent (car indent-stack)))))) ;; Just started a new nesting level. ;; Compute the standard indent for this level. (let ((val (calculate-c-indent (if (car indent-stack) (- (car indent-stack)))))) (setcar indent-stack (setq this-indent val)))) ;; Adjust line indentation according to its contents (if (or (looking-at "case[ \t]") (and (looking-at "[A-Za-z]") (save-excursion (forward-sexp 1) (looking-at ":")))) (setq this-indent (max 1 (+ this-indent c-label-offset)))) (if (= (following-char) ?}) (setq this-indent (- this-indent c-indent-level))) (if (= (following-char) ?{) (setq this-indent (+ this-indent c-brace-offset))) ;; Put chosen indentation into effect. (or (= (current-column) this-indent) (= (following-char) ?\#) (progn (delete-region (point) (progn (beginning-of-line) (point))) (indent-to this-indent))) ;; Indent any comment following the text. (or (looking-at comment-start-skip) (if (re-search-forward comment-start-skip (save-excursion (end-of-line) (point)) t) (progn (indent-for-comment) (beginning-of-line))))))))); (message "Indenting C expression...done") )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -