4 (defun* sepia-icompleting-recursive-read
(prompt dir
&key
10 "Like `ido-read-file-name', but without all the file-specific
11 bells-and-whistles. Arguments are:
12 list-fn list current dir
13 parent-fn get parent dir
14 chdir-fn change to dir
16 slashp-fn does dir end in slash?
18 (flet ((ido-make-file-list (prefix)
19 (setq ido-temp-list
(funcall list-fn
(or prefix
""))))
20 (ido-exhibit () (sepia-ido-exhibit))
21 (ido-is-root-directory (&optional dir
)
22 (funcall rootp-fn
(or dir ido-current-directory
)))
23 (ido-set-current-directory (dir &optional subdir foo
)
24 (funcall chdir-fn dir subdir foo
))
25 (ido-final-slash (str &rest blah
)
26 (funcall slashp-fn str
))
27 (ido-file-name-directory (x)
28 (funcall parent-fn x
))
29 ;; And stub out these two suckers...
30 (ido-is-tramp-root (&rest blah
) nil
)
31 (ido-nonreadable-directory-p (dir) nil
))
32 (setq ido-current-directory dir
)
33 (let ((ido-saved-vc-hb nil
)
34 (ido-directory-nonreadable nil
)
35 (ido-context-switch-command 'ignore
)
36 (ido-directory-too-big nil
))
37 (sepia-ido-read-internal 'file prompt nil nil t
))))
39 (defun sepia-rootp-fn (dir)
40 (member dir
'("" "::")))
42 (defun sepia-chdir-fn (dir sub blah
)
45 (sub (concat dir
(car ido-matches
)))
46 ((member dir
(list ido-current-directory
"::")) dir
)
47 ((string-match (concat "^" dir
) ido-current-directory
)
49 (t (concat ido-current-directory
(car ido-matches
)))))
50 ;; XXX what's that doing?!?
51 ;; (unless ido-matches
52 ;; (error "help! dir = %s" dir))
53 ;; (setq dir (concat ido-current-directory (car ido-matches)))
54 (if (string-equal ido-current-directory dir
)
57 (setq ido-current-directory
(ido-final-slash dir
))
58 (when (get-buffer ido-completion-buffer
)
59 (kill-buffer ido-completion-buffer
))
62 (defun sepia-list-fn (str)
63 (let ((listing-dir ido-current-directory
))
64 (when (or (not ido-current-directory
)
65 (string-match "^\\(?:::\\)?$" ido-current-directory
))
66 (setq ido-current-directory
""
69 (substring x
(length listing-dir
)))
70 (xref-apropos (concat listing-dir str
".*") t
"CODE" "STASH"))))
72 (defun sepia-dir-fn (str)
73 (if (string-match "^\\(.*::\\)[^:]+:*$" str
)
77 (defun sepia-slashp-fn (str)
79 ((string-match "::$" str
) str
)
80 ((string-match ":$" str
) (concat str
":"))
83 (defun sepia-jump-to-symbol ()
84 "Jump to a symbol's definition using ido-like completion."
86 (let ((pack (concat (sepia-buffer-package) "::")))
88 (sepia-icompleting-recursive-read "Jump to: " pack
89 :list-fn
'sepia-list-fn
90 :parent-fn
'sepia-dir-fn
91 :chdir-fn
'sepia-chdir-fn
92 :rootp-fn
'sepia-rootp-fn
93 :slashp-fn
'sepia-slashp-fn
)
96 (defun sepia-ido-exhibit ()
97 "Post command hook for `sepia-icompleting-recursive-read'.
98 Like `ido-exhibit', but without weird file-specific bells and
99 whistles. Since ido is controlled through a bunch of dynamic
100 variables, it's hard to figure out what can be safely cut."
102 (when (= ido-use-mycompletion-depth
(minibuffer-depth))
103 (let ((contents (buffer-substring-no-properties (minibuffer-prompt-end)
106 try-single-dir-match
)
109 (goto-char (point-max))
110 ;; Register the end of input, so we know where the extra stuff
111 ;; (match-status info) begins:
112 (unless (boundp 'ido-eoinput
)
113 ;; In case it got wiped out by major mode business:
114 (make-local-variable 'ido-eoinput
))
115 (setq ido-eoinput
(point))
117 ;; Handle explicit directory changes
118 (when (ido-final-slash contents
)
119 (ido-set-current-directory contents
)
120 (setq ido-exit
'refresh
)
122 (setq ido-text-init
""))
124 ;; Update the list of matches
125 (setq ido-text contents
)
128 ;; Enter something ending in a "slash"
129 (when (and ido-matches
130 (null (cdr ido-matches
))
131 (ido-final-slash (car ido-matches
))
132 try-single-dir-match
)
133 (ido-set-current-directory
134 (concat ido-current-directory
(car ido-matches
)))
135 (setq ido-exit
'refresh
)
140 (ido-set-common-completion)
141 (let ((inf (ido-completions
143 minibuffer-completion-table
144 minibuffer-completion-predicate
145 (not minibuffer-completion-confirm
))))
149 (defun sepia-ido-complete ()
150 "Try to complete the current pattern amongst the file names."
156 (when ido-completion-buffer
157 (call-interactively (setq this-command ido-cannot-complete-command
))))
159 ((= 1 (length ido-matches
))
160 ;; only one choice, so select it.
161 (if (not ido-confirm-unique-completion
)
163 (setq ido-rescan
(not ido-enable-prefix
))
164 (delete-region (minibuffer-prompt-end) (point))
165 (insert (car ido-matches
))))
167 (t ;; else there could be some completions
168 (setq res ido-common-match-string
)
169 (if (and (not (memq res
'(t nil
)))
170 (not (equal res ido-text
)))
171 ;; found something to complete, so put it in the minibuffer.
173 ;; move exact match to front if not in prefix mode
174 (setq ido-rescan
(not ido-enable-prefix
))
175 (delete-region (minibuffer-prompt-end) (point))
177 ;; else nothing to complete
179 (setq this-command ido-cannot-complete-command
)))))))
181 (defun sepia-ido-read-internal (item prompt history
&optional
182 default require-match initial
)
183 "Perform the ido-read-buffer and ido-read-file-name functions.
184 Return the name of a buffer or file selected.
185 PROMPT is the prompt to give to the user.
186 DEFAULT if given is the default directory to start with.
187 If REQUIRE-MATCH is non-nil, an existing file must be selected.
188 If INITIAL is non-nil, it specifies the initial input string."
191 (ido-entry-buffer (current-buffer))
192 (ido-process-ignore-lists t
)
193 (ido-process-ignore-lists-inhibit nil
)
194 (ido-set-default-item t
)
199 (icomplete-mode nil
) ;; prevent icomplete starting up
200 ;; Exported dynamic variables:
203 (ido-rotate-temp nil
)
204 (ido-keep-item-list nil
)
205 (ido-use-merged-list nil
)
206 (ido-try-merged-list t
)
207 (ido-pre-merge-state nil
)
208 (ido-case-fold ido-case-fold
)
209 (ido-enable-prefix ido-enable-prefix
)
210 (ido-enable-regexp ido-enable-regexp
)
213 ;; (ido-define-mode-map)
214 (ido-setup-completion-map)
215 (setq ido-text-init initial
)
217 (ido-trace "\n_LOOP_" ido-text-init
)
220 (setq ido-rotate nil
)
222 ;; XXX: set ido-default-item?
224 (if ido-keep-item-list
225 (setq ido-keep-item-list nil
227 (setq ido-ignored-list nil
228 ido-cur-list
(ido-make-file-list ido-default-item
)))
230 (setq ido-rotate-temp nil
)
233 (if (and ido-matches
(eq ido-try-merged-list
'auto
))
234 (setq ido-try-merged-list t
))
236 ((minibuffer-local-completion-map ido-completion-map
)
237 (max-mini-window-height (or ido-max-window-height
238 (and (boundp 'max-mini-window-height
)
239 max-mini-window-height
)))
240 (ido-completing-read t
)
241 (ido-require-match require-match
)
242 (ido-use-mycompletion-depth (1+ (minibuffer-depth)))
243 (show-paren-mode nil
))
244 ;; prompt the user for the file name
249 (ido-make-prompt item prompt
)
250 '(("dummy" .
1)) nil nil
; table predicate require-match
251 (prog1 ido-text-init
(setq ido-text-init nil
)) ;initial-contents
254 (if (get-buffer ido-completion-buffer
)
255 (kill-buffer ido-completion-buffer
))
258 ((eq ido-exit
'refresh
)
259 (if (and (eq ido-use-merged-list
'auto
)
260 (or (input-pending-p)))
261 (setq ido-use-merged-list nil
262 ido-keep-item-list t
))
267 ido-selected ido-text
270 (setq ido-text-init
(read-string (concat prompt
"[EDIT] ")
274 (setq ido-keep-item-list t
))
276 ((memq ido-exit
'(dired fallback findfile findbuffer
))
279 ((eq ido-exit
'updir
)
280 ;; cannot go up if already at the root-dir (Unix) or at the
281 ;; root-dir of a certain drive (Windows or MS-DOS).
282 (unless (ido-is-root-directory)
283 (ido-set-current-directory (ido-file-name-directory
284 (substring ido-current-directory
0 -
2)))
285 (setq ido-set-default-item t
)))
287 ;; Handling the require-match must be done in a better way.
288 ((and require-match
(not (ido-existing-item-p)))
289 (error "must specify valid item"))
293 (if (or (eq ido-exit
'takeprompt
)
296 ;; else take head of list
297 (ido-name (car ido-matches
))))
301 ((ido-final-slash ido-selected
)
302 (ido-set-current-directory ido-current-directory ido-selected
)
303 (setq ido-set-default-item t
))