SHOW:
|
|
- or go back to the newest paste.
1 | ;;; ppindent.el --- Indents C preprocessor directives | |
2 | ||
3 | ;; Copyright (C) 2007 Free Software Foundation, Inc. | |
4 | ||
5 | ;; Author: Craig McDaniel <craigmcd@gmail.com> | |
6 | ;; Keywords: languages, c | |
7 | ;; Maintainer: Craig McDaniel <craigmcd@gmail.com> | |
8 | ||
9 | ;; This file is free software; you can redistribute it and/or modify | |
10 | ;; it under the terms of the GNU General Public License as published by | |
11 | ;; the Free Software Foundation; either version 2, or (at your option) | |
12 | ;; any later version. | |
13 | ||
14 | ;; This file is distributed in the hope that it will be useful, | |
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | ;; GNU General Public License for more details. | |
18 | ||
19 | ;; You should have received a copy of the GNU General Public License | |
20 | ;; along with GNU Emacs; see the file COPYING. If not, write to | |
21 | ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 | ;; Boston, MA 02111-1307, USA. | |
23 | ||
24 | ;;; Commentary: | |
25 | ||
26 | ;; PPINDENT indents C-preprocessor statements depending on the current | |
27 | ;; #if..., #el.., #endif level. It only modifies lines with "#" as the | |
28 | ;; first non-blank character and therefore does not conflict with the | |
29 | ;; normal C indentation. Unlike a true indent, it inserts the | |
30 | ;; requisite number of spaces after, rather than before the "#" | |
31 | ;; character. This type of preprocesor indent is commonly used to | |
32 | ;; provide the most compatibility with different C-compilers. | |
33 | ;; | |
34 | ;; Example: | |
35 | ||
36 | ;; #ifdef WOO | |
37 | ;; .... | |
38 | ;; #if defined(X) && !defined(Y) | |
39 | ;; #ifdef Q8 | |
40 | ;; ... | |
41 | ;; #else | |
42 | ;; ... | |
43 | ;; .... | |
44 | ;; #elif defined (Z) | |
45 | ;; .... | |
46 | ;; #endif | |
47 | ;; #endif | |
48 | ;; #endif | |
49 | ||
50 | ;; After "M-x ppindent-c" becomes: | |
51 | ||
52 | ;; #ifdef WOO | |
53 | ;; .... | |
54 | - | ;; # if defined(X) && !defined(Y) |
54 | + | ;; #if defined(X) && !defined(Y) |
55 | - | ;; # ifdef Q8 |
55 | + | ;; #ifdef Q8 |
56 | ;; ... | |
57 | - | ;; # else |
57 | + | ;; #else |
58 | ;; ... | |
59 | ;; .... | |
60 | - | ;; # elif defined (Z) |
60 | + | ;; #elif defined (Z) |
61 | ;; .... | |
62 | - | ;; # endif |
62 | + | ;; #endif |
63 | - | ;; # endif |
63 | + | ;; #endif |
64 | ;; #endif | |
65 | ||
66 | ;; Two functions are provided: PPINDENT-C indents as described | |
67 | ;; above. PPINDENT-H does not indent the first level, assuming that | |
68 | ;; .h/.hpp files use an #ifdef guard around the entire file. | |
69 | ||
70 | ;; You can customize PPINDENT-INCREMENT if you want to use something | |
71 | ;; other than 2 spaces for the indent. | |
72 | ||
73 | ;;; History: | |
74 | ||
75 | ;; 2007-01-19 WCM Initial version | |
76 | ||
77 | ;;; Code: | |
78 | ||
79 | (provide 'ppindent) | |
80 | ||
81 | (defgroup pp-indent nil | |
82 | "Indent C preproccessor directives." | |
83 | :group 'c) | |
84 | ||
85 | (defcustom ppindent-increment 2 | |
86 | "Number of spaces per indention level. | |
87 | ||
88 | Used in C pre-processor indent functions ppindent-c and ppindent-h" | |
89 | :type 'number | |
90 | :group 'pp-indent) | |
91 | ||
92 | (defun starts-withp (str prefix) | |
93 | "str starts with prefix" | |
94 | (eql (compare-strings prefix nil nil str nil (length prefix)) t)) | |
95 | ||
96 | (defun my-make-string (length init) | |
97 | "just like make-string, but makes an empty string if length is negative" | |
98 | (when (minusp length) | |
99 | (setf length 0)) | |
100 | (make-string length init)) | |
101 | ||
102 | (defun ppindent-aux (start) | |
103 | (let ((cnt start)) | |
104 | (goto-char (point-min)) | |
105 | (while (re-search-forward "^[ \t]*#[ \t]*\\(.*\\)" nil t) | |
106 | (cond ((starts-withp (match-string-no-properties 1) "if") | |
107 | (replace-match (concat (my-make-string cnt ?\s) "#\\1")) | |
108 | (incf cnt ppindent-increment)) | |
109 | ((starts-withp (match-string-no-properties 1) "el") | |
110 | (when (< (- cnt ppindent-increment) start) | |
111 | (throw 'err `(,(line-number-at-pos) "Unmatched #else or #elif"))) | |
112 | (replace-match (concat (my-make-string | |
113 | (- cnt ppindent-increment) | |
114 | ?\s) "#\\1"))) | |
115 | ((starts-withp (match-string-no-properties 1) "endif") | |
116 | (when (< (- cnt ppindent-increment) start) | |
117 | (throw 'err `(,(line-number-at-pos) "Unmatched #endif"))) | |
118 | (decf cnt ppindent-increment) | |
119 | (replace-match (concat (my-make-string cnt ?\s) "#\\1"))) | |
120 | (t | |
121 | (replace-match (concat (my-make-string cnt ?\s) "#\\1"))))))) | |
122 | ||
123 | (defun ppindent-buffer (start) | |
124 | (let ((result (catch 'err (save-excursion (ppindent-aux start))))) | |
125 | (when result | |
126 | (goto-line (car result)) | |
127 | (error "Error: %s" (cadr result))))) | |
128 | ||
129 | (defun ppindent-c () | |
130 | "Indent all C pre-processor statements" | |
131 | (interactive) | |
132 | (ppindent-buffer 0)) | |
133 | ||
134 | (defun ppindent-h () | |
135 | "Indent C pre-processor statements, keeping first level #ifdef unindented" | |
136 | (interactive) | |
137 | (ppindent-buffer (- ppindent-increment))) |