home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / lisp / modes / c-comment.el < prev    next >
Encoding:
Text File  |  1992-06-29  |  10.3 KB  |  295 lines

  1. ;;; C Comment Edit
  2. ;;; Copyright (C) 1987, 1988, 1989 Kyle E. Jones
  3. ;;;
  4. ;;; Verbatim copies of this file may be freely redistributed.
  5. ;;;
  6. ;;; Modified versions of this file may be redistributed provided that this
  7. ;;; notice remains unchanged, the file contains prominent notice of
  8. ;;; author and time of modifications, and redistribution of the file
  9. ;;; is not further restricted in any way.
  10. ;;;
  11. ;;; This file is distributed `as is', without warranties of any kind.
  12.  
  13. (provide 'c-comment-edit)
  14.  
  15. (defvar c-comment-leader " *"
  16.   "*Leader used when rebuilding edited C comments.  The value of this variable
  17. should be a two-character string.  Values of "  ", " *" and "**" produce the
  18. comment styles:
  19.     /*    /*    /*
  20.       ...     * ...    ** ...
  21.       ...     * ...    ** ...
  22.     */     */    */
  23. respectively.")
  24.  
  25. (defconst c-comment-leader-regexp "^[     ]*\\(\\*\\*\\|\\*\\)?[ ]?"
  26.   "Regexp used to match C comment leaders.")
  27.  
  28. (defvar c-comment-edit-mode 'text-mode
  29.   "*Major mode used by `c-comment-edit' when editing C comments.")
  30.  
  31. (defvar c-comment-edit-hook nil
  32.   "*Function to call whenever `c-comment-edit' is used.
  33. The function is called just before the `c-comment-edit' function allows you to
  34. begin editing the comment.")
  35.  
  36. (defvar c-comment-edit-buffer-alist nil
  37.   "Assoc list of C buffers and their associated comment buffers.
  38. Elements are of the form (C-BUFFER COMMENT-BUFFER COMMENT-START COMMENT-END)
  39. COMMENT-START and COMMENT-END are markers in the C-BUFFER.")
  40.  
  41. (defmacro save-point (&rest body)
  42.   "Save value of point, evalutes FORMS and restore value of point.
  43. If the saved value of point is no longer valid go to (point-max).
  44. The variable `save-point' is lambda-bound to the value of point for
  45. the duration of this call."
  46.   (list 'let '((save-point (point)))
  47.     (list 'unwind-protect
  48.           (cons 'progn body)
  49.           '(goto-char (min (point-max) save-point)))))
  50.  
  51. (defmacro marker (pos &optional buffer)
  52.   (list 'set-marker '(make-marker) pos buffer))
  53.  
  54. (defun c-comment-edit (search-prefix)
  55.   "Edit multi-line C comments.
  56. This command allows the easy editing of a multi-line C comment like this:
  57.    /*
  58.     * ...
  59.     * ...
  60.     */
  61. The comment may be indented or flush with the left margin.
  62.  
  63. If point is within a comment, that comment is used.  Otherwise the
  64. comment to be edited is found by searching forward from point.
  65.  
  66. With one \\[universal-argument] searching starts after moving back one
  67.   paragraph.
  68. With two \\[universal-argument]'s searching starts at the beginning of the
  69.   current or proceeding C function.
  70. With three \\[universal-argument]'s searching starts at the beginning of the
  71.   current page.
  72. With four \\[universal-argument]'s searching starts at the beginning of the
  73.   current buffer (clipping restrictions apply).
  74.  
  75. Once located, the comment is copied into a temporary buffer, the comment
  76. leaders and delimiters are stripped away and the resulting buffer is
  77. selected for editing.  The major mode of this buffer is controlled by
  78. the variable `c-comment-edit-mode'.
  79.  
  80. Use \\[c-comment-edit-end] when you have finished editing the comment.  The
  81. comment will be inserted into the original buffer with the appropriate
  82. delimiters and indention, replacing the old version of the comment.  If
  83. you don't want your edited version of the comment to replace the
  84. original, use \\[c-comment-edit-abort]." 
  85.   (interactive "*P")
  86.   (let ((c-buffer (current-buffer))
  87.     marker tem c-comment-fill-column c-comment-buffer
  88.     c-comment-start c-comment-end
  89.     (inhibit-quit t))
  90.     ;; honor search-prefix
  91.     (cond ((equal search-prefix '(4))
  92.        (backward-paragraph))
  93.       ((equal search-prefix '(16))
  94.        (end-of-defun)
  95.        (beginning-of-defun)
  96.        (backward-paragraph))
  97.       ((equal search-prefix '(64))
  98.        (backward-page))
  99.       ((equal search-prefix '(256))
  100.        (goto-char (point-min))))
  101.     (if (and (null search-prefix) (setq tem (within-c-comment-p)))
  102.     (setq c-comment-start (marker (car tem))
  103.           c-comment-end (marker (cdr tem)))
  104.       (let (start end)
  105.     (condition-case error-data
  106.         (save-point
  107.           (search-forward "/*")
  108.           (setq start (- (point) 2))
  109.           (search-forward "*/")
  110.           (setq end (point)))
  111.       (search-failed (error "No C comment found.")))
  112.     (setq c-comment-start (marker start))
  113.     (setq c-comment-end (marker end))))
  114.     ;; calculate the correct fill-column for the comment
  115.     (setq c-comment-fill-column (- fill-column
  116.                    (save-excursion
  117.                      (goto-char c-comment-start)
  118.                      (current-column))))
  119.     ;; create the comment buffer
  120.     (setq c-comment-buffer
  121.       (generate-new-buffer (concat (buffer-name) " *C Comment Edit*")))
  122.     ;; link into the c-comment-edit-buffer-alist
  123.     (setq c-comment-edit-buffer-alist
  124.       (cons (list (current-buffer) c-comment-buffer
  125.               c-comment-start c-comment-end)
  126.         c-comment-edit-buffer-alist))
  127.     ;; copy to the comment to the comment-edit buffer
  128.     (copy-to-buffer c-comment-buffer (+ c-comment-start 2) (- c-comment-end 2))
  129.     ;; mark the position of point, relative to the beginning of the
  130.     ;; comment, in the comment buffer.  (iff point is within a comment.)
  131.     (or search-prefix (< (point) c-comment-start)
  132.     (setq marker (marker (+ (- (point) c-comment-start 2) 1)
  133.                  c-comment-buffer)))
  134.     ;; select the comment buffer for editing
  135.     (switch-to-buffer c-comment-buffer)
  136.     ;; remove the comment leaders and delimiters
  137.     (goto-char (point-min))
  138.     (while (not (eobp))
  139.       (and (re-search-forward c-comment-leader-regexp nil t)
  140.        (replace-match "" nil t))
  141.       (forward-line))
  142.     ;; run appropriate major mode
  143.     (funcall (or c-comment-edit-mode 'fundamental-mode))
  144.     ;; override user's default fill-column here since it will lose if
  145.     ;; the comment is indented in the C buffer.
  146.     (setq fill-column c-comment-fill-column)
  147.     ;; delete one leading whitespace char
  148.     (goto-char (point-min))
  149.     (if (looking-at "[ \n\t]")
  150.     (delete-char 1))
  151.     ;; restore cursor if possible
  152.     (goto-char (or marker (point-min)))
  153.     (set-buffer-modified-p nil))
  154.   ;; run user hook, if present.
  155.   (if c-comment-edit-hook
  156.       (funcall c-comment-edit-hook))
  157.   ;; final admonition
  158.   (message
  159.    (substitute-command-keys
  160.     "Type \\[c-comment-edit-end] to end edit, \\[c-comment-edit-abort] to abort with no change.")))
  161.  
  162. (defun c-comment-edit-end ()
  163.   "End c-comment-edit.
  164. C comment is replaced by its edited counterpart in the appropriate C buffer.
  165. Indentation will be the same as the original."
  166.   (interactive)
  167.   (let ((tuple (find-c-comment-buffer)))
  168.     (if (null tuple)
  169.     (error "Not a c-comment-edit buffer."))
  170.     (let ((inhibit-quit t)
  171.       (c-comment-c-buffer (car tuple))
  172.       (c-comment-buffer (nth 1 tuple))
  173.       (c-comment-start (nth 2 tuple))
  174.       (c-comment-end (nth 3 tuple)))
  175.       (cond
  176.        ((buffer-modified-p)
  177.     ;; rebuild the comment
  178.     (goto-char (point-min))
  179.     (insert "/*\n")
  180.     (if (string= c-comment-leader "  ")
  181.         (while (not (eobp))
  182.           (if (not (eolp))
  183.           (insert c-comment-leader " "))
  184.           (forward-line))
  185.       (while (not (eobp))
  186.         (insert c-comment-leader (if (eolp) "" " "))
  187.         (forward-line)))
  188.     (if (not (char-equal (preceding-char) ?\n))
  189.         (insert "\n"))
  190.     (insert (if (string= c-comment-leader " *") " */" "*/"))
  191.     ;; indent if necessary
  192.     (let ((indention
  193.            (save-excursion
  194.          (set-buffer c-comment-c-buffer)
  195.          (goto-char c-comment-start)
  196.          (current-column))))
  197.       (goto-char (point-min))
  198.       (cond ((not (zerop indention))
  199.          ;; first line is already indented
  200.          ;; in the C buffer
  201.          (forward-line)
  202.          (while (not (eobp))
  203.            (indent-to indention)
  204.            (forward-line)))))
  205.     ;; replace the old comment with the new
  206.     (save-excursion
  207.       (set-buffer c-comment-c-buffer)
  208.       (save-point
  209.         (save-excursion
  210.           (delete-region c-comment-start c-comment-end)
  211.           (goto-char c-comment-start)
  212.           (set-buffer c-comment-buffer)
  213.           (append-to-buffer c-comment-c-buffer
  214.                 (point-min) (point-max))))))
  215.        (t (message "No change.")))
  216.       ;; switch to the C buffer
  217.       (if (get-buffer-window c-comment-c-buffer)
  218.       (select-window (get-buffer-window c-comment-c-buffer))
  219.     (switch-to-buffer c-comment-c-buffer))
  220.       ;; delete the window viewing the comment buffer
  221.       (and (get-buffer-window c-comment-buffer)
  222.        (delete-window (get-buffer-window c-comment-buffer)))
  223.       ;; unlink the tuple from c-comment-edit-buffer-alist
  224.       (setq c-comment-edit-buffer-alist
  225.         (delq tuple c-comment-edit-buffer-alist))
  226.       ;; let Emacs reclaim various resources
  227.       (save-excursion
  228.     (set-buffer c-comment-buffer)
  229.     (set-buffer-modified-p nil)
  230.     (kill-buffer c-comment-buffer))
  231.       (set-marker c-comment-start nil)
  232.       (set-marker c-comment-end nil))))
  233.  
  234. (defun c-comment-edit-abort ()
  235.   "Abort a c-comment-edit with no change."
  236.   (interactive)
  237.   (let* ((tuple (find-c-comment-buffer))
  238.      (c-comment-c-buffer (car tuple))
  239.      (c-comment-buffer (nth 1 tuple))
  240.      (c-comment-start (nth 2 tuple))
  241.      (c-comment-end (nth 3 tuple)))
  242.     (if (null tuple)
  243.     (error "Not a c-comment-edit buffer."))
  244.     ;; switch to the C buffer
  245.     (if (get-buffer-window c-comment-c-buffer)
  246.     (select-window (get-buffer-window c-comment-c-buffer))
  247.       (switch-to-buffer c-comment-c-buffer))
  248.     (let ((inhibit-quit t))
  249.       (save-excursion
  250.     (set-buffer c-comment-buffer)
  251.     (set-buffer-modified-p nil)
  252.     (kill-buffer c-comment-buffer))
  253.       ;; unlink the tuple from c-comment-edit-buffer-alist
  254.       (setq c-comment-edit-buffer-alist
  255.         (delq tuple c-comment-edit-buffer-alist))
  256.       (set-marker c-comment-start nil)
  257.       (set-marker c-comment-end nil)
  258.       (message "Aborted with no change."))))
  259.  
  260. ;; this loses on /* /* */ but doing it right would be grim.
  261. (defun within-c-comment-p ()
  262.   (condition-case error-data
  263.       (let (start end)
  264.     (save-point
  265.       (search-backward "/*")
  266.       (setq start (point))
  267.       (search-forward "*/")
  268.       (setq end (point)))
  269.     (if (< (point) end) (cons start end) nil))
  270.     (search-failed nil)))
  271.  
  272. (defun find-c-comment-buffer (&optional buffer)
  273.   (or buffer (setq buffer (current-buffer)))
  274.   (let ((list c-comment-edit-buffer-alist))
  275.     (catch 'return-value
  276.       (while list
  277.     (if (eq (nth 1 (car list)) buffer)
  278.         (throw 'return-value (car list))
  279.       (setq list (cdr list)))))))
  280.         
  281. (defun find-c-comment-c-buffer (&optional buffer)
  282.   (or buffer (setq buffer (current-buffer)))
  283.   (let ((list c-comment-edit-buffer-alist))
  284.     (catch 'return-value
  285.       (while list
  286.     (if (eq (car (car list)) buffer)
  287.         (throw 'return-value (car list))
  288.       (setq list (cdr list)))))))
  289.  
  290. ;; keys;
  291. (define-key mode-specific-map "\e" 'c-comment-edit-end)
  292. (define-key mode-specific-map "\C-]" 'c-comment-edit-abort)
  293.  
  294.  
  295.