diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/modes/xrdb-mode.el	Mon Aug 13 08:51:03 2007 +0200
@@ -0,0 +1,411 @@
+;;; xrdb-mode.el --- mode for editing X resource database files
+
+;; Author:        1994-1997 Barry A. Warsaw
+;; Maintainer:    tools-help@python.org
+;; Created:       May 1994
+;; Version:       1.17
+;; Last Modified: 1997/02/21 22:28:59
+;; Keywords:      data languages
+
+;; Copyright (C) 1994 Barry A. Warsaw
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2 of the License, or
+;; (at your option) any later version.
+;; 
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;; 
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, write to the Free Software
+;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;; Commentary:
+;;
+;; In 1994 I wrote:
+;;
+;; "I used to be like you.  I used to hack on X resource database files
+;;  all the time, and when I did, I found this mode to be fairly
+;;  useful.  It's by no means perfect.  At one time I had a collection
+;;  of hacks that did some nice indentation of resource lines, but
+;;  they were not organized in any way.  This mode was my attempt to
+;;  congeal this mess into a proper major mode.  I release it now, not
+;;  because it will change your life, but because I don't plan to do
+;;  anything more with it.
+;;
+;;  I have since been enlightened and no longer have to cavort with
+;;  mere mortal X hackers anymore.  I like my brain cells, so now I
+;;  use NEXTSTEP where all is glory.  Or would you say I traded one
+;;  vice for another?  Hmm...  Anyway, if you are still down in the
+;;  trenches and would like to inherit this file, let me know.  I
+;;  don't intend to do any work on it any more... unless I lose my
+;;  place in paradise.  I promise to be good, Steve.  :-) :-)"
+;;
+;; I have fallen from grace.
+
+;; Code:
+
+
+;; These variables are available for your customization
+(defvar xrdb-mode-hook nil
+  "*Hook to be run when `xrdb-mode' is entered.")
+
+(defvar xrdb-subdivide-by 'paragraph
+  "*Extent of alignment calculations.
+Can be one of `buffer', `paragraph', `page', or `line'.  Do a
+\\[describe-function] xrdb-indent-buffer RET for more information.")
+
+
+
+;; no need to customize anything below this line
+(defconst xrdb-comment-re "^[ \t]*[!]"
+  "Character which starts a comment.")
+(defconst xrdb-separator-char ?:
+  "Character which separates resource specs from values.")
+
+
+;; utilities
+(defsubst xrdb-point (position)
+  ;; Returns the value of point at certain commonly referenced POSITIONs.
+  ;; POSITION can be one of the following symbols:
+  ;; 
+  ;; bol  -- beginning of line
+  ;; eol  -- end of line
+  ;; bod  -- beginning of defun
+  ;; boi  -- back to indentation
+  ;; ionl -- indentation of next line
+  ;; iopl -- indentation of previous line
+  ;; bonl -- beginning of next line
+  ;; bopl -- beginning of previous line
+  ;; bop  -- beginning of paragraph
+  ;; eop  -- end of paragraph
+  ;; bopg -- beginning of page
+  ;; eopg -- end of page
+  ;; 
+  ;; This function does not modify point or mark.
+  (let ((here (point)))
+    (cond
+     ((eq position 'bol)  (beginning-of-line))
+     ((eq position 'eol)  (end-of-line))
+     ((eq position 'boi)  (back-to-indentation))
+     ((eq position 'bonl) (forward-line 1))
+     ((eq position 'bopl) (forward-line -1))
+     ((eq position 'bop)  (forward-paragraph -1))
+     ((eq position 'eop)  (forward-paragraph 1))
+     ((eq position 'bopg)  (forward-page -1))
+     ((eq position 'eopg)  (forward-page 1))
+     (t
+      (error "unknown buffer position requested: %s" position)))
+    (prog1
+	(point)
+      (goto-char here))
+    ))
+
+(defsubst xrdb-skip-to-separator ()
+  ;; skip forward from the beginning of the line to the separator
+  ;; character as given by xrdb-separator-char. Returns t if the
+  ;; char was found, otherwise, nil.
+  (beginning-of-line)
+  (skip-chars-forward
+   (concat "^" (char-to-string xrdb-separator-char))
+   (xrdb-point 'eol))
+  (= (following-char) xrdb-separator-char))
+
+
+
+;; commands
+(defun xrdb-electric-separator (arg)
+  "Insert the separator character.
+Re-align the line unless an argument is given."
+  (interactive "P")
+  ;; first insert the character
+  (self-insert-command (prefix-numeric-value arg))
+  ;; only do electric behavior if arg is not given
+  (if (not arg)
+      (xrdb-align-to (xrdb-point 'bol)
+		     (xrdb-point 'bonl)
+		     (save-excursion
+		       (beginning-of-line)
+		       (forward-comment (- (point-max)))
+		       (beginning-of-line)
+		       (xrdb-skip-to-separator)
+		       (current-column)))))
+
+(defun xrdb-align-to (start end goalcolumn)
+  (interactive "r\nnAlign to column: ")
+  (save-excursion
+    (save-restriction
+      (narrow-to-region start end)
+      (beginning-of-buffer)
+      (while (< (point) (point-max))
+	(if (and (not (looking-at xrdb-comment-re))
+		 (xrdb-skip-to-separator)
+		 goalcolumn)
+	    (indent-code-rigidly (xrdb-point 'bol)
+				 (xrdb-point 'bonl)
+				 (- goalcolumn (current-column))))
+	(forward-line 1)))))
+
+(defun xrdb-indent-line (arg)
+  "Re-align current line."
+  (interactive "P")
+  ;; narrow to the region specified by xrdb-subdivide-by
+  (save-excursion
+    (save-restriction
+      (widen)
+      (cond
+       ((eq xrdb-subdivide-by 'buffer))
+       ((eq xrdb-subdivide-by 'page)
+	(narrow-to-page))
+       ((eq xrdb-subdivide-by 'paragraph)
+	(narrow-to-region (xrdb-point 'bop) (xrdb-point 'eop)))
+       (t
+	(narrow-to-region (xrdb-point 'bopl) (xrdb-point 'bonl))
+	))
+      ;; indent line
+      (xrdb-align-to (xrdb-point 'bol) (xrdb-point 'bonl)
+		     (xrdb-region-goal-column))
+      )))
+
+(defun xrdb-indent-region (start end)
+  "Re-align region."
+  (interactive "r")
+  ;; narrow to region
+  (save-excursion
+    (save-restriction
+      (narrow-to-region start end)
+      (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column))
+      )))
+
+(defun xrdb-indent-page ()
+  "Re-align the current page."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (narrow-to-page)
+      (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column))
+      )))
+
+(defun xrdb-indent-paragraph ()
+  "Re-align the current paragraph."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (narrow-to-region (xrdb-point 'bop) (xrdb-point 'eop))
+      (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column))
+      )))
+
+(defun xrdb-indent-buffer (arg)
+  "Re-align the entire buffer.
+Alignment calculations are controlled by the variable
+`xrdb-subdivide-by', which can take the values `buffer', `paragraph',
+`page', or `line', with the following meanings:
+
+ buffer - all non-comment lines are aligned with the longest line in
+          the buffer.  Since every line must be scanned, this will
+	  take the longest to perform.
+
+ paragraph - alignment of lines spanning paragraphs. A paragraph is
+             defined as all contiguous lines between blank or comment
+	     lines.
+
+ page - alignment of lines spanning pages (i.e. separated by
+        page-delimiter, usually ^L).
+
+ none - alignment of lines based on the previous line.
+
+With optional \\[universal-argument], queries for alignment subdivision."
+  (interactive "P")
+  (let ((align-by (if (not arg)
+		      xrdb-subdivide-by
+		    (completing-read
+		     "Align by: "
+		     '(("buffer" . buffer)
+		       ("paragraph" . paragraph)
+		       ("page" . page)
+		       ("line" . line))
+		     nil t (format "%s" xrdb-subdivide-by)))))
+    (message "Aligning by %s..." align-by)
+    (save-excursion
+      (save-restriction
+	(widen)
+	(cond
+	 ;; by buffer
+	 ((eq align-by 'buffer)
+	  (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column)))
+	 ;; by paragraph
+	 ((eq align-by 'paragraph)
+	  (beginning-of-buffer)
+	  (while (< (point) (point-max))
+	    (narrow-to-region (point) (xrdb-point 'eop))
+	    (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column))
+	    (beginning-of-buffer)
+	    (widen)
+	    (forward-paragraph 1)
+	    ))
+	 ;; by page
+	 ((eq align-by 'page)
+	  (beginning-of-buffer)
+	  (while (< (point) (point-max))
+	    (narrow-to-region (point) (xrdb-point 'eopg))
+	    (xrdb-align-to (point-min) (point-max) (xrdb-region-goal-column))
+	    (beginning-of-buffer)
+	    (widen)
+	    (forward-page 1)
+	    ))
+	 ;; by line
+	 (t
+	  (beginning-of-buffer)
+	  (let ((prev-goalcol 0))
+	    (while (< (point) (point-max))
+	      ;; skip comments and blank lines
+	      (if (not (looking-at paragraph-start))
+		  (progn
+		    (xrdb-align-to (xrdb-point 'bol) (xrdb-point 'bonl)
+				   prev-goalcol)
+		    (xrdb-skip-to-separator)
+		    (setq prev-goalcol (- (point) (xrdb-point 'boi)))
+		    ))
+	      (forward-line 1))))
+	 )))
+    (message "Aligning by %s... done." align-by)
+    ))
+
+
+;; major-mode stuff
+(defvar xrdb-mode-abbrev-table nil
+  "Abbrev table used in `xrdb-mode' buffers.")
+(define-abbrev-table 'xrdb-mode-abbrev-table ())
+
+
+(defvar xrdb-mode-syntax-table nil
+  "Syntax table used in `xrdb-mode' buffers.")
+(if xrdb-mode-syntax-table
+    ()
+  (setq xrdb-mode-syntax-table (make-syntax-table))
+  (modify-syntax-entry ?!  "<" xrdb-mode-syntax-table)
+  (modify-syntax-entry ?\n ">" xrdb-mode-syntax-table))
+
+
+(defvar xrdb-mode-map ()
+  "Keymap used in `xrdb-mode' buffers.")
+(if xrdb-mode-map
+    ()
+  (setq xrdb-mode-map (make-sparse-keymap))
+  (let ((ekey (char-to-string xrdb-separator-char)))
+    ;; make the separator key electric
+    (define-key xrdb-mode-map ekey 'xrdb-electric-separator)
+    (define-key xrdb-mode-map "\t" 'xrdb-indent-line)
+    (define-key xrdb-mode-map "\C-c\C-a" 'xrdb-indent-paragraph)
+    (define-key xrdb-mode-map "\C-c\C-b" 'xrdb-submit-bug-report)
+    (define-key xrdb-mode-map "\C-c\C-p" 'xrdb-indent-page)
+    (define-key xrdb-mode-map "\C-c\C-r" 'xrdb-indent-region)
+    (define-key xrdb-mode-map "\C-c\C-u" 'xrdb-indent-buffer)
+    (define-key xrdb-mode-map "\C-c>"    'xrdb-align-to)
+    ))
+
+(defun xrdb-mode ()
+  "Major mode for editing xrdb config files"
+  (interactive)
+  (kill-all-local-variables)
+  (set-syntax-table xrdb-mode-syntax-table)
+  (setq major-mode 'xrdb-mode
+	mode-name "xrdb"
+	local-abbrev-table xrdb-mode-abbrev-table)
+  (use-local-map xrdb-mode-map)
+  ;; local variables
+  (make-local-variable 'parse-sexp-ignore-comments)
+  (make-local-variable 'comment-start)
+  (make-local-variable 'comment-end)
+  (make-local-variable 'paragraph-start)
+  (make-local-variable 'paragraph-separate)
+  (make-local-variable 'paragraph-ignore-fill-prefix)
+  ;; now set their values
+  (setq parse-sexp-ignore-comments t
+	comment-start "! "
+	comment-end "")
+  (setq indent-region-function 'xrdb-indent-region
+	paragraph-ignore-fill-prefix t
+	paragraph-start (concat "^[ \t]*$\\|^[ \t]*[!]\\|" page-delimiter)
+	paragraph-separate paragraph-start)
+  (run-hooks 'xrdb-mode-hook))
+
+
+
+;; faces and font-locking
+(require 'font-lock)
+(make-face 'xrdb-option-name-face)
+(make-face 'xrdb-option-value-face)
+(or (face-differs-from-default-p 'xrdb-option-name-face)
+    (copy-face 'font-lock-keyword-face 'xrdb-option-name-face))
+(or (face-differs-from-default-p 'xrdb-option-value-face)
+    (copy-face 'font-lock-string-face 'xrdb-option-value-face))
+
+(defvar xrdb-font-lock-keywords
+  (list '("^[ \t]*\\([^\n:]*:\\)[ \t]*\\(.*\\)$"
+	  (1 xrdb-option-name-face)
+	  (2 xrdb-option-value-face)))
+  "Additional expressions to highlight in Xrdb mode.")
+
+(put 'xrdb-mode 'font-lock-defaults '(xrdb-font-lock-keywords nil))
+
+
+
+;; commands
+(defun xrdb-region-goal-column ()
+  ;; Returns the goal column of the current region.  Assumes the
+  ;; buffer has been narrowed to the region to scan.
+  (save-excursion
+    (beginning-of-buffer)
+    (let ((goalcol -1)
+	  linecol)
+      (while (< (point) (point-max))
+	;; skip any comments
+	(if (and (not (looking-at xrdb-comment-re))
+		 (xrdb-skip-to-separator)
+		 (< goalcol (setq linecol (current-column)))
+		 )
+	    (setq goalcol linecol))
+	(forward-line 1))
+      (if (< goalcol 0)
+	  nil
+	goalcol))))
+
+
+
+;; submitting bug reports
+
+(defconst xrdb-version "1.17"
+  "xrdb-mode version number.")
+
+(defconst xrdb-mode-help-address "tools-help@python.org"
+  "Address for xrdb-mode bug reports.")
+
+(eval-when-compile
+  (require 'reporter))
+
+(defun xrdb-submit-bug-report ()
+  "Submit via mail a bug report on xrdb-mode."
+  (interactive)
+  ;; load in reporter
+  (let ((reporter-prompt-for-summary-p t)
+	(varlist '(xrdb-subdivide-by
+		   xrdb-mode-hook
+		   )))
+    (and (if (y-or-n-p "Do you want to submit a report on xrdb-mode? ")
+	     t
+	   (message "")
+	   nil)
+	 (require 'reporter)
+	 (reporter-submit-bug-report
+	  xrdb-mode-help-address "xrdb-mode" varlist nil nil "Dear Barry,")
+	 )))
+
+
+(provide 'xrdb-mode)
+;; xrdb-mode.el ends here