home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / source / jade-3.2.lha / jade-3.2 / lisp / xc.jl < prev   
Encoding:
Text File  |  1994-10-02  |  5.1 KB  |  155 lines

  1. ;;;; xc-mode.jl -- new indentation for C mode
  2.  
  3. ;;; Needless to say this doesn't work 100% yet :-{
  4. ;;; Require this file (`xc') to use it.
  5.  
  6. (provide 'xc)
  7.  
  8.  
  9. ;; User options to define the indentation style
  10.  
  11. ;; Example settings:
  12. ;;                   BSD  GNU  K&R
  13. ;; c-body-indent      4    2    5
  14. ;; c-brace-indent    -4    0   -5
  15. ;; c-case-indent     -4   -2   -5
  16. ;; c-label-indent    -4   -2   -5
  17.  
  18. (defvar c-body-indent 4
  19.   "Indentation of code with respect to its containing block.")
  20. (defvar c-brace-indent -4
  21.   "Extra indentation of braces relative to the body of the code they
  22. contain.")
  23. (defvar c-case-indent -4
  24.   "Extra indentation for case statements.")
  25. (defvar c-label-indent -4
  26.   "Extra indentation for labels.")
  27.  
  28.  
  29. ;; Installation; hooks into c-mode, installing its own indentation function
  30. (add-hook 'c-mode-hook #'(lambda ()
  31.                (setq mode-indent-line 'xc-indent-line
  32.                  mode-name "XC")
  33.                (eval-hook 'xc-mode-hook)
  34.                nil))
  35.  
  36.  
  37. ;; The business
  38.  
  39. (defun xc-indent-line (&optional pos)
  40.   "Indent the line at POS (or the cursor) assuming that it's C source code."
  41.   (set-indent-pos (xc-indent-pos pos)))
  42.  
  43. ;; Attempt to find the previous statement
  44. (defun xc-backward-stmt (pos)
  45.   (let*
  46.       (stmt-pos
  47.        back-1-pos)
  48.     (error-protect
  49.     (while (setq pos (c-backward-exp 1 pos t))
  50.       (cond
  51.        ((null back-1-pos)
  52.         (setq back-1-pos pos))
  53.        ((/= (pos-line back-1-pos) (pos-line pos))
  54.         ;; Gone past the start of this line
  55.         (error "Ignored")))        ; break the loop
  56.       (setq stmt-pos pos))
  57.       (error))
  58.     stmt-pos))
  59.  
  60. ;; POS should point to an `else' keyword, the position of it's matching `if'
  61. ;; will be returned.
  62. (defun xc-balance-ifs (pos &optional depth)
  63.   (unless depth
  64.     (setq depth 1))
  65.   (while (and (/= depth 0)
  66.           (setq pos (xc-backward-stmt pos)))
  67.     (cond
  68.      ((and (looking-at "else[\t ]*" pos)
  69.        (not (looking-at "[\t ]*if[\t ]*\\(" (match-end))))
  70.       (setq depth (1+ depth)))
  71.      ((looking-at "if" pos)
  72.       (setq depth (1- depth)))))
  73.   (when (zerop depth)
  74.     pos))
  75.  
  76. ;; Work out where to indent LINE-POS to.
  77. (defun xc-indent-pos (&optional line-pos)
  78.   (setq line-pos (if line-pos
  79.              (line-start line-pos)
  80.            (line-start)))
  81.   ;; Check for cpp op
  82.   (if (regexp-match-line "^[\t ]*#" line-pos)
  83.       (pos 0 (pos-line line-pos))
  84.     (let*
  85.     ((pos (copy-pos line-pos))
  86.      (exp-pos (xc-backward-stmt pos))
  87.      exp-ind)
  88.       ;; Find the beginning of the expression to indent relative to
  89.       (unless exp-pos
  90.     ;; Start of the containing expression
  91.     (when (find-prev-regexp "[\{\(]" pos)
  92.       (setq exp-pos (match-start))))
  93.       (setq exp-ind (char-to-glyph-pos exp-pos))
  94.       (unless (equal (indent-pos exp-pos) exp-ind)
  95.     (when (and (regexp-match-line "^[\t ]*([^][(){}\"'a-zA-Z0-9_\t ]+)"
  96.                       (line-start exp-pos))
  97.            (< (match-start 1) exp-pos))
  98.       ;; Back up over the bits of punctuation
  99.       (setq exp-ind (char-to-glyph-pos (match-start 1)))))
  100.       ;; First look at previous line and see how it affects the one we're
  101.       ;; trying to indent
  102.       (cond
  103.        ((= (get-char exp-pos) ?\})
  104.     (unless (zerop (pos-col exp-pos))
  105.       (left-char (+ c-body-indent c-brace-indent) exp-ind)))
  106. ;      ((regexp-match-line "^[\t ]*{" exp-pos)
  107. ;    (setq exp-ind (right-char c-body-indent (indent-pos exp-pos))))
  108.        ((looking-at ".*{" exp-pos)
  109.     (setq exp-ind (right-char c-body-indent (indent-pos exp-pos))))
  110.        ((looking-at "(if|for|while|switch)[\t ]*\\(.*$|(else|do)([^a-z]|$)"
  111.             exp-pos)
  112.     (right-char c-body-indent exp-ind))
  113.        ((= (get-char exp-pos) ?\}))
  114.        ((looking-at ".*\;" exp-pos)
  115.     (let
  116.         ((prev (xc-backward-stmt exp-pos)))
  117.       ;; *Need to loop here searching back to the correct level*
  118.       (when (and prev (/= (pos-col prev) (pos-col exp-pos))
  119.              (not (looking-at "case .*:|default[\t ]*:|.*;" prev)))
  120.         ;; A continuation?
  121.         (when (and (looking-at "else[\t ]*" prev)
  122.                (not (looking-at "[\t ]*if[\t ]*\\(" (match-end))))
  123.           (unless (setq prev (xc-balance-ifs prev))
  124.         (error "Beginning of buffer"))
  125.           (let
  126.           ((tmp (xc-backward-stmt prev)))
  127.         (while (and tmp (looking-at "if[\t ]*\\(" tmp))
  128.           (setq prev tmp)
  129.           (unless (setq tmp (xc-backward-stmt tmp))
  130.             (error "Beginning of buffer")))))
  131.         (set-pos-col exp-ind (pos-col (char-to-glyph-pos prev))))))
  132.        ((looking-at "case .*:|default[\t ]*:" exp-pos)
  133.     (left-char c-case-indent exp-ind))
  134.        ((looking-at "[a-zA-Z_][a-zA-Z0-9_]+:" exp-pos)
  135.     (unless (left-char c-label-indent exp-ind)
  136.       (setq exp-ind (pos 0 (pos-line exp-pos))))))
  137.       ;; Next, look at the contents of this line and see if it needs any
  138.       ;; special treatment
  139.       (unless (empty-line-p line-pos)
  140.     (when (regexp-match-line "^[\t\f ]+" line-pos)
  141.       (setq line-pos (match-end)))
  142.     (cond
  143.      ((= (get-char line-pos) ?\{)
  144.       (if (< (pos-col exp-pos) (- c-brace-indent))
  145.           (set-pos-col exp-pos 0)
  146.         (right-char c-brace-indent exp-ind)))
  147.      ((= (get-char line-pos) ?\})
  148.       (left-char c-body-indent exp-ind))
  149.      ((looking-at "case .*:|default[\t ]*:" line-pos)
  150.       (right-char c-case-indent exp-ind))
  151.      ((looking-at "[a-zA-Z_]+[a-zA-Z0-9_]*:" line-pos)
  152.       (right-char c-label-indent exp-ind))))
  153.       (set-pos-line exp-ind (pos-line line-pos))
  154.       exp-ind)))
  155.