Initial Commit
[packages] / xemacs-packages / xslide / xslide-process.el
1 ;;;; xslide-process.el --- Process an XSL stylesheet
2 ;; $Id: xslide-process.el,v 1.3 2003/06/05 22:13:01 tonygraham Exp $
3
4 ;; Copyright (C) 1998, 1999, 2000, 2001 Tony Graham
5
6 ;; Author: Tony Graham <tkg@menteith.com>
7
8 ;;; This file is not part of GNU Emacs.
9
10 ;; This program is free software; you can redistribute it and/or
11 ;; modify it under the terms of the GNU General Public License
12 ;; as published by the Free Software Foundation; either version 2
13 ;; of the License, or (at your option) any later version.
14 ;; 
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19 ;; 
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with this program; if not, write to the Free Software
22 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
24 \f
25 ;;;; Commentary:
26
27 ;; Originally copied almost wholesale from psgml.el by Lennart Staflin
28
29 ;; Send bugs to xslide-bug@menteith.com
30 ;; Use `xsl-submit-bug-report' for bug reports
31
32 \f
33 ;;;; Variables:
34
35
36
37 (defcustom xsl-offer-save t
38   "*If non-nil, ask about saving modified buffers before \\[xsl-process] is run."
39   :type '(choice (const :tag "Yes" t) (const :tag "No" nil))
40   :group 'xsl-process)
41
42 (defcustom xsl-process-browse-output nil
43   "*If non-nil, open output in browser after \\[xsl-process] is run."
44   :type '(choice (const :tag "Yes" t) (const :tag "No" nil))
45   :group 'xsl-process)
46
47 (defcustom xsl-process-find-output nil
48   "*If non-nil, find output file after \\[xsl-process] is run."
49   :type '(choice (const :tag "Yes" t) (const :tag "No" nil))
50   :group 'xsl-process)
51
52 (defcustom xsl-process-command
53   (list
54    ;; XT Windows executable
55    "xt %i %s %o"
56    ;; XT Java
57    "java com.jclark.xsl.Driver %i %s %o"
58    ;; Xalan-Java 2
59    "java org.apache.xalan.xslt.Process -IN %i -XSL %s -OUT %o"
60    ;; Instant Saxon
61    "saxon -o %o %i %s"
62    ;; Instant Saxon using xml-stylesheet PI
63    "saxon -o %o %i"
64    ;; Saxon
65    "java com.icl.saxon.StyleSheet -o %o %i %s"
66    ;; Saxon using xml-stylesheet PI
67    "java com.icl.saxon.StyleSheet -o %o %i"
68    ;; xsltproc
69    "xsltproc -o %o %s %i"
70    ;; jd.xslt
71    "java jd.xml.xslt.Stylesheet -out %o %i %s"
72    ;; Oracle XDK for Java
73    "java oracle.xml.parser.v2.oraxsl %i %s %o"
74    )
75   "*The shell command to process an XSL document.
76
77 This is a `format' control string that by default should contain three
78 `%s' conversion specifications: the first will be replaced by the
79 value of `xsl-process-input-file' \(or the empty string, if nil\); the
80 second will be replaced by `xsl-process-stylesheet-file' \(or the empty
81 string, if nil\); the third will be replaced by
82 `xsl-process-output-file' \(or the empty string, if nil\).
83
84 If `xsl-process-files' is non-nil, the format string should contain
85 one `%s' conversion specification for each element of its result.
86
87 If `xsl-process-command' is a list, then every element should be a
88 string.  The strings will be tried in order and %-sequences in the
89 string will be replaced according to the list below, if the string contains
90 %-sequences with no replacement value the next string will be tried.
91
92 %b means the visited file of the current buffer
93 %i means the value of `xsl-process-input-file'
94 %s means the value of `xsl-process-stylesheet-file'
95 %o means the value of `xsl-process-output-file'
96 "
97   :type '(repeat :tag "Commands" string)
98   :group 'xsl-process)
99
100 (defvar xsl-process-files nil
101   "If non-nil, a function of no arguments that returns a list of file names.
102 These file names will serve as the arguments to the `xsl-process-command'
103 format control string instead of the defaults.")
104
105 (defcustom xsl-process-error-regexps
106   '(
107     ;; Xalan-Java 2
108     ;;   file:///path/to/foo.xsl; Line 9; Column 12; ...
109     ("^file:\\([^;]+\\)\\; Line \\([0-9]+\\)\\;\\( Column \\([0-9]+\\)\\;\\)?"
110      1 2 4)
111
112     ;; Saxon
113     ;;   Error at xsl:output on line 9 of file:/path/to/foo.xsl:
114     ;;   Error on line 9 column 5 of file:/path/to/foo.xsl:
115     ("^Error\\( at [^ ]+\\)? on line \\([0-9]+\\)\\( column \\([0-9]+\\)\\)? of file:\\(\\(/[A-Za-z]:\\)?[^:]+\\):$"
116      5 2 4)
117
118     ;; Oracle
119     ;;   file:/path/to/foo.xsl<Line 9, Column 17>: ...
120     ("^file:\\([^<]+\\)<Line \\([0-9]+\\)\\(, Column \\([0-9]+\\)\\)?>:"
121      1 2 4)
122
123     ;; jd.xslt
124     ;;   - uri       = file:/path/to/foo.xsl
125     ;;   - line      = 9
126     ;;   - column    = -1
127     ;; ...or...
128     ;;   - uri       = file:/path/to/foo.xsl
129     ;;   - element   = xsl:output (line 9)
130     ("^- uri[ \t]+= file:\\(.+\\)\\([\r\n+]- \\(\\([^(]*?(\\)?line[ \t]+\\(= \\)?\\([0-9]+\\)\\)?\\)?\\([\r\n]+- column[ \t]+= \\([0-9]+\\)\\)?" 1 6 8)
131
132     ;; Generic
133     (".*\\<file:\\(\\(/[A-Za-z]:\\)?[^:]+\\):[ \t]*\\(\\([0-9]+\\):[ \t]*\\(\\([0-9]+\\):\\)?\\)?"
134      1 4 6)
135     (".*\\([^ ]+\\.x[ms]l\\):[ \t]*\\([0-9]+\\):[ \t]*\\(\\([0-9]+\\):\\)?"
136      1 2 4)
137     ("^\\([^:]+\\): \\([0-9]+\\): error:"
138      1 2)
139     )
140   "*Alist of regexps to recognize error messages from `xsl-process'.
141 See `compilation-error-regexp-alist'."
142   :type '(repeat :tag "Regexps"
143                  (list (regexp :tag "Regexp")
144                        (integer :tag "File index")
145                        (integer :tag "Line index")
146                        (choice :tag "Column index"
147                                (integer)
148                                (const :tag "None" nil))))
149   :group 'xsl-process)
150
151 (defvar xsl-xml-source nil
152   "*If non-nil, this is the name of the XML source file.")
153 (put 'xsl-xml-source 'xsl-type 'string)
154
155 (defvar xsl-xsl-result nil
156   "*If non-nil, this is the name of the XSL result file.")
157 (put 'xsl-xsl-result 'xsl-type 'string)
158
159 (defvar xsl-process-command-history nil
160   "The minibuffer history list for `xsl-process''s COMMAND argument.")
161 ;;(make-variable-buffer-local 'xsl-process-command-history)
162
163 (eval-and-compile
164   (autoload 'compile-internal "compile" ""))
165
166 (defun xsl-subst-expand-char (c parts)
167   (cdr-safe (assq (downcase c) parts)))
168
169 (defun xsl-subst-expand (s parts)
170   (loop for i from 0 to (1- (length s))
171         as c = (aref s i)
172         concat (if (eq c ?%)
173                    (or (xsl-subst-expand-char (aref s (incf i)) parts)
174                        (return nil)) 
175                  (char-to-string (aref s i)))))
176
177 (defun xsl-populate-process-command-history ()
178   (cond
179    ((consp xsl-process-command)
180     (let ((process-subst
181            (list
182             (cons ?b (and (buffer-file-name)
183                           (file-name-nondirectory (buffer-file-name))))
184             (cons ?i xsl-process-input-file)
185             (cons ?s xsl-process-stylesheet-file)
186             (cons ?o xsl-process-output-file))))
187       (setq xsl-process-command-history
188             (append
189              (mapcar (lambda (x)
190                        (xsl-subst-expand x process-subst))
191                      xsl-process-command)
192              xsl-process-command-history))))
193 ;;      (loop for template in xsl-process-command
194 ;;          append
195 ;;          (xsl-subst-expand template process-subst)
196 ;;          into
197 ;;          xsl-process-command-history)))
198    (t
199     (apply 'format xsl-process-command
200            (if xsl-process-files
201                (funcall xsl-process-files)
202              (list (or xsl-xml-source "")
203                    (let ((name (buffer-file-name)))
204                      (if name
205                          (file-name-nondirectory name)
206                        ""))
207                    (or xsl-xsl-result "")))))))
208
209 (defvar xsl-process-input-file nil
210   "Filename of input file for `xsl-process' command")
211
212 (defvar xsl-process-input-history nil
213   "The minibuffer history list for `xsl-get-process-parameters''s INPUT argument.")
214
215 (defvar xsl-process-stylesheet-file nil
216   "Filename of stylesheet file for `xsl-process' command")
217
218 (defvar xsl-process-stylesheet-history nil
219   "The minibuffer history list for `xsl-get-process-parameters''s STYLESHEET argument.")
220
221 (defvar xsl-process-output-file nil
222   "Filename of output file for `xsl-process' command")
223
224 (defvar xsl-process-output-history nil
225   "The minibuffer history list for `xsl-get-process-parameters''s OUTPUT argument.")
226
227 (defun xsl-get-process-parameters ()
228   "Get and set the parameters for the `xsl-process' command"
229   (interactive)
230   (setq xsl-process-input-file
231         (xsl-read-from-minibuffer "Input file: "
232                               (concat (file-name-sans-extension
233                                        (file-name-nondirectory
234                                         (buffer-file-name)))
235                                       ".xml")
236                               'xsl-process-input-history))
237   (setq xsl-process-stylesheet-file
238         (xsl-read-from-minibuffer "Stylesheet file: "
239                               (file-name-nondirectory
240                                (buffer-file-name))
241                               'xsl-process-stylesheet-history))
242   (setq xsl-process-output-file
243         (xsl-read-from-minibuffer "Output file: "
244                               (concat (file-name-sans-extension
245                                        (file-name-nondirectory
246                                         xsl-process-input-file))
247                                       ".html")
248                               'xsl-process-output-history)))
249
250 (defun xsl-process (command)
251   "Process an XSL stylesheet.
252
253 Runs COMMAND, a shell command, in a separate process asynchronously
254 with output going to the buffer *XSL process*.  You can then use the
255 command \\[next-error] to find the next error message and move to the
256 line in the XSL document that caused it.
257
258 The first time that the program is run and whenever you provide a
259 prefix argument, e.g. \\[universal-argument] \\[xsl-process], prompts
260 for input filename, stylesheet file, and output filename.  Those
261 values are used with the templates in `xsl-process-command' to
262 populate this command's command history with the command lines to run
263 several XSLT processors using those values.  Use M-p and M-n to step
264 through the predefined commands, edit a command if necessary, or enter
265 a new command line.  The next time that this command is run, the
266 previously executed command is used as the default.
267
268 If `xsl-process-browse-output' is non-nil, the filename entered in
269 response to the \"Output file:\" prompt is opened in a browser using
270 `browse-url'.
271
272 If `xsl-process-view-output' is non-nil, the filename entered in
273 response to the \"Output file:\" prompt is opened in a buffer."
274   (interactive
275    (list (progn
276            (if (or
277                 current-prefix-arg
278                 (null xsl-process-command-history))
279                (progn
280                  (xsl-get-process-parameters)
281                  (xsl-populate-process-command-history)))
282            (read-from-minibuffer "Process command: "
283                                      (car xsl-process-command-history)
284                                      nil nil
285                                      'xsl-process-command-history))))
286   (if xsl-offer-save
287       (save-some-buffers nil nil))
288   (compile-internal command "No more errors" "XSL process"
289                     nil
290                     xsl-process-error-regexps)
291   (if xsl-process-browse-output
292       (browse-url xsl-process-output-file))
293   (if xsl-process-find-output
294       (switch-to-buffer
295        (find-file-noselect (expand-file-name xsl-process-output-file)))))
296
297
298 (provide 'xslide-process)