X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/8086a70c32f8243142e43a6d7c629de540bdf803..0db097a55749dc040ef5d8daec7d7806cbb4281c:/lisp/files.el diff --git a/lisp/files.el b/lisp/files.el index 464d9854e7..df63e016c6 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -444,13 +444,21 @@ use `before-save-hook'.") (defcustom enable-local-variables t "*Control use of local variables in files you visit. -The value can be t, nil or something else. +The value can be t, nil, :safe, or something else. A value of t means file local variables specifications are obeyed -if all the specified variables are safe. If any variables are -not safe, you will be queries before setting them. -A value of nil means file local variables are ignored. -Any other value means to always query. +if all the specified variable values are safe; if any values are +not safe, Emacs queries you, once, whether to set them all. +\(When you say yes to certain values, they are remembered as safe.) + +:safe means set the safe variables, and ignore the rest. +:all means set all variables, whether safe or not. + (Don't set it permanently to :all.) +nil means always ignore the file local variables. + +Any other value means always query you once whether to set them all. +\(When you say yes to certain values, they are remembered as safe, but +this has no effect when `enable-local-variables' is \"something else\".) This variable also controls use of major modes specified in a -*- line. @@ -458,7 +466,9 @@ a -*- line. The command \\[normal-mode], when used interactively, always obeys file local variable specifications and the -*- line, and ignores this variable." - :type '(choice (const :tag "Obey" t) + :type '(choice (const :tag "Query Unsafe" t) + (const :tag "Safe Only" :safe) + (const :tag "Do all" :all) (const :tag "Ignore" nil) (other :tag "Query" other)) :group 'find-file) @@ -698,7 +708,7 @@ This is an interface to the function `load'." (interactive (list (completing-read "Load library: " 'locate-file-completion - (cons load-path load-suffixes)))) + (cons load-path (get-load-suffixes))))) (load library)) (defun file-remote-p (file) @@ -989,6 +999,20 @@ documentation for additional customization information." (pop-to-buffer buffer t norecord) (raise-frame (window-frame (selected-window))))) +(defun display-buffer-other-frame (buffer) + "Switch to buffer BUFFER in another frame. +This uses the function `display-buffer' as a subroutine; see its +documentation for additional customization information." + (interactive "BDisplay buffer in other frame: ") + (let ((pop-up-frames t) + same-window-buffer-names same-window-regexps + (old-window (selected-window)) + new-window) + (setq new-window (display-buffer buffer t)) + (lower-frame (window-frame new-window)) + (make-frame-invisible (window-frame old-window)) + (make-frame-visible (window-frame old-window)))) + (defvar find-file-default nil "Used within `find-file-read-args'.") @@ -1764,8 +1788,7 @@ Uses the visited file name, the -*- line, and the local variables spec. This function is called automatically from `find-file'. In that case, we may set up the file-specified mode and local variables, -depending on the value of `enable-local-variables': if it is t, we do; -if it is nil, we don't; otherwise, we query. +depending on the value of `enable-local-variables'. In addition, if `local-enable-local-variables' is nil, we do not set local variables (though we do notice a mode specified with -*-.) @@ -1871,7 +1894,7 @@ in that case, this function acts as if `enable-local-variables' were t." ;; `auto-coding-alist' with `no-conversion' coding system. ("\\.\\(arc\\|zip\\|lzh\\|zoo\\|[jew]ar\\|xpi\\)\\'" . archive-mode) ("\\.\\(ARC\\|ZIP\\|LZH\\|ZOO\\|[JEW]AR\\|XPI\\)\\'" . archive-mode) - ("\\.sx[dmicw]\\'" . archive-mode) ; OpenOffice.org + ("\\.\\(sx[dmicw]\\|odt\\)\\'" . archive-mode) ; OpenOffice.org ;; Mailer puts message to be edited in ;; /tmp/Re.... or Message ("\\`/tmp/Re" . text-mode) @@ -1954,6 +1977,9 @@ REGEXP and search the list again for another match. If the file name matches `inhibit-first-line-modes-regexps', then `auto-mode-alist' is not processed. +The extensions whose FUNCTION is `archive-mode' should also +appear in `auto-coding-alist' with `no-conversion' coding system. + See also `interpreter-mode-alist', which detects executable script modes based on the interpreters they specify to run, and `magic-mode-alist', which determines modes based on file contents.") @@ -2218,6 +2244,138 @@ Otherwise, return nil; point may be changed." (setq end (point)) (goto-char beg) end)))) + +;;; Handling file local variables + +(defvar ignored-local-variables + '(ignored-local-variables safe-local-variable-values) + "Variables to be ignored in a file's local variable spec.") + +(defvar hack-local-variables-hook nil + "Normal hook run after processing a file's local variables specs. +Major modes can use this to examine user-specified local variables +in order to initialize other data structure based on them.") + +(defcustom safe-local-variable-values nil + "List variable-value pairs that are considered safe. +Each element is a cons cell (VAR . VAL), where VAR is a variable +symbol and VAL is a value that is considered safe." + :group 'find-file + :type 'alist) + +(defcustom safe-local-eval-forms nil + "*Expressions that are considered safe in an `eval:' local variable. +Add expressions to this list if you want Emacs to evaluate them, when +they appear in an `eval' local variable specification, without first +asking you for confirmation." + :group 'find-file + :version "22.1" + :type '(repeat sexp)) + +;; Risky local variables: +(mapc (lambda (var) (put var 'risky-local-variable t)) + '(after-load-alist + auto-mode-alist + buffer-auto-save-file-name + buffer-file-name + buffer-file-truename + buffer-undo-list + dabbrev-case-fold-search + dabbrev-case-replace + debugger + default-text-properties + display-time-string + enable-local-eval + enable-local-variables + eval + exec-directory + exec-path + file-name-handler-alist + font-lock-defaults + format-alist + frame-title-format + global-mode-string + header-line-format + icon-title-format + ignored-local-variables + imenu--index-alist + imenu-generic-expression + inhibit-quit + input-method-alist + load-path + max-lisp-eval-depth + max-specpdl-size + minor-mode-alist + minor-mode-map-alist + minor-mode-overriding-map-alist + mode-line-buffer-identification + mode-line-format + mode-line-modes + mode-line-modified + mode-line-mule-info + mode-line-position + mode-line-process + mode-name + outline-level + overriding-local-map + overriding-terminal-local-map + parse-time-rules + process-environment + rmail-output-file-alist + safe-local-variable-values + safe-local-eval-forms + save-some-buffers-action-alist + special-display-buffer-names + standard-input + standard-output + unread-command-events + vc-mode)) + +;; Safe local variables: +;; +;; For variables defined by major modes, the safety declarations can go into +;; the major mode's file, since that will be loaded before file variables are +;; processed. +;; +;; For variables defined by minor modes, put the safety declarations in the +;; file defining the minor mode after the defcustom/defvar using an autoload +;; cookie, e.g.: +;; +;; ;;;###autoload(put 'variable 'safe-local-variable 'stringp) +;; +;; Otherwise, when Emacs visits a file specifying that local variable, the +;; minor mode file may not be loaded yet. +;; +;; For variables defined in the C source code the declaration should go here: + +;; FIXME: Some variables should be moved according to the rules above. +(let ((string-or-null (lambda (a) (or (stringp a) (null a))))) + (eval + `(mapc (lambda (pair) + (put (car pair) 'safe-local-variable (cdr pair))) + '((byte-compile-dynamic . t) + (byte-compile-dynamic-docstrings . t) + (byte-compile-warnings . t) + (c-basic-offset . integerp) + (c-file-style . stringp) + (c-indent-level . integerp) + (comment-column . integerp) + (compile-command . string-or-null-p) + (find-file-visit-truename . t) + (fill-column . integerp) + (fill-prefix . string-or-null-p) + (indent-tabs-mode . t) + (kept-old-versions . integerp) + (kept-new-versions . integerp) + (left-margin . t) + (no-byte-compile . t) + (no-update-autoloads . t) + (outline-regexp . string-or-null-p) + (tab-width . integerp) ;; C source code + (truncate-lines . t) ;; C source code + (version-control . t))))) + +(put 'c-set-style 'safe-local-eval-function t) (defun hack-local-variables-confirm (vars unsafe-vars risky-vars) (if noninteractive @@ -2225,6 +2383,7 @@ Otherwise, return nil; point may be changed." (let ((name (if buffer-file-name (file-name-nondirectory buffer-file-name) (concat "buffer " (buffer-name)))) + (offer-save (and (eq enable-local-variables t) unsafe-vars)) prompt char) (save-window-excursion (let ((buf (get-buffer-create "*Local Variables*"))) @@ -2243,9 +2402,12 @@ Otherwise, return nil; point may be changed." (insert "A local variables list is specified in " name "."))) (insert "\n\nDo you want to apply it? You can type y -- to apply the local variables list. -n -- to ignore the local variables list. -! -- to apply the local variables list, and mark these values (*) as - safe (in the future, they can be set automatically.)\n\n") +n -- to ignore the local variables list.") + (if offer-save + (insert " +! -- to apply the local variables list, and permanently mark these + values (*) as safe (in the future, they will be set automatically.)\n\n") + (insert "\n\n")) (dolist (elt vars) (cond ((member elt unsafe-vars) (insert " * ")) @@ -2257,12 +2419,16 @@ n -- to ignore the local variables list. (insert " : ") (princ (cdr elt) buf) (insert "\n")) - (if (< (line-number-at-pos) (window-body-height)) - (setq prompt "Please type y, n, or !: ") - (goto-char (point-min)) - (setq prompt "Please type y, n, or !, or C-v to scroll: ")) - (let ((inhibit-quit t) - (cursor-in-echo-area t) + (setq prompt + (format "Please type %s%s: " + (if offer-save "y, n, or !" "y or n") + (if (< (line-number-at-pos) (window-body-height)) + "" + ", or C-v to scroll"))) + (goto-char (point-min)) + (let ((cursor-in-echo-area t) + (exit-chars + (if offer-save '(?! ?y ?n ?\s ?\C-g) '(?y ?n ?\s ?\C-g))) done) (while (not done) (message prompt) @@ -2272,17 +2438,19 @@ n -- to ignore the local variables list. (condition-case nil (scroll-up) (error (goto-char (point-min)))) - (setq done (memq (downcase char) - '(?! ?y ?n ?\s ?\C-g)))))) - (if (= char ?\C-g) - (setq quit-flag nil))) + (setq done (memq (downcase char) exit-chars)))))) (setq char (downcase char)) - (when (and (= char ?!) unsafe-vars) + (when (and offer-save (= char ?!) unsafe-vars) (dolist (elt unsafe-vars) (add-to-list 'safe-local-variable-values elt)) - (customize-save-variable - 'safe-local-variable-values - safe-local-variable-values)) + ;; When this is called from desktop-restore-file-buffer, + ;; coding-system-for-read may be non-nil. Reset it before + ;; writing to .emacs. + (if (or custom-file user-init-file) + (let ((coding-system-for-read nil)) + (customize-save-variable + 'safe-local-variable-values + safe-local-variable-values)))) (kill-buffer buf) (or (= char ?!) (= char ?\s) @@ -2346,18 +2514,6 @@ and VAL is the specified value." mode-specified result)))) -(defvar hack-local-variables-hook nil - "Normal hook run after processing a file's local variables specs. -Major modes can use this to examine user-specified local variables -in order to initialize other data structure based on them.") - -(defcustom safe-local-variable-values nil - "List variable-value pairs that are considered safe. -Each element is a cons cell (VAR . VAL), where VAR is a variable -symbol and VAL is a value that is considered safe." - :group 'find-file - :type 'alist) - (defun hack-local-variables (&optional mode-only) "Parse and put into effect this buffer's local variables spec. If MODE-ONLY is non-nil, all we do is check whether the major mode @@ -2470,107 +2626,25 @@ is specified, returning t if it is specified." (and (risky-local-variable-p var val) (push elt risky-vars)) (push elt unsafe-vars)))) - (if (or (and (eq enable-local-variables t) - (null unsafe-vars) - (null risky-vars)) - (hack-local-variables-confirm - result unsafe-vars risky-vars)) + (if (eq enable-local-variables :safe) + ;; If caller wants only the safe variables, + ;; install only them. (dolist (elt result) - (hack-one-local-variable (car elt) (cdr elt))))) + (unless (or (memq (car elt) unsafe-vars) + (memq (car elt) risky-vars)) + (hack-one-local-variable (car elt) (cdr elt)))) + ;; Query, except in the case where all are known safe + ;; if the user wants no quuery in that case. + (if (or (and (eq enable-local-variables t) + (null unsafe-vars) + (null risky-vars)) + (eq enable-local-variables :all) + (hack-local-variables-confirm + result unsafe-vars risky-vars)) + (dolist (elt result) + (hack-one-local-variable (car elt) (cdr elt)))))) (run-hooks 'hack-local-variables-hook)))))) -(defvar ignored-local-variables - '(ignored-local-variables safe-local-variable-values) - "Variables to be ignored in a file's local variable spec.") - -;; Get confirmation before setting these variables as locals in a file. -(put 'debugger 'risky-local-variable t) -(put 'enable-local-eval 'risky-local-variable t) -(put 'ignored-local-variables 'risky-local-variable t) -(put 'ignored-local-variables 'safe-local-variable-values t) -(put 'eval 'risky-local-variable t) -(put 'file-name-handler-alist 'risky-local-variable t) -(put 'inhibit-quit 'risky-local-variable t) -(put 'minor-mode-alist 'risky-local-variable t) -(put 'minor-mode-map-alist 'risky-local-variable t) -(put 'minor-mode-overriding-map-alist 'risky-local-variable t) -(put 'overriding-local-map 'risky-local-variable t) -(put 'overriding-terminal-local-map 'risky-local-variable t) -(put 'auto-mode-alist 'risky-local-variable t) -(put 'after-load-alist 'risky-local-variable t) -(put 'buffer-file-name 'risky-local-variable t) -(put 'buffer-undo-list 'risky-local-variable t) -(put 'buffer-auto-save-file-name 'risky-local-variable t) -(put 'buffer-file-truename 'risky-local-variable t) -(put 'default-text-properties 'risky-local-variable t) -(put 'exec-path 'risky-local-variable t) -(put 'load-path 'risky-local-variable t) -(put 'exec-directory 'risky-local-variable t) -(put 'process-environment 'risky-local-variable t) -(put 'dabbrev-case-fold-search 'risky-local-variable t) -(put 'dabbrev-case-replace 'risky-local-variable t) -;; Don't wait for outline.el to be loaded, for the sake of outline-minor-mode. -(put 'outline-level 'risky-local-variable t) -(put 'rmail-output-file-alist 'risky-local-variable t) -(put 'font-lock-defaults 'risky-local-variable t) -(put 'special-display-buffer-names 'risky-local-variable t) -(put 'frame-title-format 'risky-local-variable t) -(put 'global-mode-string 'risky-local-variable t) -(put 'header-line-format 'risky-local-variable t) -(put 'icon-title-format 'risky-local-variable t) -(put 'input-method-alist 'risky-local-variable t) -(put 'format-alist 'risky-local-variable t) -(put 'vc-mode 'risky-local-variable t) -(put 'imenu-generic-expression 'risky-local-variable t) -(put 'imenu--index-alist 'risky-local-variable t) -(put 'standard-input 'risky-local-variable t) -(put 'standard-output 'risky-local-variable t) -(put 'unread-command-events 'risky-local-variable t) -(put 'max-lisp-eval-depth 'risky-local-variable t) -(put 'max-specpdl-size 'risky-local-variable t) -(put 'mode-line-format 'risky-local-variable t) -(put 'mode-line-modified 'risky-local-variable t) -(put 'mode-line-mule-info 'risky-local-variable t) -(put 'mode-line-buffer-identification 'risky-local-variable t) -(put 'mode-line-modes 'risky-local-variable t) -(put 'mode-line-position 'risky-local-variable t) -(put 'mode-line-process 'risky-local-variable t) -(put 'mode-name 'risky-local-variable t) -(put 'display-time-string 'risky-local-variable t) -(put 'parse-time-rules 'risky-local-variable t) - -;; Commonly-encountered local variables that are safe: -(let ((string-or-null (lambda (a) (or (stringp a) (null a))))) - (eval - `(mapc (lambda (pair) - (put (car pair) 'safe-local-variable (cdr pair))) - '((byte-compile-dynamic . t) - (c-basic-offset . integerp) - (c-file-style . stringp) - (c-indent-level . integerp) - (comment-column . integerp) - (compile-command . ,string-or-null) - (fill-column . integerp) - (fill-prefix . ,string-or-null) - (indent-tabs-mode . t) - (ispell-check-comments . (lambda (a) - (or (null a) - (eq t a) - (eq 'exclusive a)))) - (ispell-local-dictionary . ,string-or-null) - (kept-new-versions . integerp) - (no-byte-compile . t) - (no-update-autoloads . t) - (outline-regexp . ,string-or-null) - (page-delimiter . ,string-or-null) - (paragraph-start . ,string-or-null) - (paragraph-separate . ,string-or-null) - (sentence-end . ,string-or-null) - (sentence-end-double-space . t) - (tab-width . integerp) - (truncate-lines . t) - (version-control . t))))) - (defun safe-local-variable-p (sym val) "Non-nil if SYM is safe as a file-local variable with value VAL. It is safe if any of these conditions are met: @@ -2608,17 +2682,6 @@ It is dangerous if either of these conditions are met: -[0-9]+$\\|font-lock-syntactic-keywords$\\|-frame-alist$\\|-mode-alist$\\|\ -map$\\|-map-alist$" (symbol-name sym)))) -(defcustom safe-local-eval-forms nil - "*Expressions that are considered \"safe\" in an `eval:' local variable. -Add expressions to this list if you want Emacs to evaluate them, when -they appear in an `eval' local variable specification, without first -asking you for confirmation." - :group 'find-file - :version "22.1" - :type '(repeat sexp)) - -(put 'c-set-style 'safe-local-eval-function t) - (defun hack-one-local-variable-quotep (exp) (and (consp exp) (eq (car exp) 'quote) (consp (cdr exp)))) @@ -2635,12 +2698,14 @@ asking you for confirmation." (and (eq (car exp) 'put) (hack-one-local-variable-quotep (nth 1 exp)) (hack-one-local-variable-quotep (nth 2 exp)) - (memq (nth 1 (nth 2 exp)) - '(lisp-indent-hook)) - ;; Only allow safe values of lisp-indent-hook; - ;; not functions. - (or (numberp (nth 3 exp)) - (equal (nth 3 exp) ''defun))) + (let ((prop (nth 1 (nth 2 exp))) (val (nth 3 exp))) + (cond ((eq prop 'lisp-indent-hook) + ;; Only allow safe values of lisp-indent-hook; + ;; not functions. + (or (numberp val) (equal val ''defun))) + ((eq prop 'edebug-form-spec) + ;; Only allow indirect form specs. + (edebug-basic-spec val))))) ;; Allow expressions that the user requested. (member exp safe-local-eval-forms) ;; Certain functions can be allowed with safe arguments @@ -3636,7 +3701,6 @@ This requires the external program `diff' to be in your `exec-path'." (?d diff-buffer-with-file "view changes in file")) "ACTION-ALIST argument used in call to `map-y-or-n-p'.") -(put 'save-some-buffers-action-alist 'risky-local-variable t) (defvar buffer-save-without-query nil "Non-nil means `save-some-buffers' should save this buffer without asking.") @@ -5113,6 +5177,7 @@ With prefix arg, silently save all file-visiting buffers, then kill." (define-key ctl-x-5-map "f" 'find-file-other-frame) (define-key ctl-x-5-map "\C-f" 'find-file-other-frame) (define-key ctl-x-5-map "r" 'find-file-read-only-other-frame) +(define-key ctl-x-5-map "\C-o" 'display-buffer-other-frame) ;; arch-tag: bc68d3ea-19ca-468b-aac6-3a4a7766101f ;;; files.el ends here