;; $Id: c-mode.el,v 1.16 2012/12/27 07:29:31 grog Exp $ ;; This is the way defined in the MySQL docco. It seems to correspond ;; to the following command in the cc-mode docco: ;; ;; (c-add-style "MySQL" my-c-style) (require 'cc-mode) (defconst mysql-c-style '((c-tab-always-indent . t) (c-comment-only-line-offset . 0) (comment-column . 48) (c-hanging-braces-alist . ((substatement-open before after) (brace-list-open))) (c-hanging-colons-alist . ((member-init-intro before) (inher-intro) (case-label after) (label after) (access-label after))) (c-cleanup-list . (scope-operator empty-defun-braces defun-close-semi)) (c-basic-offset . 2) (c-hanging-semi&comma-criteria . nil) (c-offsets-alist . ((statement-block-intro . +) (knr-argdecl-intro . 0) (substatement-open . 0) (label . -) (statement-cont . +) (arglist-intro . c-lineup-arglist-intro-after-paren) (arglist-close . c-lineup-arglist) )) (c-indent-comment-alist . ((anchored-comment column . 0) (end-block space . 1) (cpp-end-block space . 2) (other column . 48) )) ;; outdent # (and not £!) at beginning of line (c-electric-pound-behaviour . ((alignleft))) ;; these are default for C mode, but not for C++ (comment-start . "/* ") (comment-end . " */") (c-echo-syntactic-information-p . t) (fill-column . 80) ) "MySQL") (defconst mybsd-c-style '((c-basic-offset . 8) (c-comment-only-line-offset . 0) (indent-tabs-mode t) (c-offsets-alist . ((statement-block-intro . +) (knr-argdecl-intro . +) (substatement-open . 0) (substatement-label . 0) (label . 0) (statement-cont . +) (inline-open . 0) (inexpr-class . 0)))) "MyBSD") (defconst freebsd-c-style ; Adapted from Tony Finch http://myfreebsd.homeunix.net/freebsd/emacs-rc.html '((c-basic-offset . 8) (c-comment-only-line-offset . 0) (indent-tabs-mode t) (comment-column . 48) (c-offsets-alist . ((string . c-lineup-dont-change) ;; Relpos: Beg of previous line. (c . c-lineup-C-comments) ;; Relpos: Beg of the comment. (defun-open . 0) ;; Relpos: Boi at the func decl start when inside classes, bol ;; at the func decl start when at top level. (defun-close . 0) ;; Relpos: Boi at the func decl start. (defun-block-intro . +) ;; Relpos: Boi at the block open. (class-open . 0) ;; Relpos: Boi at the class decl start. (class-close . 0) ;; Relpos: Boi at the class decl start. (inline-open . +) ;; Relpos: None for functions (inclass got the relpos then), ;; boi at the lambda start for lambdas. (inline-close . 0) ;; Relpos: For functions: Boi at the func decl start. For ;; lambdas: At the block open if it's at boi, at the boi of the ;; lambda start otherwise. (func-decl-cont . +) ;; Relpos: Boi at the func decl start. (knr-argdecl-intro . +) ;; Relpos: Boi at the current line. (knr-argdecl . 0) ;; Relpos: Boi at the argdecl intro line. (topmost-intro . 0) ;; Relpos: Bol at the last line of previous construct. (topmost-intro-cont . 0) ;; Relpos: Boi at the topmost intro line. (member-init-intro . +) ;; Relpos: Boi at the func decl arglist open. (member-init-cont . c-lineup-multi-inher) ;; Relpos: Beg of the first member init. (inher-intro . +) ;; Relpos: Java: Boi at the class decl start. Otherwise: Boi ;; of current line (a bug?), unless it begins with an inher ;; start colon, in which case boi of previous line is used. (inher-cont . c-lineup-multi-inher) ;; Relpos: Java: At the implements/extends keyword start. ;; Otherwise: At the inher start colon, or boi at the class ;; decl start if the first inherit clause hangs and it's not a ;; func-local inherit clause (when does that occur?). (block-open . 0) ;; Relpos: Inexpr statement: Boi at the the preceding ;; paren. Otherwise: None. (block-close . 0) ;; Relpos: At the open brace if it's at boi. Otherwise boi at ;; the start of the statement the open brace hangs on, or boi ;; at the preceding paren for inexpr statements. (brace-list-open . 0) ;; Relpos: Boi at the brace list decl start, but a starting ;; "typedef" token is ignored. (brace-list-close . 0) ;; Relpos: Boi at the brace list open. (brace-list-intro . +) ;; Relpos: Boi at the brace list open. (brace-list-entry . 0) ;; Relpos: At the first non-ws char after the open paren if the ;; first token is on the same line, otherwise boi at that ;; token. ;(brace-entry-open . 0) ; emacs-20 incompat ;; Relpos: Same as brace-list-entry. (statement . 0) ;; Relpos: After a ';' in the condition clause of a for ;; statement: At the first token after the starting paren. ;; Otherwise: Boi at the start of the closest non-hanging ;; previous statement, but after any switch label. (statement-cont . *) ;; Relpos: After the first token in the condition clause of a ;; for statement: At the first token after the starting paren. ;; On the first line in a continued expression that starts with ;; a stream op and there's no stream op on the previous line: ;; Boi of previous line. Otherwise: Boi at the beginning of ;; the statement, but after any type of label. (statement-block-intro . +) ;; Relpos: At the block start if it's at boi, otherwise boi at ;; the start of the statement the open brace hangs on, or boi ;; at the preceding paren for inexpr statements. (statement-case-intro . +) ;; Relpos: At the label keyword (always at boi). (statement-case-open . +) ;; Relpos: At the label keyword (always at boi). ;; (substatement . fanf-else-if-magic) ;; Relpos: Boi at the containing statement or else clause. (substatement-open . 0) ;; Relpos: Boi at the containing statement or else clause. (case-label . 0) ;; Relpos: At the switch block start if it's at boi, otherwise ;; boi at the start of the switch condition clause. (access-label . -) ;; Relpos: Eol (a bug?). (label . 0) ;; Relpos: At the start of the containing block if it's at boi, ;; otherwise boi at the start of the sexp before the block. (do-while-closure . 0) ;; Relpos: Boi at the corresponding while keyword. (else-clause . 0) ;; Relpos: Boi at the corresponding if keyword. ;(catch-clause . 0) ; emacs-20 incompat ;; Relpos: Boi at the previous try or catch keyword in the try ;; statement. (comment-intro . c-lineup-comment) ;; Relpos: None. (arglist-intro . *) ;; Relpos: Boi at the open paren, or at the first non-ws after ;; the open paren of the surrounding sexp, whichever is later. (arglist-cont . *) ;; Relpos: At the first token after the open paren. (arglist-cont-nonempty . *) ;; Relpos: Boi at the open paren, or at the first non-ws after ;; the open paren of the surrounding sexp, whichever is later. (arglist-close . *) ;; Relpos: Boi at the open paren, or at the first non-ws after ;; the open paren of the surrounding sexp, whichever is later. (stream-op . c-lineup-streamop) ;; Relpos: Boi at the first stream op in the statement. (inclass . +) ;; Relpos: At the class open brace if it's at boi, otherwise ;; boi at the class decl start. (cpp-macro . -1000) ; instead of emacs-21's [0] ;; Relpos: None. (cpp-macro-cont . +) ;; Relpos: At the macro start (always at boi). (friend . 0) ;; Relpos: None. (objc-method-intro . -1000) ; instead of emacs-21's [0] ;; Relpos: Boi. (objc-method-args-cont . c-lineup-ObjC-method-args) ;; Relpos: At the method start (always at boi). (objc-method-call-cont . c-lineup-ObjC-method-call) ;; Relpos: At the open bracket. (extern-lang-open . 0) ;; Relpos: Boi at the extern keyword. (extern-lang-close . 0) ;; Relpos: Boi at the corresponding extern keyword. (inextern-lang . +) ;; Relpos: At the extern block open brace if it's at boi, ;; otherwise boi at the extern keyword. (namespace-open . 0) ;; Relpos: Boi at the namespace keyword. (namespace-close . 0) ;; Relpos: Boi at the corresponding namespace keyword. (innamespace . +) ;; Relpos: At the namespace block open brace if it's at boi, ;; otherwise boi at the namespace keyword. (template-args-cont . +) ; instead of (c-lineup-template-args +) ;; Relpos: Boi at the decl start. ; (inlambda . c-lineup-inexpr-block) ; emacs-20 incompat ;; Relpos: None. ; (lambda-intro-cont . +) ; emacs-20 incompat ;; Relpos: Boi at the lambda start. ; (inexpr-statement . 0) ; emacs-20 incompat ;; Relpos: None. ; (inexpr-class . +) ; emacs-20 incompat ;; Relpos: None. (c-offsets-alist . ((statement-block-intro . +) ))) "FreeBSD") (defconst lemis-c-style '((c-tab-always-indent . t) (c-comment-only-line-offset . 0) (comment-column . 60) (c-hanging-braces-alist . ((substatement-open before after) (brace-list-open))) (c-hanging-colons-alist . ((member-init-intro before) (inher-intro) (case-label after) (label after) (access-label after))) (c-cleanup-list . (scope-operator empty-defun-braces defun-close-semi)) (c-basic-offset . 2) (indent-tabs-mode nil) ;;;; tab with spaces. (c-hanging-semi&comma-criteria . nil) (c-offsets-alist . ((statement-block-intro . 0) (knr-argdecl-intro . 0) (substatement-open . 2) (label . -) (block-open . 0) (block-close . 0) (statement-cont . +) (arglist-intro . c-lineup-arglist-intro-after-paren) (arglist-close . c-lineup-arglist) )) (c-indent-comment-alist . ((anchored-comment column . 0) (end-block space . 1) (cpp-end-block space . 2) (other column . 48) )) ;; outdent # (and not £!) at beginning of line (c-electric-pound-behaviour . ((alignleft))) ;; these are default for C mode, but not for C++ (comment-start . "/* ") (comment-end . " */") (c-echo-syntactic-information-p . t) (fill-column . 80) ) "LEMIS") (defface tab-show-face '((t (:background "linen"))) "Used for tabs and such.") (defvar c-mode-extra-keywords '(("\t" . 'tab-show-face))) ;; Customizations for all modes in CC Mode. (defun my-c-mode-common-hook () ;; add my personal style and set it for the current buffer (c-add-style "LEMIS" lemis-c-style t) (c-add-style "FreeBSD" freebsd-c-style t) (c-add-style "MySQL" mybsd-c-style t) (if (string-match "/FreeBSD/" buffer-file-name) (c-set-style "freebsd") (c-set-style "lemis") ) ;; other customizations (font-lock-add-keywords nil c-mode-extra-keywords) ;; we like auto-newline but not hungry-delete (c-toggle-auto-newline 1) ;; key bindings for all supported languages. We can put these in ;; c-mode-base-map because c-mode-map, c++-mode-map, objc-mode-map, ;; java-mode-map, idl-mode-map, and pike-mode-map inherit from it. (define-key c-mode-base-map "\C-m" 'c-context-line-break) ) (add-hook 'c-mode-common-hook 'my-c-mode-common-hook) (add-hook 'c-mode-common-hook 'font-lock-mode) (defun my-c-initialization-hook () (define-key c-mode-base-map "\e" 'indent-all-comments) ;invoke with ctrl-Alt-Shift-_ (define-key c-mode-base-map "\C-m" 'c-context-line-break) (define-key c-mode-base-map "\e/" 'indent-next-comment) ;invoke with Alt-/ (define-key c-mode-base-map "" 'clear-trailing-junk-and-save) (setq indent-tabs-mode t) ) (add-hook 'c-initialization-hook 'my-c-initialization-hook) ;; Stewart's stuff ;; ;; (setq c-style-alist ;; (cons ;; '("MySQL" ;; ) ;; c-style-alist) ;; ) ;; ;; (c-set-style "MySQL") ;; (setq c-default-style "MySQL") ;; ;; ;; run this for mysql source ;; (defun mysql-c-mode-common-hook () (setq indent-tabs-mode nil)) ;; ;; ;; linux kernel style ;; (defun linux-c-mode-common-hook () linux-c-mode) ;; ;; (setq my-c-mode-common-hook '(lambda () ;; (turn-on-font-lock) ;; (setq comment-column 48) ;; ) ;; ) ;; ;; ;; predicates to check ;; (defvar my-style-selective-mode-hook nil) ;; ;; (add-hook 'my-style-selective-mode-hook ;; '((string-match "MySQL" (buffer-file-name)) . mysql-c-mode-common-hook) ;; ) ;; End Stewart's stuff ;;;; (if c-mode-map ;;;; () ;;;; (setq c-mode-map (make-sparse-keymap))) (defun indent-next-line () (interactive) (next-line 1) (apply (or (lookup-key (current-local-map) "\t") (lookup-key (current-global-map) "\t") ) nil ) ) ;indent the line according to what tab thinks ;;;; (define-key c-mode-map ";" 'self-insert-command) ; no electric semis, please ;;;; (define-key c-mode-map ":" 'self-insert-command) ; and no electric colons either (electric-c-terminator) ;;;; (define-key c-mode-map "\e\C-h" 'mark-c-function) ;;;; (define-key c-mode-map "\e\C-q" 'indent-c-exp) ;;;; (define-key c-mode-map "\177" 'backward-delete-char-untabify) ;;;; (define-key c-mode-map "\t" 'c-indent-command) ;;;; ; These added by Grog, 13 November 1991 ;;;; (define-key c-mode-map " " 'newline-and-indent) ;newline indents by default ;;;; (define-key c-mode-map " ;;;; " 'newline) ;and LF goes to the start of the line ;;;; Comment starts: space or tab, then /* or //. (setq definite-comment-start "[ ]\\(/\\*\\|//\\)") (defun indent-next-comment () "Skip to next comment, if it exists, and adjust it to the comment column. If the comment is at the beginning of the line, it is not adjusted. This function uses indent-comment (in c-mode.el), which cannot handle nested comments on the same line, so the cursor is positioned on the next line after the function completes." (interactive) ;can be used as a command (if (re-search-forward definite-comment-start nil t) ;position at beginning of comment (progn (if (> (current-column) 20) (comment-indent) ) ;and indent the comment (forward-line) t ) ;we found a comment nil ) ) ;no comments left (defun indent-all-comments () "Adjust all comments in the file which are not at the beginning of the line." (interactive) (save-excursion (goto-char (point-min)) ;to the start of the buffer (while (indent-next-comment)) ;and indent without comments (goto-char (point-min)) ;to the start of the buffer (replace-regexp "[ ]+$" "" nil) ;then remove trailing white space nil) ) ;;; Altereed version of function in lisp/newcomment.el: don't limit ;;; the length to fill-column. ;;; get the rest of the stuff first. (load-library "newcomment") ;;;###autoload (defun comment-indent (&optional continue) "Indent this line's comment to comment column, or insert an empty comment. If CONTINUE is non-nil, use the `comment-continue' markers if any." (interactive "*") (comment-normalize-vars) (let* ((empty (save-excursion (beginning-of-line) (looking-at "[ \t]*$"))) (starter (or (and continue comment-continue) (and empty block-comment-start) comment-start)) (ender (or (and continue comment-continue "") (and empty block-comment-end) comment-end))) (unless starter (error "No comment syntax defined")) (beginning-of-line) (let* ((eolpos (line-end-position)) (begpos (comment-search-forward eolpos t)) cpos indent) ;; An existing comment? (if begpos (setq cpos (point-marker)) ;; If none, insert one. (save-excursion ;; Some comment-indent-function insist on not moving comments that ;; are in column 0, so we first go to the likely target column. (indent-to comment-column) (setq begpos (point)) (insert starter) (setq cpos (point-marker)) (insert ender))) (goto-char begpos) ;; Compute desired indent. (setq indent (save-excursion (funcall comment-indent-function))) (if (not indent) ;; comment-indent-function refuses delegates to indent. (indent-according-to-mode) ;;;; ;; Avoid moving comments past the fill-column. ;;;; (unless (save-excursion (skip-chars-backward " \t") (bolp)) ;;;; (setq indent ;;;; (min indent ;;;; (+ (current-column) ;;;; (- fill-column ;;;; (save-excursion (end-of-line) (current-column))))))) (if (= (current-column) indent) (goto-char begpos) ;; If that's different from current, change it. (skip-chars-backward " \t") (delete-region (point) begpos) (indent-to (if (bolp) indent (max indent (1+ (current-column))))))) (goto-char cpos) (set-marker cpos nil)))) ;;;; See indent-hints for various commands to interactively tidy up.