X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/bbf5eb2805e13c8e93f512c678054654c0917100..36045ff3301341130c1e2048a0fa73ec72fc68bf:/lisp/progmodes/executable.el diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el index 42d16cbdb5..1f27d33cda 100644 --- a/lisp/progmodes/executable.el +++ b/lisp/progmodes/executable.el @@ -1,16 +1,17 @@ -;;; executable.el --- base functionality for executable interpreter scripts +;;; executable.el --- base functionality for executable interpreter scripts -*- byte-compile-dynamic: t -*- -;; Copyright (C) 1994, 1995, 1996 by Free Software Foundation, Inc. +;; Copyright (C) 1994, 1995, 1996, 2000, 2001, 2002, 2003, 2004, 2005, +;; 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. -;; Author: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389 +;; Author: Daniel Pfeiffer ;; Keywords: languages, unix ;; This file is part of GNU Emacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; GNU Emacs 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. +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,9 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; along with GNU Emacs. If not, see . ;;; Commentary: @@ -53,18 +52,21 @@ ;;; Code: (defgroup executable nil - "Base functionality for executable interpreter scripts" + "Base functionality for executable interpreter scripts." :group 'processes) -(defcustom executable-insert 'other +;; This used to default to `other', but that doesn't seem to have any +;; significance. fx 2000-02-11. +(defcustom executable-insert t ; 'other "*Non-nil means offer to add a magic number to a file. This takes effect when you switch to certain major modes, including Shell-script mode (`sh-mode'). When you type \\[executable-set-magic], it always offers to add or update the magic number." - :type '(choice (const :tag "off" nil) - (const :tag "on" t) - symbol) +;;; :type '(choice (const :tag "off" nil) +;;; (const :tag "on" t) +;;; symbol) + :type 'boolean :group 'executable) @@ -72,8 +74,8 @@ update the magic number." "*If non-nil, ask user before changing an existing magic number. When this is `function', only ask when called non-interactively." :type '(choice (const :tag "Don't Ask" nil) - (const :tag "Ask" t) - (const :tag "Ask when non-interactive" function)) + (const :tag "Ask when non-interactive" function) + (other :tag "Ask" t)) :group 'executable) @@ -94,7 +96,8 @@ When this is `function', only ask when called non-interactively." This mode passed to `set-file-modes' is taken absolutely when negative, or relative to the files existing modes. Do nothing if this is nil. Typical values are 73 (+x) or -493 (rwxr-xr-x)." - :type 'integer + :type '(choice integer + (const nil)) :group 'executable) @@ -102,7 +105,7 @@ Typical values are 73 (+x) or -493 (rwxr-xr-x)." (defcustom executable-self-display "tail" "*Command you use with argument `+2' to make text files self-display. -Note that the like of `more' doesn't work too well under Emacs \\[shell]." +Note that the like of `more' doesn't work too well under Emacs \\[shell]." :type 'string :group 'executable) @@ -134,20 +137,28 @@ This can be included in `font-lock-keywords' by modes that call `executable'.") See `compilation-error-regexp-alist'.") ;; The C function openp slightly modified would do the trick fine -(defun executable-find (command) - "Search for COMMAND in exec-path and return the absolute file name. -Return nil if COMMAND is not found anywhere in `exec-path'." - (let ((list exec-path) - file) - (while list - (setq list (if (and (setq file (expand-file-name command (car list))) - (file-executable-p file) - (not (file-directory-p file))) - nil - (setq file nil) - (cdr list)))) - file)) +(defvaralias 'executable-binary-suffixes 'exec-suffixes) +;;;###autoload +(defun executable-command-find-posix-p (&optional program) + "Check if PROGRAM handles arguments Posix-style. +If PROGRAM is non-nil, use that instead of \"find\"." + ;; Pick file to search from location we know + (let* ((dir (file-truename data-directory)) + (file (car (directory-files dir nil "^[^.]")))) + (with-temp-buffer + (call-process (or program "find") + nil + (current-buffer) + nil + dir + "-name" + file + "-maxdepth" + "1") + (goto-char (point-min)) + (if (search-forward file nil t) + t)))) (defun executable-chmod () "This gets called after saving a file to assure that it be executable. @@ -163,20 +174,20 @@ non-executable files." (file-modes buffer-file-name))))))) +;;;###autoload (defun executable-interpret (command) "Run script with user-specified args, and collect output in a buffer. -While script runs asynchronously, you can use the \\[next-error] command -to find the next error." +While script runs asynchronously, you can use the \\[next-error] +command to find the next error. The buffer is also in `comint-mode' and +`compilation-shell-minor-mode', so that you can answer any prompts." (interactive (list (read-string "Run script: " (or executable-command buffer-file-name)))) (require 'compile) (save-some-buffers (not compilation-ask-about-save)) - (make-local-variable 'executable-command) - (compile-internal (setq executable-command command) - "No more errors." "Interpretation" - ;; Give it a simpler regexp to match. - nil executable-error-regexp-alist)) + (set (make-local-variable 'executable-command) command) + (let ((compilation-error-regexp-alist executable-error-regexp-alist)) + (compilation-start command t (lambda (x) "*interpretation*")))) @@ -192,13 +203,19 @@ executable." (let* ((name (read-string "Name or file name of interpreter: ")) (arg (read-string (format "Argument for %s: " name)))) (list name arg (eq executable-query 'function) t))) + (setq interpreter (if (file-name-absolute-p interpreter) interpreter (or (executable-find interpreter) - (error "Interpreter %s not recognized" interpreter))) - argument (concat interpreter + (error "Interpreter %s not recognized" + interpreter)))) + + (setq argument (concat (if (string-match "\\`/:" interpreter) + (replace-match "" nil nil interpreter) + interpreter) (and argument (string< "" argument) " ") argument)) + (or buffer-read-only (if buffer-file-name (string-match executable-magicless-file-regexp @@ -206,36 +223,29 @@ executable." (not (or insert-flag executable-insert)) (> (point-min) 1) (save-excursion - (let ((point (point-marker)) - (buffer-modified-p (buffer-modified-p))) - (goto-char (point-min)) - (make-local-hook 'after-save-hook) - (add-hook 'after-save-hook 'executable-chmod nil t) - (if (looking-at "#![ \t]*\\(.*\\)$") - (and (goto-char (match-beginning 1)) - ;; If the line ends in a space, - ;; don't offer to change it. - (not (= (char-after (1- (match-end 1))) ?\ )) - (not (string= argument - (buffer-substring (point) (match-end 1)))) - (if (or (not executable-query) no-query-flag - (save-window-excursion - ;; Make buffer visible before question. - (switch-to-buffer (current-buffer)) - (y-or-n-p (concat "Replace magic number by `" - executable-prefix argument "'? ")))) - (progn - (replace-match argument t t nil 1) - (message "Magic number changed to `%s'" - (concat executable-prefix argument))))) - (insert executable-prefix argument ?\n) - (message "Magic number changed to `%s'" - (concat executable-prefix argument))) -;;; (or insert-flag -;;; (eq executable-insert t) -;;; (set-buffer-modified-p buffer-modified-p)) - ))) - interpreter) + (goto-char (point-min)) + (add-hook 'after-save-hook 'executable-chmod nil t) + (if (looking-at "#![ \t]*\\(.*\\)$") + (and (goto-char (match-beginning 1)) + ;; If the line ends in a space, + ;; don't offer to change it. + (not (= (char-after (1- (match-end 1))) ?\s)) + (not (string= argument + (buffer-substring (point) (match-end 1)))) + (if (or (not executable-query) no-query-flag + (save-window-excursion + ;; Make buffer visible before question. + (switch-to-buffer (current-buffer)) + (y-or-n-p (concat "Replace magic number by `" + executable-prefix argument "'? ")))) + (progn + (replace-match argument t t nil 1) + (message "Magic number changed to `%s'" + (concat executable-prefix argument))))) + (insert executable-prefix argument ?\n) + (message "Magic number changed to `%s'" + (concat executable-prefix argument))))) + interpreter) @@ -248,8 +258,23 @@ The magic number of such a command displays all lines but itself." (setq this-command 'executable-set-magic)) (executable-set-magic executable-self-display "+2")) - +;;;###autoload +(defun executable-make-buffer-file-executable-if-script-p () + "Make file executable according to umask if not already executable. +If file already has any execute bits set at all, do not change existing +file modes." + (and (>= (buffer-size) 2) + (save-restriction + (widen) + (string= "#!" (buffer-substring (point-min) (+ 2 (point-min))))) + (let* ((current-mode (file-modes (buffer-file-name))) + (add-mode (logand ?\111 (default-file-modes)))) + (or (/= (logand ?\111 current-mode) 0) + (zerop add-mode) + (set-file-modes (buffer-file-name) + (logior current-mode add-mode)))))) (provide 'executable) -;; executable.el ends here +;; arch-tag: 58458d1c-d9db-45ec-942b-8bbb1d5e319d +;;; executable.el ends here