Mercurial > emacs
comparison lisp/ido.el @ 53323:a053c8c470f3
Handle non-readable directories.
(ido-decorations): Add 9th element for non-readable directory.
(ido-directory-nonreadable): New dynamic var.
(ido-set-current-directory): Set it.
(ido-read-buffer, ido-file-internal):
(ido-read-file-name, ido-read-directory-name): Let-bind it.
(ido-file-name-all-completions1): Return empty list for
non-readable directory.
(ido-exhibit): Print [Not readable] if directory is not readable.
(ido-expand-directory): New defun (based on tiny fix from Karl Chen).
(ido-read-file-name, ido-file-internal, ido-read-directory-name):
Use it.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Sat, 27 Dec 2003 21:56:51 +0000 |
parents | 77088b91def1 |
children | 4b85f31aef7c |
comparison
equal
deleted
inserted
replaced
53322:a8f0b8194a03 | 53323:a053c8c470f3 |
---|---|
683 "*String used by ido to separate the alternatives in the minibuffer. | 683 "*String used by ido to separate the alternatives in the minibuffer. |
684 Obsolete. Set 3rd element of `ido-decorations' instead." | 684 Obsolete. Set 3rd element of `ido-decorations' instead." |
685 :type '(choice string (const nil)) | 685 :type '(choice string (const nil)) |
686 :group 'ido) | 686 :group 'ido) |
687 | 687 |
688 (defcustom ido-decorations '( "{" "}" " | " " | ..." "[" "]" " [No match]" " [Matched]") | 688 (defcustom ido-decorations '( "{" "}" " | " " | ..." "[" "]" " [No match]" " [Matched]" " [Not readable]") |
689 "*List of strings used by ido to display the alternatives in the minibuffer. | 689 "*List of strings used by ido to display the alternatives in the minibuffer. |
690 There are 8 elements in this list, each is a pair of strings: | 690 There are 9 elements in this list: |
691 1st and 2nd elements are used as brackets around the prospect list, | 691 1st and 2nd elements are used as brackets around the prospect list, |
692 3rd element is the separator between prospects (ignored if ido-separator is set), | 692 3rd element is the separator between prospects (ignored if ido-separator is set), |
693 4th element is the string inserted at the end of a truncated list of prospects, | 693 4th element is the string inserted at the end of a truncated list of prospects, |
694 5th and 6th elements are used as brackets around the common match string which | 694 5th and 6th elements are used as brackets around the common match string which |
695 can be completed using TAB, | 695 can be completed using TAB, |
696 7th element is the string displayed when there are a no matches, and | 696 7th element is the string displayed when there are a no matches, and |
697 8th element displayed if there is a single match (and faces are not used)." | 697 8th element is displayed if there is a single match (and faces are not used). |
698 9th element is displayed when the current directory is non-readable." | |
698 :type '(repeat string) | 699 :type '(repeat string) |
699 :group 'ido) | 700 :group 'ido) |
700 | 701 |
701 (defcustom ido-use-faces t | 702 (defcustom ido-use-faces t |
702 "*Non-nil means use ido faces to highlighting first match, only match and | 703 "*Non-nil means use ido faces to highlighting first match, only match and |
928 (defvar ido-cur-list) | 929 (defvar ido-cur-list) |
929 | 930 |
930 ;; Stores the list of items which are ignored when building | 931 ;; Stores the list of items which are ignored when building |
931 ;; `ido-cur-list'. It is in no specific order. | 932 ;; `ido-cur-list'. It is in no specific order. |
932 (defvar ido-ignored-list) | 933 (defvar ido-ignored-list) |
934 | |
935 ;; Remember if current directory is non-readable (so we cannot do completion). | |
936 (defvar ido-directory-nonreadable) | |
933 | 937 |
934 ;; Keep current item list if non-nil. | 938 ;; Keep current item list if non-nil. |
935 (defvar ido-keep-item-list) | 939 (defvar ido-keep-item-list) |
936 | 940 |
937 ;; Process ido-ignore-* lists. | 941 ;; Process ido-ignore-* lists. |
1404 nil | 1408 nil |
1405 (ido-trace "cd" dir) | 1409 (ido-trace "cd" dir) |
1406 (setq ido-current-directory dir) | 1410 (setq ido-current-directory dir) |
1407 (if (get-buffer ido-completion-buffer) | 1411 (if (get-buffer ido-completion-buffer) |
1408 (kill-buffer ido-completion-buffer)) | 1412 (kill-buffer ido-completion-buffer)) |
1413 (setq ido-directory-nonreadable (not (file-readable-p dir))) | |
1409 t)) | 1414 t)) |
1410 | 1415 |
1411 (defun ido-set-current-home (&optional dir) | 1416 (defun ido-set-current-home (&optional dir) |
1412 ;; Set ido's current directory to user's home directory | 1417 ;; Set ido's current directory to user's home directory |
1413 (ido-set-current-directory (expand-file-name (or dir "~/")))) | 1418 (ido-set-current-directory (expand-file-name (or dir "~/")))) |
1810 Return the name of a buffer selected. | 1815 Return the name of a buffer selected. |
1811 PROMPT is the prompt to give to the user. DEFAULT if given is the default | 1816 PROMPT is the prompt to give to the user. DEFAULT if given is the default |
1812 buffer to be selected, which will go to the front of the list. | 1817 buffer to be selected, which will go to the front of the list. |
1813 If REQUIRE-MATCH is non-nil, an existing-buffer must be selected. | 1818 If REQUIRE-MATCH is non-nil, an existing-buffer must be selected. |
1814 If INITIAL is non-nil, it specifies the initial input string." | 1819 If INITIAL is non-nil, it specifies the initial input string." |
1815 (let ((ido-current-directory nil)) | 1820 (let ((ido-current-directory nil) |
1821 (ido-directory-nonreadable nil)) | |
1816 (ido-read-internal 'buffer prompt 'ido-buffer-history default require-match initial))) | 1822 (ido-read-internal 'buffer prompt 'ido-buffer-history default require-match initial))) |
1817 | 1823 |
1818 (defun ido-record-work-directory (&optional dir) | 1824 (defun ido-record-work-directory (&optional dir) |
1819 (when (and (numberp ido-max-work-directory-list) (> ido-max-work-directory-list 0)) | 1825 (when (and (numberp ido-max-work-directory-list) (> ido-max-work-directory-list 0)) |
1820 (if (and (setq dir (or dir ido-current-directory)) (> (length dir) 0)) | 1826 (if (and (setq dir (or dir ido-current-directory)) (> (length dir) 0)) |
1849 (and ido-work-file-list (equal (car ido-work-file-list) name)) | 1855 (and ido-work-file-list (equal (car ido-work-file-list) name)) |
1850 (setq ido-work-file-list (cons name (delete name ido-work-file-list)))) | 1856 (setq ido-work-file-list (cons name (delete name ido-work-file-list)))) |
1851 (if (> (length ido-work-file-list) ido-max-work-file-list) | 1857 (if (> (length ido-work-file-list) ido-max-work-file-list) |
1852 (setcdr (nthcdr (1- ido-max-work-file-list) ido-work-file-list) nil)))) | 1858 (setcdr (nthcdr (1- ido-max-work-file-list) ido-work-file-list) nil)))) |
1853 | 1859 |
1860 (defun ido-expand-directory (dir) | |
1861 ;; Expand DIR or use DEFAULT-DIRECTORY if nil. | |
1862 ;; Add final slash to result in case it was missing from DEFAULT-DIRECTORY. | |
1863 (ido-final-slash (expand-file-name (or dir default-directory)) t)) | |
1864 | |
1854 (defun ido-file-internal (method &optional fallback default prompt item initial) | 1865 (defun ido-file-internal (method &optional fallback default prompt item initial) |
1855 ;; Internal function for ido-find-file and friends | 1866 ;; Internal function for ido-find-file and friends |
1856 (unless item | 1867 (unless item |
1857 (setq item 'file)) | 1868 (setq item 'file)) |
1858 (let ((ido-current-directory (expand-file-name (or default default-directory))) | 1869 (let* ((ido-current-directory (ido-expand-directory default)) |
1859 filename) | 1870 (ido-directory-nonreadable (not (file-readable-p ido-current-directory))) |
1871 filename) | |
1860 | 1872 |
1861 (cond | 1873 (cond |
1862 ((or (not ido-mode) (ido-is-slow-ftp-host)) | 1874 ((or (not ido-mode) (ido-is-slow-ftp-host)) |
1863 (setq filename t | 1875 (setq filename t |
1864 ido-exit 'fallback)) | 1876 ido-exit 'fallback)) |
2691 (if ido-temp-list | 2703 (if ido-temp-list |
2692 (nconc ido-temp-list items) | 2704 (nconc ido-temp-list items) |
2693 (setq ido-temp-list items))) | 2705 (setq ido-temp-list items))) |
2694 | 2706 |
2695 (defun ido-file-name-all-completions1 (dir) | 2707 (defun ido-file-name-all-completions1 (dir) |
2696 (if (and ido-enable-tramp-completion | 2708 (cond |
2697 (string-match "\\`/\\([^/:]+:\\([^/:@]+@\\)?\\)\\'" dir)) | 2709 ((not (file-readable-p dir)) '()) |
2698 | 2710 ((and ido-enable-tramp-completion |
2699 ;; Trick tramp's file-name-all-completions handler to DTRT, as it | 2711 (string-match "\\`/\\([^/:]+:\\([^/:@]+@\\)?\\)\\'" dir)) |
2700 ;; has some pretty obscure requirements. This seems to work... | 2712 |
2701 ;; /ftp: => (f-n-a-c "/ftp:" "") | 2713 ;; Trick tramp's file-name-all-completions handler to DTRT, as it |
2702 ;; /ftp:kfs: => (f-n-a-c "" "/ftp:kfs:") | 2714 ;; has some pretty obscure requirements. This seems to work... |
2703 ;; /ftp:kfs@ => (f-n-a-c "ftp:kfs@" "/") | 2715 ;; /ftp: => (f-n-a-c "/ftp:" "") |
2704 ;; /ftp:kfs@kfs: => (f-n-a-c "" "/ftp:kfs@kfs:") | 2716 ;; /ftp:kfs: => (f-n-a-c "" "/ftp:kfs:") |
2705 ;; Currently no attempt is made to handle multi: stuff. | 2717 ;; /ftp:kfs@ => (f-n-a-c "ftp:kfs@" "/") |
2706 | 2718 ;; /ftp:kfs@kfs: => (f-n-a-c "" "/ftp:kfs@kfs:") |
2707 (let* ((prefix (match-string 1 dir)) | 2719 ;; Currently no attempt is made to handle multi: stuff. |
2708 (user-flag (match-beginning 2)) | 2720 |
2709 (len (and prefix (length prefix))) | 2721 (let* ((prefix (match-string 1 dir)) |
2710 compl) | 2722 (user-flag (match-beginning 2)) |
2711 (if user-flag | 2723 (len (and prefix (length prefix))) |
2712 (setq dir (substring dir 1))) | 2724 compl) |
2713 (require 'tramp nil t) | 2725 (if user-flag |
2714 (ido-trace "tramp complete" dir) | 2726 (setq dir (substring dir 1))) |
2715 (setq compl (file-name-all-completions dir (if user-flag "/" ""))) | 2727 (require 'tramp nil t) |
2716 (if (> len 0) | 2728 (ido-trace "tramp complete" dir) |
2717 (mapcar (lambda (c) (substring c len)) compl) | 2729 (setq compl (file-name-all-completions dir (if user-flag "/" ""))) |
2718 compl)) | 2730 (if (> len 0) |
2719 (file-name-all-completions "" dir))) | 2731 (mapcar (lambda (c) (substring c len)) compl) |
2732 compl))) | |
2733 (t | |
2734 (file-name-all-completions "" dir)))) | |
2720 | 2735 |
2721 (defun ido-file-name-all-completions (dir) | 2736 (defun ido-file-name-all-completions (dir) |
2722 ;; Return name of all files in DIR | 2737 ;; Return name of all files in DIR |
2723 ;; Uses and updates ido-dir-file-cache | 2738 ;; Uses and updates ido-dir-file-cache |
2724 (if (and (numberp ido-max-dir-file-cache) (> ido-max-dir-file-cache 0) | 2739 (if (and (numberp ido-max-dir-file-cache) (> ido-max-dir-file-cache 0) |
3516 (ido-set-current-directory | 3531 (ido-set-current-directory |
3517 (if (memq system-type '(windows-nt ms-dos)) | 3532 (if (memq system-type '(windows-nt ms-dos)) |
3518 (expand-file-name "/" ido-current-directory) | 3533 (expand-file-name "/" ido-current-directory) |
3519 "/")) | 3534 "/")) |
3520 (setq refresh t)) | 3535 (setq refresh t)) |
3536 ((and ido-directory-nonreadable | |
3537 (file-directory-p (concat ido-current-directory (file-name-directory contents)))) | |
3538 (ido-set-current-directory | |
3539 (concat ido-current-directory (file-name-directory contents))) | |
3540 (setq refresh t)) | |
3521 (t | 3541 (t |
3522 (ido-trace "try single dir") | 3542 (ido-trace "try single dir") |
3523 (setq try-single-dir-match t)))) | 3543 (setq try-single-dir-match t)))) |
3524 | 3544 |
3525 ((and (string-equal (substring contents -2 -1) "/") | 3545 ((and (string-equal (substring contents -2 -1) "/") |
3572 (concat ido-current-directory (car ido-matches))) | 3592 (concat ido-current-directory (car ido-matches))) |
3573 (setq ido-exit 'refresh) | 3593 (setq ido-exit 'refresh) |
3574 (exit-minibuffer)) | 3594 (exit-minibuffer)) |
3575 | 3595 |
3576 (when (and (not ido-matches) | 3596 (when (and (not ido-matches) |
3597 (not ido-directory-nonreadable) | |
3577 ;; ido-rescan ? | 3598 ;; ido-rescan ? |
3578 ido-process-ignore-lists | 3599 ido-process-ignore-lists |
3579 ido-ignored-list) | 3600 ido-ignored-list) |
3580 (let ((ido-process-ignore-lists nil) | 3601 (let ((ido-process-ignore-lists nil) |
3581 (ido-rotate ido-rotate) | 3602 (ido-rotate ido-rotate) |
3594 ido-rescan | 3615 ido-rescan |
3595 (not ido-matches) | 3616 (not ido-matches) |
3596 (memq ido-cur-item '(file dir)) | 3617 (memq ido-cur-item '(file dir)) |
3597 (not (ido-is-root-directory)) | 3618 (not (ido-is-root-directory)) |
3598 (> (length contents) 1) | 3619 (> (length contents) 1) |
3599 (not (string-match "[$]" contents))) | 3620 (not (string-match "[$]" contents)) |
3621 (not ido-directory-nonreadable)) | |
3600 (ido-trace "merge?") | 3622 (ido-trace "merge?") |
3601 (if ido-use-merged-list | 3623 (if ido-use-merged-list |
3602 (ido-undo-merge-work-directory contents nil) | 3624 (ido-undo-merge-work-directory contents nil) |
3603 (when (and (eq ido-try-merged-list t) | 3625 (when (and (eq ido-try-merged-list t) |
3604 (numberp ido-auto-merge-work-directories-length) | 3626 (numberp ido-auto-merge-work-directories-length) |
3656 first) | 3678 first) |
3657 (if ind (setq first (concat first ind))) | 3679 (if ind (setq first (concat first ind))) |
3658 (setq comps (cons first (cdr comps))))) | 3680 (setq comps (cons first (cdr comps))))) |
3659 | 3681 |
3660 (cond ((null comps) | 3682 (cond ((null comps) |
3661 (if ido-report-no-match | 3683 (cond |
3662 (nth 6 ido-decorations) ;; [No Match] | 3684 (ido-directory-nonreadable |
3663 "")) | 3685 (or (nth 8 ido-decorations) " [Not readable]")) |
3686 (ido-report-no-match | |
3687 (nth 6 ido-decorations)) ;; [No match] | |
3688 (t ""))) | |
3664 | 3689 |
3665 ((null (cdr comps)) ;one match | 3690 ((null (cdr comps)) ;one match |
3666 (concat (if (> (length (ido-name (car comps))) (length name)) | 3691 (concat (if (> (length (ido-name (car comps))) (length name)) |
3667 ;; when there is one match, show the matching file name in full | 3692 ;; when there is one match, show the matching file name in full |
3668 (concat (nth 4 ido-decorations) ;; [ ... ] | 3693 (concat (nth 4 ido-decorations) ;; [ ... ] |
3769 ((or (eq predicate 'file-directory-p) | 3794 ((or (eq predicate 'file-directory-p) |
3770 (memq this-command ido-read-file-name-as-directory-commands)) | 3795 (memq this-command ido-read-file-name-as-directory-commands)) |
3771 (ido-read-directory-name prompt dir default-filename mustmatch initial)) | 3796 (ido-read-directory-name prompt dir default-filename mustmatch initial)) |
3772 ((and (not (memq this-command ido-read-file-name-non-ido)) | 3797 ((and (not (memq this-command ido-read-file-name-non-ido)) |
3773 (or (null predicate) (eq predicate 'file-exists-p))) | 3798 (or (null predicate) (eq predicate 'file-exists-p))) |
3774 (let (filename | 3799 (let* (filename |
3775 ido-saved-vc-hb | 3800 ido-saved-vc-hb |
3776 (vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends)) | 3801 (vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends)) |
3777 (ido-current-directory (expand-file-name (or dir default-directory))) | 3802 (ido-current-directory (ido-expand-directory dir)) |
3778 (ido-work-directory-index -1) | 3803 (ido-directory-nonreadable (not (file-readable-p ido-current-directory))) |
3779 (ido-work-file-index -1) | 3804 (ido-work-directory-index -1) |
3780 (ido-find-literal nil)) | 3805 (ido-work-file-index -1) |
3806 (ido-find-literal nil)) | |
3781 (setq filename | 3807 (setq filename |
3782 (ido-read-internal 'file prompt 'ido-file-history default-filename mustmatch initial)) | 3808 (ido-read-internal 'file prompt 'ido-file-history default-filename mustmatch initial)) |
3783 (if filename | 3809 (if filename |
3784 (concat ido-current-directory filename)))) | 3810 (concat ido-current-directory filename)))) |
3785 (t | 3811 (t |
3788 | 3814 |
3789 ;;;###autoload | 3815 ;;;###autoload |
3790 (defun ido-read-directory-name (prompt &optional dir default-dirname mustmatch initial) | 3816 (defun ido-read-directory-name (prompt &optional dir default-dirname mustmatch initial) |
3791 "Read directory name, prompting with PROMPT and completing in directory DIR. | 3817 "Read directory name, prompting with PROMPT and completing in directory DIR. |
3792 See `read-file-name' for additional parameters." | 3818 See `read-file-name' for additional parameters." |
3793 (let (filename | 3819 (let* (filename |
3794 ido-saved-vc-hb | 3820 ido-saved-vc-hb |
3795 (ido-current-directory (expand-file-name (or dir default-directory))) | 3821 (ido-current-directory (ido-expand-directory dir)) |
3796 (ido-work-directory-index -1) | 3822 (ido-directory-nonreadable (not (file-readable-p ido-current-directory))) |
3797 (ido-work-file-index -1)) | 3823 (ido-work-directory-index -1) |
3824 (ido-work-file-index -1)) | |
3798 (setq filename | 3825 (setq filename |
3799 (ido-read-internal 'dir prompt 'ido-file-history default-dirname mustmatch initial)) | 3826 (ido-read-internal 'dir prompt 'ido-file-history default-dirname mustmatch initial)) |
3800 (if filename | 3827 (if filename |
3801 (if (and (stringp filename) (string-equal filename ".")) | 3828 (if (and (stringp filename) (string-equal filename ".")) |
3802 ido-current-directory | 3829 ido-current-directory |