X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/ac1a0ce1c6ba60a3faddc64463cb7a697b9d8fd2..f1be615c41027bfc11425c9e62598bc25fa323e1:/lisp/files.el diff --git a/lisp/files.el b/lisp/files.el index b1f6fe6e4c..4acdb54208 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -28,8 +28,6 @@ ;;; Code: -(eval-when-compile (require 'cl-lib)) - (defvar font-lock-keywords) (defgroup backup nil @@ -782,10 +780,10 @@ one or more of those symbols." (read-file-name-internal string pred action)) ((eq (car-safe action) 'boundaries) (let ((suffix (cdr action))) - (list* 'boundaries - (length (file-name-directory string)) - (let ((x (file-name-directory suffix))) - (if x (1- (length x)) (length suffix)))))) + `(boundaries + ,(length (file-name-directory string)) + ,@(let ((x (file-name-directory suffix))) + (if x (1- (length x)) (length suffix)))))) (t (let ((names '()) ;; If we have files like "foo.el" and "foo.elc", we could load one of @@ -878,12 +876,12 @@ or mount points potentially requiring authentication as a different user.") ;; nil))) (defun locate-dominating-file (file name) - "Look up the directory hierarchy from FILE for a file named NAME. + "Look up the directory hierarchy from FILE for a directory containing NAME. Stop at the first parent directory containing a file NAME, and return the directory. Return nil if not found. - -This function only tests if FILE exists. If you care about whether -it is readable, regular, etc., you should test the result." +Instead of a string, NAME can also be a predicate taking one argument +\(a directory) and returning a non-nil value if that directory is the one for +which we're looking." ;; We used to use the above locate-dominating-files code, but the ;; directory-files call is very costly, so we're much better off doing ;; multiple calls using the code in here. @@ -910,16 +908,14 @@ it is readable, regular, etc., you should test the result." ;; (setq user (nth 2 (file-attributes file))) ;; (and prev-user (not (equal user prev-user)))) (string-match locate-dominating-stop-dir-regexp file))) - ;; FIXME? maybe this function should (optionally?) - ;; use file-readable-p instead. In many cases, an unreadable - ;; FILE is no better than a non-existent one. - ;; See eg dir-locals-find-file. - (setq try (file-exists-p (expand-file-name name file))) + (setq try (if (stringp name) + (file-exists-p (expand-file-name name file)) + (funcall name file))) (cond (try (setq root file)) ((equal file (setq file (file-name-directory (directory-file-name file)))) (setq file nil)))) - root)) + (if root (file-name-as-directory root)))) (defun executable-find (command) @@ -1004,7 +1000,7 @@ Tip: You can use this expansion of remote identifier components (setq list (cdr list)))) (or (car list) "ssh"))) "Program to use to execute commands on a remote host (e.g. ssh or rsh)." - :version "24.2" ; ssh rather than rsh, etc + :version "24.3" ; ssh rather than rsh, etc :initialize 'custom-initialize-delay :group 'environment :type 'file) @@ -1083,9 +1079,7 @@ containing it, until no links are left at any level. (delq (rassq 'ange-ftp-completion-hook-function tem) tem))))) (or prev-dirs (setq prev-dirs (list nil))) - ;; andrewi@harlequin.co.uk - none of the following code (except for - ;; invoking the file-name handler) currently applies on Windows - ;; (ie. there are no native symlinks), but there is an issue with + ;; andrewi@harlequin.co.uk - on Windows, there is an issue with ;; case differences being ignored by the OS, and short "8.3 DOS" ;; name aliases existing for all files. (The short names are not ;; reported by directory-files, but can be used to refer to files.) @@ -1095,31 +1089,15 @@ containing it, until no links are left at any level. ;; it is stored on disk (expanding short name aliases with the full ;; name in the process). (if (eq system-type 'windows-nt) - (let ((handler (find-file-name-handler filename 'file-truename))) - ;; For file name that has a special handler, call handler. - ;; This is so that ange-ftp can save time by doing a no-op. - (if handler - (setq filename (funcall handler 'file-truename filename)) - ;; If filename contains a wildcard, newname will be the old name. - (unless (string-match "[[*?]" filename) - ;; If filename exists, use the long name. If it doesn't exist, - ;; drill down until we find a directory that exists, and use - ;; the long name of that, with the extra non-existent path - ;; components concatenated. - (let ((longname (w32-long-file-name filename)) - missing rest) - (if longname - (setq filename longname) - ;; Include the preceding directory separator in the missing - ;; part so subsequent recursion on the rest works. - (setq missing (concat "/" (file-name-nondirectory filename))) - (let ((length (length missing))) - (setq rest - (if (> length (length filename)) - "" - (substring filename 0 (- length))))) - (setq filename (concat (file-truename rest) missing)))))) - (setq done t))) + (unless (string-match "[[*?]" filename) + ;; If filename exists, use its long name. If it doesn't + ;; exist, the recursion below on the directory of filename + ;; will drill down until we find a directory that exists, + ;; and use the long name of that, with the extra + ;; non-existent path components concatenated. + (let ((longname (w32-long-file-name filename))) + (if longname + (setq filename longname))))) ;; If this file directly leads to a link, process that iteratively ;; so that we don't use lots of stack. @@ -1139,6 +1117,8 @@ containing it, until no links are left at any level. (setq dirfile (directory-file-name dir)) ;; If these are equal, we have the (or a) root directory. (or (string= dir dirfile) + (and (memq system-type '(windows-nt ms-dos cygwin)) + (eq (compare-strings dir 0 nil dirfile 0 nil t) t)) ;; If this is the same dir we last got the truename for, ;; save time--don't recalculate. (if (assoc dir (car prev-dirs)) @@ -1469,23 +1449,26 @@ file names with wildcards." (find-file filename) (current-buffer))) -(defun find-file-read-only (filename &optional wildcards) - "Edit file FILENAME but don't allow changes. -Like \\[find-file], but marks buffer as read-only. -Use \\[toggle-read-only] to permit editing." - (interactive - (find-file-read-args "Find file read-only: " - (confirm-nonexistent-file-or-buffer))) +(defun find-file--read-only (fun filename wildcards) (unless (or (and wildcards find-file-wildcards (not (string-match "\\`/:" filename)) (string-match "[[*?]" filename)) (file-exists-p filename)) (error "%s does not exist" filename)) - (let ((value (find-file filename wildcards))) - (mapc (lambda (b) (with-current-buffer b (toggle-read-only 1))) + (let ((value (funcall fun filename wildcards))) + (mapc (lambda (b) (with-current-buffer b (read-only-mode 1))) (if (listp value) value (list value))) value)) +(defun find-file-read-only (filename &optional wildcards) + "Edit file FILENAME but don't allow changes. +Like \\[find-file], but marks buffer as read-only. +Use \\[toggle-read-only] to permit editing." + (interactive + (find-file-read-args "Find file read-only: " + (confirm-nonexistent-file-or-buffer))) + (find-file--read-only #'find-file filename wildcards)) + (defun find-file-read-only-other-window (filename &optional wildcards) "Edit file FILENAME in another window but don't allow changes. Like \\[find-file-other-window], but marks buffer as read-only. @@ -1493,15 +1476,7 @@ Use \\[toggle-read-only] to permit editing." (interactive (find-file-read-args "Find file read-only other window: " (confirm-nonexistent-file-or-buffer))) - (unless (or (and wildcards find-file-wildcards - (not (string-match "\\`/:" filename)) - (string-match "[[*?]" filename)) - (file-exists-p filename)) - (error "%s does not exist" filename)) - (let ((value (find-file-other-window filename wildcards))) - (mapc (lambda (b) (with-current-buffer b (toggle-read-only 1))) - (if (listp value) value (list value))) - value)) + (find-file--read-only #'find-file-other-window filename wildcards)) (defun find-file-read-only-other-frame (filename &optional wildcards) "Edit file FILENAME in another frame but don't allow changes. @@ -1510,15 +1485,7 @@ Use \\[toggle-read-only] to permit editing." (interactive (find-file-read-args "Find file read-only other frame: " (confirm-nonexistent-file-or-buffer))) - (unless (or (and wildcards find-file-wildcards - (not (string-match "\\`/:" filename)) - (string-match "[[*?]" filename)) - (file-exists-p filename)) - (error "%s does not exist" filename)) - (let ((value (find-file-other-frame filename wildcards))) - (mapc (lambda (b) (with-current-buffer b (toggle-read-only 1))) - (if (listp value) value (list value))) - value)) + (find-file--read-only #'find-file-other-frame filename wildcards)) (defun find-alternate-file-other-window (filename &optional wildcards) "Find file FILENAME as a replacement for the file in the next window. @@ -1547,7 +1514,11 @@ expand wildcards (if any) and replace the file with multiple files." (other-window 1) (find-alternate-file filename wildcards)))) -(defvar kill-buffer-hook) ; from buffer.c +;; Defined and used in buffer.c, but not as a DEFVAR_LISP. +(defvar kill-buffer-hook nil + "Hook run when a buffer is killed. +The buffer being killed is current while the hook is running. +See `kill-buffer'.") (defun find-alternate-file (filename &optional wildcards) "Find file FILENAME, select its buffer, kill previous buffer. @@ -1650,7 +1621,7 @@ Choose the buffer's name using `generate-new-buffer-name'." "Regexp to match the automounter prefix in a directory name." :group 'files :type 'regexp) -(make-obsolete-variable 'automount-dir-prefix 'directory-abbrev-alist "24.2") +(make-obsolete-variable 'automount-dir-prefix 'directory-abbrev-alist "24.3") (defvar abbreviated-home-dir nil "The user's homedir abbreviated according to `directory-abbrev-alist'.") @@ -2022,6 +1993,8 @@ Do you want to revisit the file normally now? ") (after-find-file error (not nowarn))) (current-buffer)))) +(defvar file-name-buffer-file-type-alist) ;From dos-w32.el. + (defun insert-file-contents-literally (filename &optional visit beg end replace) "Like `insert-file-contents', but only reads in the file literally. A buffer may be modified in several ways after reading into the buffer, @@ -2033,21 +2006,14 @@ This function ensures that none of these modifications will take place." (after-insert-file-functions nil) (coding-system-for-read 'no-conversion) (coding-system-for-write 'no-conversion) - (find-buffer-file-type-function - (if (fboundp 'find-buffer-file-type) - (symbol-function 'find-buffer-file-type) - nil)) + (file-name-buffer-file-type-alist '(("" . t))) (inhibit-file-name-handlers + ;; FIXME: Yuck!! We should turn insert-file-contents-literally + ;; into a file operation instead! (append '(jka-compr-handler image-file-handler epa-file-handler) inhibit-file-name-handlers)) (inhibit-file-name-operation 'insert-file-contents)) - (unwind-protect - (progn - (fset 'find-buffer-file-type (lambda (_filename) t)) - (insert-file-contents filename visit beg end replace)) - (if find-buffer-file-type-function - (fset 'find-buffer-file-type find-buffer-file-type-function) - (fmakunbound 'find-buffer-file-type))))) + (insert-file-contents filename visit beg end replace))) (defun insert-file-1 (filename insert-func) (if (file-directory-p filename) @@ -2179,7 +2145,7 @@ unless NOMODES is non-nil." (not buffer-read-only) (save-excursion (goto-char (point-max)) - (insert "\n"))) + (ignore-errors (insert "\n")))) (when (and buffer-read-only view-read-only (not (eq (get major-mode 'mode-class) 'special))) @@ -2772,7 +2738,7 @@ we don't actually set it to the same mode the buffer already has." (cadr mode)) (setq mode (car mode) name (substring name 0 (match-beginning 0))) - (setq name)) + (setq name nil)) (when mode (set-auto-mode-0 mode keep-mode-if-same) (setq done t)))))) @@ -2871,7 +2837,8 @@ symbol and VAL is a value that is considered safe." ;; This should be here at least as long as Emacs supports write-file-hooks. '((add-hook 'write-file-hooks 'time-stamp) (add-hook 'write-file-functions 'time-stamp) - (add-hook 'before-save-hook 'time-stamp)) + (add-hook 'before-save-hook 'time-stamp nil t) + (add-hook 'before-save-hook 'delete-trailing-whitespace nil t)) "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 @@ -2984,20 +2951,16 @@ UNSAFE-VARS is the list of those that aren't marked as safe or risky. RISKY-VARS is the list of those that are marked as risky. If these settings come from directory-local variables, then DIR-NAME is the name of the associated directory. Otherwise it is nil." - (if noninteractive - nil - (save-window-excursion - (let* ((name (or dir-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)) - (exit-chars - (if offer-save '(?! ?y ?n ?\s ?\C-g) '(?y ?n ?\s ?\C-g))) - (buf (pop-to-buffer "*Local Variables*")) - prompt char) - (set (make-local-variable 'cursor-type) nil) + (unless noninteractive + (let ((name (cond (dir-name) + (buffer-file-name + (file-name-nondirectory buffer-file-name)) + ((concat "buffer " (buffer-name))))) + (offer-save (and (eq enable-local-variables t) + unsafe-vars)) + (buf (get-buffer-create "*Local Variables*"))) + ;; Set up the contents of the *Local Variables* buffer. + (with-current-buffer buf (erase-buffer) (cond (unsafe-vars @@ -3032,25 +2995,35 @@ n -- to ignore the local variables list.") (let ((print-escape-newlines t)) (prin1 (cdr elt) buf)) (insert "\n")) - (setq prompt - (format "Please type %s%s: " - (if offer-save "y, n, or !" "y or n") - (if (< (line-number-at-pos) (window-body-height)) - "" - (push ?\C-v exit-chars) - ", or C-v to scroll"))) - (goto-char (point-min)) - (while (null char) - (setq char (read-char-choice prompt exit-chars t)) - (when (eq char ?\C-v) - (condition-case nil - (scroll-up) - (error (goto-char (point-min)))) - (setq char nil))) - (kill-buffer buf) - (when (and offer-save (= char ?!) unsafe-vars) - (customize-push-and-save 'safe-local-variable-values unsafe-vars)) - (memq char '(?! ?\s ?y)))))) + (set (make-local-variable 'cursor-type) nil) + (set-buffer-modified-p nil) + (goto-char (point-min))) + + ;; Display the buffer and read a choice. + (save-window-excursion + (pop-to-buffer buf) + (let* ((exit-chars '(?y ?n ?\s ?\C-g ?\C-v)) + (prompt (format "Please type %s%s: " + (if offer-save "y, n, or !" "y or n") + (if (< (line-number-at-pos (point-max)) + (window-body-height)) + "" + (push ?\C-v exit-chars) + ", or C-v to scroll"))) + char) + (if offer-save (push ?! exit-chars)) + (while (null char) + (setq char (read-char-choice prompt exit-chars t)) + (when (eq char ?\C-v) + (condition-case nil + (scroll-up) + (error (goto-char (point-min)) + (recenter 1))) + (setq char nil))) + (when (and offer-save (= char ?!) unsafe-vars) + (customize-push-and-save 'safe-local-variable-values unsafe-vars)) + (prog1 (memq char '(?! ?\s ?y)) + (quit-window t))))))) (defun hack-local-variables-prop-line (&optional mode-only) "Return local variables specified in the -*- line. @@ -3136,11 +3109,15 @@ DIR-NAME is the name of the associated directory. Otherwise it is nil." ;; Obey `enable-local-eval'. ((eq var 'eval) (when enable-local-eval - (push elt all-vars) - (or (eq enable-local-eval t) - (hack-one-local-variable-eval-safep (eval (quote val))) - (safe-local-variable-p var val) - (push elt unsafe-vars)))) + (let ((safe (or (hack-one-local-variable-eval-safep val) + ;; In case previously marked safe (bug#5636). + (safe-local-variable-p var val)))) + ;; If not safe and e-l-v = :safe, ignore totally. + (when (or safe (not (eq enable-local-variables :safe))) + (push elt all-vars) + (or (eq enable-local-eval t) + safe + (push elt unsafe-vars)))))) ;; Ignore duplicates (except `mode') in the present list. ((and (assq var all-vars) (not (eq var 'mode))) nil) ;; Accept known-safe variables. @@ -3670,7 +3647,7 @@ is found. Returns the new class name." (defcustom enable-remote-dir-locals nil "Non-nil means dir-local variables will be applied to remote files." - :version "24.2" + :version "24.3" :type 'boolean :group 'find-file) @@ -4085,6 +4062,12 @@ the value is \"\"." (if period ""))))) +(defun file-name-base (&optional filename) + "Return the base name of the FILENAME: no directory, no extension. +FILENAME defaults to `buffer-file-name'." + (file-name-sans-extension + (file-name-nondirectory (or filename (buffer-file-name))))) + (defcustom make-backup-file-name-function nil "A function to use instead of the default `make-backup-file-name'. A value of nil gives the default `make-backup-file-name' behavior. @@ -4348,7 +4331,9 @@ on a DOS/Windows machine, it returns FILENAME in expanded form." default-directory)))) (setq filename (expand-file-name filename)) (let ((fremote (file-remote-p filename)) - (dremote (file-remote-p directory))) + (dremote (file-remote-p directory)) + (fold-case (or (memq system-type '(ms-dos cygwin windows-nt)) + read-file-name-completion-ignore-case))) (if ;; Conditions for separate trees (or ;; Test for different filesystems on DOS/Windows @@ -4357,7 +4342,7 @@ on a DOS/Windows machine, it returns FILENAME in expanded form." (memq system-type '(ms-dos cygwin windows-nt)) (or ;; Test for different drive letters - (not (eq t (compare-strings filename 0 2 directory 0 2))) + (not (eq t (compare-strings filename 0 2 directory 0 2 fold-case))) ;; Test for UNCs on different servers (not (eq t (compare-strings (progn @@ -4382,16 +4367,16 @@ on a DOS/Windows machine, it returns FILENAME in expanded form." (while (not (or (eq t (compare-strings filename-dir nil (length directory) - directory nil nil case-fold-search)) + directory nil nil fold-case)) (eq t (compare-strings filename nil (length directory) - directory nil nil case-fold-search)))) + directory nil nil fold-case)))) (setq directory (file-name-directory (substring directory 0 -1)) ancestor (if (equal ancestor ".") ".." (concat "../" ancestor)))) ;; Now ancestor is empty, or .., or ../.., etc. (if (eq t (compare-strings filename nil (length directory) - directory nil nil case-fold-search)) + directory nil nil fold-case)) ;; We matched within FILENAME's directory part. ;; Add the rest of FILENAME onto ANCESTOR. (let ((rest (substring filename (length directory)))) @@ -4514,7 +4499,8 @@ Before and after saving the buffer, this function runs (or buffer-file-name (let ((filename (expand-file-name - (read-file-name "File to save in: ") nil))) + (read-file-name "File to save in: " + nil (expand-file-name (buffer-name)))))) (if (file-exists-p filename) (if (file-directory-p filename) ;; Signal an error if the user specified the name of an @@ -4838,37 +4824,12 @@ prints a message in the minibuffer. Instead, use `set-buffer-modified-p'." "Modification-flag cleared")) (set-buffer-modified-p arg)) -(defun toggle-read-only (&optional arg) - "Change whether this buffer is read-only. -With prefix argument ARG, make the buffer read-only if ARG is -positive, otherwise make it writable. If buffer is read-only -and `view-read-only' is non-nil, enter view mode. - -This function is usually the wrong thing to use in a Lisp program. -It can have side-effects beyond changing the read-only status of a buffer -\(e.g., enabling view mode), and does not affect read-only regions that -are caused by text properties. To make a buffer read-only in Lisp code, -set `buffer-read-only'. To ignore read-only status (whether due to text -properties or buffer state) and make changes, temporarily bind -`inhibit-read-only'." - (interactive "P") - (if (and arg - (if (> (prefix-numeric-value arg) 0) buffer-read-only - (not buffer-read-only))) ; If buffer-read-only is set correctly, - nil ; do nothing. - ;; Toggle. - (cond - ((and buffer-read-only view-mode) - (View-exit-and-edit) - (make-local-variable 'view-read-only) - (setq view-read-only t)) ; Must leave view mode. - ((and (not buffer-read-only) view-read-only - ;; If view-mode is already active, `view-mode-enter' is a nop. - (not view-mode) - (not (eq (get major-mode 'mode-class) 'special))) - (view-mode-enter)) - (t (setq buffer-read-only (not buffer-read-only)) - (force-mode-line-update))))) +(defun toggle-read-only (&optional arg interactive) + (declare (obsolete read-only-mode "24.3")) + (interactive (list current-prefix-arg t)) + (if interactive + (call-interactively 'read-only-mode) + (read-only-mode (or arg 'toggle)))) (defun insert-file (filename) "Insert contents of file FILENAME into buffer after point. @@ -5395,23 +5356,26 @@ non-nil, it is called instead of rereading visited file contents." (not (file-exists-p file-name))) (error "Auto-save file %s not current" (abbreviate-file-name file-name))) - ((save-window-excursion - (with-output-to-temp-buffer "*Directory*" - (buffer-disable-undo standard-output) - (save-excursion - (let ((switches dired-listing-switches)) - (if (file-symlink-p file) - (setq switches (concat switches " -L"))) - (set-buffer standard-output) - ;; Use insert-directory-safely, not insert-directory, - ;; because these files might not exist. In particular, - ;; FILE might not exist if the auto-save file was for - ;; a buffer that didn't visit a file, such as "*mail*". - ;; The code in v20.x called `ls' directly, so we need - ;; to emulate what `ls' did in that case. - (insert-directory-safely file switches) - (insert-directory-safely file-name switches)))) - (yes-or-no-p (format "Recover auto save file %s? " file-name))) + ((with-temp-buffer-window + "*Directory*" nil + #'(lambda (window _value) + (with-selected-window window + (unwind-protect + (yes-or-no-p (format "Recover auto save file %s? " file-name)) + (when (window-live-p window) + (quit-restore-window window 'kill))))) + (with-current-buffer standard-output + (let ((switches dired-listing-switches)) + (if (file-symlink-p file) + (setq switches (concat switches " -L"))) + ;; Use insert-directory-safely, not insert-directory, + ;; because these files might not exist. In particular, + ;; FILE might not exist if the auto-save file was for + ;; a buffer that didn't visit a file, such as "*mail*". + ;; The code in v20.x called `ls' directly, so we need + ;; to emulate what `ls' did in that case. + (insert-directory-safely file switches) + (insert-directory-safely file-name switches)))) (switch-to-buffer (find-file-noselect file t)) (let ((inhibit-read-only t) ;; Keep the current buffer-file-coding-system. @@ -5951,11 +5915,12 @@ returns nil." (when (and directory-free-space-program ;; Avoid failure if the default directory does ;; not exist (Bug#2631, Bug#3911). - (let ((default-directory "/")) - (eq (call-process directory-free-space-program + (let ((default-directory + (locate-dominating-file dir 'file-directory-p))) + (eq (process-file directory-free-space-program nil t nil directory-free-space-args - dir) + (file-relative-name dir)) 0))) ;; Assume that the "available" column is before the ;; "capacity" column. Find the "%" and scan backward. @@ -6371,8 +6336,15 @@ if any returns nil. If `confirm-kill-emacs' is non-nil, calls it." (setq active t)) (setq processes (cdr processes))) (or (not active) - (progn (list-processes t) - (yes-or-no-p "Active processes exist; kill them and exit anyway? "))))) + (with-temp-buffer-window + (get-buffer-create "*Process List*") nil + #'(lambda (window _value) + (with-selected-window window + (unwind-protect + (yes-or-no-p "Active processes exist; kill them and exit anyway? ") + (when (window-live-p window) + (quit-restore-window window 'kill))))) + (list-processes t))))) ;; Query the user for other things, perhaps. (run-hook-with-args-until-failure 'kill-emacs-query-functions) (or (null confirm-kill-emacs) @@ -6461,19 +6433,19 @@ only these files will be asked to be saved." "/" (substring (car pair) 2))))) (setq file-arg-indices (cdr file-arg-indices)))) - (cl-case method - (identity (car arguments)) - (add (concat "/:" (apply operation arguments))) - (insert-file-contents + (pcase method + (`identity (car arguments)) + (`add (concat "/:" (apply operation arguments))) + (`insert-file-contents (let ((visit (nth 1 arguments))) (prog1 (apply operation arguments) (when (and visit buffer-file-name) (setq buffer-file-name (concat "/:" buffer-file-name)))))) - (unquote-then-quote + (`unquote-then-quote (let ((buffer-file-name (substring buffer-file-name 2))) (apply operation arguments))) - (t + (_ (apply operation arguments))))) ;; Symbolic modes and read-file-modes.