mlandau@bbn.com (Matt Landau) (01/19/90)
Having recently been forced by circumstances to switch from using Unipress Emacs -- which I really liked -- to Gnu Emacs -- which I'm really coming to appreciate, except for the lack of a good SunView bitmap-based terminal driver -- I find myself looking for a new C programming mode. Can anyone supply a pointer to a *truly* electric C-mode? Something along the lines of Ray Dunn's C+ mode for MockLisp would be nice; in particular, something that understands that you really *do* want indentation after "if", "while", and "for" statements that aren't followed by braces. Try as I might, I cannot get Gnu's c-mode to figure that one out. (On the other hand, writing the helper functions to enable c-fill.el's c-comment mode on /* and disable is on */ was pleasantly trivial :-) I've already tried running C+ mode through translate-to-mocklisp, but the things it does with MockLisp are too gross for the automated translator to handle. They're also too gross for me to translate by hand, at least without more time than I have and a copy of the Elisp Reference Manual! So, that leaves me looking for a more powerful C mode. Will the power of the net come through again? -- Matt Landau Waiting for a flash of enlightenment mlandau@bbn.com in all this blood and thunder
rberlin@birdland.sun.com (Rich Berlin) (01/20/90)
> except for the lack of a good SunView bitmap-based terminal driver Have you checked out emacstool? It's in the gnuemacs etc directory. Gives you mouse support, configurable menu on the right button, and some other goodies. > particular, something that understands that you really *do* want > indentation after "if", "while", and "for" statements that aren't > followed by braces. Try as I might, I cannot get Gnu's c-mode to > figure that one out. Here are the settings I use. I think they'll do what you want. (c-indent-level . 4) (c-continued-statement-offset . 4) (c-brace-offset . 0) (c-continued-brace-offset . -4) (c-brace-imaginary-offset . 0) (c-argdecl-indent . 4) (c-label-offset . -2) (c-auto-newline . nil) (fill-column . 75) -- Rich
mlandau@bbn.com (Matt Landau) (01/20/90)
rberlin@birdland.sun.com (Rich Berlin) writes: >> Try as I might, I cannot get Gnu's c-mode to figure that one out. >(c-continued-statement-offset . 4) >(c-continued-brace-offset . -4) This turned out to be the combination of things I was looking for. No need for 10 more people to follow up and tell me so :-) -- Matt Landau Waiting for a flash of enlightenment mlandau@bbn.com in all this blood and thunder
msb@hosmsb.ATT.COM (Mike Balenger) (01/20/90)
>>>>> 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 <mark@comp.vuw.ac.nz> - 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)))) -- ---------------------------------------------------------------------- <cute quote> Michael S. Balenger (201) 949-8789 <cute disclaimer> AT&T Bell Labs Room 1L-405 msb@ho5cad.att.com Crawfords Corner Road att!ho5cad!msb Holmdel, NJ 07733
mcdaniel@amara.UUCP (Tim McDaniel) (01/23/90)
>;; Mark Davies <mark@comp.vuw.ac.nz> - Dec 1985, revised Jun 1987 >;; 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) This didn't work for me. It would load my text .emacs file, but not the byte-compiled "equivalent" of it. I'm not sure why: my version of emacs? the way I autoloaded elec-c? Anyway, I did (autoload 'elec-c-mode "elec-c" "" t) ... (setq c-mode-hook 'elec-c-mode) (setq elec-c-mode-hook '(lambda () (setq c-auto-newline t) ... ) ) instead, and that works both ways. -- Tim McDaniel Applied Dynamics International, Ann Arbor, MI Internet: mcdaniel%amara.uucp@mailgw.cc.umich.edu UUCP: {uunet,sharkey}!amara!mcdaniel