]> code.delx.au - gnu-emacs/blobdiff - lisp/files.el
* lisp/electric.el (electric-pair-pairs): New var.
[gnu-emacs] / lisp / files.el
index 138261b64dd9df769c9958089d94ea7cd0eb6228..ca698cab33dd732730f9443ab0844aac118bf6a9 100644 (file)
@@ -5,6 +5,7 @@
 ;;   2007, 2008, 2009, 2010  Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
+;; Package: emacs
 
 ;; This file is part of GNU Emacs.
 
@@ -66,9 +67,9 @@ Use this feature when you have directories which you normally refer to
 via absolute symbolic links.  Make TO the name of the link, and FROM
 the name it is linked to."
   :type '(repeat (cons :format "%v"
-                      :value ("" . "")
+                      :value ("\\`" . "")
                       (regexp :tag "From")
-                      (regexp :tag "To")))
+                      (string :tag "To")))
   :group 'abbrev
   :group 'find-file)
 
@@ -123,6 +124,7 @@ the default for a new file created there by you.
 This variable is relevant only if `backup-by-copying' is nil."
   :type 'boolean
   :group 'backup)
+(put 'backup-by-copying-when-mismatch 'permanent-local t)
 
 (defcustom backup-by-copying-when-privileged-mismatch 200
   "Non-nil means create backups by copying to preserve a privileged owner.
@@ -187,17 +189,6 @@ If the buffer is visiting a new file, the value is nil.")
   "Non-nil if visited file was read-only when visited.")
 (make-variable-buffer-local 'buffer-file-read-only)
 
-(defcustom temporary-file-directory
-  (file-name-as-directory
-   (cond ((memq system-type '(ms-dos windows-nt))
-         (or (getenv "TEMP") (getenv "TMPDIR") (getenv "TMP") "c:/temp"))
-        (t
-         (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") "/tmp"))))
-  "The directory for writing temporary files."
-  :group 'files
-  :initialize 'custom-initialize-delay
-  :type 'directory)
-
 (defcustom small-temporary-file-directory
   (if (eq system-type 'ms-dos) (getenv "TMPDIR"))
   "The directory for writing small temporary files.
@@ -574,6 +565,9 @@ Runs the usual ange-ftp hook, but only for completion operations."
          (inhibit-file-name-operation op))
       (apply op args))))
 
+(declare-function dos-convert-standard-filename "dos-fns.el" (filename))
+(declare-function w32-convert-standard-filename "w32-fns.el" (filename))
+
 (defun convert-standard-filename (filename)
   "Convert a standard file's name to something suitable for the OS.
 This means to guarantee valid names and perhaps to canonicalize
@@ -591,15 +585,20 @@ and also turn slashes into backslashes if the shell requires it (see
 `w32-shell-dos-semantics').
 
 See Info node `(elisp)Standard File Names' for more details."
-  (if (eq system-type 'cygwin)
-      (let ((name (copy-sequence filename))
-           (start 0))
-       ;; Replace invalid filename characters with !
-       (while (string-match "[?*:<>|\"\000-\037]" name start)
-              (aset name (match-beginning 0) ?!)
-         (setq start (match-end 0)))
-       name)
-    filename))
+  (cond
+   ((eq system-type 'cygwin)
+    (let ((name (copy-sequence filename))
+         (start 0))
+      ;; Replace invalid filename characters with !
+      (while (string-match "[?*:<>|\"\000-\037]" name start)
+       (aset name (match-beginning 0) ?!)
+       (setq start (match-end 0)))
+      name))
+   ((eq system-type 'windows-nt)
+    (w32-convert-standard-filename filename))
+   ((eq system-type 'ms-dos)
+    (dos-convert-standard-filename filename))
+   (t filename)))
 
 (defun read-directory-name (prompt &optional dir default-dirname mustmatch initial)
   "Read directory name, prompting with PROMPT and completing in directory DIR.
@@ -749,21 +748,45 @@ one or more of those symbols."
              (let ((x (file-name-directory suffix)))
                (if x (1- (length x)) (length suffix))))))
    (t
-    (let ((names nil)
+    (let ((names '())
+          ;; If we have files like "foo.el" and "foo.elc", we could load one of
+          ;; them with "foo.el", "foo.elc", or "foo", where just "foo" is the
+          ;; preferred way.  So if we list all 3, that gives a lot of redundant
+          ;; entries for the poor soul looking just for "foo".  OTOH, sometimes
+          ;; the user does want to pay attention to the extension.  We try to
+          ;; diffuse this tension by stripping the suffix, except when the
+          ;; result is a single element (i.e. usually we only list "foo" unless
+          ;; it's the only remaining element in the list, in which case we do
+          ;; list "foo", "foo.elc" and "foo.el").
+          (fullnames '())
          (suffix (concat (regexp-opt suffixes t) "\\'"))
          (string-dir (file-name-directory string))
           (string-file (file-name-nondirectory string)))
       (dolist (dir dirs)
-       (unless dir
-         (setq dir default-directory))
-       (if string-dir (setq dir (expand-file-name string-dir dir)))
-       (when (file-directory-p dir)
-         (dolist (file (file-name-all-completions
-                        string-file dir))
-           (push file names)
-           (when (string-match suffix file)
-             (setq file (substring file 0 (match-beginning 0)))
-              (push file names)))))
+        (unless dir
+          (setq dir default-directory))
+        (if string-dir (setq dir (expand-file-name string-dir dir)))
+        (when (file-directory-p dir)
+          (dolist (file (file-name-all-completions
+                         string-file dir))
+            (if (not (string-match suffix file))
+                (push file names)
+              (push file fullnames)
+              (push (substring file 0 (match-beginning 0)) names)))))
+      ;; Switching from names to names+fullnames creates a non-monotonicity
+      ;; which can cause problems with things like partial-completion.
+      ;; To minimize the problem, filter out completion-regexp-list, so that
+      ;; M-x load-library RET t/x.e TAB finds some files.  Also remove elements
+      ;; from `names' which only matched `string' when they still had
+      ;; their suffix.
+      (setq names (all-completions string names))
+      ;; Remove duplicates of the first element, so that we can easily check
+      ;; if `names' really only contains a single element.
+      (when (cdr names) (setcdr names (delete (car names) (cdr names))))
+      (unless (cdr names)
+        ;; There's no more than one matching non-suffixed element, so expand
+        ;; the list by adding the suffixed elements as well.
+        (setq names (nconc names fullnames)))
       (completion-table-with-context
        string-dir names string-file pred action)))))
 
@@ -902,6 +925,36 @@ to that remote system.
        (funcall handler 'file-remote-p file identification connected)
       nil)))
 
+(defcustom remote-file-name-inhibit-cache 10
+  "Whether to use the remote file-name cache for read access.
+
+When `nil', always use the cached values.
+When `t', never use them.
+A number means use them for that amount of seconds since they were
+cached.
+
+File attributes of remote files are cached for better performance.
+If they are changed out of Emacs' control, the cached values
+become invalid, and must be invalidated.
+
+In case a remote file is checked regularly, it might be
+reasonable to let-bind this variable to a value less then the
+time period between two checks.
+Example:
+
+  \(defun display-time-file-nonempty-p \(file)
+    \(let \(\(remote-file-name-inhibit-cache \(- display-time-interval 5)))
+      \(and \(file-exists-p file)
+           \(< 0 \(nth 7 \(file-attributes \(file-chase-links file)))))))"
+  :group 'files
+  :version "24.1"
+  :type `(choice
+         (const   :tag "Do not inhibit file name cache" nil)
+         (const   :tag "Do not use file name cache" t)
+         (integer :tag "Do not use file name cache"
+                  :format "Do not use file name cache older then %v seconds"
+                  :value 10)))
+
 (defun file-local-copy (file)
   "Copy the file FILE into a temporary file on this machine.
 Returns the name of the local copy, or nil, if FILE is directly
@@ -2179,6 +2232,15 @@ since only a single case-insensitive search through the alist is made."
      (cons (purecopy (car elt)) (cdr elt)))
    `(;; do this first, so that .html.pl is Polish html, not Perl
      ("\\.s?html?\\(\\.[a-zA-Z_]+\\)?\\'" . html-mode)
+     ("\\.svgz?\\'" . image-mode)
+     ("\\.svgz?\\'" . xml-mode)
+     ("\\.x[bp]m\\'" . image-mode)
+     ("\\.x[bp]m\\'" . c-mode)
+     ("\\.p[bpgn]m\\'" . image-mode)
+     ("\\.tiff?\\'" . image-mode)
+     ("\\.gif\\'" . image-mode)
+     ("\\.png\\'" . image-mode)
+     ("\\.jpe?g\\'" . image-mode)
      ("\\.te?xt\\'" . text-mode)
      ("\\.[tT]e[xX]\\'" . tex-mode)
      ("\\.ins\\'" . tex-mode)          ;Installation files for TeX packages.
@@ -2214,6 +2276,14 @@ since only a single case-insensitive search through the alist is made."
      ("\\.te?xi\\'" . texinfo-mode)
      ("\\.[sS]\\'" . asm-mode)
      ("\\.asm\\'" . asm-mode)
+     ("\\.css\\'" . css-mode)
+     ("\\.mixal\\'" . mixal-mode)
+     ("\\.gcov\\'" . compilation-mode)
+     ;; Besides .gdbinit, gdb documents other names to be usable for init
+     ;; files, cross-debuggers can use something like
+     ;; .PROCESSORNAME-gdbinit so that the host and target gdbinit files
+     ;; don't interfere with each other.
+     ("/\\.[a-z0-9-]*gdbinit" . gdb-script-mode)
      ("[cC]hange\\.?[lL]og?\\'" . change-log-mode)
      ("[cC]hange[lL]og[-.][0-9]+\\'" . change-log-mode)
      ("\\$CHANGE_LOG\\$\\.TXT" . change-log-mode)
@@ -2230,6 +2300,7 @@ since only a single case-insensitive search through the alist is made."
      ("\\.cl[so]\\'" . latex-mode)             ;LaTeX 2e class option
      ("\\.bbl\\'" . latex-mode)
      ("\\.bib\\'" . bibtex-mode)
+     ("\\.bst\\'" . bibtex-style-mode)
      ("\\.sql\\'" . sql-mode)
      ("\\.m[4c]\\'" . m4-mode)
      ("\\.mf\\'" . metafont-mode)
@@ -2260,7 +2331,6 @@ ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|7Z\\)\\'" . archive-mode)
      ;; /tmp/Re.... or Message
      ("\\`/tmp/Re" . text-mode)
      ("/Message[0-9]*\\'" . text-mode)
-     ("\\.zone\\'" . zone-mode)
      ;; some news reader is reported to use this
      ("\\`/tmp/fol/" . text-mode)
      ("\\.oak\\'" . scheme-mode)
@@ -2279,6 +2349,20 @@ ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|7Z\\)\\'" . archive-mode)
      ("[:/]_emacs\\'" . emacs-lisp-mode)
      ("/crontab\\.X*[0-9]+\\'" . shell-script-mode)
      ("\\.ml\\'" . lisp-mode)
+     ;; Linux-2.6.9 uses some different suffix for linker scripts:
+     ;; "ld", "lds", "lds.S", "lds.in", "ld.script", and "ld.script.balo".
+     ;; eCos uses "ld" and "ldi".  Netbsd uses "ldscript.*".
+     ("\\.ld[si]?\\'" . ld-script-mode)
+     ("ld\\.?script\\'" . ld-script-mode)
+     ;; .xs is also used for ld scripts, but seems to be more commonly
+     ;; associated with Perl .xs files (C with Perl bindings).  (Bug#7071)
+     ("\\.xs\\'" . c-mode)
+     ;; Explained in binutils ld/genscripts.sh.  Eg:
+     ;; A .x script file is the default script.
+     ;; A .xr script is for linking without relocation (-r flag).  Etc.
+     ("\\.x[abdsru]?[cnw]?\\'" . ld-script-mode)
+     ("\\.zone\\'" . dns-mode)
+     ("\\.soa\\'" . dns-mode)
      ;; Common Lisp ASDF package system.
      ("\\.asd\\'" . lisp-mode)
      ("\\.\\(asn\\|mib\\|smi\\)\\'" . snmp-mode)
@@ -2294,7 +2378,6 @@ ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|7Z\\)\\'" . archive-mode)
      ("#\\*mail\\*" . mail-mode)
      ("\\.g\\'" . antlr-mode)
      ("\\.ses\\'" . ses-mode)
-     ("\\.\\(soa\\|zone\\)\\'" . dns-mode)
      ("\\.docbook\\'" . sgml-mode)
      ("\\.com\\'" . dcl-mode)
      ("/config\\.\\(?:bat\\|log\\)\\'" . fundamental-mode)
@@ -2776,8 +2859,12 @@ asking you for confirmation."
        (no-update-autoloads     . booleanp)
        (tab-width               . integerp)   ;; C source code
        (truncate-lines          . booleanp)   ;; C source code
+       (word-wrap               . booleanp) ;; C source code
        (bidi-display-reordering . booleanp))) ;; C source code
 
+(put 'bidi-paragraph-direction 'safe-local-variable
+     (lambda (v) (memq v '(nil right-to-left left-to-right))))
+
 (put 'c-set-style 'safe-local-eval-function t)
 
 (defvar file-local-variables-alist nil
@@ -4629,16 +4716,17 @@ or multiple mail buffers, etc."
       (force-mode-line-update))))
 
 (defun make-directory (dir &optional parents)
-  "Create the directory DIR and any nonexistent parent dirs.
-If DIR already exists as a directory, signal an error, unless PARENTS is set.
+  "Create the directory DIR and optionally any nonexistent parent dirs.
+If DIR already exists as a directory, signal an error, unless
+PARENTS is non-nil.
 
-Interactively, the default choice of directory to create
-is the current default directory for file names.
-That is useful when you have visited a file in a nonexistent directory.
+Interactively, the default choice of directory to create is the
+current buffer's default directory.  That is useful when you have
+visited a file in a nonexistent directory.
 
-Noninteractively, the second (optional) argument PARENTS says whether
-to create parent directories if they don't exist.  Interactively,
-this happens by default."
+Noninteractively, the second (optional) argument PARENTS, if
+non-nil, says whether to create parent directories that don't
+exist.  Interactively, this happens by default."
   (interactive
    (list (read-file-name "Make directory: " default-directory default-directory
                         nil nil)
@@ -4667,21 +4755,32 @@ this happens by default."
 
 (defconst directory-files-no-dot-files-regexp
   "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
-  "Regexp of file names excluging \".\" an \"..\".")
+  "Regexp matching any file name except \".\" and \"..\".")
 
-(defun delete-directory (directory &optional recursive)
+(defun delete-directory (directory &optional recursive trash)
   "Delete the directory named DIRECTORY.  Does not follow symlinks.
-If RECURSIVE is non-nil, all files in DIRECTORY are deleted as well."
+If RECURSIVE is non-nil, all files in DIRECTORY are deleted as well.
+TRASH non-nil means to trash the directory instead, provided
+`delete-by-moving-to-trash' is non-nil.
+
+When called interactively, TRASH is t if no prefix argument is
+given.  With a prefix argument, TRASH is nil."
   (interactive
-   (let ((dir (expand-file-name
-              (read-file-name
-               "Delete directory: "
-               default-directory default-directory nil nil))))
+   (let* ((trashing (and delete-by-moving-to-trash
+                        (null current-prefix-arg)))
+         (dir (expand-file-name
+               (read-file-name
+                (if trashing
+                    "Move directory to trash: "
+                  "Delete directory: ")
+                default-directory default-directory nil nil))))
      (list dir
           (if (directory-files dir nil directory-files-no-dot-files-regexp)
               (y-or-n-p
-               (format "Directory `%s' is not empty, really delete? " dir))
-            nil))))
+               (format "Directory `%s' is not empty, really %s? "
+                       dir (if trashing "trash" "delete")))
+            nil)
+          (null current-prefix-arg))))
   ;; If default-directory is a remote directory, make sure we find its
   ;; delete-directory handler.
   (setq directory (directory-file-name (expand-file-name directory)))
@@ -4689,7 +4788,7 @@ If RECURSIVE is non-nil, all files in DIRECTORY are deleted as well."
     (cond
      (handler
       (funcall handler 'delete-directory directory recursive))
-     (delete-by-moving-to-trash
+     ((and delete-by-moving-to-trash trash)
       ;; Only move non-empty dir to trash if recursive deletion was
       ;; requested.  This mimics the non-`delete-by-moving-to-trash'
       ;; case, where the operation fails in delete-directory-internal.
@@ -4709,8 +4808,8 @@ If RECURSIVE is non-nil, all files in DIRECTORY are deleted as well."
                  ;; (and (file-directory-p fn) (not (file-symlink-p fn)))
                  ;; but more efficient
                  (if (eq t (car (file-attributes file)))
-                     (delete-directory file recursive)
-                   (delete-file file)))
+                     (delete-directory file recursive nil)
+                   (delete-file file nil)))
                ;; We do not want to delete "." and "..".
                (directory-files
                 directory 'full directory-files-no-dot-files-regexp)))
@@ -4755,10 +4854,14 @@ this happens by default."
       (mapc
        (lambda (file)
         (let ((target (expand-file-name
-                       (file-name-nondirectory file) newname)))
-          (if (file-directory-p file)
-              (copy-directory file target keep-time parents)
-            (copy-file file target t keep-time))))
+                       (file-name-nondirectory file) newname))
+              (attrs (file-attributes file)))
+          (cond ((file-directory-p file)
+                 (copy-directory file target keep-time parents))
+                ((stringp (car attrs)) ; Symbolic link
+                 (make-symbolic-link (car attrs) target t))
+                (t
+                 (copy-file file target t keep-time)))))
        ;; We do not want to copy "." and "..".
        (directory-files        directory 'full directory-files-no-dot-files-regexp))
 
@@ -5150,30 +5253,6 @@ The optional second argument indicates whether to kill internal buffers too."
         (kill-buffer-ask buffer)))))
 
 \f
-(defun auto-save-mode (arg)
-  "Toggle auto-saving of contents of current buffer.
-With prefix argument ARG, turn auto-saving on if positive, else off."
-  (interactive "P")
-  (setq buffer-auto-save-file-name
-        (and (if (null arg)
-                (or (not buffer-auto-save-file-name)
-                    ;; If auto-save is off because buffer has shrunk,
-                    ;; then toggling should turn it on.
-                    (< buffer-saved-size 0))
-              (or (eq arg t) (listp arg) (and (integerp arg) (> arg 0))))
-            (if (and buffer-file-name auto-save-visited-file-name
-                     (not buffer-read-only))
-                buffer-file-name
-              (make-auto-save-file-name))))
-  ;; If -1 was stored here, to temporarily turn off saving,
-  ;; turn it back on.
-  (and (< buffer-saved-size 0)
-       (setq buffer-saved-size 0))
-  (if (called-interactively-p 'interactive)
-      (message "Auto-save %s (in this buffer)"
-              (if buffer-auto-save-file-name "on" "off")))
-  buffer-auto-save-file-name)
-
 (defun rename-auto-save-file ()
   "Adjust current buffer's auto save file name for current conditions.
 Also rename any existing auto save file, if it was made in this session."
@@ -5537,12 +5616,14 @@ preference to the program given by this variable."
 
 (defun get-free-disk-space (dir)
   "Return the amount of free space on directory DIR's file system.
-The result is a string that gives the number of free 1KB blocks,
-or nil if the system call or the program which retrieve the information
-fail.  It returns also nil when DIR is a remote directory.
-
-This function calls `file-system-info' if it is available, or invokes the
-program specified by `directory-free-space-program' if that is non-nil."
+The return value is a string describing the amount of free
+space (normally, the number of free 1KB blocks).
+
+This function calls `file-system-info' if it is available, or
+invokes the program specified by `directory-free-space-program'
+and `directory-free-space-args'.  If the system call or program
+is unsuccessful, or if DIR is a remote directory, this function
+returns nil."
   (unless (file-remote-p dir)
     ;; Try to find the number of free blocks.  Non-Posix systems don't
     ;; always have df, but might have an equivalent system call.
@@ -5562,19 +5643,17 @@ program specified by `directory-free-space-program' if that is non-nil."
                                         directory-free-space-args
                                         dir)
                           0)))
-           ;; Usual format is a header line followed by a line of
-           ;; numbers.
+           ;; Assume that the "available" column is before the
+           ;; "capacity" column.  Find the "%" and scan backward.
            (goto-char (point-min))
            (forward-line 1)
-           (if (not (eobp))
-               (progn
-                 ;; Move to the end of the "available blocks" number.
-                 (skip-chars-forward "^ \t")
-                 (forward-word 3)
-                 ;; Copy it into AVAILABLE.
-                 (let ((end (point)))
-                   (forward-word -1)
-                   (buffer-substring (point) end))))))))))
+           (when (re-search-forward
+                  "[[:space:]]+[^[:space:]]+%[^%]*$"
+                  (line-end-position) t)
+             (goto-char (match-beginning 0))
+             (let ((endpt (point)))
+               (skip-chars-backward "^[:space:]")
+               (buffer-substring-no-properties (point) endpt)))))))))
 
 ;; The following expression replaces `dired-move-to-filename-regexp'.
 (defvar directory-listing-before-filename-regexp
@@ -6366,5 +6445,4 @@ Otherwise, trash FILENAME using the freedesktop.org conventions,
 (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