[emacs-rpm-spec-mode] Initial import

Karel Klíč kklic at fedoraproject.org
Thu Sep 20 12:45:33 UTC 2012


commit 38eeec90439148976f83eb6d37860ed37eb7d4e4
Author: Karel Klic <kklic at redhat.com>
Date:   Thu Sep 20 14:46:42 2012 +0200

    Initial import

 emacs-rpm-spec-mode.spec        |   65 ++
 rpm-spec-mode-changelog.patch   |   47 ++
 rpm-spec-mode-compilation.patch |   89 +++
 rpm-spec-mode-init.el           |    5 +
 rpm-spec-mode-utc.patch         |   31 +
 rpm-spec-mode-xemacs.patch      |  809 +++++++++++++++++++++++++
 rpm-spec-mode.el                | 1240 +++++++++++++++++++++++++++++++++++++++
 7 files changed, 2286 insertions(+), 0 deletions(-)
---
diff --git a/emacs-rpm-spec-mode.spec b/emacs-rpm-spec-mode.spec
new file mode 100644
index 0000000..9ef8d7e
--- /dev/null
+++ b/emacs-rpm-spec-mode.spec
@@ -0,0 +1,65 @@
+Name: emacs-rpm-spec-mode
+Version: 0.12
+Release: 3%{?dist}
+Summary: Major GNU Emacs mode for editing RPM spec files
+Group: Applications/Editors
+License: GPLv2+
+# Alternative upstream?
+# https://bitbucket.org/xemacs/prog-modes/raw/eacc4cb30d0c/rpm-spec-mode.el
+URL: http://tihlde.org/~stigb/rpm-spec-mode.el
+Source0: http://tihlde.org/~stigb/rpm-spec-mode.el
+Source1: rpm-spec-mode-init.el
+BuildArch: noarch
+BuildRequires: emacs
+# Temporary requirement to prevent conflict with older emacs packages
+# that embed rpm-spec-mode.
+Requires: emacs(bin) >= %{_emacs_evr}
+#Requires: emacs(bin) >= %{_emacs_version}
+# Sent to upstream
+Patch0: rpm-spec-mode-xemacs.patch
+# Sent to upstream
+Patch1: rpm-spec-mode-compilation.patch
+# Sent to upstream
+Patch2: rpm-spec-mode-utc.patch
+# Sent to upstream
+Patch3: rpm-spec-mode-changelog.patch
+
+%description
+Major GNU Emacs mode for editing RPM spec files.
+
+%prep
+%setup -q -n rpm-spec-mode-%{version} -T -c
+cp %SOURCE0 $RPM_BUILD_DIR/rpm-spec-mode-%{version}
+
+%patch0 -p1 -b .xemacs
+%patch1 -p1 -b .compilation
+%patch2 -p1 -b .utc
+%patch3 -p1 -b .changelog
+
+%build
+%_emacs_bytecompile rpm-spec-mode.el
+
+%install
+mkdir -p %{buildroot}/%{_emacs_sitelispdir}/rpm-spec-mode
+install -m 644 rpm-spec-mode.el{,c} %{buildroot}/%{_emacs_sitelispdir}/rpm-spec-mode
+
+# Install rpm-spec-mode-init.el
+mkdir -p %{buildroot}%{_emacs_sitestartdir}
+install -m 644 %SOURCE1 %{buildroot}%{_emacs_sitestartdir}
+
+%files
+%{_emacs_sitestartdir}/rpm-spec-mode-init.el
+%{_emacs_sitelispdir}/rpm-spec-mode/rpm-spec-mode.el
+%{_emacs_sitelispdir}/rpm-spec-mode/rpm-spec-mode.elc
+
+%changelog
+* Wed Sep 19 2012 Karel Klíč <kklic at redhat.com> - 0.12-3
+- Removed build dependency on emacs-el
+- Require emacs without embedded rpm-spec-mode to avoid conflicts
+  during updates
+
+* Tue Sep 18 2012 Karel Klíč <kklic at redhat.com> - 0.12-2
+- Moved rpm-spec-mode.el{,c} to a subdirectory
+
+* Fri Sep 14 2012 Karel Klíč <kklic at redhat.com> - 0.12-1
+- Initial package
diff --git a/rpm-spec-mode-changelog.patch b/rpm-spec-mode-changelog.patch
new file mode 100644
index 0000000..a99cde3
--- /dev/null
+++ b/rpm-spec-mode-changelog.patch
@@ -0,0 +1,47 @@
+--- rpm-spec-mode/rpm-spec-mode.el.orig	2011-11-10 17:22:20.000000000 +0100
++++ rpm-spec-mode/rpm-spec-mode.el	2011-11-23 15:59:13.959987280 +0100
+@@ -491,6 +491,7 @@ value returned by function `user-mail-ad
+        (set-keymap-name rpm-spec-mode-map 'rpm-spec-mode-map))
+   (define-key rpm-spec-mode-map "\C-c\C-c"  'rpm-change-tag)
+   (define-key rpm-spec-mode-map "\C-c\C-e"  'rpm-add-change-log-entry)
++  (define-key rpm-spec-mode-map "\C-c\C-w"  'rpm-goto-add-change-log-entry)
+   (define-key rpm-spec-mode-map "\C-c\C-i"  'rpm-insert-tag)
+   (define-key rpm-spec-mode-map "\C-c\C-n"  'rpm-forward-section)
+   (define-key rpm-spec-mode-map "\C-c\C-o"  'rpm-goto-section)
+@@ -719,10 +720,8 @@ This variable is global by default, but 
+ If `rpm-change-log-uses-utc' is nil, \"today\" means the local time zone."
+   (format-time-string "%a %b %e %Y" nil rpm-change-log-uses-utc))
+ 
+-(defun rpm-add-change-log-entry (&optional change-log-entry)
+-  "Find change log and add an entry for today."
+-  (interactive "sChange log entry: ")
+-  (save-excursion
++(defun rpm-goto-add-change-log-header ()
++  "Find change log and add header (if needed) for today"
+     (rpm-goto-section "changelog")
+     (let* ((address (rpm-spec-user-mail-address))
+            (fullname (or rpm-spec-user-full-name (user-full-name)))
+@@ -733,8 +732,21 @@ If `rpm-change-log-uses-utc' is nil, \"t
+                                 (concat " - " (rpm-find-spec-version t))))))
+       (if (not (search-forward string nil t))
+           (insert "\n" string "\n")
+-        (forward-line 2))
+-      (insert "- " change-log-entry "\n"))))
++        (forward-line 2))))
++
++(defun rpm-add-change-log-entry (&optional change-log-entry)
++  "Find change log and add an entry for today."
++  (interactive "sChange log entry: ")
++  (save-excursion
++    (rpm-goto-add-change-log-header)
++      (insert "- " change-log-entry "\n")))
++
++(defun rpm-goto-add-change-log-entry ()
++  "Goto change log and add an header for today (if needed)."
++  (interactive)
++  (rpm-goto-add-change-log-header)
++  (insert "- \n")
++  (end-of-line '0))
+ 
+ ;;------------------------------------------------------------
+ 
diff --git a/rpm-spec-mode-compilation.patch b/rpm-spec-mode-compilation.patch
new file mode 100644
index 0000000..d2074db
--- /dev/null
+++ b/rpm-spec-mode-compilation.patch
@@ -0,0 +1,89 @@
+diff -up rpm-spec-mode-0.12/rpm-spec-mode.el.compilation rpm-spec-mode-0.12/rpm-spec-mode.el
+--- rpm-spec-mode-0.12/rpm-spec-mode.el.compilation	2012-09-14 18:06:57.886393814 +0200
++++ rpm-spec-mode-0.12/rpm-spec-mode.el	2012-09-14 18:08:22.444398922 +0200
+@@ -62,6 +62,7 @@
+ ;;
+ 
+ ;;; Code:
++(require 'compile)
+ 
+ (defconst rpm-spec-mode-version "0.12" "Version of `rpm-spec-mode'.")
+ 
+@@ -189,11 +190,6 @@ value returned by function `user-mail-ad
+   :type 'boolean
+   :group 'rpm-spec)
+ 
+-(defcustom rpm-spec-use-compilation-mode t
+-  "*If non-nil, build in `compilation-mode' if it's available."
+-  :type 'boolean
+-  :group 'rpm-spec)
+-
+ (defcustom rpm-spec-default-release "1"
+   "*Default value for the Release tag in new spec files."
+   :type 'string
+@@ -225,6 +221,11 @@ value returned by function `user-mail-ad
+   :type 'string
+   :group 'rpm-spec)
+ 
++(defcustom rpm-spec-auto-topdir nil
++  "*Automatically detect an rpm build directory tree and define _topdir."
++  :type 'boolean
++  :group 'rpm-spec)
++
+ (defgroup rpm-spec-faces nil
+   "Font lock faces for `rpm-spec-mode'."
+   :prefix "rpm-spec-"
+@@ -1025,20 +1026,30 @@ leave point at previous location."
+       (setq buildoptions (cons "--nodeps" buildoptions)))
+   (if (and rpm-spec-sign-gpg (not rpm-no-gpg))
+       (setq buildoptions (cons "--sign" buildoptions)))
+-  (save-excursion
+-    (set-buffer (get-buffer rpm-buffer-name))
+-    (and rpm-spec-use-compilation-mode
+-         (fboundp 'compilation-mode)
+-         (compilation-mode))
+-    (goto-char (point-max)))
+-  (let* ((process-environment (cons "EMACS=t" process-environment))
+-         (process
+-          (apply 'start-process rpm-spec-build-command rpm-buffer-name
+-                 rpm-spec-build-command buildoptions)))
+-    (if (and rpm-spec-sign-gpg (not rpm-no-gpg))
+-        (let ((rpm-passwd-cache (read-passwd "GPG passphrase: ")))
+-          (process-send-string process (concat rpm-passwd-cache "\n"))))
+-    (set-process-filter process 'rpm-command-filter)))
++
++  (if rpm-spec-auto-topdir
++      (if (string-match ".*/SPECS/$" default-directory)
++	  (let ((topdir (expand-file-name default-directory)))
++	    (setq buildoptions
++		  (cons
++		   (concat "--define \"_topdir " 
++			   (replace-regexp-in-string "/SPECS/$" "" topdir)
++			   "\"")
++		   buildoptions)))))
++
++  (progn
++    (defun list->string (lst)
++      (if (cdr lst)
++	  (concat (car lst) " " (list->string (cdr lst)))
++	(car lst)))
++    (compilation-start (list->string (cons rpm-spec-build-command buildoptions)) 'rpmbuild-mode))
++  
++  (if (and rpm-spec-sign-gpg (not rpm-no-gpg))
++      (let ((build-proc (get-buffer-process
++			 (get-buffer
++			  (compilation-buffer-name "rpmbuild" nil nil))))
++	    (rpm-passwd-cache (read-passwd "GPG passphrase: ")))
++	(process-send-string build-proc (concat rpm-passwd-cache "\n")))))
+ 
+ (defun rpm-build-prepare (&optional arg)
+   "Run a `rpmbuild -bp'."
+@@ -1409,5 +1420,8 @@ if one is present in the file."
+ ;;;###autoload(add-to-list 'auto-mode-alist '("\\.spec\\(\\.in\\)?$" . rpm-spec-mode))
+ 
+ (provide 'rpm-spec-mode)
++;;;###autoload
++(define-compilation-mode rpmbuild-mode "RPM build" ""
++  (set (make-local-variable 'compilation-disable-input) t))
+ 
+ ;;; rpm-spec-mode.el ends here
diff --git a/rpm-spec-mode-init.el b/rpm-spec-mode-init.el
new file mode 100644
index 0000000..6fc7627
--- /dev/null
+++ b/rpm-spec-mode-init.el
@@ -0,0 +1,5 @@
+;; rpm-spec-mode for spec files
+(add-to-list 'load-path "/usr/share/emacs/site-lisp/rpm-spec-mode")
+(autoload 'rpm-spec-mode "rpm-spec-mode" "RPM spec mode." t)
+(add-to-list 'auto-mode-alist '("\\.spec\\(\\.in\\)?$" . rpm-spec-mode))
+(setq-default rpm-change-log-uses-utc t)
diff --git a/rpm-spec-mode-utc.patch b/rpm-spec-mode-utc.patch
new file mode 100644
index 0000000..3f00f23
--- /dev/null
+++ b/rpm-spec-mode-utc.patch
@@ -0,0 +1,31 @@
+--- rpm-spec-mode/rpm-spec-mode.el~	2009-06-11 11:01:53.000000000 +0200
++++ rpm-spec-mode/rpm-spec-mode.el	2009-06-11 11:05:24.000000000 +0200
+@@ -708,6 +708,17 @@
+ 
+ ;;------------------------------------------------------------
+ 
++(defvar rpm-change-log-uses-utc nil
++  "*If non-nil, \\[rpm-add-change-log-entry] will use Universal time (UTC).
++If this is nil, it uses local time as returned by `current-time'.
++
++This variable is global by default, but you can make it buffer-local.")
++
++(defsubst rpm-change-log-date-string ()
++  "Return the date string for today, inserted by \\[rpm-add-change-log-entry].
++If `rpm-change-log-uses-utc' is nil, \"today\" means the local time zone."
++  (format-time-string "%a %b %e %Y" nil rpm-change-log-uses-utc))
++
+ (defun rpm-add-change-log-entry (&optional change-log-entry)
+   "Find change log and add an entry for today."
+   (interactive "sChange log entry: ")
+@@ -715,8 +726,8 @@
+     (rpm-goto-section "changelog")
+     (let* ((address (rpm-spec-user-mail-address))
+            (fullname (or rpm-spec-user-full-name (user-full-name)))
+-           (string (concat "* " (substring (current-time-string) 0 11)
+-                           (substring (current-time-string) -4) " "
++           (system-time-locale "C")
++           (string (concat "* " (rpm-change-log-date-string) " "
+                            fullname " <" address ">"
+                            (and rpm-spec-insert-changelog-version
+                                 (concat " - " (rpm-find-spec-version t))))))
diff --git a/rpm-spec-mode-xemacs.patch b/rpm-spec-mode-xemacs.patch
new file mode 100644
index 0000000..c31d1d6
--- /dev/null
+++ b/rpm-spec-mode-xemacs.patch
@@ -0,0 +1,809 @@
+--- rpm-spec-mode/rpm-spec-mode.el	2012-09-14 13:53:50.146393928 +0200
++++ rpm-spec-mode/rpm-spec-mode-x.el	2012-09-13 18:02:26.049394233 +0200
+@@ -20,8 +20,8 @@
+ 
+ ;; You should have received a copy of the GNU General Public License
+ ;; along with XEmacs; see the file COPYING.  If not, write to the
+-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+-;; MA 02111-1307, USA.
++;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++;; Boston, MA 02110-1301 USA.
+ 
+ ;;; Synched up with: not in GNU Emacs.
+ 
+@@ -33,12 +33,13 @@
+ ;;     Tim Powers <timp at redhat.com> and Trond Eivind Glomsrød
+ ;;          <teg at redhat.com> for Red Hat adaptions and some fixes.
+ ;;     Chmouel Boudjnah <chmouel at mandrakesoft.com> for Mandrake fixes.
++;;     Ville Skyttä  <scop at xemacs.org> for some fixes.
+ 
+ ;;; ToDo:
+ 
+ ;; - rewrite function names.
+ ;; - autofill changelog entries.
+-;; - customize rpm-tags-list and rpm-group-tags-list.
++;; - customize rpm-tags-list, rpm-obsolete-tags-list and rpm-group-tags-list.
+ ;; - get values from `rpm --showrc'.
+ ;; - ssh/rsh for compile.
+ ;; - finish integrating the new navigation functions in with existing stuff.
+@@ -70,7 +71,7 @@
+   :group 'languages)
+ 
+ (defcustom rpm-spec-build-command "rpmbuild"
+-  "Command for building a RPM package."
++  "Command for building an RPM package."
+   :type 'string
+   :group 'rpm-spec)
+ 
+@@ -95,7 +96,7 @@
+   :group 'rpm-spec)
+ 
+ (defcustom rpm-spec-buildroot ""
+-  "Override the BuildRoot tag with directory <dir>."
++  "When building, override the BuildRoot tag with directory <dir>."
+   :type 'string
+   :group 'rpm-spec)
+ 
+@@ -125,11 +126,20 @@
+   :type 'boolean
+   :group 'rpm-spec)
+ 
++(define-obsolete-variable-alias
++  'rpm-spec-test 'rpm-spec-nobuild)
++
+ (defcustom rpm-spec-nobuild nil
+   "Do not execute any build stages.  Useful for testing out spec files."
+   :type 'boolean
+   :group 'rpm-spec)
+ 
++(defcustom rpm-spec-quiet nil
++  "Print as little as possible.
++Normally only error messages will be displayed."
++  :type 'boolean
++  :group 'rpm-spec)
++
+ (defcustom rpm-spec-sign-gpg nil
+   "Embed a GPG signature in the package.
+ This signature can be used to verify the integrity and the origin of
+@@ -142,11 +152,6 @@
+   :type 'boolean
+   :group 'rpm-spec)
+ 
+-(defcustom rpm-spec-old-rpm nil
+-  "Set if using `rpm' as command for building packages."
+-  :type 'boolean
+-  :group 'rpm-spec)
+-
+ (define-obsolete-variable-alias
+   'rpm-initialize-sections 'rpm-spec-initialize-sections)
+ 
+@@ -179,8 +184,50 @@
+                  string)
+   :group 'rpm-spec)
+ 
++(defcustom rpm-spec-indent-heading-values nil
++  "*Indent values for all tags in the \"heading\" of the spec file."
++  :type 'boolean
++  :group 'rpm-spec)
++
++(defcustom rpm-spec-use-compilation-mode t
++  "*If non-nil, build in `compilation-mode' if it's available."
++  :type 'boolean
++  :group 'rpm-spec)
++
++(defcustom rpm-spec-default-release "1"
++  "*Default value for the Release tag in new spec files."
++  :type 'string
++  :group 'rpm-spec)
++
++(defcustom rpm-spec-default-epoch nil
++  "*If non-nil, default value for the Epoch tag in new spec files."
++  :type '(choice (const :tag "No Epoch" nil) integer)
++  :group 'rpm-spec)
++
++(defcustom rpm-spec-default-buildroot
++  "%{_tmppath}/%{name}-%{version}-%{release}-root"
++  "*Default value for the BuildRoot tag in new spec files."
++  :type 'integer
++  :group 'rpm-spec)
++
++(defcustom rpm-spec-default-build-section ""
++  "*Default %build section in new spec files."
++  :type 'string
++  :group 'rpm-spec)
++
++(defcustom rpm-spec-default-install-section "rm -rf $RPM_BUILD_ROOT\n"
++  "*Default %install section in new spec files."
++  :type 'string
++  :group 'rpm-spec)
++
++(defcustom rpm-spec-default-clean-section "rm -rf $RPM_BUILD_ROOT\n"
++  "*Default %clean section in new spec files."
++  :type 'string
++  :group 'rpm-spec)
++
+ (defgroup rpm-spec-faces nil
+   "Font lock faces for `rpm-spec-mode'."
++  :prefix "rpm-spec-"
+   :group 'rpm-spec
+   :group 'faces)
+ 
+@@ -188,88 +235,105 @@
+ ;; variables used by navigation functions.
+ 
+ (defconst rpm-sections
+-  '("preamble" "description" "prep" "setup" "build" "install" "clean"
++  '("preamble" "description" "prep" "setup" "build" "install" "check" "clean"
+     "changelog" "files")
+   "Partial list of section names.")
+ (defvar rpm-section-list
+   '(("preamble") ("description") ("prep") ("setup") ("build") ("install")
+-    ("clean") ("changelog") ("files"))
++    ("check") ("clean") ("changelog") ("files"))
+   "Partial list of section names.")
+ (defconst rpm-scripts
+   '("pre" "post" "preun" "postun"
+-    "trigger" "triggerin" "triggerun" "triggerpostun")
++    "trigger" "triggerin" "triggerprein" "triggerun" "triggerpostun"
++    "pretrans" "posttrans")
+   "List of rpm scripts.")
+ (defconst rpm-section-seperate "^%\\(\\w+\\)\\s-")
+ (defconst rpm-section-regexp
+   (eval-when-compile
+     (concat "^%"
+             (regexp-opt
+-             ;; From RPM 4.1 sources, file build/parseSpec.c: partList[].
+-             '("build" "changelog" "clean" "description" "files" "install"
+-               "package" "post" "postun" "pre" "prep" "preun" "trigger"
+-               "triggerin" "triggerpostun" "triggerun" "verifyscript") t)
++             ;; From RPM 4.6.0 sources, file build/parseSpec.c: partList[].
++             '("build" "changelog" "check" "clean" "description" "files"
++               "install" "package" "post" "postun" "pretrans" "posttrans"
++               "pre" "prep" "preun" "trigger" "triggerin" "triggerpostun"
++               "triggerprein" "triggerun" "verifyscript") t)
+             "\\b"))
+   "Regular expression to match beginning of a section.")
+ 
+ ;;------------------------------------------------------------
+ 
+ (defface rpm-spec-tag-face
+-  '(( ((class color) (background light)) (:foreground "blue") )
++  '(( ((class color) (background light)) (:foreground "blue3") )
+     ( ((class color) (background dark)) (:foreground "blue") ))
+-  "*The face used for tags."
++  "*Face for tags."
++  :group 'rpm-spec-faces)
++
++(defface rpm-spec-obsolete-tag-face
++  '(( ((class color)) (:foreground "white" :background "red") ))
++  "*Face for obsolete tags."
+   :group 'rpm-spec-faces)
+ 
+ (defface rpm-spec-macro-face
+   '(( ((class color) (background light)) (:foreground "purple") )
+     ( ((class color) (background dark)) (:foreground "yellow") ))
+-  "*The face used for macros."
++  "*Face for RPM macros and variables."
+   :group 'rpm-spec-faces)
+ 
+ (defface rpm-spec-var-face
+   '(( ((class color) (background light)) (:foreground "maroon") )
+     ( ((class color) (background dark)) (:foreground "maroon") ))
+-  "*The face used for environment variables."
++  "*Face for environment variables."
+   :group 'rpm-spec-faces)
+ 
+ (defface rpm-spec-doc-face
+-  '(( ((class color) (background light)) (:foreground "magenta") )
++  '(( ((class color) (background light)) (:foreground "magenta3") )
+     ( ((class color) (background dark)) (:foreground "magenta") ))
+-  "*The face used for document files."
++  "*Face for %doc entries in %files."
+   :group 'rpm-spec-faces)
+ 
+ (defface rpm-spec-dir-face
+-  '(( ((class color) (background light)) (:foreground "green") )
++  '(( ((class color) (background light)) (:foreground "green4") )
+     ( ((class color) (background dark)) (:foreground "green") ))
+-  "*The face used for directories."
++  "*Face for %dir entries in %files."
+   :group 'rpm-spec-faces)
+ 
+ (defface rpm-spec-package-face
+-  '(( ((class color) (background light)) (:foreground "red") )
++  '(( ((class color) (background light)) (:foreground "red3") )
+     ( ((class color) (background dark)) (:foreground "red") ))
+-  "*The face used for files."
++  "*Face for package tag."
+   :group 'rpm-spec-faces)
+ 
+ (defface rpm-spec-ghost-face
+-  '(( ((class color) (background light)) (:foreground "red") )
++  '(( ((class color) (background light)) (:foreground "gray50") )
+     ( ((class color) (background dark)) (:foreground "red") ))
+-  "*The face used for ghost tags."
++  "*Face for %ghost and %config entries in %files."
++  :group 'rpm-spec-faces)
++
++(defface rpm-spec-section-face
++  '(( ((class color) (background light)) (:foreground "purple" :underline t) )
++    ( ((class color) (background dark)) (:foreground "yellow" :underline t) ))
++  "*Face for section markers."
+   :group 'rpm-spec-faces)
+ 
+ ;;; GNU emacs font-lock needs these...
+ (defvar rpm-spec-macro-face
+-  'rpm-spec-macro-face "*Face for macros.")
++  'rpm-spec-macro-face "*Face for RPM macros and variables.")
+ (defvar rpm-spec-var-face
+   'rpm-spec-var-face "*Face for environment variables.")
+ (defvar rpm-spec-tag-face
+   'rpm-spec-tag-face "*Face for tags.")
++(defvar rpm-spec-obsolete-tag-face
++  'rpm-spec-tag-face "*Face for obsolete tags.")
+ (defvar rpm-spec-package-face
+   'rpm-spec-package-face "*Face for package tag.")
+ (defvar rpm-spec-dir-face
+-  'rpm-spec-dir-face "*Face for directory entries.")
++  'rpm-spec-dir-face "*Face for %dir entries in %files.")
+ (defvar rpm-spec-doc-face
+-  'rpm-spec-doc-face "*Face for documentation entries.")
++  'rpm-spec-doc-face "*Face for %doc entries in %files.")
+ (defvar rpm-spec-ghost-face
+-  'rpm-spec-ghost-face "*Face for \"%ghost\" files.")
++  'rpm-spec-ghost-face "*Face for %ghost and %config entries in %files.")
++(defvar rpm-spec-section-face
++  'rpm-spec-section-face "*Face for section markers.")
+ 
+ (defvar rpm-default-umask "-"
+   "*Default umask for files, specified with \"%attr\".")
+@@ -281,24 +345,31 @@
+ ;;------------------------------------------------------------
+ 
+ (defvar rpm-no-gpg nil "Tell rpm not to sign package.")
++(defvar rpm-spec-nobuild-option "--nobuild" "Option for no build.")
+ 
+ (defvar rpm-tags-list
+-  ;; From RPM 4.1 sources, file build/parsePreamble.c: preambleList[].")
++  ;; From RPM 4.4.9 sources, file build/parsePreamble.c: preambleList[], and
++  ;; a few macros that aren't tags, but useful here.
+   '(("AutoProv")
+     ("AutoReq")
+     ("AutoReqProv")
+     ("BuildArch")
+     ("BuildArchitectures")
+     ("BuildConflicts")
++    ("BuildEnhances")
++    ("BuildPlatforms")
+     ("BuildPreReq")
+     ("BuildRequires")
+     ("BuildRoot")
++    ("BuildSuggests")
+     ("Conflicts")
+-    ("Copyright")
++    ("CVSId")
+     ("%description")
+     ("Distribution")
++    ("DistTag")
+     ("DistURL")
+     ("DocDir")
++    ("Enhances")
+     ("Epoch")
+     ("ExcludeArch")
+     ("ExcludeOS")
+@@ -308,6 +379,8 @@
+     ("Group")
+     ("Icon")
+     ("%ifarch")
++    ("Keyword")
++    ("Keywords")
+     ("License")
+     ("Name")
+     ("NoPatch")
+@@ -322,17 +395,40 @@
+     ("Provides")
+     ("Release")
+     ("Requires")
+-    ("RHNPlatform")
+-    ("Serial")
++    ("RepoTag")
+     ("Source")
++    ("Suggests")
+     ("Summary")
++    ("SVNId")
+     ("URL")
++    ("Variant")
++    ("Variants")
+     ("Vendor")
+-    ("Version"))
++    ("Version")
++    ("XMajor")
++    ("XMinor")
++    )
+   "List of elements that are valid tags.")
+ 
++(defvar rpm-tags-regexp
++  (concat "\\(\\<" (regexp-opt (mapcar 'car rpm-tags-list))
++	  "\\|\\(Patch\\|Source\\)[0-9]+\\>\\)")
++  "Regular expression for matching valid tags.")
++
++(defvar rpm-obsolete-tags-list
++  ;; From RPM sources, file build/parsePreamble.c: preambleList[].
++  '(("Copyright")    ;; 4.4.2
++    ("RHNPlatform")  ;; 4.4.2, 4.4.9
++    ("Serial")       ;; 4.4.2, 4.4.9
++    )
++  "List of elements that are obsolete tags in some versions of rpm.")
++
++(defvar rpm-obsolete-tags-regexp
++  (regexp-opt (mapcar 'car rpm-obsolete-tags-list) 'words)
++  "Regular expression for matching obsolete tags.")
++
+ (defvar rpm-group-tags-list
+-  ;; From RPM 4.1 sources, file GROUPS.
++  ;; From RPM 4.4.9 sources, file GROUPS.
+   '(("Amusements/Games")
+     ("Amusements/Graphics")
+     ("Applications/Archiving")
+@@ -421,9 +517,10 @@
+   (define-key rpm-spec-mode-map "\C-c\C-xi" 'rpm-change-timecheck-option)
+   (define-key rpm-spec-mode-map "\C-c\C-xn" 'rpm-toggle-nobuild)
+   (define-key rpm-spec-mode-map "\C-c\C-xo" 'rpm-files-owner)
+-  (define-key rpm-spec-mode-map "\C-c\C-xp" 'rpm-change-target-option)
+   (define-key rpm-spec-mode-map "\C-c\C-xr" 'rpm-toggle-rmsource)
++  (define-key rpm-spec-mode-map "\C-c\C-xq" 'rpm-toggle-quiet)
+   (define-key rpm-spec-mode-map "\C-c\C-xs" 'rpm-toggle-short-circuit)
++  (define-key rpm-spec-mode-map "\C-c\C-xt" 'rpm-change-target-option)
+   (define-key rpm-spec-mode-map "\C-c\C-xu" 'rpm-files-umask)
+   ;;(define-key rpm-spec-mode-map "\C-q" 'indent-spec-exp)
+   ;;(define-key rpm-spec-mode-map "\t" 'sh-indent-line)
+@@ -466,6 +563,8 @@
+                 :style toggle :selected rpm-spec-clean]
+                ["No build"      rpm-toggle-nobuild
+                 :style toggle :selected rpm-spec-nobuild]
++               ["Quiet"         rpm-toggle-quiet
++                :style toggle :selected rpm-spec-quiet]
+                ["GPG sign"      rpm-toggle-sign-gpg
+                 :style toggle :selected rpm-spec-sign-gpg]
+                ["Ignore dependencies" rpm-toggle-nodeps
+@@ -488,33 +587,41 @@
+               )))
+ 
+ (defvar rpm-spec-font-lock-keywords
+-  '(
+-    ("%[a-zA-Z0-9_]+" 0 rpm-spec-macro-face)
+-    ("^\\([a-zA-Z0-9]+\\)\\(\([a-zA-Z0-9,]+\)\\):"
+-     (1 rpm-spec-tag-face)
+-     (2 rpm-spec-ghost-face))
+-    ("^\\([a-zA-Z0-9]+\\):" 1 rpm-spec-tag-face)
+-    ("%\\(de\\(fine\\|scription\\)\\|files\\|package\\)[ \t]+\\([^-][^ \t\n]*\\)"
++  (list
++   (cons rpm-section-regexp rpm-spec-section-face)
++   '("%[a-zA-Z0-9_]+" 0 rpm-spec-macro-face)
++   (cons (concat "^" rpm-obsolete-tags-regexp "\\(\([a-zA-Z0-9,_]+\)\\)[ \t]*:")
++         '((1 'rpm-spec-obsolete-tag-face)
++           (2 'rpm-spec-ghost-face)))
++   (cons (concat "^" rpm-tags-regexp "\\(\([a-zA-Z0-9,_]+\)\\)[ \t]*:")
++         '((1 'rpm-spec-tag-face)
++           (3 'rpm-spec-ghost-face)))
++   (cons (concat "^" rpm-obsolete-tags-regexp "[ \t]*:")
++         '(1 'rpm-spec-obsolete-tag-face))
++   (cons (concat "^" rpm-tags-regexp "[ \t]*:")
++         '(1 'rpm-spec-tag-face))
++   '("%\\(de\\(fine\\|scription\\)\\|files\\|global\\|package\\)[ \t]+\\([^-][^ \t\n]*\\)"
+      (3 rpm-spec-package-face))
+-    ("%p\\(ost\\|re\\)\\(un\\)?[ \t]+\\([^-][^ \t\n]*\\)"
++   '("%p\\(ost\\|re\\)\\(un\\|trans\\)?[ \t]+\\([^-][^ \t\n]*\\)"
+      (3 rpm-spec-package-face))
+-    ("%configure " 0 rpm-spec-macro-face)
+-    ("%dir[ \t]+\\([^ \t\n]+\\)[ \t]*" 1 rpm-spec-dir-face)
+-    ("%doc\\(dir\\)?[ \t]+\\(.*\\)\n" 2 rpm-spec-doc-face)
+-    ("%\\(ghost\\|config\\)[ \t]+\\(.*\\)\n" 2 rpm-spec-ghost-face)
+-    ("^%.+-[a-zA-Z][ \t]+\\([a-zA-Z0-9\.-]+\\)" 1 rpm-spec-doc-face)
+-    ("^\\(.+\\)(\\([a-zA-Z]\\{2,2\\}\\)):"
++   '("%configure " 0 rpm-spec-macro-face)
++   '("%dir[ \t]+\\([^ \t\n]+\\)[ \t]*" 1 rpm-spec-dir-face)
++   '("%doc\\(dir\\)?[ \t]+\\(.*\\)\n" 2 rpm-spec-doc-face)
++   '("%\\(ghost\\|config\\([ \t]*(.*)\\)?\\)[ \t]+\\(.*\\)\n"
++     3 rpm-spec-ghost-face)
++   '("^%.+-[a-zA-Z][ \t]+\\([a-zA-Z0-9\.-]+\\)" 1 rpm-spec-doc-face)
++   '("^\\(.+\\)(\\([a-zA-Z]\\{2,2\\}\\)):"
+      (1 rpm-spec-tag-face)
+      (2 rpm-spec-doc-face))
+-    ("^\\*\\(.*[0-9] \\)\\(.*\\)\\(<.*>\\)\\(.*\\)\n"
++   '("^\\*\\(.*[0-9] \\)\\(.*\\)<\\(.*\\)>\\(.*\\)\n"
+      (1 rpm-spec-dir-face)
+      (2 rpm-spec-package-face)
+      (3 rpm-spec-tag-face)
+-     (4 font-lock-warning-face))
+-    ("%{[^{}]*}" 0 rpm-spec-macro-face)
+-    ("$[a-zA-Z0-9_]+" 0 rpm-spec-var-face)
+-    ("${[a-zA-Z0-9_]+}" 0 rpm-spec-var-face)
+-    )
++     (4 rpm-spec-ghost-face))
++   '("%{[^{}]*}" 0 rpm-spec-macro-face)
++   '("$[a-zA-Z0-9_]+" 0 rpm-spec-var-face)
++   '("${[a-zA-Z0-9_]+}" 0 rpm-spec-var-face)
++   )
+   "Additional expressions to highlight in `rpm-spec-mode'.")
+ 
+ ;;Initialize font lock for xemacs
+@@ -526,6 +633,8 @@
+ 
+ ;;------------------------------------------------------------
+ 
++(add-hook 'rpm-spec-mode-new-file-hook 'rpm-spec-initialize)
++
+ ;;;###autoload
+ (defun rpm-spec-mode ()
+   "Major mode for editing RPM spec files.
+@@ -553,13 +662,13 @@
+                     "Post menu for `rpm-spec-mode'." rpm-spec-mode-menu)
+   (easy-menu-add rpm-spec-mode-menu)
+ 
+-  (if (= (buffer-size) 0)
+-      (rpm-spec-initialize))
++  (if (and (= (buffer-size) 0) rpm-spec-initialize-sections)
++      (run-hooks 'rpm-spec-mode-new-file-hook))
+ 
+-  (if (executable-find "rpmbuild")
+-      (setq rpm-spec-build-command "rpmbuild")
+-    (setq rpm-spec-old-rpm t)
+-    (setq rpm-spec-build-command "rpm"))
++  (if (not (executable-find "rpmbuild"))
++      (progn
++	(setq rpm-spec-build-command "rpm")
++	(setq rpm-spec-nobuild-option "--test")))
+   
+   (make-local-variable 'paragraph-start)
+   (setq paragraph-start (concat "$\\|" page-delimiter))
+@@ -602,13 +711,13 @@
+   (interactive "sChange log entry: ")
+   (save-excursion
+     (rpm-goto-section "changelog")
+-    (let* ((address (or rpm-spec-user-mail-address (user-mail-address)))
++    (let* ((address (rpm-spec-user-mail-address))
+            (fullname (or rpm-spec-user-full-name (user-full-name)))
+            (string (concat "* " (substring (current-time-string) 0 11)
+                            (substring (current-time-string) -4) " "
+                            fullname " <" address ">"
+                            (and rpm-spec-insert-changelog-version
+-                                (concat " " (rpm-find-spec-version t))))))
++                                (concat " - " (rpm-find-spec-version t))))))
+       (if (not (search-forward string nil t))
+           (insert "\n" string "\n")
+         (forward-line 2))
+@@ -732,7 +841,7 @@
+           (replace-match
+            (concat what ": " (read-from-minibuffer
+                               (concat "New " what ": ") (match-string 1))))
+-        (message (concat what " tag not found...")))))))
++        (message "%s tag not found..." what))))))
+ 
+ (defun rpm-change-n (what &optional arg)
+   "Change given tag with possible number."
+@@ -746,7 +855,7 @@
+              (concat what number ": "
+                      (read-file-name (concat "New " what number " file: ")
+                                      "" "" nil (match-string 1)))))
+-        (message (concat what " number \"" number "\" not found..."))))))
++        (message "%s number \"%s\" not found..." what number)))))
+ 
+ (defun rpm-insert-group (group)
+   "Insert Group tag."
+@@ -783,7 +892,7 @@
+   (interactive "p")
+   (beginning-of-line)
+   (insert "Packager: " (or rpm-spec-user-full-name (user-full-name))
+-          " <" (or rpm-spec-user-mail-address (user-mail-address)) ">\n"))
++          " <" (rpm-spec-user-mail-address) ">\n"))
+ 
+ (defun rpm-change-packager (&optional arg)
+   "Update Packager tag."
+@@ -878,6 +987,9 @@
+ 
+ (defun rpm-build (buildoptions)
+   "Build this RPM package."
++  (if (and (buffer-modified-p)
++           (y-or-n-p (format "Buffer %s modified, save it? " (buffer-name))))
++      (save-buffer))
+   (setq rpm-buffer-name
+         (concat "*" rpm-spec-build-command " " buildoptions " "
+                 (file-name-nondirectory buffer-file-name) "*"))
+@@ -906,18 +1018,23 @@
+       (setq buildoptions (cons "--target" (cons rpm-spec-target
+                                                 buildoptions))))
+   (if rpm-spec-nobuild
+-      (setq buildoptions (cons (if rpm-spec-old-rpm "--test" "--nobuild")
+-			       buildoptions)))
++      (setq buildoptions (cons rpm-spec-nobuild-option buildoptions)))
++  (if rpm-spec-quiet
++      (setq buildoptions (cons "--quiet" buildoptions)))
+   (if rpm-spec-nodeps
+       (setq buildoptions (cons "--nodeps" buildoptions)))
+   (if (and rpm-spec-sign-gpg (not rpm-no-gpg))
+       (setq buildoptions (cons "--sign" buildoptions)))
+   (save-excursion
+     (set-buffer (get-buffer rpm-buffer-name))
++    (and rpm-spec-use-compilation-mode
++         (fboundp 'compilation-mode)
++         (compilation-mode))
+     (goto-char (point-max)))
+-  (let ((process
+-         (apply 'start-process rpm-spec-build-command rpm-buffer-name
+-		rpm-spec-build-command buildoptions)))
++  (let* ((process-environment (cons "EMACS=t" process-environment))
++         (process
++          (apply 'start-process rpm-spec-build-command rpm-buffer-name
++                 rpm-spec-build-command buildoptions)))
+     (if (and rpm-spec-sign-gpg (not rpm-no-gpg))
+         (let ((rpm-passwd-cache (read-passwd "GPG passphrase: ")))
+           (process-send-string process (concat rpm-passwd-cache "\n"))))
+@@ -927,8 +1044,8 @@
+   "Run a `rpmbuild -bp'."
+   (interactive "p")
+   (if rpm-spec-short-circuit
+-      (message (concat "Cannot run `" rpm-spec-build-command
+-		       " -bp' with --short-circuit"))
++      (message "Cannot run `%s -bp' with --short-circuit"
++	       rpm-spec-build-command)
+     (setq rpm-no-gpg t)
+     (rpm-build "-bp")))
+ 
+@@ -936,8 +1053,8 @@
+   "Run a `rpmbuild -bl'."
+   (interactive "p")
+   (if rpm-spec-short-circuit
+-      (message (concat "Cannot run `" rpm-spec-build-command
+-		       " -bl' with --short-circuit"))
++      (message "Cannot run `%s -bl' with --short-circuit"
++	       rpm-spec-build-command)
+     (setq rpm-no-gpg t)
+     (rpm-build "-bl")))
+ 
+@@ -957,8 +1074,8 @@
+   "Run a `rpmbuild -bb'."
+   (interactive "p")
+   (if rpm-spec-short-circuit
+-      (message (concat "Cannot run `" rpm-spec-build-command
+-		       " -bb' with --short-circuit"))
++      (message "Cannot run `%s -bb' with --short-circuit"
++	       rpm-spec-build-command)
+     (setq rpm-no-gpg nil)
+     (rpm-build "-bb")))
+ 
+@@ -966,8 +1083,8 @@
+   "Run a `rpmbuild -bs'."
+   (interactive "p")
+   (if rpm-spec-short-circuit
+-      (message (concat "Cannot run `" rpm-spec-build-command
+-		       " -bs' with --short-circuit"))
++      (message "Cannot run `%s -bs' with --short-circuit"
++	       rpm-spec-build-command)
+     (setq rpm-no-gpg nil)
+     (rpm-build "-bs")))
+ 
+@@ -975,8 +1092,8 @@
+   "Run a `rpmbuild -ba'."
+   (interactive "p")
+   (if rpm-spec-short-circuit
+-      (message (concat "Cannot run `" rpm-spec-build-command
+-		       " -ba' with --short-circuit"))
++      (message "Cannot run `%s -ba' with --short-circuit"
++	       rpm-spec-build-command)
+     (setq rpm-no-gpg nil)
+     (rpm-build "-ba")))
+ 
+@@ -1022,9 +1139,17 @@
+   (interactive "p")
+   (setq rpm-spec-nobuild (not rpm-spec-nobuild))
+   (rpm-update-mode-name)
+-  (message (concat "Turned `" (if rpm-spec-old-rpm "--test" "--nobuild") "' "
++  (message (concat "Turned `" rpm-spec-nobuild-option "' "
+                    (if rpm-spec-nobuild "on" "off") ".")))
+ 
++(defun rpm-toggle-quiet (&optional arg)
++  "Toggle `rpm-spec-quiet'."
++  (interactive "p")
++  (setq rpm-spec-quiet (not rpm-spec-quiet))
++  (rpm-update-mode-name)
++  (message (concat "Turned `--quiet' "
++                   (if rpm-spec-quiet "on" "off") ".")))
++
+ (defun rpm-toggle-sign-gpg (&optional arg)
+   "Toggle `rpm-spec-sign-gpg'."
+   (interactive "p")
+@@ -1059,6 +1184,7 @@
+                       (if rpm-spec-nobuild       "N")
+                       (if rpm-spec-rmsource      "R")
+                       (if rpm-spec-short-circuit "S")
++		      (if rpm-spec-quiet         "Q")
+                       ))
+   (if (not (equal modes ""))
+       (setq mode-name (concat mode-name ":" modes))))
+@@ -1106,14 +1232,18 @@
+   (interactive "p")
+   (save-excursion
+     (goto-char (point-min))
+-    (if (search-forward-regexp "^Release:[ \t]*\\([0-9]+\\)\\(.*\\)" nil t)
+-        (let ((release (1+ (string-to-int (match-string 1)))))
+-          (setq release (concat (int-to-string release) (match-string 2)))
+-          (replace-match (concat "Release: " release))
+-          (message (concat "Release tag changed to " release ".")))
+-      (if (search-forward-regexp "^Release:[ \t]*%{?\\([^}]*\\)}?$" nil t)
++    (if (search-forward-regexp
++         ;; Try to find the last digit-only group of a dot-separated release string
++         (concat "^\\(Release[ \t]*:[ \t]*\\)"
++                 "\\(.*[ \t\\.}]\\)\\([0-9]+\\)\\([ \t\\.%].*\\|$\\)") nil t)
++        (let ((release (1+ (string-to-int (match-string 3)))))
++          (setq release
++                (concat (match-string 2) (int-to-string release) (match-string 4)))
++          (replace-match (concat (match-string 1) release))
++          (message "Release tag changed to %s." release))
++      (if (search-forward-regexp "^Release[ \t]*:[ \t]*%{?\\([^}]*\\)}?$" nil t)
+           (rpm-increase-release-with-macros)
+-        (message "No Release tag found...")))))
++        (message "No Release tag to increase found...")))))
+ 
+ ;;------------------------------------------------------------
+ 
+@@ -1121,22 +1251,32 @@
+   "Get the value of FIELD, searching up to buffer position MAX.
+ See `search-forward-regexp'."
+   (save-excursion
+-    (ignore-errors
++    (condition-case nil
+       (let ((str
+              (progn
+                (goto-char (point-min))
+-               (search-forward-regexp (concat
+-                                       field ":[ \t]*\\(.*?\\)[ \t]*$") max)
++               (search-forward-regexp
++                (concat "^" field ":[ \t]*\\(.*?\\)[ \t]*$") max)
+                (match-string 1))))
+-        (if (string-match "%{?\\([^}]*\\)}?$" str)
+-            (progn
+-              (goto-char (point-min))
+-              (search-forward-regexp
+-               (concat "%define[ \t]+" (substring str (match-beginning 1)
+-                                                  (match-end 1))
+-                       "[ \t]+\\(.*\\)"))
+-              (match-string 1))
+-          str)))))
++        ;; Try to expand macros
++        (if (string-match "\\(%{?\\(\\?\\)?\\)\\([a-zA-Z0-9_]*\\)\\(}?\\)" str)
++            (let ((start-string (substring str 0 (match-beginning 1)))
++                  (end-string (substring str (match-end 4))))
++              (if (progn
++                    (goto-char (point-min))
++                    (search-forward-regexp
++                     (concat "%\\(define\\|global\\)[ \t]+"
++                             (match-string 3 str)
++                             "[ \t]+\\(.*\\)") nil t))
++                  ;; Got it - replace.
++                  (concat start-string (match-string 2) end-string)
++                (if (match-string 2 str)
++                    ;; Conditionally evaluated macro - remove it.
++                    (concat start-string end-string)
++                  ;; Leave as is.
++                  str)))
++          str))
++      (error nil))))
+ 
+ (defun rpm-find-spec-version (&optional with-epoch)
+   "Get the version string.
+@@ -1159,7 +1299,7 @@
+     (let ((str
+            (progn
+              (goto-char (point-min))
+-             (search-forward-regexp (concat "Release:[ \t]*\\(.+\\).*$") nil)
++             (search-forward-regexp "^Release[ \t]*:[ \t]*\\(.+\\).*$" nil)
+              (match-string 1))))
+       (let ((inrel
+              (if (string-match "%{?\\([^}]*\\)}?$" str)
+@@ -1176,13 +1316,13 @@
+                str)))
+         (setq dinrel inrel)
+         (replace-match (concat "%define " dinrel))
+-        (message (concat "Release tag changed to " dinrel "."))))))
++        (message "Release tag changed to %s." dinrel)))))
+ 
+ ;;------------------------------------------------------------
+ 
+ (defun rpm-spec-initialize ()
+   "Create a default spec file if one does not exist or is empty."
+-  (let (file name version (release "1"))
++  (let (file name version (release rpm-spec-default-release))
+     (setq file (if (buffer-file-name)
+                    (file-name-nondirectory (buffer-file-name))
+                  (buffer-name)))
+@@ -1197,30 +1337,64 @@
+      ((eq (string-match "\\(.*\\).spec" file) 0)
+       (setq name (match-string 1 file))))
+ 
++    (if rpm-spec-indent-heading-values
++	(insert
++	 "Summary:        "
++	 "\nName:           " (or name "")
++	 "\nVersion:        " (or version "")
++	 "\nRelease:        " (or release "")
++	 (if rpm-spec-default-epoch
++	     (concat "\nEpoch:          "
++		     (int-to-string rpm-spec-default-epoch))
++	   "")
++	 "\nLicense:        "
++	 "\nGroup:          "
++	 "\nURL:            "
++	 "\nSource0:        %{name}-%{version}.tar.gz"
++	 "\nBuildRoot:      " rpm-spec-default-buildroot)
++      (insert
++       "Summary: "
++       "\nName: " (or name "")
++       "\nVersion: " (or version "")
++       "\nRelease: " (or release "")
++       (if rpm-spec-default-epoch
++	   (concat "\nEpoch: " (int-to-string rpm-spec-default-epoch))
++	 "")
++       "\nLicense: "
++       "\nGroup: "
++       "\nURL: "
++       "\nSource0: %{name}-%{version}.tar.gz"
++       "\nBuildRoot: " rpm-spec-default-buildroot))
++
+     (insert
+-     "Summary: "
+-     "\nName: " (or name "")
+-     "\nVersion: " (or version "")
+-     "\nRelease: " (or release "")
+-     "\nLicense: "
+-     "\nGroup: "
+-     "\nURL: "
+-     "\nSource0: %{name}-%{version}.tar.gz"
+-     "\nBuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot"
+      "\n\n%description\n"
+      "\n%prep"
+      "\n%setup -q"
+-     "\n\n%build"
+-     "\n\n%install"
+-     "\nrm -rf $RPM_BUILD_ROOT"
+-     "\n\n%clean"
+-     "\nrm -rf $RPM_BUILD_ROOT"
++     "\n\n%build\n"
++     (or rpm-spec-default-build-section "")
++     "\n%install\n"
++     (or rpm-spec-default-install-section "")
++     "\n%clean\n"
++     (or rpm-spec-default-clean-section "")
+      "\n\n%files"
+      "\n%defattr(-,root,root,-)"
+      "\n%doc\n"
+      "\n\n%changelog\n")
+ 
+-    (rpm-add-change-log-entry "Initial build.\n")))
++    (end-of-line 1)
++    (rpm-add-change-log-entry "Initial build.")))
++
++;;------------------------------------------------------------
++
++(defun rpm-spec-user-mail-address ()
++  "User mail address helper."
++  (cond
++   (rpm-spec-user-mail-address
++    rpm-spec-user-mail-address)
++   ((fboundp 'user-mail-address)
++    (user-mail-address))
++   (t
++    user-mail-address)))
+ 
+ ;;------------------------------------------------------------
+ 
+@@ -1232,8 +1406,7 @@
+            rpm-spec-mode-version
+            " by Stig Bjørlykke, <stigb at tihlde.org>")))
+ 
+-;;;###autoload
+-(add-to-list 'auto-mode-alist '("\\.spec$" . rpm-spec-mode))
++;;;###autoload(add-to-list 'auto-mode-alist '("\\.spec\\(\\.in\\)?$" . rpm-spec-mode))
+ 
+ (provide 'rpm-spec-mode)
+ 
diff --git a/rpm-spec-mode.el b/rpm-spec-mode.el
new file mode 100644
index 0000000..bc147b4
--- /dev/null
+++ b/rpm-spec-mode.el
@@ -0,0 +1,1240 @@
+;;; rpm-spec-mode.el --- RPM spec file editing commands for Emacs/XEmacs
+
+;; Copyright (C) 1997-2002 Stig Bjørlykke, <stigb at tihlde.org>
+
+;; Author:   Stig Bjørlykke, <stigb at tihlde.org>
+;; Keywords: unix, languages
+;; Version:  0.12
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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, or (at your option)
+;; any later version.
+
+;; XEmacs 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 XEmacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+;; MA 02111-1307, USA.
+
+;;; Synched up with: not in GNU Emacs.
+
+;;; Thanx to:
+
+;;     Tore Olsen <toreo at tihlde.org> for some general fixes.
+;;     Steve Sanbeg <sanbeg at dset.com> for navigation functions and
+;;          some Emacs fixes.
+;;     Tim Powers <timp at redhat.com> and Trond Eivind Glomsrød
+;;          <teg at redhat.com> for Red Hat adaptions and some fixes.
+;;     Chmouel Boudjnah <chmouel at mandrakesoft.com> for Mandrake fixes.
+
+;;; ToDo:
+
+;; - rewrite function names.
+;; - autofill changelog entries.
+;; - customize rpm-tags-list and rpm-group-tags-list.
+;; - get values from `rpm --showrc'.
+;; - ssh/rsh for compile.
+;; - finish integrating the new navigation functions in with existing stuff.
+;; - use a single prefix consistently (internal)
+
+;;; Commentary:
+
+;; This mode is used for editing spec files used for building RPM packages.
+;;
+;; Most recent version is available from:
+;;  <URL:http://www.tihlde.org/~stigb/rpm-spec-mode.el>
+;;
+;; Put this in your .emacs file to enable autoloading of rpm-spec-mode,
+;; and auto-recognition of ".spec" files:
+;;
+;;  (autoload 'rpm-spec-mode "rpm-spec-mode.el" "RPM spec mode." t)
+;;  (setq auto-mode-alist (append '(("\\.spec" . rpm-spec-mode))
+;;                                auto-mode-alist))
+;;------------------------------------------------------------
+;;
+
+;;; Code:
+
+(defconst rpm-spec-mode-version "0.12" "Version of `rpm-spec-mode'.")
+
+(defgroup rpm-spec nil
+  "RPM spec mode with Emacs/XEmacs enhancements."
+  :prefix "rpm-spec-"
+  :group 'languages)
+
+(defcustom rpm-spec-build-command "rpmbuild"
+  "Command for building a RPM package."
+  :type 'string
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-add-attr nil
+  "Add \"%attr\" entry for file listings or not."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-short-circuit nil
+  "Skip straight to specified stage.
+(ie, skip all stages leading up to the specified stage).  Only valid
+in \"%build\" and \"%install\" stage."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-timecheck "0"
+  "Set the \"timecheck\" age (0 to disable).
+The timecheck value expresses, in seconds, the maximum age of a file
+being packaged.  Warnings will be printed for all files beyond the
+timecheck age."
+  :type 'integer
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-buildroot ""
+  "Override the BuildRoot tag with directory <dir>."
+  :type 'string
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-target ""
+  "Interpret given string as `arch-vendor-os'.
+Set the macros _target, _target_arch and _target_os accordingly"
+  :type 'string
+  :group 'rpm-spec)
+
+(define-obsolete-variable-alias
+  'rpm-completion-ignore-case 'rpm-spec-completion-ignore-case)
+
+(defcustom rpm-spec-completion-ignore-case t
+  "*Non-nil means that case differences are ignored during completion.
+A value of nil means that case is significant.
+This is used during Tempo template completion."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-clean nil
+  "Remove the build tree after the packages are made."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-rmsource nil
+  "Remove the source and spec file after the packages are made."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-nobuild nil
+  "Do not execute any build stages.  Useful for testing out spec files."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-sign-gpg nil
+  "Embed a GPG signature in the package.
+This signature can be used to verify the integrity and the origin of
+the package."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-nodeps nil
+  "Do not verify build dependencies."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-old-rpm nil
+  "Set if using `rpm' as command for building packages."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(define-obsolete-variable-alias
+  'rpm-initialize-sections 'rpm-spec-initialize-sections)
+
+(defcustom rpm-spec-initialize-sections t
+  "Automatically add empty section headings to new spec files."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(define-obsolete-variable-alias
+  'rpm-insert-version 'rpm-spec-insert-changelog-version)
+
+(defcustom rpm-spec-insert-changelog-version t
+  "Automatically add version in a new change log entry."
+  :type 'boolean
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-user-full-name nil
+  "*Full name of the user.
+This is used in the change log and the Packager tag.  It defaults to the
+value returned by function `user-full-name'."
+  :type '(choice (const :tag "Use `user-full-name'" nil)
+                 string)
+  :group 'rpm-spec)
+
+(defcustom rpm-spec-user-mail-address nil
+  "*Email address of the user.
+This is used in the change log and the Packager tag.  It defaults to the
+value returned by function `user-mail-address'."
+  :type '(choice (const :tag "Use `user-mail-address'" nil)
+                 string)
+  :group 'rpm-spec)
+
+(defgroup rpm-spec-faces nil
+  "Font lock faces for `rpm-spec-mode'."
+  :group 'rpm-spec
+  :group 'faces)
+
+;;------------------------------------------------------------
+;; variables used by navigation functions.
+
+(defconst rpm-sections
+  '("preamble" "description" "prep" "setup" "build" "install" "clean"
+    "changelog" "files")
+  "Partial list of section names.")
+(defvar rpm-section-list
+  '(("preamble") ("description") ("prep") ("setup") ("build") ("install")
+    ("clean") ("changelog") ("files"))
+  "Partial list of section names.")
+(defconst rpm-scripts
+  '("pre" "post" "preun" "postun"
+    "trigger" "triggerin" "triggerun" "triggerpostun")
+  "List of rpm scripts.")
+(defconst rpm-section-seperate "^%\\(\\w+\\)\\s-")
+(defconst rpm-section-regexp
+  (eval-when-compile
+    (concat "^%"
+            (regexp-opt
+             ;; From RPM 4.1 sources, file build/parseSpec.c: partList[].
+             '("build" "changelog" "clean" "description" "files" "install"
+               "package" "post" "postun" "pre" "prep" "preun" "trigger"
+               "triggerin" "triggerpostun" "triggerun" "verifyscript") t)
+            "\\b"))
+  "Regular expression to match beginning of a section.")
+
+;;------------------------------------------------------------
+
+(defface rpm-spec-tag-face
+  '(( ((class color) (background light)) (:foreground "blue") )
+    ( ((class color) (background dark)) (:foreground "blue") ))
+  "*The face used for tags."
+  :group 'rpm-spec-faces)
+
+(defface rpm-spec-macro-face
+  '(( ((class color) (background light)) (:foreground "purple") )
+    ( ((class color) (background dark)) (:foreground "yellow") ))
+  "*The face used for macros."
+  :group 'rpm-spec-faces)
+
+(defface rpm-spec-var-face
+  '(( ((class color) (background light)) (:foreground "maroon") )
+    ( ((class color) (background dark)) (:foreground "maroon") ))
+  "*The face used for environment variables."
+  :group 'rpm-spec-faces)
+
+(defface rpm-spec-doc-face
+  '(( ((class color) (background light)) (:foreground "magenta") )
+    ( ((class color) (background dark)) (:foreground "magenta") ))
+  "*The face used for document files."
+  :group 'rpm-spec-faces)
+
+(defface rpm-spec-dir-face
+  '(( ((class color) (background light)) (:foreground "green") )
+    ( ((class color) (background dark)) (:foreground "green") ))
+  "*The face used for directories."
+  :group 'rpm-spec-faces)
+
+(defface rpm-spec-package-face
+  '(( ((class color) (background light)) (:foreground "red") )
+    ( ((class color) (background dark)) (:foreground "red") ))
+  "*The face used for files."
+  :group 'rpm-spec-faces)
+
+(defface rpm-spec-ghost-face
+  '(( ((class color) (background light)) (:foreground "red") )
+    ( ((class color) (background dark)) (:foreground "red") ))
+  "*The face used for ghost tags."
+  :group 'rpm-spec-faces)
+
+;;; GNU emacs font-lock needs these...
+(defvar rpm-spec-macro-face
+  'rpm-spec-macro-face "*Face for macros.")
+(defvar rpm-spec-var-face
+  'rpm-spec-var-face "*Face for environment variables.")
+(defvar rpm-spec-tag-face
+  'rpm-spec-tag-face "*Face for tags.")
+(defvar rpm-spec-package-face
+  'rpm-spec-package-face "*Face for package tag.")
+(defvar rpm-spec-dir-face
+  'rpm-spec-dir-face "*Face for directory entries.")
+(defvar rpm-spec-doc-face
+  'rpm-spec-doc-face "*Face for documentation entries.")
+(defvar rpm-spec-ghost-face
+  'rpm-spec-ghost-face "*Face for \"%ghost\" files.")
+
+(defvar rpm-default-umask "-"
+  "*Default umask for files, specified with \"%attr\".")
+(defvar rpm-default-owner "root"
+  "*Default owner for files, specified with \"%attr\".")
+(defvar rpm-default-group "root"
+  "*Default group for files, specified with \"%attr\".")
+
+;;------------------------------------------------------------
+
+(defvar rpm-no-gpg nil "Tell rpm not to sign package.")
+
+(defvar rpm-tags-list
+  ;; From RPM 4.1 sources, file build/parsePreamble.c: preambleList[].")
+  '(("AutoProv")
+    ("AutoReq")
+    ("AutoReqProv")
+    ("BuildArch")
+    ("BuildArchitectures")
+    ("BuildConflicts")
+    ("BuildPreReq")
+    ("BuildRequires")
+    ("BuildRoot")
+    ("Conflicts")
+    ("Copyright")
+    ("%description")
+    ("Distribution")
+    ("DistURL")
+    ("DocDir")
+    ("Epoch")
+    ("ExcludeArch")
+    ("ExcludeOS")
+    ("ExclusiveArch")
+    ("ExclusiveOS")
+    ("%files")
+    ("Group")
+    ("Icon")
+    ("%ifarch")
+    ("License")
+    ("Name")
+    ("NoPatch")
+    ("NoSource")
+    ("Obsoletes")
+    ("%package")
+    ("Packager")
+    ("Patch")
+    ("Prefix")
+    ("Prefixes")
+    ("PreReq")
+    ("Provides")
+    ("Release")
+    ("Requires")
+    ("RHNPlatform")
+    ("Serial")
+    ("Source")
+    ("Summary")
+    ("URL")
+    ("Vendor")
+    ("Version"))
+  "List of elements that are valid tags.")
+
+(defvar rpm-group-tags-list
+  ;; From RPM 4.1 sources, file GROUPS.
+  '(("Amusements/Games")
+    ("Amusements/Graphics")
+    ("Applications/Archiving")
+    ("Applications/Communications")
+    ("Applications/Databases")
+    ("Applications/Editors")
+    ("Applications/Emulators")
+    ("Applications/Engineering")
+    ("Applications/File")
+    ("Applications/Internet")
+    ("Applications/Multimedia")
+    ("Applications/Productivity")
+    ("Applications/Publishing")
+    ("Applications/System")
+    ("Applications/Text")
+    ("Development/Debuggers")
+    ("Development/Languages")
+    ("Development/Libraries")
+    ("Development/System")
+    ("Development/Tools")
+    ("Documentation")
+    ("System Environment/Base")
+    ("System Environment/Daemons")
+    ("System Environment/Kernel")
+    ("System Environment/Libraries")
+    ("System Environment/Shells")
+    ("User Interface/Desktops")
+    ("User Interface/X")
+    ("User Interface/X Hardware Support")
+    )
+  "List of elements that are valid group tags.")
+
+(defvar rpm-spec-mode-syntax-table nil
+  "Syntax table in use in `rpm-spec-mode' buffers.")
+(unless rpm-spec-mode-syntax-table
+  (setq rpm-spec-mode-syntax-table (make-syntax-table))
+  (modify-syntax-entry ?\\ "\\" rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?\n ">   " rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?\f ">   " rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?\# "<   " rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?/ "." rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?* "." rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?+ "." rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?- "." rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?= "." rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?% "_" rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?< "." rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?> "." rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?& "." rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?| "." rpm-spec-mode-syntax-table)
+  (modify-syntax-entry ?\' "." rpm-spec-mode-syntax-table))
+
+(defvar rpm-spec-mode-map nil
+  "Keymap used in `rpm-spec-mode'.")
+(unless rpm-spec-mode-map
+  (setq rpm-spec-mode-map (make-sparse-keymap))
+  (and (functionp 'set-keymap-name)
+       (set-keymap-name rpm-spec-mode-map 'rpm-spec-mode-map))
+  (define-key rpm-spec-mode-map "\C-c\C-c"  'rpm-change-tag)
+  (define-key rpm-spec-mode-map "\C-c\C-e"  'rpm-add-change-log-entry)
+  (define-key rpm-spec-mode-map "\C-c\C-i"  'rpm-insert-tag)
+  (define-key rpm-spec-mode-map "\C-c\C-n"  'rpm-forward-section)
+  (define-key rpm-spec-mode-map "\C-c\C-o"  'rpm-goto-section)
+  (define-key rpm-spec-mode-map "\C-c\C-p"  'rpm-backward-section)
+  (define-key rpm-spec-mode-map "\C-c\C-r"  'rpm-increase-release-tag)
+  (define-key rpm-spec-mode-map "\C-c\C-u"  'rpm-insert-true-prefix)
+  (define-key rpm-spec-mode-map "\C-c\C-ba" 'rpm-build-all)
+  (define-key rpm-spec-mode-map "\C-c\C-bb" 'rpm-build-binary)
+  (define-key rpm-spec-mode-map "\C-c\C-bc" 'rpm-build-compile)
+  (define-key rpm-spec-mode-map "\C-c\C-bi" 'rpm-build-install)
+  (define-key rpm-spec-mode-map "\C-c\C-bl" 'rpm-list-check)
+  (define-key rpm-spec-mode-map "\C-c\C-bp" 'rpm-build-prepare)
+  (define-key rpm-spec-mode-map "\C-c\C-bs" 'rpm-build-source)
+  (define-key rpm-spec-mode-map "\C-c\C-dd" 'rpm-insert-dir)
+  (define-key rpm-spec-mode-map "\C-c\C-do" 'rpm-insert-docdir)
+  (define-key rpm-spec-mode-map "\C-c\C-fc" 'rpm-insert-config)
+  (define-key rpm-spec-mode-map "\C-c\C-fd" 'rpm-insert-doc)
+  (define-key rpm-spec-mode-map "\C-c\C-ff" 'rpm-insert-file)
+  (define-key rpm-spec-mode-map "\C-c\C-fg" 'rpm-insert-ghost)
+  (define-key rpm-spec-mode-map "\C-c\C-xa" 'rpm-toggle-add-attr)
+  (define-key rpm-spec-mode-map "\C-c\C-xb" 'rpm-change-buildroot-option)
+  (define-key rpm-spec-mode-map "\C-c\C-xc" 'rpm-toggle-clean)
+  (define-key rpm-spec-mode-map "\C-c\C-xd" 'rpm-toggle-nodeps)
+  (define-key rpm-spec-mode-map "\C-c\C-xf" 'rpm-files-group)
+  (define-key rpm-spec-mode-map "\C-c\C-xg" 'rpm-toggle-sign-gpg)
+  (define-key rpm-spec-mode-map "\C-c\C-xi" 'rpm-change-timecheck-option)
+  (define-key rpm-spec-mode-map "\C-c\C-xn" 'rpm-toggle-nobuild)
+  (define-key rpm-spec-mode-map "\C-c\C-xo" 'rpm-files-owner)
+  (define-key rpm-spec-mode-map "\C-c\C-xp" 'rpm-change-target-option)
+  (define-key rpm-spec-mode-map "\C-c\C-xr" 'rpm-toggle-rmsource)
+  (define-key rpm-spec-mode-map "\C-c\C-xs" 'rpm-toggle-short-circuit)
+  (define-key rpm-spec-mode-map "\C-c\C-xu" 'rpm-files-umask)
+  ;;(define-key rpm-spec-mode-map "\C-q" 'indent-spec-exp)
+  ;;(define-key rpm-spec-mode-map "\t" 'sh-indent-line)
+  )
+
+(defconst rpm-spec-mode-menu
+  (purecopy '("RPM spec"
+              ["Insert Tag..."           rpm-insert-tag                t]
+              ["Change Tag..."           rpm-change-tag                t]
+              "---"
+              ["Go to section..."        rpm-mouse-goto-section  :keys "C-c C-o"]
+              ["Forward section"         rpm-forward-section           t]
+              ["Backward section"        rpm-backward-section          t]
+              "---"
+              ["Add change log entry..." rpm-add-change-log-entry      t]
+              ["Increase release tag"    rpm-increase-release-tag      t]
+              "---"
+              ("Add file entry"
+               ["Regular file..."        rpm-insert-file               t]
+               ["Config file..."         rpm-insert-config             t]
+               ["Document file..."       rpm-insert-doc                t]
+               ["Ghost file..."          rpm-insert-ghost              t]
+               "---"
+               ["Directory..."           rpm-insert-dir                t]
+               ["Document directory..."  rpm-insert-docdir             t]
+               "---"
+               ["Insert %{prefix}"       rpm-insert-true-prefix        t]
+               "---"
+               ["Default add \"%attr\" entry" rpm-toggle-add-attr
+                :style toggle :selected rpm-spec-add-attr]
+               ["Change default umask for files..."  rpm-files-umask   t]
+               ["Change default owner for files..."  rpm-files-owner   t]
+               ["Change default group for files..."  rpm-files-group   t])
+              ("Build Options"
+               ["Short circuit" rpm-toggle-short-circuit
+                :style toggle :selected rpm-spec-short-circuit]
+               ["Remove source" rpm-toggle-rmsource
+                :style toggle :selected rpm-spec-rmsource]
+               ["Clean"         rpm-toggle-clean
+                :style toggle :selected rpm-spec-clean]
+               ["No build"      rpm-toggle-nobuild
+                :style toggle :selected rpm-spec-nobuild]
+               ["GPG sign"      rpm-toggle-sign-gpg
+                :style toggle :selected rpm-spec-sign-gpg]
+               ["Ignore dependencies" rpm-toggle-nodeps
+                :style toggle :selected rpm-spec-nodeps]
+               "---"
+               ["Change timecheck value..."  rpm-change-timecheck-option   t]
+               ["Change buildroot value..."  rpm-change-buildroot-option   t]
+               ["Change target value..."     rpm-change-target-option      t])
+              ("RPM Build"
+               ["Execute \"%prep\" stage"    rpm-build-prepare             t]
+               ["Do a \"list check\""        rpm-list-check                t]
+               ["Do the \"%build\" stage"    rpm-build-compile             t]
+               ["Do the \"%install\" stage"  rpm-build-install             t]
+               "---"
+               ["Build binary package"       rpm-build-binary              t]
+               ["Build source package"       rpm-build-source              t]
+               ["Build binary and source"    rpm-build-all                 t])
+              "---"
+              ["About rpm-spec-mode"         rpm-about-rpm-spec-mode       t]
+              )))
+
+(defvar rpm-spec-font-lock-keywords
+  '(
+    ("%[a-zA-Z0-9_]+" 0 rpm-spec-macro-face)
+    ("^\\([a-zA-Z0-9]+\\)\\(\([a-zA-Z0-9,]+\)\\):"
+     (1 rpm-spec-tag-face)
+     (2 rpm-spec-ghost-face))
+    ("^\\([a-zA-Z0-9]+\\):" 1 rpm-spec-tag-face)
+    ("%\\(de\\(fine\\|scription\\)\\|files\\|package\\)[ \t]+\\([^-][^ \t\n]*\\)"
+     (3 rpm-spec-package-face))
+    ("%p\\(ost\\|re\\)\\(un\\)?[ \t]+\\([^-][^ \t\n]*\\)"
+     (3 rpm-spec-package-face))
+    ("%configure " 0 rpm-spec-macro-face)
+    ("%dir[ \t]+\\([^ \t\n]+\\)[ \t]*" 1 rpm-spec-dir-face)
+    ("%doc\\(dir\\)?[ \t]+\\(.*\\)\n" 2 rpm-spec-doc-face)
+    ("%\\(ghost\\|config\\)[ \t]+\\(.*\\)\n" 2 rpm-spec-ghost-face)
+    ("^%.+-[a-zA-Z][ \t]+\\([a-zA-Z0-9\.-]+\\)" 1 rpm-spec-doc-face)
+    ("^\\(.+\\)(\\([a-zA-Z]\\{2,2\\}\\)):"
+     (1 rpm-spec-tag-face)
+     (2 rpm-spec-doc-face))
+    ("^\\*\\(.*[0-9] \\)\\(.*\\)\\(<.*>\\)\\(.*\\)\n"
+     (1 rpm-spec-dir-face)
+     (2 rpm-spec-package-face)
+     (3 rpm-spec-tag-face)
+     (4 font-lock-warning-face))
+    ("%{[^{}]*}" 0 rpm-spec-macro-face)
+    ("$[a-zA-Z0-9_]+" 0 rpm-spec-var-face)
+    ("${[a-zA-Z0-9_]+}" 0 rpm-spec-var-face)
+    )
+  "Additional expressions to highlight in `rpm-spec-mode'.")
+
+;;Initialize font lock for xemacs
+(put 'rpm-spec-mode 'font-lock-defaults '(rpm-spec-font-lock-keywords))
+
+(defvar rpm-spec-mode-abbrev-table nil
+  "Abbrev table in use in `rpm-spec-mode' buffers.")
+(define-abbrev-table 'rpm-spec-mode-abbrev-table ())
+
+;;------------------------------------------------------------
+
+;;;###autoload
+(defun rpm-spec-mode ()
+  "Major mode for editing RPM spec files.
+This is much like C mode except for the syntax of comments.  It uses
+the same keymap as C mode and has the same variables for customizing
+indentation.  It has its own abbrev table and its own syntax table.
+
+Turning on RPM spec mode calls the value of the variable `rpm-spec-mode-hook'
+with no args, if that value is non-nil."
+  (interactive)
+  (kill-all-local-variables)
+  (condition-case nil
+      (require 'shindent)
+    (error
+     (require 'sh-script)))
+  (require 'cc-mode)
+  (use-local-map rpm-spec-mode-map)
+  (setq major-mode 'rpm-spec-mode)
+  (rpm-update-mode-name)
+  (setq local-abbrev-table rpm-spec-mode-abbrev-table)
+  (set-syntax-table rpm-spec-mode-syntax-table)
+
+  (require 'easymenu)
+  (easy-menu-define rpm-spec-call-menu rpm-spec-mode-map
+                    "Post menu for `rpm-spec-mode'." rpm-spec-mode-menu)
+  (easy-menu-add rpm-spec-mode-menu)
+
+  (if (= (buffer-size) 0)
+      (rpm-spec-initialize))
+
+  (if (executable-find "rpmbuild")
+      (setq rpm-spec-build-command "rpmbuild")
+    (setq rpm-spec-old-rpm t)
+    (setq rpm-spec-build-command "rpm"))
+  
+  (make-local-variable 'paragraph-start)
+  (setq paragraph-start (concat "$\\|" page-delimiter))
+  (make-local-variable 'paragraph-separate)
+  (setq paragraph-separate paragraph-start)
+  (make-local-variable 'paragraph-ignore-fill-prefix)
+  (setq paragraph-ignore-fill-prefix t)
+;  (make-local-variable 'indent-line-function)
+;  (setq indent-line-function 'c-indent-line)
+  (make-local-variable 'require-final-newline)
+  (setq require-final-newline t)
+  (make-local-variable 'comment-start)
+  (setq comment-start "# ")
+  (make-local-variable 'comment-end)
+  (setq comment-end "")
+  (make-local-variable 'comment-column)
+  (setq comment-column 32)
+  (make-local-variable 'comment-start-skip)
+  (setq comment-start-skip "#+ *")
+;  (make-local-variable 'comment-indent-function)
+;  (setq comment-indent-function 'c-comment-indent)
+  ;;Initialize font lock for GNU emacs.
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults '(rpm-spec-font-lock-keywords nil t))
+  (run-hooks 'rpm-spec-mode-hook))
+
+(defun rpm-command-filter (process string)
+  "Filter to process normal output."
+  (save-excursion
+    (set-buffer (process-buffer process))
+    (save-excursion
+      (goto-char (process-mark process))
+      (insert-before-markers string)
+      (set-marker (process-mark process) (point)))))
+
+;;------------------------------------------------------------
+
+(defun rpm-add-change-log-entry (&optional change-log-entry)
+  "Find change log and add an entry for today."
+  (interactive "sChange log entry: ")
+  (save-excursion
+    (rpm-goto-section "changelog")
+    (let* ((address (or rpm-spec-user-mail-address (user-mail-address)))
+           (fullname (or rpm-spec-user-full-name (user-full-name)))
+           (string (concat "* " (substring (current-time-string) 0 11)
+                           (substring (current-time-string) -4) " "
+                           fullname " <" address ">"
+                           (and rpm-spec-insert-changelog-version
+                                (concat " " (rpm-find-spec-version t))))))
+      (if (not (search-forward string nil t))
+          (insert "\n" string "\n")
+        (forward-line 2))
+      (insert "- " change-log-entry "\n"))))
+
+;;------------------------------------------------------------
+
+(defun rpm-insert-f (&optional filetype filename)
+  "Insert new \"%files\" entry."
+  (save-excursion
+    (and (rpm-goto-section "files") (rpm-end-of-section))
+    (if (or (eq filename 1) (not filename))
+        (insert (read-file-name
+                 (concat filetype "filename: ") "" "" nil) "\n")
+      (insert filename "\n"))
+    (forward-line -1)
+    (if rpm-spec-add-attr
+        (let ((rpm-default-mode rpm-default-umask))
+          (insert "%attr(" rpm-default-mode ", " rpm-default-owner ", "
+                  rpm-default-group ") ")))
+    (insert filetype)))
+
+(defun rpm-insert-file (&optional filename)
+  "Insert regular file."
+  (interactive "p")
+  (rpm-insert-f "" filename))
+
+(defun rpm-insert-config (&optional filename)
+  "Insert config file."
+  (interactive "p")
+  (rpm-insert-f "%config " filename))
+
+(defun rpm-insert-doc (&optional filename)
+  "Insert doc file."
+  (interactive "p")
+  (rpm-insert-f "%doc " filename))
+
+(defun rpm-insert-ghost (&optional filename)
+  "Insert ghost file."
+  (interactive "p")
+  (rpm-insert-f "%ghost " filename))
+
+(defun rpm-insert-dir (&optional dirname)
+  "Insert directory."
+  (interactive "p")
+  (rpm-insert-f "%dir " dirname))
+
+(defun rpm-insert-docdir (&optional dirname)
+  "Insert doc directory."
+  (interactive "p")
+  (rpm-insert-f "%docdir " dirname))
+
+;;------------------------------------------------------------
+(defun rpm-completing-read (prompt table &optional pred require init hist)
+  "Read from the minibuffer, with completion.
+Like `completing-read', but the variable `rpm-spec-completion-ignore-case'
+controls whether case is significant."
+  (let ((completion-ignore-case rpm-spec-completion-ignore-case))
+    (completing-read prompt table pred require init hist)))
+
+(defun rpm-insert (&optional what file-completion)
+  "Insert given tag.  Use file-completion if argument is t."
+  (beginning-of-line)
+  (if (not what)
+      (setq what (rpm-completing-read "Tag: " rpm-tags-list)))
+  (if (string-match "^%" what)
+      (setq read-text (concat "Packagename for " what ": ")
+            insert-text (concat what " "))
+    (setq read-text (concat what ": ")
+          insert-text (concat what ": ")))
+  (cond
+   ((string-equal what "Group")
+    (rpm-insert-group))
+   ((string-equal what "Source")
+    (rpm-insert-n "Source"))
+   ((string-equal what "Patch")
+    (rpm-insert-n "Patch"))
+   (t
+    (if file-completion
+        (insert insert-text (read-file-name (concat read-text) "" "" nil) "\n")
+      (insert insert-text (read-from-minibuffer (concat read-text)) "\n")))))
+
+(defun rpm-topdir ()
+  (or
+   (getenv "RPM")
+   (getenv "rpm")
+   (if (file-directory-p "~/rpm") "~/rpm/")
+   (if (file-directory-p "~/RPM") "~/RPM/")
+   (if (file-directory-p "/usr/src/redhat/") "/usr/src/redhat/")
+   "/usr/src/RPM"))
+
+(defun rpm-insert-n (what &optional arg)
+  "Insert given tag with possible number."
+  (save-excursion
+    (goto-char (point-max))
+    (if (search-backward-regexp (concat "^" what "\\([0-9]*\\):") nil t)
+        (let ((release (1+ (string-to-int (match-string 1)))))
+          (forward-line 1)
+          (let ((default-directory (concat (rpm-topdir) "/SOURCES/")))
+            (insert what (int-to-string release) ": "
+                    (read-file-name (concat what "file: ") "" "" nil) "\n")))
+      (goto-char (point-min))
+      (rpm-end-of-section)
+      (insert what ": " (read-from-minibuffer (concat what "file: ")) "\n"))))
+
+(defun rpm-change (&optional what arg)
+  "Update given tag."
+  (save-excursion
+    (if (not what)
+        (setq what (rpm-completing-read "Tag: " rpm-tags-list)))
+    (cond
+     ((string-equal what "Group")
+      (rpm-change-group))
+     ((string-equal what "Source")
+      (rpm-change-n "Source"))
+     ((string-equal what "Patch")
+      (rpm-change-n "Patch"))
+     (t
+      (goto-char (point-min))
+      (if (search-forward-regexp (concat "^" what ":\\s-*\\(.*\\)$") nil t)
+          (replace-match
+           (concat what ": " (read-from-minibuffer
+                              (concat "New " what ": ") (match-string 1))))
+        (message (concat what " tag not found...")))))))
+
+(defun rpm-change-n (what &optional arg)
+  "Change given tag with possible number."
+  (save-excursion
+    (goto-char (point-min))
+    (let ((number (read-from-minibuffer (concat what " number: "))))
+      (if (search-forward-regexp
+           (concat "^" what number ":\\s-*\\(.*\\)") nil t)
+          (let ((default-directory (concat (rpm-topdir) "/SOURCES/")))
+            (replace-match
+             (concat what number ": "
+                     (read-file-name (concat "New " what number " file: ")
+                                     "" "" nil (match-string 1)))))
+        (message (concat what " number \"" number "\" not found..."))))))
+
+(defun rpm-insert-group (group)
+  "Insert Group tag."
+  (interactive (list (rpm-completing-read "Group: " rpm-group-tags-list)))
+  (beginning-of-line)
+  (insert "Group: " group "\n"))
+
+(defun rpm-change-group (&optional arg)
+  "Update Group tag."
+  (interactive "p")
+  (save-excursion
+    (goto-char (point-min))
+    (if (search-forward-regexp "^Group: \\(.*\\)$" nil t)
+        (replace-match
+         (concat "Group: "
+                 (insert (rpm-completing-read "Group: " rpm-group-tags-list
+                                              nil nil (match-string 1)))))
+      (message "Group tag not found..."))))
+
+(defun rpm-insert-tag (&optional arg)
+  "Insert or change a tag."
+  (interactive "p")
+  (if current-prefix-arg
+      (rpm-change)
+    (rpm-insert)))
+
+(defun rpm-change-tag (&optional arg)
+  "Change a tag."
+  (interactive "p")
+  (rpm-change))
+
+(defun rpm-insert-packager (&optional arg)
+  "Insert Packager tag."
+  (interactive "p")
+  (beginning-of-line)
+  (insert "Packager: " (or rpm-spec-user-full-name (user-full-name))
+          " <" (or rpm-spec-user-mail-address (user-mail-address)) ">\n"))
+
+(defun rpm-change-packager (&optional arg)
+  "Update Packager tag."
+  (interactive "p")
+  (rpm-change "Packager"))
+
+;;------------------------------------------------------------
+
+(defun rpm-current-section nil
+  (interactive)
+  (save-excursion
+    (rpm-forward-section)
+    (rpm-backward-section)
+    (if (bobp) "preamble"
+      (buffer-substring (match-beginning 1) (match-end 1)))))
+
+(defun rpm-backward-section nil
+  "Move backward to the beginning of the previous section.
+Go to beginning of previous section."
+  (interactive)
+  (or (re-search-backward rpm-section-regexp nil t)
+      (goto-char (point-min))))
+
+(defun rpm-beginning-of-section nil
+  "Move backward to the beginning of the current section.
+Go to beginning of current section."
+  (interactive)
+  (or (and (looking-at rpm-section-regexp) (point))
+      (re-search-backward rpm-section-regexp nil t)
+      (goto-char (point-min))))
+
+(defun rpm-forward-section nil
+  "Move forward to the beginning of the next section."
+  (interactive)
+  (forward-char)
+  (if (re-search-forward rpm-section-regexp nil t)
+      (progn (forward-line 0) (point))
+    (goto-char (point-max))))
+
+(defun rpm-end-of-section nil
+  "Move forward to the end of this section."
+  (interactive)
+  (forward-char)
+  (if (re-search-forward rpm-section-regexp nil t)
+      (forward-line -1)
+    (goto-char (point-max)))
+;;  (while (or (looking-at paragraph-separate) (looking-at "^\\s-*#"))
+  (while (looking-at "^\\s-*\\($\\|#\\)")
+    (forward-line -1))
+  (forward-line 1)
+  (point))
+
+(defun rpm-goto-section (section)
+  "Move point to the beginning of the specified section;
+leave point at previous location."
+  (interactive (list (rpm-completing-read "Section: " rpm-section-list)))
+  (push-mark)
+  (goto-char (point-min))
+  (or
+   (equal section "preamble")
+   (re-search-forward (concat "^%" section "\\b") nil t)
+   (let ((s (cdr rpm-sections)))
+     (while (not (equal section (car s)))
+       (re-search-forward (concat "^%" (car s) "\\b") nil t)
+       (setq s (cdr s)))
+     (if (re-search-forward rpm-section-regexp nil t)
+         (forward-line -1) (goto-char (point-max)))
+     (insert "\n%" section "\n"))))
+
+(defun rpm-mouse-goto-section (&optional section)
+  (interactive
+   (x-popup-menu
+    nil
+    (list "sections"
+          (cons "Sections" (mapcar (lambda (e) (list e e)) rpm-sections))
+          (cons "Scripts" (mapcar (lambda (e) (list e e)) rpm-scripts))
+          )))
+  ;; If user doesn't pick a section, exit quietly.
+  (and section
+       (if (member section rpm-sections)
+           (rpm-goto-section section)
+         (goto-char (point-min))
+         (or (re-search-forward (concat "^%" section "\\b") nil t)
+             (and (re-search-forward "^%files\\b" nil t) (forward-line -1))
+             (goto-char (point-max))))))
+
+(defun rpm-insert-true-prefix ()
+  (interactive)
+  (insert "%{prefix}"))
+
+;;------------------------------------------------------------
+
+(defun rpm-build (buildoptions)
+  "Build this RPM package."
+  (setq rpm-buffer-name
+        (concat "*" rpm-spec-build-command " " buildoptions " "
+                (file-name-nondirectory buffer-file-name) "*"))
+  (rpm-process-check rpm-buffer-name)
+  (if (get-buffer rpm-buffer-name)
+      (kill-buffer rpm-buffer-name))
+  (create-file-buffer rpm-buffer-name)
+  (display-buffer rpm-buffer-name)
+  (setq buildoptions (list buildoptions buffer-file-name))
+  (if (or rpm-spec-short-circuit rpm-spec-nobuild)
+      (setq rpm-no-gpg t))
+  (if rpm-spec-rmsource
+      (setq buildoptions (cons "--rmsource" buildoptions)))
+  (if rpm-spec-clean
+      (setq buildoptions (cons "--clean" buildoptions)))
+  (if rpm-spec-short-circuit
+      (setq buildoptions (cons "--short-circuit" buildoptions)))
+  (if (and (not (equal rpm-spec-timecheck "0"))
+           (not (equal rpm-spec-timecheck "")))
+      (setq buildoptions (cons "--timecheck" (cons rpm-spec-timecheck
+                                                   buildoptions))))
+  (if (not (equal rpm-spec-buildroot ""))
+      (setq buildoptions (cons "--buildroot" (cons rpm-spec-buildroot
+                                                   buildoptions))))
+  (if (not (equal rpm-spec-target ""))
+      (setq buildoptions (cons "--target" (cons rpm-spec-target
+                                                buildoptions))))
+  (if rpm-spec-nobuild
+      (setq buildoptions (cons (if rpm-spec-old-rpm "--test" "--nobuild")
+			       buildoptions)))
+  (if rpm-spec-nodeps
+      (setq buildoptions (cons "--nodeps" buildoptions)))
+  (if (and rpm-spec-sign-gpg (not rpm-no-gpg))
+      (setq buildoptions (cons "--sign" buildoptions)))
+  (save-excursion
+    (set-buffer (get-buffer rpm-buffer-name))
+    (goto-char (point-max)))
+  (let ((process
+         (apply 'start-process rpm-spec-build-command rpm-buffer-name
+		rpm-spec-build-command buildoptions)))
+    (if (and rpm-spec-sign-gpg (not rpm-no-gpg))
+        (let ((rpm-passwd-cache (read-passwd "GPG passphrase: ")))
+          (process-send-string process (concat rpm-passwd-cache "\n"))))
+    (set-process-filter process 'rpm-command-filter)))
+
+(defun rpm-build-prepare (&optional arg)
+  "Run a `rpmbuild -bp'."
+  (interactive "p")
+  (if rpm-spec-short-circuit
+      (message (concat "Cannot run `" rpm-spec-build-command
+		       " -bp' with --short-circuit"))
+    (setq rpm-no-gpg t)
+    (rpm-build "-bp")))
+
+(defun rpm-list-check (&optional arg)
+  "Run a `rpmbuild -bl'."
+  (interactive "p")
+  (if rpm-spec-short-circuit
+      (message (concat "Cannot run `" rpm-spec-build-command
+		       " -bl' with --short-circuit"))
+    (setq rpm-no-gpg t)
+    (rpm-build "-bl")))
+
+(defun rpm-build-compile (&optional arg)
+  "Run a `rpmbuild -bc'."
+  (interactive "p")
+  (setq rpm-no-gpg t)
+  (rpm-build "-bc"))
+
+(defun rpm-build-install (&optional arg)
+  "Run a `rpmbuild -bi'."
+  (interactive "p")
+  (setq rpm-no-gpg t)
+  (rpm-build "-bi"))
+
+(defun rpm-build-binary (&optional arg)
+  "Run a `rpmbuild -bb'."
+  (interactive "p")
+  (if rpm-spec-short-circuit
+      (message (concat "Cannot run `" rpm-spec-build-command
+		       " -bb' with --short-circuit"))
+    (setq rpm-no-gpg nil)
+    (rpm-build "-bb")))
+
+(defun rpm-build-source (&optional arg)
+  "Run a `rpmbuild -bs'."
+  (interactive "p")
+  (if rpm-spec-short-circuit
+      (message (concat "Cannot run `" rpm-spec-build-command
+		       " -bs' with --short-circuit"))
+    (setq rpm-no-gpg nil)
+    (rpm-build "-bs")))
+
+(defun rpm-build-all (&optional arg)
+  "Run a `rpmbuild -ba'."
+  (interactive "p")
+  (if rpm-spec-short-circuit
+      (message (concat "Cannot run `" rpm-spec-build-command
+		       " -ba' with --short-circuit"))
+    (setq rpm-no-gpg nil)
+    (rpm-build "-ba")))
+
+(defun rpm-process-check (buffer)
+  "Check if BUFFER has a running process.
+If so, give the user the choice of aborting the process or the current
+command."
+  (let ((process (get-buffer-process (get-buffer buffer))))
+    (if (and process (eq (process-status process) 'run))
+        (if (yes-or-no-p (concat "Process `" (process-name process)
+                                 "' running.  Kill it? "))
+            (delete-process process)
+          (error "Cannot run two simultaneous processes ...")))))
+
+;;------------------------------------------------------------
+
+(defun rpm-toggle-short-circuit (&optional arg)
+  "Toggle `rpm-spec-short-circuit'."
+  (interactive "p")
+  (setq rpm-spec-short-circuit (not rpm-spec-short-circuit))
+  (rpm-update-mode-name)
+  (message (concat "Turned `--short-circuit' "
+                   (if rpm-spec-short-circuit "on" "off") ".")))
+
+(defun rpm-toggle-rmsource (&optional arg)
+  "Toggle `rpm-spec-rmsource'."
+  (interactive "p")
+  (setq rpm-spec-rmsource (not rpm-spec-rmsource))
+  (rpm-update-mode-name)
+  (message (concat "Turned `--rmsource' "
+                   (if rpm-spec-rmsource "on" "off") ".")))
+
+(defun rpm-toggle-clean (&optional arg)
+  "Toggle `rpm-spec-clean'."
+  (interactive "p")
+  (setq rpm-spec-clean (not rpm-spec-clean))
+  (rpm-update-mode-name)
+  (message (concat "Turned `--clean' "
+                   (if rpm-spec-clean "on" "off") ".")))
+
+(defun rpm-toggle-nobuild (&optional arg)
+  "Toggle `rpm-spec-nobuild'."
+  (interactive "p")
+  (setq rpm-spec-nobuild (not rpm-spec-nobuild))
+  (rpm-update-mode-name)
+  (message (concat "Turned `" (if rpm-spec-old-rpm "--test" "--nobuild") "' "
+                   (if rpm-spec-nobuild "on" "off") ".")))
+
+(defun rpm-toggle-sign-gpg (&optional arg)
+  "Toggle `rpm-spec-sign-gpg'."
+  (interactive "p")
+  (setq rpm-spec-sign-gpg (not rpm-spec-sign-gpg))
+  (rpm-update-mode-name)
+  (message (concat "Turned `--sign' "
+                   (if rpm-spec-sign-gpg "on" "off") ".")))
+
+(defun rpm-toggle-add-attr (&optional arg)
+  "Toggle `rpm-spec-add-attr'."
+  (interactive "p")
+  (setq rpm-spec-add-attr (not rpm-spec-add-attr))
+  (rpm-update-mode-name)
+  (message (concat "Default add \"attr\" entry turned "
+                   (if rpm-spec-add-attr "on" "off") ".")))
+
+(defun rpm-toggle-nodeps (&optional arg)
+  "Toggle `rpm-spec-nodeps'."
+  (interactive "p")
+  (setq rpm-spec-nodeps (not rpm-spec-nodeps))
+  (rpm-update-mode-name)
+  (message (concat "Turned `--nodeps' "
+                   (if rpm-spec-nodeps "on" "off") ".")))
+
+(defun rpm-update-mode-name ()
+  "Update `mode-name' according to values set."
+  (setq mode-name "RPM-SPEC")
+  (setq modes (concat (if rpm-spec-add-attr      "A")
+                      (if rpm-spec-clean         "C")
+                      (if rpm-spec-nodeps        "D")
+                      (if rpm-spec-sign-gpg      "G")
+                      (if rpm-spec-nobuild       "N")
+                      (if rpm-spec-rmsource      "R")
+                      (if rpm-spec-short-circuit "S")
+                      ))
+  (if (not (equal modes ""))
+      (setq mode-name (concat mode-name ":" modes))))
+
+;;------------------------------------------------------------
+
+(defun rpm-change-timecheck-option (&optional arg)
+  "Change the value for timecheck."
+  (interactive "p")
+  (setq rpm-spec-timecheck
+        (read-from-minibuffer "New timecheck: " rpm-spec-timecheck)))
+
+(defun rpm-change-buildroot-option (&optional arg)
+  "Change the value for buildroot."
+  (interactive "p")
+  (setq rpm-spec-buildroot
+        (read-from-minibuffer "New buildroot: " rpm-spec-buildroot)))
+
+(defun rpm-change-target-option (&optional arg)
+  "Change the value for target."
+  (interactive "p")
+  (setq rpm-spec-target
+        (read-from-minibuffer "New target: " rpm-spec-target)))
+
+(defun rpm-files-umask (&optional arg)
+  "Change the default umask for files."
+  (interactive "p")
+  (setq rpm-default-umask
+        (read-from-minibuffer "Default file umask: " rpm-default-umask)))
+
+(defun rpm-files-owner (&optional arg)
+  "Change the default owner for files."
+  (interactive "p")
+  (setq rpm-default-owner
+        (read-from-minibuffer "Default file owner: " rpm-default-owner)))
+
+(defun rpm-files-group (&optional arg)
+  "Change the source directory."
+  (interactive "p")
+  (setq rpm-default-group
+        (read-from-minibuffer "Default file group: " rpm-default-group)))
+
+(defun rpm-increase-release-tag (&optional arg)
+  "Increase the release tag by 1."
+  (interactive "p")
+  (save-excursion
+    (goto-char (point-min))
+    (if (search-forward-regexp "^Release:[ \t]*\\([0-9]+\\)\\(.*\\)" nil t)
+        (let ((release (1+ (string-to-int (match-string 1)))))
+          (setq release (concat (int-to-string release) (match-string 2)))
+          (replace-match (concat "Release: " release))
+          (message (concat "Release tag changed to " release ".")))
+      (if (search-forward-regexp "^Release:[ \t]*%{?\\([^}]*\\)}?$" nil t)
+          (rpm-increase-release-with-macros)
+        (message "No Release tag found...")))))
+
+;;------------------------------------------------------------
+
+(defun rpm-spec-field-value (field max)
+  "Get the value of FIELD, searching up to buffer position MAX.
+See `search-forward-regexp'."
+  (save-excursion
+    (ignore-errors
+      (let ((str
+             (progn
+               (goto-char (point-min))
+               (search-forward-regexp (concat
+                                       field ":[ \t]*\\(.*?\\)[ \t]*$") max)
+               (match-string 1))))
+        (if (string-match "%{?\\([^}]*\\)}?$" str)
+            (progn
+              (goto-char (point-min))
+              (search-forward-regexp
+               (concat "%define[ \t]+" (substring str (match-beginning 1)
+                                                  (match-end 1))
+                       "[ \t]+\\(.*\\)"))
+              (match-string 1))
+          str)))))
+
+(defun rpm-find-spec-version (&optional with-epoch)
+  "Get the version string.
+If WITH-EPOCH is non-nil, the string contains the Epoch/Serial value,
+if one is present in the file."
+  (save-excursion
+    (goto-char (point-min))
+    (let* ((max (search-forward-regexp rpm-section-regexp))
+           (version (rpm-spec-field-value "Version" max))
+           (release (rpm-spec-field-value "Release" max))
+           (epoch   (rpm-spec-field-value "Epoch"   max)) )
+      (when (and version (< 0 (length version)))
+        (unless epoch (setq epoch (rpm-spec-field-value "Serial" max)))
+        (concat (and with-epoch epoch (concat epoch ":"))
+                version
+                (and release (concat "-" release)))))))
+
+(defun rpm-increase-release-with-macros ()
+  (save-excursion
+    (let ((str
+           (progn
+             (goto-char (point-min))
+             (search-forward-regexp (concat "Release:[ \t]*\\(.+\\).*$") nil)
+             (match-string 1))))
+      (let ((inrel
+             (if (string-match "%{?\\([^}]*\\)}?$" str)
+                 (progn
+                   (goto-char (point-min))
+                   (setq macros (substring str (match-beginning 1)
+                                           (match-end 1)))
+                   (search-forward-regexp
+                    (concat "%define[ \t]+" macros
+                            "[ \t]+\\(\\([0-9]\\|\\.\\)+\\)\\(.*\\)"))
+                   (concat macros " " (int-to-string (1+ (string-to-int
+                                                          (match-string 1))))
+                           (match-string 3)))
+               str)))
+        (setq dinrel inrel)
+        (replace-match (concat "%define " dinrel))
+        (message (concat "Release tag changed to " dinrel "."))))))
+
+;;------------------------------------------------------------
+
+(defun rpm-spec-initialize ()
+  "Create a default spec file if one does not exist or is empty."
+  (let (file name version (release "1"))
+    (setq file (if (buffer-file-name)
+                   (file-name-nondirectory (buffer-file-name))
+                 (buffer-name)))
+    (cond
+     ((eq (string-match "\\(.*\\)-\\([^-]*\\)-\\([^-]*\\).spec" file) 0)
+      (setq name (match-string 1 file))
+      (setq version (match-string 2 file))
+      (setq release (match-string 3 file)))
+     ((eq (string-match "\\(.*\\)-\\([^-]*\\).spec" file) 0)
+      (setq name (match-string 1 file))
+      (setq version (match-string 2 file)))
+     ((eq (string-match "\\(.*\\).spec" file) 0)
+      (setq name (match-string 1 file))))
+
+    (insert
+     "Summary: "
+     "\nName: " (or name "")
+     "\nVersion: " (or version "")
+     "\nRelease: " (or release "")
+     "\nLicense: "
+     "\nGroup: "
+     "\nURL: "
+     "\nSource0: %{name}-%{version}.tar.gz"
+     "\nBuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot"
+     "\n\n%description\n"
+     "\n%prep"
+     "\n%setup -q"
+     "\n\n%build"
+     "\n\n%install"
+     "\nrm -rf $RPM_BUILD_ROOT"
+     "\n\n%clean"
+     "\nrm -rf $RPM_BUILD_ROOT"
+     "\n\n%files"
+     "\n%defattr(-,root,root,-)"
+     "\n%doc\n"
+     "\n\n%changelog\n")
+
+    (rpm-add-change-log-entry "Initial build.\n")))
+
+;;------------------------------------------------------------
+
+(defun rpm-about-rpm-spec-mode (&optional arg)
+  "About `rpm-spec-mode'."
+  (interactive "p")
+  (message
+   (concat "rpm-spec-mode version "
+           rpm-spec-mode-version
+           " by Stig Bjørlykke, <stigb at tihlde.org>")))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.spec$" . rpm-spec-mode))
+
+(provide 'rpm-spec-mode)
+
+;;; rpm-spec-mode.el ends here


More information about the scm-commits mailing list