Mercurial > hg > xemacs-beta
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. |