home *** CD-ROM | disk | FTP | other *** search
- ;;;; xc-mode.jl -- new indentation for C mode
-
- ;;; Needless to s0¼Ö6Ç&ñX9ÃÔòèÆ¡NPúüe!MYGDL%1-åe³t@8)ñ5ÕF"DÉ©ínð:Z×ÔÃÀL»(9BJæËüJ)Æl¢%ÑÊúR³xPPË}j\lJúN/VÎ6Ú4ÃÑÜao,2Dè»×Dà!!¾¶6Yf67×ÂlؼrS̨©Èsf|ùØéåØJÚyæñðúñÂí¼ðffÆ
- 4µ2X^umIÁ
`¤Êyç¤x|Ñ ål¦Ï¥N¼@%ß<Ìæm¥D3
- ž EXåêêLEuÂ8*µO\o¦V1¬¥rHZ
- ùP %À@ÑDáºÕ^S×ML
- ^ wÕ*Å~S·<àYñ<à -2 -5
-
- (defvar c-body-indent 4
- "Indentation of code with respect to its containing block.")
- (defvar c-brace-indent -4
- "Extra indentation of braces relative to the body of the code they
- contain.")
- (defvar c-case-indent -4
- "Extra indentation for case statements.")
- (defvar c-label-indent -4
- "Extra indentation for labels.")
-
-
- ;; Installation; hooks into c-mode, installing its own indentation function
- (add-hook 'c-mode-hook #'(lambda ()
- (setq mode-indent-line 'xc-indent-line
- mode-name "XC")
- (eval-hook 'xc-mode-hook)
- nil))
-
-
- ;; The business
-
- (defun xc-indent-line (&optional pos)
- "Indent the line at POS (or the cursor) assuming that it's C source code."
- (set-indent-pos (xc-indent-pos pos)))
-
- ;; Attempt to find the previous statement
- (defun xc-backward-stmt (pos)
- (let*
- (stmt-pos
- back-1-pos)
- (error-protect
- (while (setq pos (c-backward-exp 1 pos t))
- (cond
- ((null back-1-pos)
- (setq back-1-pos pos))
- ((/= (pos-line back-1-pos) (pos-line pos))
- ;; Gone past the start of this line
- (error "Ignored"))) ; break the loop
- (setq stmt-pos pos))
- (error))
- stmt-pos))
-
- ;; POS should point to an `else' keyword, the position of it's matching `if'
- ;; will be returned.
- (defun xc-balance-ifs (pos &optional depth)
- (unless depth
- (setq depth 1))
- (while (and (/= depth 0)
- (setq pos (xc-backward-stmt pos)))
- (cond
- ((and (looking-at "else[\t ]*" pos)
- (not (looking-at "[\t ]*if[\t ]*\\(" (match-end))))
- (setq depth (1+ depth)))
- ((looking-at "if" pos)
- (setq depth (1- depth)))))
- (when (zerop depth)
- pos))
-
- ;; Work out where to indent LINE-POS to.
- (defun xc-indent-pos (&optional line-pos)
- (setq line-pos (if line-pos
- (line-start line-pos)
- (line-start)))
- ;; Check for cpp op
- (if (regexp-match-line "^[\t ]*#" line-pos)
- (pos 0 (pos-line line-pos))
- (let*
- ((pos (copy-pos line-pos))
- (exp-pos (xc-backward-stmt pos))
- exp-ind)
- ;; Find the beginning of the expression to indent relative to
- (unless exp-pos
- ;; Start of the containing expression
- (when (find-prev-regexp "[\{\(]" pos)
- (setq exp-pos (match-start))))
- (setq exp-ind (char-to-glyph-pos exp-pos))
- (unless (equal (indent-pos exp-pos) exp-ind)
- (when (and (regexp-match-line "^[\t ]*([^][(){}\"'a-zA-Z0-9_\t ]+)"
- (line-start exp-pos))
- (< (match-start 1) exp-pos))
- ;; Back up over the bits of punctuation
- (setq exp-ind (char-to-glyph-pos (match-start 1)))))
- ;; First look at previous line and see how it affects the one we're
- ;; trying to indent
- (cond
- ((= (get-char exp-pos) ?\})
- (unless (zerop (pos-col exp-pos))
- (left-char (+ c-body-indent c-brace-indent) exp-ind)))
- ; ((regexp-match-line "^[\t ]*{" exp-pos)
- ; (setq exp-ind (right-char c-body-indent (indent-pos exp-pos))))
- ((looking-at ".*{" exp-pos)
- (setq exp-ind (right-char c-body-indent (indent-pos exp-pos))))
- ((looking-at "(if|for|while|switch)[\t ]*\\(.*$|(else|do)([^a-z]|$)"
- exp-pos)
- (right-char c-body-indent exp-ind))
- ((= (get-char exp-pos) ?\}))
- ((looking-at ".*\;" exp-pos)
- (let
- ((prev (xc-backward-stmt exp-pos)))
- ;; *Need to loop here searching back to the correct level*
- (when (and prev (/= (pos-col prev) (pos-col exp-pos))
- (not (looking-at "case .*:|default[\t ]*:|.*;" prev)))
- ;; A continuation?
- (when (and (looking-at "else[\t ]*" prev)
- (not (looking-at "[\t ]*if[\t ]*\\(" (match-end))))
- (unless (setq prev (xc-balance-ifs prev))
- (error "Beginning of buffer"))
- (let
- ((tmp (xc-backward-stmt prev)))
- (while (and tmp (looking-at "if[\t ]*\\(" tmp))
- (setq prev tmp)
- (unless (setq tmp (xc-backward-stmt tmp))
- (error "Beginning of buffer")))))
- (set-pos-col exp-ind (pos-col (char-to-glyph-pos prev))))))
- ((looking-at "case .*:|default[\t ]*:" exp-pos)
- (left-char c-case-indent exp-ind))
- ((looking-at "[a-zA-Z_][a-zA-Z0-9_]+:" exp-pos)
- (unless (left-char c-label-indent exp-ind)
- (setq exp-ind (pos 0 (pos-line exp-pos))))))
- ;; Next, look at the contents of this line and see if it needs any
- ;; special treatment
- (unless (empty-line-p line-pos)
- (when (regexp-match-line "^[\t\f ]+" line-pos)
- (setq line-pos (match-end)))
- (cond
- ((= (get-char line-pos) ?\{)
- (if (< (pos-col exp-pos) (- c-brace-indent))
- (set-pos-col exp-pos 0)
- (right-char c-brace-indent exp-ind)))
- ((= (get-char line-pos) ?\})
- (left-char c-body-indent exp-ind))
- ((looking-at "case .*:|default[\t ]*:" line-pos)
- (right-char c-case-indent exp-ind))
- ((looking-at "[a-zA-Z_]+[a-zA-Z0-9_]*:" line-pos)
- (right-char c-label-indent exp-ind))))
- (set-pos-line exp-ind (pos-line line-pos))
- exp-ind)))
-