Add arch taglines
[bpt/emacs.git] / lisp / progmodes / glasses.el
CommitLineData
efd68b8a
GM
1;;; glasses.el --- make cantReadThis readable
2
7aee34d3 3;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
efd68b8a 4
7aee34d3
GM
5;; Author: Milan Zamazal <pdm@zamazal.org>
6;; Maintainer: Milan Zamazal <pdm@zamazal.org>
efd68b8a
GM
7;; Keywords: tools
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
25
26;;; Commentary:
27
28;; This file defines a minor mode for making unreadableIdentifiersLikeThis
29;; readable. In some environments, for instance Java, it is common to use such
30;; unreadable identifiers. It is not good to use underscores in identifiers of
31;; your own project in such an environment to make your sources more readable,
32;; since it introduces undesirable confusion, which is worse than the
33;; unreadability. Fortunately, you use Emacs for the subproject, so the
34;; problem can be solved some way.
35;;
36;; This file defines the `glasses-mode' minor mode, which displays underscores
37;; between all the pairs of lower and upper English letters. (This only
38;; displays underscores, the text is not changed actually.) Alternatively, you
39;; can say you want the capitals in some given face (e.g. bold).
40;;
41;; The mode does something usable, though not perfect. Improvement suggestions
42;; from Emacs experts are welcome.
43;;
44;; If you like in-identifier separators different from underscores, change the
45;; value of the variable `glasses-separator' appropriately. See also the
46;; variables `glasses-face' and `glasses-convert-on-write-p'. You can also use
47;; the command `M-x customize-group RET glasses RET'.
48;;
49;; If you set any of the variables `glasses-separator' or `glasses-face' after
170c1b26 50;; glasses.el is loaded in a different way than through customize, you
efd68b8a
GM
51;; should call the function `glasses-set-overlay-properties' afterwards.
52
53;;; Code:
54
55
56(eval-when-compile
57 (require 'cl))
58
59
60;;; User variables
61
62
63(defgroup glasses nil
170c1b26 64 "Make unreadable code likeThis(one) readable."
c17c99ad 65 :version "21.1"
efd68b8a
GM
66 :group 'tools)
67
68
69(defcustom glasses-separator "_"
70 "*String to be displayed as a visual separator in unreadable identifiers."
71 :group 'glasses
72 :type 'string
73 :set 'glasses-custom-set
74 :initialize 'custom-initialize-default)
75
76
77(defcustom glasses-face nil
78 "*Face to be put on capitals of an identifier looked through glasses.
79If it is nil, no face is placed at the capitalized letter.
80
81For example, you can set `glasses-separator' to an empty string and
82`glasses-face' to `bold'. Then unreadable identifiers will have no separators,
83but will have their capitals in bold."
84 :group 'glasses
85 :type 'symbol
86 :set 'glasses-custom-set
87 :initialize 'custom-initialize-default)
88
89
170c1b26
GM
90(defcustom glasses-separate-parentheses-p t
91 "*If non-nil, ensure space between an identifier and an opening parenthesis."
92 :group 'glasses
93 :type 'boolean)
94
95
96(defcustom glasses-uncapitalize-p nil
97 "*If non-nil, downcase embedded capital letters in identifiers.
98Only identifiers starting with lower case letters are affected, letters inside
99other identifiers are unchanged."
100 :group 'glasses
101 :type 'boolean
102 :set 'glasses-custom-set
103 :initialize 'custom-initialize-default)
104
105
106(defcustom glasses-uncapitalize-regexp "[a-z]"
107 "*Regexp matching beginnings of words to be uncapitalized.
108Only words starting with this regexp are uncapitalized.
109The regexp is case sensitive.
110It has any effect only when `glasses-uncapitalize-p' is non-nil."
111 :group 'glasses
112 :type 'regexp
113 :set 'glasses-custom-set
114 :initialize 'custom-initialize-default)
115
116
efd68b8a
GM
117(defcustom glasses-convert-on-write-p nil
118 "*If non-nil, remove separators when writing glasses buffer to a file.
119If you are confused by glasses so much, that you write the separators into code
120during coding, set this variable to t. The separators will be removed on each
121file write then.
122
123Note the removal action does not try to be much clever, so it can remove real
124separators too."
125 :group 'glasses
126 :type 'boolean)
127
128
129(defun glasses-custom-set (symbol value)
130 "Set value of the variable SYMBOL to VALUE and update overlay categories.
131Used in :set parameter of some customized glasses variables."
c17c99ad 132 (set-default symbol value)
efd68b8a
GM
133 (glasses-set-overlay-properties))
134
135
136;;; Utility functions
137
138
139(defun glasses-set-overlay-properties ()
140 "Set properties of glasses overlays.
141Consider current setting of user variables."
142 ;; In-identifier overlay
143 (put 'glasses 'evaporate t)
144 (put 'glasses 'before-string glasses-separator)
145 (put 'glasses 'face glasses-face)
146 ;; Beg-identifier overlay
147 (put 'glasses-init 'evaporate t)
170c1b26
GM
148 (put 'glasses-init 'face glasses-face)
149 ;; Parenthesis overlay
150 (put 'glasses-parenthesis 'evaporate t)
151 (put 'glasses-parenthesis 'before-string " "))
efd68b8a
GM
152
153(glasses-set-overlay-properties)
154
155
156(defun glasses-overlay-p (overlay)
157 "Return whether OVERLAY is an overlay of glasses mode."
170c1b26
GM
158 (memq (overlay-get overlay 'category)
159 '(glasses glasses-init glasses-parenthesis)))
efd68b8a
GM
160
161
170c1b26
GM
162(defun glasses-make-overlay (beg end &optional category)
163 "Create and return readability overlay over the region from BEG to END.
164CATEGORY is the overlay category. If it is nil, use the `glasses' category."
efd68b8a 165 (let ((overlay (make-overlay beg end)))
170c1b26
GM
166 (overlay-put overlay 'category (or category 'glasses))
167 overlay))
efd68b8a
GM
168
169
170(defun glasses-make-readable (beg end)
171 "Make identifiers in the region from BEG to END readable."
172 (let ((case-fold-search nil))
173 (save-excursion
174 (save-match-data
175 ;; Face only
176 (goto-char beg)
177 (while (re-search-forward
178 "\\<\\([A-Z]\\)[a-zA-Z]*\\([a-z][A-Z]\\|[A-Z][a-z]\\)"
179 end t)
170c1b26
GM
180 (glasses-make-overlay (match-beginning 1) (match-end 1)
181 'glasses-init))
efd68b8a 182 ;; Face + separator
170c1b26 183 (goto-char beg)
efd68b8a
GM
184 (while (re-search-forward "[a-z]\\([A-Z]\\)\\|[A-Z]\\([A-Z]\\)[a-z]"
185 end t)
170c1b26
GM
186 (let* ((n (if (match-string 1) 1 2))
187 (o (glasses-make-overlay (match-beginning n) (match-end n))))
188 (goto-char (match-beginning n))
189 (when (and glasses-uncapitalize-p
15cca6c4
GM
190 (save-match-data
191 (looking-at "[A-Z]\\($\\|[^A-Z]\\)"))
170c1b26
GM
192 (save-excursion
193 (save-match-data
194 (re-search-backward "\\<.")
195 (looking-at glasses-uncapitalize-regexp))))
196 (overlay-put o 'invisible t)
197 (overlay-put o 'after-string (downcase (match-string n))))))
198 ;; Parentheses
199 (when glasses-separate-parentheses-p
200 (goto-char beg)
7aee34d3 201 (while (re-search-forward "[a-zA-Z]_*\\(\(\\)" end t)
170c1b26
GM
202 (glasses-make-overlay (match-beginning 1) (match-end 1)
203 'glasses-parenthesis)))))))
efd68b8a
GM
204
205
206(defun glasses-make-unreadable (beg end)
207 "Return identifiers in the region from BEG to END to their unreadable state."
208 (dolist (o (overlays-in beg end))
209 (when (glasses-overlay-p o)
210 (delete-overlay o))))
211
212
213(defun glasses-convert-to-unreadable ()
214 "Convert current buffer to unreadable identifiers and return nil.
215This function modifies buffer contents, it removes all the separators,
216recognized according to the current value of the variable `glasses-separator'."
217 (when (and glasses-convert-on-write-p
218 (not (string= glasses-separator "")))
971c5b28
GM
219 (let ((case-fold-search nil)
220 (separator (regexp-quote glasses-separator)))
efd68b8a
GM
221 (save-excursion
222 (goto-char (point-min))
223 (while (re-search-forward
971c5b28
GM
224 (format "[a-z]\\(%s\\)[A-Z]\\|[A-Z]\\(%s\\)[A-Z][a-z]"
225 separator separator)
226 nil t)
efd68b8a
GM
227 (let ((n (if (match-string 1) 1 2)))
228 (replace-match "" t nil nil n)
170c1b26
GM
229 (goto-char (match-end n))))
230 (when glasses-separate-parentheses-p
231 (goto-char (point-min))
a21822f8 232 (while (re-search-forward "[a-zA-Z]_*\\( \\)\(" nil t)
170c1b26 233 (replace-match "" t nil nil 1))))))
efd68b8a
GM
234 ;; nil must be returned to allow use in write file hooks
235 nil)
236
237
5610cefd 238(defun glasses-change (beg end &optional old-len)
efd68b8a
GM
239 "After-change function updating glass overlays."
240 (let ((beg-line (save-excursion (goto-char beg) (line-beginning-position)))
241 (end-line (save-excursion (goto-char end) (line-end-position))))
242 (glasses-make-unreadable beg-line end-line)
243 (glasses-make-readable beg-line end-line)))
244
245
246;;; Minor mode definition
247
248
efd68b8a 249;;;###autoload
5610cefd 250(define-minor-mode glasses-mode
efd68b8a
GM
251 "Minor mode for making identifiers likeThis readable.
252When this mode is active, it tries to add virtual separators (like underscores)
253at places they belong to."
5610cefd
GM
254 nil " o^o" nil
255 (save-excursion
256 (save-restriction
257 (widen)
258 ;; We erase all the overlays anyway, to avoid dual sight in some
259 ;; circumstances
260 (glasses-make-unreadable (point-min) (point-max))
261 (if glasses-mode
262 (progn
263 (jit-lock-register 'glasses-change)
264 (add-hook 'local-write-file-hooks
265 'glasses-convert-to-unreadable nil t))
266 (jit-lock-unregister 'glasses-change)
267 (remove-hook 'local-write-file-hooks
268 'glasses-convert-to-unreadable t)))))
efd68b8a
GM
269
270
271;;; Announce
272
273(provide 'glasses)
274
275
ab5796a9 276;;; arch-tag: a3515167-c89e-484f-90a1-d85143e52b12
efd68b8a 277;;; glasses.el ends here