Xref: utzoo comp.emacs:7574 gnu.emacs:2157 Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!tut.cis.ohio-state.edu!ucbvax!bloom-beacon!bu.edu!bu-cs!att!cbnewsh!hosmsb!msb From: msb@hosmsb.ATT.COM (Mike Balenger) Newsgroups: comp.emacs,gnu.emacs Subject: Re: Seeking Truly Electric-C mode for Gnu Emacs Message-ID: Date: 20 Jan 90 10:26:41 GMT References: <13364@granite.BBN.COM> Sender: msb@cbnewsh.ATT.COM Reply-To: msb@ho5cad.ATT.COM (Mike Balenger) Distribution: comp Organization: AT&T Bell Laboratories Lines: 417 In-reply-to: mlandau@bbn.com's message of 19 Jan 90 09:01:14 GMT >>>>> On 19 Jan 90 09:01:14 GMT, mlandau@bbn.com (Matt Landau) said: mlandau> Having recently been forced by circumstances to switch from mlandau> using Unipress Emacs -- which I really liked -- to Gnu Emacs mlandau> -- which I'm really coming to appreciate, except for the lack mlandau> of a good SunView bitmap-based terminal driver -- I find mlandau> myself looking for a new C programming mode. I had asked the same question back in October. I haven't gotten around to playing with this code, but if you get a chance to, please post a review. Mike Balenger ================================================================ >>>>On Fri, 13 Oct 89, 1989, wpkege%snll-arpagw.llnl.gov@lll-lcc.llnl.gov (kegelmeyer william p) said: wpkege> Greetings: wpkege> wpkege> This message is in response to your request to hear what I wpkege> learned when I requested information on a "full-featured wpkege> C-mode" for GNU emacs from the net. There was only one wpkege> substantive response, but it was entirely adequate. Dana wpkege> Chee, dana@bellcore.com, pointed me to a package written by wpkege> Mark Davies, mark@comp.vuw.ac.nz, that was intenend to look wpkege> like Gosling elec-c mode, which is exactly what I was looking wpkege> for. Mr. Davies posted this in NOvember of 1988; I wrote to wpkege> ask if he had a more recent version, and he indicated that it wpkege> hasn't changed substantially since he posted it. wpkege> wpkege> The mode file follows in this message. wpkege> wpkege> Philip Kegelmeyer wpkege> wpkege> Sandia National Laboratories voice: (415) 294-3016 wpkege> Imaging Technologies Division ARPANET: wpkege@sandia.llnl.gov wpkege> P.O. Box 969, ORG 8435 alternative: wpkege@snll-arpagw.llnl.gov wpkege> Livermore, CA, 94551-0969 wpkege> --------------------cut here-------------------------- ;; elec C code editing commands for Emacs ;; Mark Davies - Dec 1985, revised Jun 1987 ;; (C) Copyright 1987 Mark Davies ;; This file is released under the terms of the GNU Emacs General Public ;; Licence. ;; I invoke this from my .emacs file with the following incantation ;; (defvar c-mode-hook 'elec-c-mode) ;; (defvar elec-c-mode-hook '(lambda () (auto-fill-mode 1))) ;; (setq c-auto-newline t) ;; Things to do: ;; o allow option to put open braces on separate line. ie. formatting ala ;; Stallman. ;; o place the statement on current line in condition of a new if/while/do ;; construct. ;; o Add Comments (defvar elec-c-mode-abbrev-table nil "Abbrev table in use in elec-C-mode buffers.") (defvar elec-c-mode-map nil "Keymap used in elec C mode.") (defvar elec-c-verbatim nil "Should abbrevs be expanded explicitly?") (setq elec-c-mode-map (make-sparse-keymap)) (define-key elec-c-mode-map "{" 'elec-c-left-brace) (define-key elec-c-mode-map "}" 'electric-c-brace) (define-key elec-c-mode-map "(" 'elec-c-opening-brac) (define-key elec-c-mode-map "[" 'elec-c-opening-brac) (define-key elec-c-mode-map ";" 'elec-c-semi) (define-key elec-c-mode-map ":" 'electric-c-terminator) (define-key elec-c-mode-map "\e\C-h" 'mark-c-function) (define-key elec-c-mode-map "\e\C-q" 'indent-c-exp) (define-key elec-c-mode-map "\177" 'backward-delete-char-untabify) (define-key elec-c-mode-map "\C-c\C-c" 'elec-c-close-block) (define-key elec-c-mode-map "\C-cv" 'toggle-verbatim) (define-key elec-c-mode-map "\e{" 'elec-c-remove-braces) (define-key elec-c-mode-map "\C-j" 'elec-c-linefeed) (define-key elec-c-mode-map "\t" 'c-indent-command) (modify-syntax-entry ?# "w" c-mode-syntax-table) (modify-syntax-entry ?_ "w" c-mode-syntax-table) (defconst comment-edged nil "*Use comments of the form: /* * ... */") (defun elec-c-mode () "High powered C editing mode Elec C mode provides expansion of the C control constructs: if, else, while, for, do, and switch. The user types the keyword immediately followed by a space, which causes the construct to be expanded, and the user positioned where (s)he is most likely to want to be. eg. when the user types a space following \"if\" the following appears in the buffer: if () { } and the cursor is between the parentheses. The user can then type some boolean expression within the parens. Having done that, typing \\[elec-c-linefeed] places you, appropriately indented on a new line between the braces. Various characters in C almost always come in pairs: {}, (), []. When the user types the first, he gets the second as well, with optional special formatting done on {}. You can always quote (with \\[quoted-insert]) the left \"paren\" to avoid the expansion. #de, and #in are defined as abbreviations for #define and #include respectively. With auto-fill-mode on, three types of automatic formatting of comments are possible. The default is of the form /* ... ... */ /* ... ... */ If comment-multi-line is set non-nil you get comments of the form /* ... ... ... ... */ If additionally comment-edged is set non-nil you get comments of the form /* * ... ... */ Expression and list commands understand all C brackets. Tab indents for C code. Paragraphs are separated by blank lines only. Delete converts tabs to spaces as it moves back. \\{elec-c-mode-map} Variables controlling indentation style: c-auto-newline Non-nil means automatically newline before and after braces, and after colons and semicolons, inserted in C code. with this on colons and semicolons want to go to the end of the line. c-indent-level Indentation of C statements within surrounding block. The surrounding block's indentation is the indentation of the line on which the open-brace appears. c-continued-statement-offset Extra indentation given to a substatement, such as the then-clause of an if or body of a while c-brace-offset Extra indentation for a line if it starts with an open brace. c-brace-imaginary-offset An open brace following other text is treated as if it were this far to the right of the start of its line. c-argdecl-indent Indentation level of declarations of C function arguments. c-label-offset Extra indentation for line that is a label, or case or default. Turning on elec C mode calls the value of the variable elec-c-mode-hook with no args, if that value is non-nil." (interactive) (kill-all-local-variables) (use-local-map elec-c-mode-map) (setq major-mode 'elec-c-mode) (setq mode-name "elec C") (if (not elec-c-mode-abbrev-table) (let ((prev-a-c abbrevs-changed)) (define-abbrev-table 'elec-c-mode-abbrev-table '( ("main" "main" elec-main 0) ("argc" "argc" elec-argc 0) ("if" "if" elec-if-while 0) ("switch" "switch" elec-if-while 0) ("while" "while" elec-if-while 0) ("else" "else" elec-else 0) ("for" "for" elec-for 0) ("do" "do" elec-do 0) ("#d" "#define" nil 0) ("#de" "#define" nil 0) ("#e" "#endif" nil 0) ("#i" "#ifdef" nil 0) ("#in" "#include" nil 0))) (setq abbrevs-changed prev-a-c))) (setq local-abbrev-table elec-c-mode-abbrev-table) (abbrev-mode 1) (set-syntax-table c-mode-syntax-table) (make-local-variable 'elec-c-verbatim) (make-local-variable 'paragraph-start) (setq paragraph-start (concat "^$\\|" page-delimiter)) (make-local-variable 'paragraph-separate) (setq paragraph-separate paragraph-start) (make-local-variable 'indent-line-function) (setq indent-line-function 'c-indent-line) (make-local-variable 'require-final-newline) (setq require-final-newline t) (make-local-variable 'comment-start) (setq comment-start "/* ") (make-local-variable 'comment-end) (setq comment-end " */") (make-local-variable 'comment-column) (setq comment-column 32) (make-local-variable 'comment-start-skip) (setq comment-start-skip "/\\*+ *") (make-local-variable 'comment-indent-hook) (setq comment-indent-hook 'c-comment-indent) (make-local-variable 'parse-sexp-ignore-comments) (setq parse-sexp-ignore-comments t) (run-hooks 'elec-c-mode-hook)) ; so lets hope noone writes *LARGE* C files. (defun elec-c-inside-comment-p () (nth 4 (parse-partial-sexp (point-min) (point)))) (defun elec-c-inside-string-p () (nth 3 (parse-partial-sexp (point-min) (point)))) (defun elec-c-inside-comment-or-string-p () (let ((parse-state (parse-partial-sexp (point-min) (point)))) (or (nth 4 parse-state) (nth 3 parse-state)))) (defun elec-c-open-block () (interactive) (search-forward "{") (backward-char 1) (forward-sexp 1) (backward-char 1) (split-line) (c-indent-line)) (defun elec-c-close-block () (interactive) (while (not (looking-at "{")) (backward-up-list 1)) (forward-sexp 1) (save-excursion (next-line -1) (delete-blank-lines) (beginning-of-line) (if (looking-at "[ \t]*$") (kill-line 1))) (end-of-line) (newline) (c-indent-line)) (defun elec-c-remove-braces () "remove the surrounding pair of {}'s from the function." (interactive) (save-excursion (while (not (looking-at "{")) (backward-up-list 1)) (let (end) (save-excursion ; kill tail (forward-sexp 1) (delete-char -1) (delete-horizontal-space) (and (bolp) (eolp) (delete-char 1)) (setq end (point-marker))) (delete-char 1) ; kill head (delete-horizontal-space) (and (bolp) (eolp) (delete-char 1)) (while (<= (point) (marker-position end)) (c-indent-line) (forward-line 1))))) (defun elec-c-linefeed () "Go to end of line, open a new line and indent appropriately." (interactive) (end-of-line) (newline-and-indent)) (defun elec-c-semi (arg) "Insert character and correct line's indentation." (interactive "P") (if c-auto-newline (let ((end (point))) (if (not (save-excursion (beginning-of-line) (skip-chars-forward " \t") (or (= (following-char) ?#) (progn (beginning-of-defun) (let ((pps (parse-partial-sexp (point) end))) (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))) (end-of-line)) (electric-c-terminator arg)) (self-insert-command (prefix-numeric-value arg)))) (defun elec-c-left-brace () "if c-auto-newline is on insert matching close brace and format appropriately." (interactive) (if (or (not c-auto-newline) (c-inside-parens-p) (elec-c-inside-comment-or-string-p)) (insert ?{) (end-of-line) (delete-horizontal-space) (if (/= (char-syntax (preceding-char)) ? ) (insert ? )) (insert ?{) (c-indent-line) (insert "\n\n}") (c-indent-line) (next-line -1) (c-indent-line))) (defun elec-c-opening-brac () "For one of (, [ insert it and its pair, and postion point in the centre" (interactive) (insert last-command-char) (if (not (elec-c-inside-comment-or-string-p)) (save-excursion (cond ((= last-command-char ?\() (insert ?\))) ((= last-command-char ?[) (insert ?])))))) (defun elec-main () (if (elec-c-inside-comment-or-string-p) nil (insert-string " ()\n{\n}\n") (search-backward ")") (setq unread-command-char ?\^?))) (defun elec-argc () (if (save-excursion (beginning-of-line) (looking-at "[ \t]*main[ \t](argc")) (progn (insert-string ", argv") (end-of-line) (newline) (c-indent-line) (insert-string "int argc;") (newline) (c-indent-line) (insert-string "char *argv [];") (elec-c-open-block) (setq unread-command-char ?\^?)))) (defun elec-if-while () (if (elec-c-inside-comment-or-string-p) nil (insert-string " () {\n}") (c-indent-line) (search-backward ")") (setq unread-command-char ?\^?))) (defun elec-else () (if (elec-c-inside-comment-or-string-p) nil (insert-string " {\n\n}") (c-indent-line) (next-line -1) (c-indent-line) (setq unread-command-char ?\^?))) (defun elec-for () (if (elec-c-inside-comment-or-string-p) nil (insert-string " (;;) {\n}") (c-indent-line) (search-backward ";;)") (setq unread-command-char ?\^?))) (defun elec-do () (if (elec-c-inside-comment-or-string-p) nil (insert-string " {\n\n} while ();") (c-indent-line) (next-line -1) (c-indent-line) (setq unread-command-char ?\^?))) ; this is a HACK but I can't think of a better place to do it. (defun calculate-c-indent-within-comment () "Return the indentation amount for line, assuming that the current line is to be regarded as part of a block comment." (let (end star-start) (and (eq major-mode 'elec-c-mode) comment-edged (/= last-command-char ?\t) (save-excursion (insert "* "))) (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 toggle-verbatim (arg) "Toggle elec-c verbatim mode. Doesn't expand keywords unless explicitly This command toggles that mode (off->on, on->off), with an argument, turns it on iff arg is positive, otherwise off." (interactive "P") (abbrev-mode arg) (or (assq 'elec-c-verbatim minor-mode-alist) (setq minor-mode-alist (append minor-mode-alist (list '(elec-c-verbatim " Verbatim"))))) (setq elec-c-verbatim (if (null arg) (not elec-c-verbatim) (> (prefix-numeric-value arg) 0)))) -- ---------------------------------------------------------------------- Michael S. Balenger (201) 949-8789 AT&T Bell Labs Room 1L-405 msb@ho5cad.att.com Crawfords Corner Road att!ho5cad!msb Holmdel, NJ 07733