comparison lisp/prim/files.el @ 74:54cc21c15cbb r20-0b32

Import from CVS: tag r20-0b32
author cvs
date Mon, 13 Aug 2007 09:04:33 +0200
parents b9518feda344
children 6a378aca36af
comparison
equal deleted inserted replaced
73:e2d7a37b7c8d 74:54cc21c15cbb
747 747
748 (defun create-file-buffer (filename) 748 (defun create-file-buffer (filename)
749 "Create a suitably named buffer for visiting FILENAME, and return it. 749 "Create a suitably named buffer for visiting FILENAME, and return it.
750 FILENAME (sans directory) is used unchanged if that name is free; 750 FILENAME (sans directory) is used unchanged if that name is free;
751 otherwise a string <2> or <3> or ... is appended to get an unused name." 751 otherwise a string <2> or <3> or ... is appended to get an unused name."
752 (let ((lastname (file-name-nondirectory filename))) 752 (let ((handler (find-file-name-handler filename 'create-file-buffer)))
753 (if (string= lastname "") 753 (if handler
754 (setq lastname filename)) 754 (funcall handler 'create-file-buffer filename)
755 (generate-new-buffer lastname))) 755 (let ((lastname (file-name-nondirectory filename)))
756 (if (string= lastname "")
757 (setq lastname filename))
758 (generate-new-buffer lastname)))))
756 759
757 (defun generate-new-buffer (name) 760 (defun generate-new-buffer (name)
758 "Create and return a buffer with a name based on NAME. 761 "Create and return a buffer with a name based on NAME.
759 Choose the buffer's name using `generate-new-buffer-name'." 762 Choose the buffer's name using `generate-new-buffer-name'."
760 (get-buffer-create (generate-new-buffer-name name))) 763 (get-buffer-create (generate-new-buffer-name name)))
765 (defun abbreviate-file-name (filename &optional hack-homedir) 768 (defun abbreviate-file-name (filename &optional hack-homedir)
766 "Return a version of FILENAME shortened using `directory-abbrev-alist'. 769 "Return a version of FILENAME shortened using `directory-abbrev-alist'.
767 See documentation of variable `directory-abbrev-alist' for more information. 770 See documentation of variable `directory-abbrev-alist' for more information.
768 If optional argument HACK-HOMEDIR is non-nil, then this also substitutes 771 If optional argument HACK-HOMEDIR is non-nil, then this also substitutes
769 \"~\" for the user's home directory." 772 \"~\" for the user's home directory."
770 ;; Get rid of the prefixes added by the automounter. 773 (let ((handler (find-file-name-handler filename 'abbreviate-file-name)))
771 ;(if (and (string-match automount-dir-prefix filename) 774 (if handler
772 ; (file-exists-p (file-name-directory 775 (funcall handler 'abbreviate-file-name filename hack-homedir)
773 ; (substring filename (1- (match-end 0)))))) 776 ;; Get rid of the prefixes added by the automounter.
774 ; (setq filename (substring filename (1- (match-end 0))))) 777 ;;(if (and (string-match automount-dir-prefix filename)
775 (let ((tail directory-abbrev-alist)) 778 ;; (file-exists-p (file-name-directory
776 ;; If any elt of directory-abbrev-alist matches this name, 779 ;; (substring filename (1- (match-end 0))))))
777 ;; abbreviate accordingly. 780 ;; (setq filename (substring filename (1- (match-end 0)))))
778 (while tail 781 (let ((tail directory-abbrev-alist))
779 (if (string-match (car (car tail)) filename) 782 ;; If any elt of directory-abbrev-alist matches this name,
780 (setq filename 783 ;; abbreviate accordingly.
781 (concat (cdr (car tail)) (substring filename (match-end 0))))) 784 (while tail
782 (setq tail (cdr tail)))) 785 (if (string-match (car (car tail)) filename)
783 (if hack-homedir 786 (setq filename
784 (progn 787 (concat (cdr (car tail)) (substring filename (match-end 0)))))
785 ;; Compute and save the abbreviated homedir name. 788 (setq tail (cdr tail))))
786 ;; We defer computing this until the first time it's needed, to 789 (if hack-homedir
787 ;; give time for directory-abbrev-alist to be set properly. 790 (progn
788 ;; We include a slash at the end, to avoid spurious matches 791 ;; Compute and save the abbreviated homedir name.
789 ;; such as `/usr/foobar' when the home dir is `/usr/foo'. 792 ;; We defer computing this until the first time it's needed, to
790 (or abbreviated-home-dir 793 ;; give time for directory-abbrev-alist to be set properly.
791 (setq abbreviated-home-dir 794 ;; We include a slash at the end, to avoid spurious matches
792 (let ((abbreviated-home-dir "$foo")) 795 ;; such as `/usr/foobar' when the home dir is `/usr/foo'.
793 (concat "\\`" (regexp-quote (abbreviate-file-name 796 (or abbreviated-home-dir
794 (expand-file-name "~"))) 797 (setq abbreviated-home-dir
795 "\\(/\\|\\'\\)")))) 798 (let ((abbreviated-home-dir "$foo"))
796 ;; If FILENAME starts with the abbreviated homedir, 799 (concat "\\`" (regexp-quote (abbreviate-file-name
797 ;; make it start with `~' instead. 800 (expand-file-name "~")))
798 (if (and (string-match abbreviated-home-dir filename) 801 "\\(/\\|\\'\\)"))))
799 ;; If the home dir is just /, don't change it. 802 ;; If FILENAME starts with the abbreviated homedir,
800 (not (and (= (match-end 0) 1) ;#### unix-specific 803 ;; make it start with `~' instead.
801 (= (aref filename 0) ?/))) 804 (if (and (string-match abbreviated-home-dir filename)
802 (not (and (or (eq system-type 'ms-dos) 805 ;; If the home dir is just /, don't change it.
803 (eq system-type 'windows-nt)) 806 (not (and (= (match-end 0) 1) ;#### unix-specific
804 (save-match-data 807 (= (aref filename 0) ?/)))
805 (string-match "^[a-zA-Z]:/$" filename))))) 808 (not (and (or (eq system-type 'ms-dos)
806 (setq filename 809 (eq system-type 'windows-nt))
807 (concat "~" 810 (save-match-data
808 (substring filename 811 (string-match "^[a-zA-Z]:/$" filename)))))
809 (match-beginning 1) (match-end 1)) 812 (setq filename
810 (substring filename (match-end 0))))))) 813 (concat "~"
811 filename) 814 (substring filename
815 (match-beginning 1) (match-end 1))
816 (substring filename (match-end 0)))))))
817 filename)))
812 818
813 (defvar find-file-not-true-dirname-list nil 819 (defvar find-file-not-true-dirname-list nil
814 "*List of logical names for which visiting shouldn't save the true dirname. 820 "*List of logical names for which visiting shouldn't save the true dirname.
815 On VMS, when you visit a file using a logical name that searches a path, 821 On VMS, when you visit a file using a logical name that searches a path,
816 you may or may not want the visited file name to record the specific 822 you may or may not want the visited file name to record the specific
1238 (setq mode (cdr (car alist)) 1244 (setq mode (cdr (car alist))
1239 keep-going nil))) 1245 keep-going nil)))
1240 (setq alist (cdr alist)))) 1246 (setq alist (cdr alist))))
1241 ;; If we can't deduce a mode from the file name, 1247 ;; If we can't deduce a mode from the file name,
1242 ;; look for an interpreter specified in the first line. 1248 ;; look for an interpreter specified in the first line.
1243 (if (null mode) 1249 (if (and (null mode)
1250 (save-excursion ; XEmacs
1251 (goto-char (point-min))
1252 (looking-at "#!")))
1244 (let ((firstline 1253 (let ((firstline
1245 (buffer-substring 1254 (buffer-substring
1246 (point-min) 1255 (point-min)
1247 (save-excursion 1256 (save-excursion
1248 (goto-char (point-min)) (end-of-line) (point))))) 1257 (goto-char (point-min)) (end-of-line) (point)))))
1454 (if (equal (downcase (symbol-name key)) "mode") 1463 (if (equal (downcase (symbol-name key)) "mode")
1455 (setq key 'mode)) 1464 (setq key 'mode))
1456 (setq result (cons (cons key val) result)) 1465 (setq result (cons (cons key val) result))
1457 (skip-chars-forward " \t;"))) 1466 (skip-chars-forward " \t;")))
1458 (setq result (nreverse result)))))) 1467 (setq result (nreverse result))))))
1459 1468
1460 (let ((set-any-p (or force (hack-local-variables-p t))) 1469 (if result
1461 (mode-p nil)) 1470 (let ((set-any-p (or force (hack-local-variables-p t)))
1462 (while result 1471 (mode-p nil))
1463 (let ((key (car (car result))) 1472 (while result
1464 (val (cdr (car result)))) 1473 (let ((key (car (car result)))
1465 (cond ((eq key 'mode) 1474 (val (cdr (car result))))
1466 (setq mode-p t) 1475 (cond ((eq key 'mode)
1467 (funcall (intern (concat (downcase (symbol-name val)) 1476 (setq mode-p t)
1468 "-mode")))) 1477 (funcall (intern (concat (downcase (symbol-name val))
1469 (set-any-p 1478 "-mode"))))
1470 (hack-one-local-variable key val)) 1479 (set-any-p
1471 (t 1480 (hack-one-local-variable key val))
1472 nil))) 1481 (t
1473 (setq result (cdr result))) 1482 nil)))
1474 mode-p))) 1483 (setq result (cdr result)))
1484 mode-p))))
1475 1485
1476 (defconst ignored-local-variables 1486 (defconst ignored-local-variables
1477 (list 'enable-local-eval) 1487 (list 'enable-local-eval)
1478 "Variables to be ignored in a file's local variable spec.") 1488 "Variables to be ignored in a file's local variable spec.")
1479 1489
1687 "Make a backup of the disk file visited by the current buffer, if appropriate. 1697 "Make a backup of the disk file visited by the current buffer, if appropriate.
1688 This is normally done before saving the buffer the first time. 1698 This is normally done before saving the buffer the first time.
1689 If the value is non-nil, it is the result of `file-modes' on the original file; 1699 If the value is non-nil, it is the result of `file-modes' on the original file;
1690 this means that the caller, after saving the buffer, should change the modes 1700 this means that the caller, after saving the buffer, should change the modes
1691 of the new file to agree with the old modes." 1701 of the new file to agree with the old modes."
1692 (if (and make-backup-files 1702 (if buffer-file-name
1693 (not backup-inhibited) 1703 (let ((handler (find-file-name-handler buffer-file-name 'backup-buffer)))
1694 (not buffer-backed-up) 1704 (if handler
1695 (file-exists-p buffer-file-name) 1705 (funcall handler 'backup-buffer)
1696 (memq (aref (elt (file-attributes buffer-file-name) 8) 0) 1706 (if (and make-backup-files
1697 '(?- ?l))) 1707 (not backup-inhibited)
1698 (let ((real-file-name buffer-file-name) 1708 (not buffer-backed-up)
1699 backup-info backupname targets setmodes) 1709 (file-exists-p buffer-file-name)
1700 ;; If specified name is a symbolic link, chase it to the target. 1710 (memq (aref (elt (file-attributes buffer-file-name) 8) 0)
1701 ;; Thus we make the backups in the directory where the real file is. 1711 '(?- ?l)))
1702 (setq real-file-name (file-chase-links real-file-name)) 1712 (let ((real-file-name buffer-file-name)
1703 (setq backup-info (find-backup-file-name real-file-name) 1713 backup-info backupname targets setmodes)
1704 backupname (car backup-info) 1714 ;; If specified name is a symbolic link, chase it to the target.
1705 targets (cdr backup-info)) 1715 ;; Thus we make the backups in the directory where the real file is.
1716 (setq real-file-name (file-chase-links real-file-name))
1717 (setq backup-info (find-backup-file-name real-file-name)
1718 backupname (car backup-info)
1719 targets (cdr backup-info))
1706 ;;; (if (file-directory-p buffer-file-name) 1720 ;;; (if (file-directory-p buffer-file-name)
1707 ;;; (error "Cannot save buffer in directory %s" buffer-file-name)) 1721 ;;; (error "Cannot save buffer in directory %s" buffer-file-name))
1708 (if backup-info 1722 (if backup-info
1709 (condition-case () 1723 (condition-case ()
1710 (let ((delete-old-versions 1724 (let ((delete-old-versions
1711 ;; If have old versions to maybe delete, 1725 ;; If have old versions to maybe delete,
1712 ;; ask the user to confirm now, before doing anything. 1726 ;; ask the user to confirm now, before doing anything.
1713 ;; But don't actually delete til later. 1727 ;; But don't actually delete til later.
1714 (and targets 1728 (and targets
1715 (or (eq delete-old-versions t) 1729 (or (eq delete-old-versions t)
1716 (eq delete-old-versions nil)) 1730 (eq delete-old-versions nil))
1717 (or delete-old-versions 1731 (or delete-old-versions
1718 (y-or-n-p (format "Delete excess backup versions of %s? " 1732 (y-or-n-p (format "Delete excess backup versions of %s? "
1719 real-file-name)))))) 1733 real-file-name))))))
1720 ;; Actually write the back up file. 1734 ;; Actually write the back up file.
1721 (condition-case ()
1722 (if (or file-precious-flag
1723 ; (file-symlink-p buffer-file-name)
1724 backup-by-copying
1725 (and backup-by-copying-when-linked
1726 (> (file-nlinks real-file-name) 1))
1727 (and backup-by-copying-when-mismatch
1728 (let ((attr (file-attributes real-file-name)))
1729 (or (nth 9 attr)
1730 (not (file-ownership-preserved-p real-file-name))))))
1731 (condition-case () 1735 (condition-case ()
1732 (copy-file real-file-name backupname t t) 1736 (if (or file-precious-flag
1737 ; (file-symlink-p buffer-file-name)
1738 backup-by-copying
1739 (and backup-by-copying-when-linked
1740 (> (file-nlinks real-file-name) 1))
1741 (and backup-by-copying-when-mismatch
1742 (let ((attr (file-attributes real-file-name)))
1743 (or (nth 9 attr)
1744 (not (file-ownership-preserved-p real-file-name))))))
1745 (condition-case ()
1746 (copy-file real-file-name backupname t t)
1747 (file-error
1748 ;; If copying fails because file BACKUPNAME
1749 ;; is not writable, delete that file and try again.
1750 (if (and (file-exists-p backupname)
1751 (not (file-writable-p backupname)))
1752 (delete-file backupname))
1753 (copy-file real-file-name backupname t t)))
1754 ;; rename-file should delete old backup.
1755 (rename-file real-file-name backupname t)
1756 (setq setmodes (file-modes backupname)))
1733 (file-error 1757 (file-error
1734 ;; If copying fails because file BACKUPNAME 1758 ;; If trouble writing the backup, write it in ~.
1735 ;; is not writable, delete that file and try again. 1759 (setq backupname (expand-file-name "~/%backup%~"))
1736 (if (and (file-exists-p backupname) 1760 (message "Cannot write backup file; backing up in ~/%%backup%%~")
1737 (not (file-writable-p backupname))) 1761 (sleep-for 1)
1738 (delete-file backupname)) 1762 (condition-case ()
1739 (copy-file real-file-name backupname t t))) 1763 (copy-file real-file-name backupname t t)
1740 ;; rename-file should delete old backup. 1764 (file-error
1741 (rename-file real-file-name backupname t) 1765 ;; If copying fails because file BACKUPNAME
1742 (setq setmodes (file-modes backupname))) 1766 ;; is not writable, delete that file and try again.
1743 (file-error 1767 (if (and (file-exists-p backupname)
1744 ;; If trouble writing the backup, write it in ~. 1768 (not (file-writable-p backupname)))
1745 (setq backupname (expand-file-name "~/%backup%~")) 1769 (delete-file backupname))
1746 (message "Cannot write backup file; backing up in ~/%%backup%%~") 1770 (copy-file real-file-name backupname t t)))))
1747 (sleep-for 1) 1771 (setq buffer-backed-up t)
1748 (condition-case () 1772 ;; Now delete the old versions, if desired.
1749 (copy-file real-file-name backupname t t) 1773 (if delete-old-versions
1750 (file-error 1774 (while targets
1751 ;; If copying fails because file BACKUPNAME 1775 (condition-case ()
1752 ;; is not writable, delete that file and try again. 1776 (delete-file (car targets))
1753 (if (and (file-exists-p backupname) 1777 (file-error nil))
1754 (not (file-writable-p backupname))) 1778 (setq targets (cdr targets))))
1755 (delete-file backupname)) 1779 setmodes)
1756 (copy-file real-file-name backupname t t))))) 1780 (file-error nil)))))))))
1757 (setq buffer-backed-up t)
1758 ;; Now delete the old versions, if desired.
1759 (if delete-old-versions
1760 (while targets
1761 (condition-case ()
1762 (delete-file (car targets))
1763 (file-error nil))
1764 (setq targets (cdr targets))))
1765 setmodes)
1766 (file-error nil))))))
1767 1781
1768 (defun file-name-sans-versions (name &optional keep-backup-version) 1782 (defun file-name-sans-versions (name &optional keep-backup-version)
1769 "Return FILENAME sans backup versions or strings. 1783 "Return FILENAME sans backup versions or strings.
1770 This is a separate procedure so your site-init or startup file can 1784 This is a separate procedure so your site-init or startup file can
1771 redefine it. 1785 redefine it.
2501 ;; Actually putting the file name in the minibuffer should be used 2515 ;; Actually putting the file name in the minibuffer should be used
2502 ;; only rarely. 2516 ;; only rarely.
2503 ;; Not just because users often use the default. 2517 ;; Not just because users often use the default.
2504 (interactive "FRecover file: ") 2518 (interactive "FRecover file: ")
2505 (setq file (expand-file-name file)) 2519 (setq file (expand-file-name file))
2506 (if (auto-save-file-name-p file) 2520 (let ((handler (or (find-file-name-handler file 'recover-file)
2507 (error "%s is an auto-save file" file)) 2521 (find-file-name-handler
2508 (let ((file-name (let ((buffer-file-name file)) 2522 (let ((buffer-file-name file))
2509 (make-auto-save-file-name)))) 2523 (make-auto-save-file-name))
2510 (cond ((if (file-exists-p file) 2524 'recover-file))))
2511 (not (file-newer-than-file-p file-name file)) 2525 (if handler
2512 (not (file-exists-p file-name))) 2526 (funcall handler 'recover-file file)
2513 (error "Auto-save file %s not current" file-name)) 2527 (if (auto-save-file-name-p file)
2514 ((save-window-excursion 2528 (error "%s is an auto-save file" file))
2515 (if (not (eq system-type 'vax-vms)) 2529 (let ((file-name (let ((buffer-file-name file))
2516 (with-output-to-temp-buffer "*Directory*" 2530 (make-auto-save-file-name))))
2517 (buffer-disable-undo standard-output) 2531 (cond ((if (file-exists-p file)
2518 (call-process "ls" nil standard-output nil 2532 (not (file-newer-than-file-p file-name file))
2519 (if (file-symlink-p file) "-lL" "-l") 2533 (not (file-exists-p file-name)))
2520 file file-name))) 2534 (error "Auto-save file %s not current" file-name))
2521 (yes-or-no-p (format "Recover auto save file %s? " file-name))) 2535 ((save-window-excursion
2522 (switch-to-buffer (find-file-noselect file t)) 2536 (if (not (eq system-type 'vax-vms))
2523 (let ((buffer-read-only nil)) 2537 (with-output-to-temp-buffer "*Directory*"
2524 (erase-buffer) 2538 (buffer-disable-undo standard-output)
2525 (insert-file-contents file-name nil)) 2539 (call-process "ls" nil standard-output nil
2526 (after-find-file nil nil t)) 2540 (if (file-symlink-p file) "-lL" "-l")
2527 (t (error "Recover-file cancelled."))))) 2541 file file-name)))
2542 (yes-or-no-p (format "Recover auto save file %s? " file-name)))
2543 (switch-to-buffer (find-file-noselect file t))
2544 (let ((buffer-read-only nil))
2545 (erase-buffer)
2546 (insert-file-contents file-name nil))
2547 (after-find-file nil nil t))
2548 (t (error "Recover-file cancelled.")))))))
2528 2549
2529 (defun recover-session () 2550 (defun recover-session ()
2530 "Recover auto save files from a previous Emacs session. 2551 "Recover auto save files from a previous Emacs session.
2531 This command first displays a Dired buffer showing you the 2552 This command first displays a Dired buffer showing you the
2532 previous sessions that you could recover from. 2553 previous sessions that you could recover from.