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