comparison lisp/modes/xrdb-mode.el @ 24:4103f0995bd7 r19-15b95

Import from CVS: tag r19-15b95
author cvs
date Mon, 13 Aug 2007 08:51:03 +0200
parents
children 441bb1e64a06
comparison
equal deleted inserted replaced
23:0edd3412f124 24:4103f0995bd7
1 ;;; xrdb-mode.el --- mode for editing X resource database files
2
3 ;; Author: 1994-1997 Barry A. Warsaw
4 ;; Maintainer: tools-help@python.org
5 ;; Created: May 1994
6 ;; Version: 1.17
7 ;; Last Modified: 1997/02/21 22:28:59
8 ;; Keywords: data languages
9
10 ;; Copyright (C) 1994 Barry A. Warsaw
11
12 ;; This file is not part of GNU Emacs.
13
14 ;; This program is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 2 of the License, or
17 ;; (at your option) any later version.
18 ;;
19 ;; This program is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
23 ;;
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with this program; if not, write to the Free Software
26 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27
28 ;;; Commentary:
29 ;;
30 ;; In 1994 I wrote:
31 ;;
32 ;; "I used to be like you. I used to hack on X resource database files
33 ;; all the time, and when I did, I found this mode to be fairly
34 ;; useful. It's by no means perfect. At one time I had a collection
35 ;; of hacks that did some nice indentation of resource lines, but
36 ;; they were not organized in any way. This mode was my attempt to
37 ;; congeal this mess into a proper major mode. I release it now, not
38 ;; because it will change your life, but because I don't plan to do
39 ;; anything more with it.
40 ;;
41 ;; I have since been enlightened and no longer have to cavort with
42 ;; mere mortal X hackers anymore. I like my brain cells, so now I
43 ;; use NEXTSTEP where all is glory. Or would you say I traded one
44 ;; vice for another? Hmm... Anyway, if you are still down in the
45 ;; trenches and would like to inherit this file, let me know. I
46 ;; don't intend to do any work on it any more... unless I lose my
47 ;; place in paradise. I promise to be good, Steve. :-) :-)"
48 ;;
49 ;; I have fallen from grace.
50
51 ;; Code:
52
53
54 ;; These variables are available for your customization
55 (defvar xrdb-mode-hook nil
56 "*Hook to be run when `xrdb-mode' is entered.")
57
58 (defvar xrdb-subdivide-by 'paragraph
59 "*Extent of alignment calculations.
60 Can be one of `buffer', `paragraph', `page', or `line'. Do a
61 \\[describe-function] xrdb-indent-buffer RET for more information.")
62
63
64
65 ;; no need to customize anything below this line
66 (defconst xrdb-comment-re "^[ \t]*[!]"
67 "Character which starts a comment.")
68 (defconst xrdb-separator-char ?:
69 "Character which separates resource specs from values.")
70
71
72 ;; utilities
73 (defsubst xrdb-point (position)
74 ;; Returns the value of point at certain commonly referenced POSITIONs.
75 ;; POSITION can be one of the following symbols:
76 ;;
77 ;; bol -- beginning of line
78 ;; eol -- end of line
79 ;; bod -- beginning of defun
80 ;; boi -- back to indentation
81 ;; ionl -- indentation of next line
82 ;; iopl -- indentation of previous line
83 ;; bonl -- beginning of next line
84 ;; bopl -- beginning of previous line
85 ;; bop -- beginning of paragraph
86 ;; eop -- end of paragraph
87 ;; bopg -- beginning of page
88 ;; eopg -- end of page
89 ;;
90 ;; This function does not modify point or mark.
91 (let ((here (point)))
92 (cond
93 ((eq position 'bol) (beginning-of-line))
94 ((eq position 'eol) (end-of-line))
95 ((eq position 'boi) (back-to-indentation))
96 ((eq position 'bonl) (forward-line 1))
97 ((eq position 'bopl) (forward-line -1))
98 ((eq position 'bop) (forward-paragraph -1))
99 ((eq position 'eop) (forward-paragraph 1))
100 ((eq position 'bopg) (forward-page -1))
101 ((eq position 'eopg) (forward-page 1))
102 (t
103 (error "unknown buffer position requested: %s" position)))
104 (prog1
105 (point)
106 (goto-char here))
107 ))
108
109 (defsubst xrdb-skip-to-separator ()
110 ;; skip forward from the beginning of the line to the separator
111 ;; character as given by xrdb-separator-char. Returns t if the
112 ;; char was found, otherwise, nil.
113 (beginning-of-line)
114 (skip-chars-forward
115 (concat "^" (char-to-string xrdb-separator-char))
116 (xrdb-point 'eol))
117 (= (following-char) xrdb-separator-char))
118
119
120
121 ;; commands
122 (defun xrdb-electric-separator (arg)
123 "Insert the separator character.
124 Re-align the line unless an argument is given."
125 (interactive "P")
126 ;; first insert the character
127 (self-insert-command (prefix-numeric-value arg))
128 ;; only do electric behavior if arg is not given
129 (if (not arg)
130 (xrdb-align-to (xrdb-point 'bol)
131 (xrdb-point 'bonl)
132 (save-excursion
133 (beginning-of-line)
134 (forward-comment (- (point-max)))
135 (beginning-of-line)
136 (xrdb-skip-to-separator)
137 (current-column)))))
138
139 (defun xrdb-align-to (start end goalcolumn)
140 (interactive "r\nnAlign to column: ")
141 (save-excursion
142 (save-restriction
143 (narrow-to-region start end)
144 (beginning-of-buffer)
145 (while (< (point) (point-max))
146 (if (and (not (looking-at xrdb-comment-re))
147 (xrdb-skip-to-separator)
148 goalcolumn)
149 (indent-code-rigidly (xrdb-point 'bol)
150 (xrdb-point 'bonl)
151 (- goalcolumn (current-column))))
152 (forward-line 1)))))
153
154 (defun xrdb-indent-line (arg)
155 "Re-align current line."
156 (interactive "P")
157 ;; narrow to the region specified by xrdb-subdivide-by
158 (save-excursion
159 (save-restriction
160 (widen)
161 (cond
162 ((eq xrdb-subdivide-by 'buffer))
163 ((eq xrdb-subdivide-by 'page)
164 (narrow-to-page))
165 ((eq xrdb-subdivide-by 'paragraph)
166 (narrow-to-region (xrdb-point 'bop) (xrdb-point 'eop)))
167 (t
168 (narrow-to-region (xrdb-point 'bopl) (xrdb-point 'bonl))
169 ))
170 ;; indent line
171 (xrdb-align-to (xrdb-point 'bol) (xrdb-point 'bonl)
172 (xrdb-region-goal-column))
173 )))
174
175 (defun xrdb-indent-region (start end)
176 "Re-align region."
177 (interactive "r")
178 ;; narrow to region
179 (save-excursion
180 (save-restriction
181 (narrow-to-region start end)
182 (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column))
183 )))
184
185 (defun xrdb-indent-page ()
186 "Re-align the current page."
187 (interactive)
188 (save-excursion
189 (save-restriction
190 (narrow-to-page)
191 (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column))
192 )))
193
194 (defun xrdb-indent-paragraph ()
195 "Re-align the current paragraph."
196 (interactive)
197 (save-excursion
198 (save-restriction
199 (narrow-to-region (xrdb-point 'bop) (xrdb-point 'eop))
200 (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column))
201 )))
202
203 (defun xrdb-indent-buffer (arg)
204 "Re-align the entire buffer.
205 Alignment calculations are controlled by the variable
206 `xrdb-subdivide-by', which can take the values `buffer', `paragraph',
207 `page', or `line', with the following meanings:
208
209 buffer - all non-comment lines are aligned with the longest line in
210 the buffer. Since every line must be scanned, this will
211 take the longest to perform.
212
213 paragraph - alignment of lines spanning paragraphs. A paragraph is
214 defined as all contiguous lines between blank or comment
215 lines.
216
217 page - alignment of lines spanning pages (i.e. separated by
218 page-delimiter, usually ^L).
219
220 none - alignment of lines based on the previous line.
221
222 With optional \\[universal-argument], queries for alignment subdivision."
223 (interactive "P")
224 (let ((align-by (if (not arg)
225 xrdb-subdivide-by
226 (completing-read
227 "Align by: "
228 '(("buffer" . buffer)
229 ("paragraph" . paragraph)
230 ("page" . page)
231 ("line" . line))
232 nil t (format "%s" xrdb-subdivide-by)))))
233 (message "Aligning by %s..." align-by)
234 (save-excursion
235 (save-restriction
236 (widen)
237 (cond
238 ;; by buffer
239 ((eq align-by 'buffer)
240 (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column)))
241 ;; by paragraph
242 ((eq align-by 'paragraph)
243 (beginning-of-buffer)
244 (while (< (point) (point-max))
245 (narrow-to-region (point) (xrdb-point 'eop))
246 (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column))
247 (beginning-of-buffer)
248 (widen)
249 (forward-paragraph 1)
250 ))
251 ;; by page
252 ((eq align-by 'page)
253 (beginning-of-buffer)
254 (while (< (point) (point-max))
255 (narrow-to-region (point) (xrdb-point 'eopg))
256 (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column))
257 (beginning-of-buffer)
258 (widen)
259 (forward-page 1)
260 ))
261 ;; by line
262 (t
263 (beginning-of-buffer)
264 (let ((prev-goalcol 0))
265 (while (< (point) (point-max))
266 ;; skip comments and blank lines
267 (if (not (looking-at paragraph-start))
268 (progn
269 (xrdb-align-to (xrdb-point 'bol) (xrdb-point 'bonl)
270 prev-goalcol)
271 (xrdb-skip-to-separator)
272 (setq prev-goalcol (- (point) (xrdb-point 'boi)))
273 ))
274 (forward-line 1))))
275 )))
276 (message "Aligning by %s... done." align-by)
277 ))
278
279
280 ;; major-mode stuff
281 (defvar xrdb-mode-abbrev-table nil
282 "Abbrev table used in `xrdb-mode' buffers.")
283 (define-abbrev-table 'xrdb-mode-abbrev-table ())
284
285
286 (defvar xrdb-mode-syntax-table nil
287 "Syntax table used in `xrdb-mode' buffers.")
288 (if xrdb-mode-syntax-table
289 ()
290 (setq xrdb-mode-syntax-table (make-syntax-table))
291 (modify-syntax-entry ?! "<" xrdb-mode-syntax-table)
292 (modify-syntax-entry ?\n ">" xrdb-mode-syntax-table))
293
294
295 (defvar xrdb-mode-map ()
296 "Keymap used in `xrdb-mode' buffers.")
297 (if xrdb-mode-map
298 ()
299 (setq xrdb-mode-map (make-sparse-keymap))
300 (let ((ekey (char-to-string xrdb-separator-char)))
301 ;; make the separator key electric
302 (define-key xrdb-mode-map ekey 'xrdb-electric-separator)
303 (define-key xrdb-mode-map "\t" 'xrdb-indent-line)
304 (define-key xrdb-mode-map "\C-c\C-a" 'xrdb-indent-paragraph)
305 (define-key xrdb-mode-map "\C-c\C-b" 'xrdb-submit-bug-report)
306 (define-key xrdb-mode-map "\C-c\C-p" 'xrdb-indent-page)
307 (define-key xrdb-mode-map "\C-c\C-r" 'xrdb-indent-region)
308 (define-key xrdb-mode-map "\C-c\C-u" 'xrdb-indent-buffer)
309 (define-key xrdb-mode-map "\C-c>" 'xrdb-align-to)
310 ))
311
312 (defun xrdb-mode ()
313 "Major mode for editing xrdb config files"
314 (interactive)
315 (kill-all-local-variables)
316 (set-syntax-table xrdb-mode-syntax-table)
317 (setq major-mode 'xrdb-mode
318 mode-name "xrdb"
319 local-abbrev-table xrdb-mode-abbrev-table)
320 (use-local-map xrdb-mode-map)
321 ;; local variables
322 (make-local-variable 'parse-sexp-ignore-comments)
323 (make-local-variable 'comment-start)
324 (make-local-variable 'comment-end)
325 (make-local-variable 'paragraph-start)
326 (make-local-variable 'paragraph-separate)
327 (make-local-variable 'paragraph-ignore-fill-prefix)
328 ;; now set their values
329 (setq parse-sexp-ignore-comments t
330 comment-start "! "
331 comment-end "")
332 (setq indent-region-function 'xrdb-indent-region
333 paragraph-ignore-fill-prefix t
334 paragraph-start (concat "^[ \t]*$\\|^[ \t]*[!]\\|" page-delimiter)
335 paragraph-separate paragraph-start)
336 (run-hooks 'xrdb-mode-hook))
337
338
339
340 ;; faces and font-locking
341 (require 'font-lock)
342 (make-face 'xrdb-option-name-face)
343 (make-face 'xrdb-option-value-face)
344 (or (face-differs-from-default-p 'xrdb-option-name-face)
345 (copy-face 'font-lock-keyword-face 'xrdb-option-name-face))
346 (or (face-differs-from-default-p 'xrdb-option-value-face)
347 (copy-face 'font-lock-string-face 'xrdb-option-value-face))
348
349 (defvar xrdb-font-lock-keywords
350 (list '("^[ \t]*\\([^\n:]*:\\)[ \t]*\\(.*\\)$"
351 (1 xrdb-option-name-face)
352 (2 xrdb-option-value-face)))
353 "Additional expressions to highlight in Xrdb mode.")
354
355 (put 'xrdb-mode 'font-lock-defaults '(xrdb-font-lock-keywords nil))
356
357
358
359 ;; commands
360 (defun xrdb-region-goal-column ()
361 ;; Returns the goal column of the current region. Assumes the
362 ;; buffer has been narrowed to the region to scan.
363 (save-excursion
364 (beginning-of-buffer)
365 (let ((goalcol -1)
366 linecol)
367 (while (< (point) (point-max))
368 ;; skip any comments
369 (if (and (not (looking-at xrdb-comment-re))
370 (xrdb-skip-to-separator)
371 (< goalcol (setq linecol (current-column)))
372 )
373 (setq goalcol linecol))
374 (forward-line 1))
375 (if (< goalcol 0)
376 nil
377 goalcol))))
378
379
380
381 ;; submitting bug reports
382
383 (defconst xrdb-version "1.17"
384 "xrdb-mode version number.")
385
386 (defconst xrdb-mode-help-address "tools-help@python.org"
387 "Address for xrdb-mode bug reports.")
388
389 (eval-when-compile
390 (require 'reporter))
391
392 (defun xrdb-submit-bug-report ()
393 "Submit via mail a bug report on xrdb-mode."
394 (interactive)
395 ;; load in reporter
396 (let ((reporter-prompt-for-summary-p t)
397 (varlist '(xrdb-subdivide-by
398 xrdb-mode-hook
399 )))
400 (and (if (y-or-n-p "Do you want to submit a report on xrdb-mode? ")
401 t
402 (message "")
403 nil)
404 (require 'reporter)
405 (reporter-submit-bug-report
406 xrdb-mode-help-address "xrdb-mode" varlist nil nil "Dear Barry,")
407 )))
408
409
410 (provide 'xrdb-mode)
411 ;; xrdb-mode.el ends here