]> code.delx.au - gnu-emacs/blobdiff - lisp/files.el
(gud-def): Add %c case.
[gnu-emacs] / lisp / files.el
index 285cd50e6af72478238be8294f38af4797287a31..76167eb27cfa1b404388bb18ade8caa56a00a60f 100644 (file)
@@ -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))))
+\f
+;;; 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,101 +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)
-           (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)
-           (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:
@@ -2572,15 +2652,11 @@ It is safe if any of these conditions are met:
  * There is a matching entry (SYM . VAL) in the
    `safe-local-variable-values' user option.
 
- * The `safe-local-variable' property of SYM is t.
-
  * The `safe-local-variable' property of SYM is a function that
    evaluates to a non-nil value with VAL as an argument."
   (or (member (cons sym val) safe-local-variable-values)
       (let ((safep (get sym 'safe-local-variable)))
-       (or (eq safep t)
-           (and (functionp safep)
-                (funcall safep val))))))
+        (and (functionp safep) (funcall safep val)))))
 
 (defun risky-local-variable-p (sym &optional ignored)
   "Non-nil if SYM could be dangerous as a file-local variable.
@@ -2602,17 +2678,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))))
 
@@ -2629,12 +2694,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
@@ -3630,7 +3697,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.")
@@ -5107,6 +5173,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