Mercurial > emacs
comparison lisp/files.el @ 50339:b8ecb0403fa1
(file-relative-name): If FILENAME and DIRECTORY are on
different drives (on DOS/Windows) or use different handlers, do
like `expand-file-name' on FILENAME and return an absolute name.
From Lars Hansen <larsh@math.ku.dk>.
author | Kai Großjohann <kgrossjo@eu.uu.net> |
---|---|
date | Sat, 29 Mar 2003 15:31:07 +0000 |
parents | 994336ed195e |
children | 8e666b72c381 |
comparison
equal
deleted
inserted
replaced
50338:155b4b78aa3b | 50339:b8ecb0403fa1 |
---|---|
2779 | 2779 |
2780 (defun file-nlinks (filename) | 2780 (defun file-nlinks (filename) |
2781 "Return number of names file FILENAME has." | 2781 "Return number of names file FILENAME has." |
2782 (car (cdr (file-attributes filename)))) | 2782 (car (cdr (file-attributes filename)))) |
2783 | 2783 |
2784 ;; (defun file-relative-name (filename &optional directory) | |
2785 ;; "Convert FILENAME to be relative to DIRECTORY (default: `default-directory'). | |
2786 ;; This function returns a relative file name which is equivalent to FILENAME | |
2787 ;; when used with that default directory as the default. | |
2788 ;; If this is impossible (which can happen on MSDOS and Windows | |
2789 ;; when the file name and directory use different drive names) | |
2790 ;; then it returns FILENAME." | |
2791 ;; (save-match-data | |
2792 ;; (let ((fname (expand-file-name filename))) | |
2793 ;; (setq directory (file-name-as-directory | |
2794 ;; (expand-file-name (or directory default-directory)))) | |
2795 ;; ;; On Microsoft OSes, if FILENAME and DIRECTORY have different | |
2796 ;; ;; drive names, they can't be relative, so return the absolute name. | |
2797 ;; (if (and (or (eq system-type 'ms-dos) | |
2798 ;; (eq system-type 'cygwin) | |
2799 ;; (eq system-type 'windows-nt)) | |
2800 ;; (not (string-equal (substring fname 0 2) | |
2801 ;; (substring directory 0 2)))) | |
2802 ;; filename | |
2803 ;; (let ((ancestor ".") | |
2804 ;; (fname-dir (file-name-as-directory fname))) | |
2805 ;; (while (and (not (string-match (concat "^" (regexp-quote directory)) fname-dir)) | |
2806 ;; (not (string-match (concat "^" (regexp-quote directory)) fname))) | |
2807 ;; (setq directory (file-name-directory (substring directory 0 -1)) | |
2808 ;; ancestor (if (equal ancestor ".") | |
2809 ;; ".." | |
2810 ;; (concat "../" ancestor)))) | |
2811 ;; ;; Now ancestor is empty, or .., or ../.., etc. | |
2812 ;; (if (string-match (concat "^" (regexp-quote directory)) fname) | |
2813 ;; ;; We matched within FNAME's directory part. | |
2814 ;; ;; Add the rest of FNAME onto ANCESTOR. | |
2815 ;; (let ((rest (substring fname (match-end 0)))) | |
2816 ;; (if (and (equal ancestor ".") | |
2817 ;; (not (equal rest ""))) | |
2818 ;; ;; But don't bother with ANCESTOR if it would give us `./'. | |
2819 ;; rest | |
2820 ;; (concat (file-name-as-directory ancestor) rest))) | |
2821 ;; ;; We matched FNAME's directory equivalent. | |
2822 ;; ancestor)))))) | |
2823 | |
2784 (defun file-relative-name (filename &optional directory) | 2824 (defun file-relative-name (filename &optional directory) |
2785 "Convert FILENAME to be relative to DIRECTORY (default: `default-directory'). | 2825 "Convert FILENAME to be relative to DIRECTORY (default: `default-directory'). |
2786 This function returns a relative file name which is equivalent to FILENAME | 2826 This function returns a relative file name which is equivalent to FILENAME |
2787 when used with that default directory as the default. | 2827 when used with that default directory as the default. |
2788 If this is impossible (which can happen on MSDOS and Windows | 2828 If FILENAME and DIRECTORY lie on different machines or on different drives |
2789 when the file name and directory use different drive names) | 2829 \(DOS/Windows), it returns FILENAME in expanded form." |
2790 then it returns FILENAME." | |
2791 (save-match-data | 2830 (save-match-data |
2792 (let ((fname (expand-file-name filename))) | 2831 (setq directory |
2793 (setq directory (file-name-as-directory | 2832 (file-name-as-directory (expand-file-name (or directory |
2794 (expand-file-name (or directory default-directory)))) | 2833 default-directory)))) |
2795 ;; On Microsoft OSes, if FILENAME and DIRECTORY have different | 2834 (setq filename (expand-file-name filename)) |
2796 ;; drive names, they can't be relative, so return the absolute name. | 2835 (let ((hf (find-file-name-handler filename 'file-local-copy)) |
2797 (if (and (or (eq system-type 'ms-dos) | 2836 (hd (find-file-name-handler directory 'file-local-copy))) |
2798 (eq system-type 'cygwin) | 2837 (when (and hf (not (get hf 'file-remote-p))) (setq hf nil)) |
2799 (eq system-type 'windows-nt)) | 2838 (when (and hd (not (get hd 'file-remote-p))) (setq hd nil)) |
2800 (not (string-equal (substring fname 0 2) | 2839 (if (and |
2801 (substring directory 0 2)))) | 2840 ;; Conditions for separate trees |
2841 (or | |
2842 ;; Test for different drives on DOS/Windows | |
2843 (and | |
2844 (memq system-type '(ms-dos cygwin windows-nt)) | |
2845 (not (string-equal (substring filename 0 2) | |
2846 (substring directory 0 2)))) | |
2847 ;; Test for different remote file handlers | |
2848 (not (eq hf hd)) | |
2849 ;; Test for different remote file system identification | |
2850 (and | |
2851 hf | |
2852 (let ((re (car (rassq hf file-name-handler-alist)))) | |
2853 (not | |
2854 (equal | |
2855 (and | |
2856 (string-match re filename) | |
2857 (substring filename 0 (match-end 0))) | |
2858 (and | |
2859 (string-match re directory) | |
2860 (substring directory 0 (match-end 0))))))))) | |
2802 filename | 2861 filename |
2803 (let ((ancestor ".") | 2862 (unless (eq (aref filename 0) ?/) |
2804 (fname-dir (file-name-as-directory fname))) | 2863 (setq filename (concat "/" filename))) |
2805 (while (and (not (string-match (concat "^" (regexp-quote directory)) fname-dir)) | 2864 (unless (eq (aref directory 0) ?/) |
2806 (not (string-match (concat "^" (regexp-quote directory)) fname))) | 2865 (setq directory (concat "/" directory))) |
2807 (setq directory (file-name-directory (substring directory 0 -1)) | 2866 (let ((ancestor ".") |
2867 (filename-dir (file-name-as-directory filename))) | |
2868 (while | |
2869 (and | |
2870 (not (string-match (concat "^" (regexp-quote directory)) | |
2871 filename-dir)) | |
2872 (not (string-match (concat "^" (regexp-quote directory)) | |
2873 filename))) | |
2874 (setq directory (file-name-directory (substring directory 0 -1)) | |
2808 ancestor (if (equal ancestor ".") | 2875 ancestor (if (equal ancestor ".") |
2809 ".." | 2876 ".." |
2810 (concat "../" ancestor)))) | 2877 (concat "../" ancestor)))) |
2811 ;; Now ancestor is empty, or .., or ../.., etc. | 2878 ;; Now ancestor is empty, or .., or ../.., etc. |
2812 (if (string-match (concat "^" (regexp-quote directory)) fname) | 2879 (if (string-match (concat "^" (regexp-quote directory)) filename) |
2813 ;; We matched within FNAME's directory part. | 2880 ;; We matched within FILENAME's directory part. |
2814 ;; Add the rest of FNAME onto ANCESTOR. | 2881 ;; Add the rest of FILENAME onto ANCESTOR. |
2815 (let ((rest (substring fname (match-end 0)))) | 2882 (let ((rest (substring filename (match-end 0)))) |
2816 (if (and (equal ancestor ".") | 2883 (if (and (equal ancestor ".") (not (equal rest ""))) |
2817 (not (equal rest ""))) | |
2818 ;; But don't bother with ANCESTOR if it would give us `./'. | 2884 ;; But don't bother with ANCESTOR if it would give us `./'. |
2819 rest | 2885 rest |
2820 (concat (file-name-as-directory ancestor) rest))) | 2886 (concat (file-name-as-directory ancestor) rest))) |
2821 ;; We matched FNAME's directory equivalent. | 2887 ;; We matched FILENAME's directory equivalent. |
2822 ancestor)))))) | 2888 ancestor)))))) |
2823 | 2889 |
2824 (defun save-buffer (&optional args) | 2890 (defun save-buffer (&optional args) |
2825 "Save current buffer in visited file if modified. Versions described below. | 2891 "Save current buffer in visited file if modified. Versions described below. |
2826 By default, makes the previous version into a backup file | 2892 By default, makes the previous version into a backup file |
2827 if previously requested or if this is the first save. | 2893 if previously requested or if this is the first save. |