(defgroup reftex): Update home page url-link.
[bpt/emacs.git] / lisp / progmodes / executable.el
1 ;;; executable.el --- base functionality for executable interpreter scripts -*- byte-compile-dynamic: t -*-
2
3 ;; Copyright (C) 1994, 1995, 1996, 2000, 2001, 2002, 2003, 2004, 2005, 2006
4 ;; Free Software Foundation, Inc.
5
6 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
7 ;; Keywords: languages, unix
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25
26 ;;; Commentary:
27
28 ;; executable.el is used by certain major modes to insert a suitable
29 ;; #! line at the beginning of the file, if the file does not already
30 ;; have one.
31
32 ;; Unless it has a magic number, a Unix file with executable mode is passed to
33 ;; a new instance of the running shell (or to a Bourne shell if a csh is
34 ;; running and the file starts with `:'). Only a shell can start such a file,
35 ;; exec() cannot, which is why it is important to have a magic number in every
36 ;; executable script. Such a magic number is made up by the characters `#!'
37 ;; the filename of an interpreter (in COFF, ELF or somesuch format) and one
38 ;; optional argument.
39
40 ;; This library is for certain major modes like sh-, awk-, perl-, tcl- or
41 ;; makefile-mode to insert or update a suitable #! line at the beginning of
42 ;; the file, if the file does not already have one and the file is not a
43 ;; default file of that interpreter (like .profile or makefile). It also
44 ;; makes the file executable if it wasn't, as soon as it's saved.
45
46 ;; It also allows debugging scripts, with an adaptation of compile, as far
47 ;; as interpreters give out meaningful error messages.
48
49 ;; Modes that use this should nconc `executable-map' to the end of their own
50 ;; keymap and `executable-font-lock-keywords' to the end of their own font
51 ;; lock keywords. Their mode-setting commands should call
52 ;; `executable-set-magic'.
53
54 ;;; Code:
55
56 (defgroup executable nil
57 "Base functionality for executable interpreter scripts."
58 :group 'processes)
59
60 ;; This used to default to `other', but that doesn't seem to have any
61 ;; significance. fx 2000-02-11.
62 (defcustom executable-insert t ; 'other
63 "*Non-nil means offer to add a magic number to a file.
64 This takes effect when you switch to certain major modes,
65 including Shell-script mode (`sh-mode').
66 When you type \\[executable-set-magic], it always offers to add or
67 update the magic number."
68 ;;; :type '(choice (const :tag "off" nil)
69 ;;; (const :tag "on" t)
70 ;;; symbol)
71 :type 'boolean
72 :group 'executable)
73
74
75 (defcustom executable-query 'function
76 "*If non-nil, ask user before changing an existing magic number.
77 When this is `function', only ask when called non-interactively."
78 :type '(choice (const :tag "Don't Ask" nil)
79 (const :tag "Ask when non-interactive" function)
80 (other :tag "Ask" t))
81 :group 'executable)
82
83
84 (defcustom executable-magicless-file-regexp "/[Mm]akefile$\\|/\\.\\(z?profile\\|bash_profile\\|z?login\\|bash_login\\|z?logout\\|bash_logout\\|.+shrc\\|esrc\\|rcrc\\|[kz]shenv\\)$"
85 "*On files with this kind of name no magic is inserted or changed."
86 :type 'regexp
87 :group 'executable)
88
89
90 (defcustom executable-prefix "#! "
91 "*Interpreter magic number prefix inserted when there was no magic number."
92 :type 'string
93 :group 'executable)
94
95
96 (defcustom executable-chmod 73
97 "*After saving, if the file is not executable, set this mode.
98 This mode passed to `set-file-modes' is taken absolutely when negative, or
99 relative to the files existing modes. Do nothing if this is nil.
100 Typical values are 73 (+x) or -493 (rwxr-xr-x)."
101 :type '(choice integer
102 (const nil))
103 :group 'executable)
104
105
106 (defvar executable-command nil)
107
108 (defcustom executable-self-display "tail"
109 "*Command you use with argument `+2' to make text files self-display.
110 Note that the like of `more' doesn't work too well under Emacs \\[shell]."
111 :type 'string
112 :group 'executable)
113
114
115 (defvar executable-font-lock-keywords
116 '(("\\`#!.*/\\([^ \t\n]+\\)" 1 font-lock-keyword-face t))
117 "*Rules for highlighting executable scripts' magic number.
118 This can be included in `font-lock-keywords' by modes that call `executable'.")
119
120
121 (defvar executable-error-regexp-alist
122 '(;; /bin/xyz: syntax error at line 14: `(' unexpected
123 ;; /bin/xyz[5]: syntax error at line 8 : ``' unmatched
124 ("^\\(.*[^[/]\\)\\(\\[[0-9]+\\]\\)?: .* error .* line \\([0-9]+\\)" 1 3)
125 ;; /bin/xyz[27]: ehco: not found
126 ("^\\(.*[^/]\\)\\[\\([0-9]+\\)\\]: .*: " 1 2)
127 ;; /bin/xyz: syntax error near unexpected token `)'
128 ;; /bin/xyz: /bin/xyz: line 2: `)'
129 ("^\\(.*[^/]\\): [^0-9\n]+\n\\1: \\1: line \\([0-9]+\\):" 1 2)
130 ;; /usr/bin/awk: syntax error at line 5 of file /bin/xyz
131 (" error .* line \\([0-9]+\\) of file \\(.+\\)$" 2 1)
132 ;; /usr/bin/awk: calling undefined function toto
133 ;; input record number 3, file awktestdata
134 ;; source line 4 of file /bin/xyz
135 ("^[^ ].+\n\\( .+\n\\)* line \\([0-9]+\\) of file \\(.+\\)$" 3 2)
136 ;; makefile:1: *** target pattern contains no `%'. Stop.
137 ("^\\(.+\\):\\([0-9]+\\): " 1 2))
138 "Alist of regexps used to match script errors.
139 See `compilation-error-regexp-alist'.")
140
141 ;; The C function openp slightly modified would do the trick fine
142 (defvaralias 'executable-binary-suffixes 'exec-suffixes)
143
144 ;;;###autoload
145 (defun executable-command-find-posix-p (&optional program)
146 "Check if PROGRAM handles arguments Posix-style.
147 If PROGRAM is non-nil, use that instead of \"find\"."
148 ;; Pick file to search from location we know
149 (let* ((dir (file-truename data-directory))
150 (file (car (directory-files dir nil "^[^.]"))))
151 (with-temp-buffer
152 (call-process (or program "find")
153 nil
154 (current-buffer)
155 nil
156 dir
157 "-name"
158 file
159 "-maxdepth"
160 "1")
161 (goto-char (point-min))
162 (if (search-forward file nil t)
163 t))))
164
165 (defun executable-chmod ()
166 "This gets called after saving a file to assure that it be executable.
167 You can set the absolute or relative mode in variable `executable-chmod' for
168 non-executable files."
169 (and executable-chmod
170 buffer-file-name
171 (or (file-executable-p buffer-file-name)
172 (set-file-modes buffer-file-name
173 (if (< executable-chmod 0)
174 (- executable-chmod)
175 (logior executable-chmod
176 (file-modes buffer-file-name)))))))
177
178
179 ;;;###autoload
180 (defun executable-interpret (command)
181 "Run script with user-specified args, and collect output in a buffer.
182 While script runs asynchronously, you can use the \\[next-error]
183 command to find the next error. The buffer is also in `comint-mode' and
184 `compilation-shell-minor-mode', so that you can answer any prompts."
185 (interactive (list (read-string "Run script: "
186 (or executable-command
187 buffer-file-name))))
188 (require 'compile)
189 (save-some-buffers (not compilation-ask-about-save))
190 (set (make-local-variable 'executable-command) command)
191 (let ((compilation-error-regexp-alist executable-error-regexp-alist))
192 (compilation-start command t (lambda (x) "*interpretation*"))))
193
194
195
196 ;;;###autoload
197 (defun executable-set-magic (interpreter &optional argument
198 no-query-flag insert-flag)
199 "Set this buffer's interpreter to INTERPRETER with optional ARGUMENT.
200 The variables `executable-magicless-file-regexp', `executable-prefix',
201 `executable-insert', `executable-query' and `executable-chmod' control
202 when and how magic numbers are inserted or replaced and scripts made
203 executable."
204 (interactive
205 (let* ((name (read-string "Name or file name of interpreter: "))
206 (arg (read-string (format "Argument for %s: " name))))
207 (list name arg (eq executable-query 'function) t)))
208
209 (setq interpreter (if (file-name-absolute-p interpreter)
210 interpreter
211 (or (executable-find interpreter)
212 (error "Interpreter %s not recognized"
213 interpreter))))
214
215 (setq argument (concat (if (string-match "\\`/:" interpreter)
216 (replace-match "" nil nil interpreter)
217 interpreter)
218 (and argument (string< "" argument) " ")
219 argument))
220
221 (or buffer-read-only
222 (if buffer-file-name
223 (string-match executable-magicless-file-regexp
224 buffer-file-name))
225 (not (or insert-flag executable-insert))
226 (> (point-min) 1)
227 (save-excursion
228 (goto-char (point-min))
229 (add-hook 'after-save-hook 'executable-chmod nil t)
230 (if (looking-at "#![ \t]*\\(.*\\)$")
231 (and (goto-char (match-beginning 1))
232 ;; If the line ends in a space,
233 ;; don't offer to change it.
234 (not (= (char-after (1- (match-end 1))) ?\s))
235 (not (string= argument
236 (buffer-substring (point) (match-end 1))))
237 (if (or (not executable-query) no-query-flag
238 (save-window-excursion
239 ;; Make buffer visible before question.
240 (switch-to-buffer (current-buffer))
241 (y-or-n-p (concat "Replace magic number by `"
242 executable-prefix argument "'? "))))
243 (progn
244 (replace-match argument t t nil 1)
245 (message "Magic number changed to `%s'"
246 (concat executable-prefix argument)))))
247 (insert executable-prefix argument ?\n)
248 (message "Magic number changed to `%s'"
249 (concat executable-prefix argument)))))
250 interpreter)
251
252
253
254 ;;;###autoload
255 (defun executable-self-display ()
256 "Turn a text file into a self-displaying Un*x command.
257 The magic number of such a command displays all lines but itself."
258 (interactive)
259 (if (eq this-command 'executable-self-display)
260 (setq this-command 'executable-set-magic))
261 (executable-set-magic executable-self-display "+2"))
262
263 ;;;###autoload
264 (defun executable-make-buffer-file-executable-if-script-p ()
265 "Make file executable according to umask if not already executable.
266 If file already has any execute bits set at all, do not change existing
267 file modes."
268 (and (>= (buffer-size) 2)
269 (save-restriction
270 (widen)
271 (string= "#!" (buffer-substring (point-min) (+ 2 (point-min)))))
272 (let* ((current-mode (file-modes (buffer-file-name)))
273 (add-mode (logand ?\111 (default-file-modes))))
274 (or (/= (logand ?\111 current-mode) 0)
275 (zerop add-mode)
276 (set-file-modes (buffer-file-name)
277 (logior current-mode add-mode))))))
278
279 (provide 'executable)
280
281 ;; arch-tag: 58458d1c-d9db-45ec-942b-8bbb1d5e319d
282 ;;; executable.el ends here