summaryrefslogtreecommitdiff
path: root/lisp/c-fill.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/c-fill.el')
-rw-r--r--lisp/c-fill.el269
1 files changed, 269 insertions, 0 deletions
diff --git a/lisp/c-fill.el b/lisp/c-fill.el
new file mode 100644
index 00000000000..457e4c4ab1d
--- /dev/null
+++ b/lisp/c-fill.el
@@ -0,0 +1,269 @@
+;;; C comment mode - An auto-filled comment mode for gnu c-mode.
+;;;
+;;; Author: Robert Mecklenburg
+;;; Computer Science Dept.
+;;; University of Utah
+;;; From: mecklen@utah-gr.UUCP (Robert Mecklenburg)
+;;; Also hartzell@Boulder.Colorado.EDU
+;;; (c) 1986, University of Utah
+;;;
+;;; Everyone is granted permission to copy, modify and redistribute
+;;; this file, provided the people they give it to can.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; I have written a "global comment" minor-mode which performs auto-fill,
+;;; fill-paragraph, and auto-indentation functions. This function only
+;;; works for comments which occupy an entire line (not comments to the
+;;; right of code). The mode has several options set through variables.
+;;; If the variable c-comment-starting-blank is non-nil multi-line
+;;; comments come out like this:
+;;;
+;;; /*
+;;; * Your favorite
+;;; * multi-line comment.
+;;; */
+;;;
+;;; otherwise they look like this:
+;;;
+;;; /* Your Favorite
+;;; * multi-line comment.
+;;; */
+;;;
+;;; If the variable c-comment-hanging-indent is non-nil K&R style comments
+;;; are indented automatically like this:
+;;;
+;;; /* my_func - For multi-line comments with hanging indent
+;;; * the text is lined up after the dash.
+;;; */
+;;;
+;;; otherwise the text "the text" (!) is lined up under my_func. If a
+;;; comment fits (as typed) on a single line it remains a single line
+;;; comment even if c-comment-starting-blank is set. If
+;;; c-comment-indenting is non-nil hitting carriage return resets the
+;;; indentation for the next line to the current line's indentation
+;;; (within the comment) like this:
+;;;
+;;; /* Typing along merrily....
+;;; * Now I indent with spaces, when I hit return
+;;; * the indentation is automatically set to
+;;; * ^ here.
+;;; */
+;;;
+;;; Due to my lack of understanding of keymaps this permanently resets M-q
+;;; to my own fill function. I would like to have the comment mode
+;;; bindings only in comment mode but I can't seem to get that to work.
+;;; If some gnu guru can clue me in, I'd appreciate it.
+;;;
+(defvar c-comment-starting-blank t
+ "*Controls whether global comments have an initial blank line.")
+(defvar c-comment-indenting t
+ "*If set global comments are indented to the level of the previous line.")
+(defvar c-comment-hanging-indent t
+ "*If true, comments will be automatically indented to the dash.")
+(defvar c-hang-already-done t
+ "If true we have performed the haning indent already for this comment.")
+
+
+;;;
+;;; c-comment-map - This is a sparse keymap for comment mode which
+;;; gets inserted when c-comment is called.
+;;;
+(defvar c-comment-mode-map ()
+ "Keymap used in C comment mode.")
+(if c-comment-mode-map
+ ()
+ (setq c-comment-mode-map (copy-keymap c-mode-map))
+ (define-key c-comment-mode-map "\e\r" 'newline)
+ (define-key c-comment-mode-map "\eq" 'set-fill-and-fill)
+ (define-key c-comment-mode-map "\r" 'set-fill-and-return))
+
+;;;
+;;; c-comment - This is a filled comment mode which can format
+;;; indented text, do hanging indents, and symetric
+;;; placement of comment delimiters.
+;;;
+(defun c-comment ()
+ "Edit a C comment with filling and indentation.
+This performs hanging indentation, symmetric placement of delimiters,
+ and Indented-Text mode style indentation. Type 'M-x apropos
+c-comment' for information on options."
+ (interactive)
+ (let
+ ;; Save old state.
+ ((auto-fill-hook (if c-comment-indenting
+ 'do-indented-auto-fill 'do-auto-fill))
+; (comment-start nil)
+ (comment-multi-line t)
+ (comment-start-skip "/*\\*+[ ]*")
+ (paragraph-start-ref paragraph-start)
+ fill-prefix paragraph-start paragraph-separate opoint)
+
+ ;; Determine if we are inside a comment.
+ (setq in-comment
+ (save-excursion
+ (and (re-search-backward "/\\*\\|\\*/" 0 t)
+ (string= "/*" (buffer-substring (point) (+ (point) 2))))))
+
+ ;; Indent the comment and set the fill prefix to comment continuation
+ ;; string. If we are already in a comment get the indentation on
+ ;; the current line.
+ (setq c-hang-already-done nil)
+
+ ;; Set the beginning of the comment and insert the blank line if needed.
+ (use-local-map c-comment-mode-map)
+ (if (not in-comment)
+ (progn (c-indent-line)
+ (insert "/* ")
+ (setq fill-prefix (get-current-fill (point)))
+ (recursive-edit)
+
+ ;; If the comment fits on one line, place the close
+ ;; comment at the end of the line. Otherwise, newline.
+ (setq opoint (point))
+ (if (and (save-excursion (beginning-of-line)
+ (search-forward "/*" opoint t))
+ (<= (+ (current-column) 3) 79))
+ (insert " */")
+ (insert "\n*/"))
+
+ (c-indent-line))
+ (progn (setq fill-prefix (get-current-fill (point)))
+ (recursive-edit)
+ (search-forward "*/" (buffer-size) t)
+ (forward-line 1)))
+
+ ;; If starting blank enabled, insert a newline, etc., but only if
+ ;; this comment requires multiple lines.
+ (if c-comment-starting-blank
+ (save-excursion
+ (setq opoint (point))
+ (forward-line -1)
+ (if (or (null (search-forward "/*" opoint t))
+ (null (search-forward "*/" opoint t)))
+ (progn
+ (search-backward "/*")
+ (re-search-forward comment-start-skip opoint t)
+ (setq fill-prefix (get-current-fill (point)))
+ (if (not (looking-at "\n"))
+ (insert ?\n fill-prefix))))))
+; (indent-new-comment-line))))))
+
+ ;; Move cursor to indentation.
+ (c-indent-line)
+ (use-local-map c-mode-map)
+ )
+ )
+
+
+;;;
+;;; set-fill-and-fill - Get the current fill for this line and fill
+;;; the paragraph.
+;;;
+(defun set-fill-and-fill (arg)
+ "Get the fill-prefix and fill the current paragraph."
+
+ (interactive "P")
+ (setq fill-prefix (get-current-fill (point)))
+ (fill-paragraph arg))
+
+;;;
+;;; set-fill-and-return - Set the current fill prefix and
+;;; indent-new-comment-line.
+;;;
+(defun set-fill-and-return ()
+ "Set the current fill prefix and move to the next line."
+
+ (interactive)
+ (if c-comment-indenting
+ (setq fill-prefix (get-current-fill (point))))
+ (insert ?\n fill-prefix))
+
+;;;
+;;; do-indented-auto-fill - Perform the auto-fill function, but get
+;;; the fill-prefix first.
+;;;
+(defun do-indented-auto-fill ()
+ "Perform auto-fill, but get fill-prefix first."
+
+ (let ((opoint (point)))
+ (save-excursion
+ (move-to-column (1+ fill-column))
+ (skip-chars-backward "^ \t\n")
+ (if (bolp)
+ (re-search-forward "[ \t]" opoint t))
+ ;; If there is a space on the line before fill-point,
+ ;; and nonspaces precede it, break the line there.
+ (if (save-excursion
+ (skip-chars-backward " \t")
+ (not (bolp)))
+
+ ;; If we are wrapping to a new line, figure out the indentation on
+ ;; the current line first.
+ (progn
+ (setq fill-prefix (get-current-fill opoint))
+ (insert ?\n fill-prefix)))))
+; (indent-new-comment-line)))))
+ )
+
+
+;;;
+;;; get-current-fill - Get the fill-prefix for the current line. This
+;;; assumes that the valid fill prefix is between
+;;; (beginning-of-line) and (point).
+;;;
+(defun get-current-fill (pnt)
+ "Get the current fill prefix.
+A valid fill prefix must be between the beginning of the line and point."
+
+ (let ((opoint pnt) fill last-char)
+ (save-excursion
+ (beginning-of-line)
+ (setq fill
+ (buffer-substring (point)
+ (progn
+ (re-search-forward comment-start-skip opoint t)
+ (point))))
+
+ ;; Be sure there is trailing white space.
+ (setq last-char (substring fill (1- (length fill)) (length fill)))
+ (if (and (not (string= " " last-char))
+ (not (string= " " last-char)))
+ (setq fill (concat fill " ")))
+
+ (setq fill (replace-letter fill "/" " "))
+
+ ;; Get the hanging indentation if we haven't already.
+ (if (and c-comment-hanging-indent (not c-hang-already-done))
+ (let ((curr (point))
+ (opnt (progn (end-of-line) (point))))
+ (beginning-of-line)
+ (if (search-forward " - " opnt t)
+ (progn
+ (setq fill (concat fill (make-string (- (point) curr) 32)))
+ (setq c-hang-already-done t)))))
+
+ ;; Set the paragraph delimiters.
+ (setq paragraph-start (concat paragraph-start-ref
+ "\\|^"
+ (regexp-quote
+ (substring fill
+ 0 (1- (length fill))))
+ "$"))
+ (setq paragraph-separate paragraph-start))
+ fill)
+ )
+
+
+;;;
+;;; replace-letter - Given a string, an old letter and a new letter,
+;;; perform the substitution.
+;;;
+(defun replace-letter (str old-letter new-letter)
+ (let (new-str c
+ (sp 0)
+ (size (length str)))
+ (while (< sp size)
+ (setq c (substring str sp (1+ sp)))
+ (setq new-str (concat new-str (if (string= c old-letter) new-letter c)))
+ (setq sp (1+ sp)))
+ new-str))