]> code.delx.au - gnu-emacs/blob - lisp/locate.el
Merge from emacs-23
[gnu-emacs] / lisp / locate.el
1 ;;; locate.el --- interface to the locate command
2
3 ;; Copyright (C) 1996, 1998, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4 ;; 2008, 2009, 2010 Free Software Foundation, Inc.
5
6 ;; Author: Peter Breton <pbreton@cs.umb.edu>
7 ;; Keywords: unix files
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software: you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation, either version 3 of the License, or
14 ;; (at your option) any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23
24 ;;; Commentary:
25
26 ;; Search a database of files and use dired commands on the result.
27 ;;
28 ;; Locate.el provides an interface to a program which searches a
29 ;; database of file names. By default, this program is the GNU locate
30 ;; command, but it could also be the BSD-style find command, or even a
31 ;; user specified command.
32 ;;
33 ;; To use the BSD-style "fast find", or any other shell command of the
34 ;; form
35 ;;
36 ;; SHELLPROGRAM Name-to-find
37 ;;
38 ;; set the variable `locate-command' in your .emacs file.
39 ;;
40 ;; To use a more complicated expression, create a function which
41 ;; takes a string (the name to find) as input and returns a list.
42 ;; The first element should be the command to be executed, the remaining
43 ;; elements should be the arguments (including the name to find). Then put
44 ;;
45 ;; (setq locate-make-command-line 'my-locate-command-line)
46 ;;
47 ;; in your .emacs, using the name of your function in place of
48 ;; my-locate-command-line.
49 ;;
50 ;; You should make sure that whichever command you use works correctly
51 ;; from a shell prompt. GNU locate and BSD find expect the file databases
52 ;; to either be in standard places or located via environment variables.
53 ;; If the latter, make sure these environment variables are set in
54 ;; your emacs process.
55 ;;
56 ;; Locate-mode assumes that each line output from the locate-command
57 ;; consists exactly of a file name, possibly preceded or trailed by
58 ;; whitespace. If your file database has other information on the line (for
59 ;; example, the file size), you will need to redefine the function
60 ;; `locate-get-file-positions' to return a list consisting of the first
61 ;; character in the file name and the last character in the file name.
62 ;;
63 ;; To use locate-mode, simply type M-x locate and then the string
64 ;; you wish to find. You can use almost all of the dired commands in
65 ;; the resulting *Locate* buffer. It is worth noting that your commands
66 ;; do not, of course, affect the file database. For example, if you
67 ;; compress a file in the locate buffer, the actual file will be
68 ;; compressed, but the entry in the file database will not be
69 ;; affected. Consequently, the database and the filesystem will be out
70 ;; of sync until the next time the database is updated.
71 ;;
72 ;; The command `locate-with-filter' keeps only lines matching a
73 ;; regular expression; this is often useful to constrain a big search.
74 ;;
75 \f
76 ;;;;; Building a database of files ;;;;;;;;;
77 ;;
78 ;; You can create a simple files database with a port of the Unix find command
79 ;; and one of the various Windows NT various scheduling utilities,
80 ;; for example the AT command from the NT Resource Kit, WinCron which is
81 ;; included with Microsoft FrontPage, or the shareware NTCron program.
82 ;;
83 ;; To set up a function which searches the files database, do something
84 ;; like this:
85 ;;
86 ;; (defvar locate-fcodes-file "c:/users/peter/fcodes")
87 ;; (defvar locate-make-command-line 'nt-locate-make-command-line)
88 ;;
89 ;; (defun nt-locate-make-command-line (arg)
90 ;; (list "grep" "-i" arg locate-fcodes-file))
91 ;;
92 ;;;;;;;; ADVICE For dired-make-relative: ;;;;;;;;;
93 ;;
94 ;; For certain dired commands to work right, you should also include the
95 ;; following in your _emacs/.emacs:
96 ;;
97 ;; (defadvice dired-make-relative (before set-no-error activate)
98 ;; "For locate mode and Windows, don't return errors"
99 ;; (if (and (eq major-mode 'locate-mode)
100 ;; (memq system-type (list 'windows-nt 'ms-dos)))
101 ;; (ad-set-arg 2 t)
102 ;; ))
103 ;;
104 ;; Otherwise, `dired-make-relative' will give error messages like
105 ;; "FILENAME: not in directory tree growing at /"
106
107 \f
108 ;;; Code:
109
110 (require 'dired)
111
112 ;; Variables
113
114 (defvar locate-current-filter nil)
115 (defvar locate-local-filter nil)
116 (defvar locate-local-search nil)
117 (defvar locate-local-prompt nil)
118
119 (defgroup locate nil
120 "Interface to the locate command."
121 :prefix "locate-"
122 :group 'external)
123
124 (defcustom locate-command "locate"
125 "Executable program for searching a database of files.
126 The Emacs commands `locate' and `locate-with-filter' use this.
127 The value should be a program that can be called from a shell
128 with one argument, SEARCH-STRING. The program determines which
129 database it searches. The output of the program should consist
130 of those file names in the database that match SEARCH-STRING,
131 listed one per line, possibly with leading or trailing
132 whitespace. If the output is in another form, you may have to
133 redefine the function `locate-get-file-positions'.
134
135 The program may interpret SEARCH-STRING as a literal string, a
136 shell pattern or a regular expression. The exact rules of what
137 constitutes a match may also depend on the program.
138
139 The standard value of this variable is \"locate\".
140 This program normally searches a database of all files on your
141 system, or of all files that you have access to. Consult the
142 documentation of that program for the details about how it determines
143 which file names match SEARCH-STRING. (Those details vary highly with
144 the version.)"
145 :type 'string
146 :group 'locate)
147
148 (defvar locate-history-list nil
149 "The history list used by the \\[locate] command.")
150
151 (defvar locate-grep-history-list nil
152 "The history list used by the \\[locate-with-filter] command.")
153
154 (defcustom locate-make-command-line 'locate-default-make-command-line
155 "Function used to create the locate command line.
156 The Emacs commands `locate' and `locate-with-filter' use this.
157 This function should take one argument, a string (the name to find)
158 and return a list of strings. The first element of the list should be
159 the name of a command to be executed by a shell, the remaining elements
160 should be the arguments to that command (including the name to find)."
161 :type 'function
162 :group 'locate)
163
164 (defcustom locate-buffer-name "*Locate*"
165 "Name of the buffer to show results from the \\[locate] command."
166 :type 'string
167 :group 'locate)
168
169 (defcustom locate-fcodes-file nil
170 "File name for the database of file names used by `locate'.
171 If non-nil, `locate' uses this name in the header of the `*Locate*'
172 buffer. If nil, it mentions no file name in that header.
173
174 Just setting this variable does not actually change the database
175 that `locate' searches. The executive program that the Emacs
176 function `locate' uses, as given by the variables `locate-command'
177 or `locate-make-command-line', determines the database."
178 :type '(choice (const :tag "None" nil) file)
179 :group 'locate)
180
181 (defcustom locate-header-face nil
182 "Face used to highlight the locate header."
183 :type '(choice (const :tag "None" nil) face)
184 :group 'locate)
185
186 ;;;###autoload
187 (defcustom locate-ls-subdir-switches (purecopy "-al")
188 "`ls' switches for inserting subdirectories in `*Locate*' buffers.
189 This should contain the \"-l\" switch, but not the \"-F\" or \"-b\" switches."
190 :type 'string
191 :group 'locate
192 :version "22.1")
193
194 (defcustom locate-update-when-revert nil
195 "This option affects how the *Locate* buffer gets reverted.
196 If non-nil, offer to update the locate database when reverting that buffer.
197 \(Normally, you need to have root privileges for this to work. See the
198 option `locate-update-path'.)
199 If nil, reverting does not update the locate database."
200 :type 'boolean
201 :group 'locate
202 :version "22.1")
203
204 (defcustom locate-update-command "updatedb"
205 "The executable program used to update the locate database."
206 :type 'string
207 :group 'locate)
208
209 (defcustom locate-update-path "/"
210 "The default directory from where `locate-update-command' is called.
211 Usually, root permissions are required to run that command. This
212 can be achieved by setting this option to \"/su::\" or \"/sudo::\"
213 \(if you have the appropriate authority). If your current user
214 permissions are sufficient to run the command, you can set this
215 option to \"/\"."
216 :type 'string
217 :group 'locate
218 :version "22.1")
219
220 (defcustom locate-prompt-for-command nil
221 "If non-nil, the `locate' command prompts for a command to run.
222 Otherwise, that behavior is invoked via a prefix argument.
223
224 Setting this option non-nil actually inverts the meaning of a prefix arg;
225 that is, with a prefix arg, you get the default behavior."
226 :group 'locate
227 :type 'boolean)
228
229 ;; Functions
230
231 (defun locate-default-make-command-line (search-string)
232 (list locate-command search-string))
233
234 (defun locate-word-at-point ()
235 (let ((pt (point)))
236 (buffer-substring-no-properties
237 (save-excursion
238 (skip-chars-backward "-a-zA-Z0-9.")
239 (point))
240 (save-excursion
241 (skip-chars-forward "-a-zA-Z0-9.")
242 (skip-chars-backward "." pt)
243 (point)))))
244
245 ;; Function for use in interactive declarations.
246 (defun locate-prompt-for-search-string ()
247 (if (or (and current-prefix-arg
248 (not locate-prompt-for-command))
249 (and (not current-prefix-arg) locate-prompt-for-command))
250 (let ((locate-cmd (funcall locate-make-command-line "")))
251 (read-from-minibuffer
252 "Run locate (like this): "
253 (cons
254 (concat (car locate-cmd) " "
255 (mapconcat 'identity (cdr locate-cmd) " "))
256 (+ 2 (length (car locate-cmd))))
257 nil nil 'locate-history-list))
258 (let* ((default (locate-word-at-point))
259 (input
260 (read-from-minibuffer
261 (if (> (length default) 0)
262 (format "Locate (default %s): " default)
263 (format "Locate: "))
264 nil nil nil 'locate-history-list default t)))
265 (and (equal input "") default
266 (setq input default))
267 input)))
268
269 ;;;###autoload
270 (defun locate (search-string &optional filter arg)
271 "Run the program `locate', putting results in `*Locate*' buffer.
272 Pass it SEARCH-STRING as argument. Interactively, prompt for SEARCH-STRING.
273 With prefix arg ARG, prompt for the exact shell command to run instead.
274
275 This program searches for those file names in a database that match
276 SEARCH-STRING and normally outputs all matching absolute file names,
277 one per line. The database normally consists of all files on your
278 system, or of all files that you have access to. Consult the
279 documentation of the program for the details about how it determines
280 which file names match SEARCH-STRING. (Those details vary highly with
281 the version.)
282
283 You can specify another program for this command to run by customizing
284 the variables `locate-command' or `locate-make-command-line'.
285
286 The main use of FILTER is to implement `locate-with-filter'. See
287 the docstring of that function for its meaning.
288
289 After preparing the results buffer, this runs `dired-mode-hook' and
290 then `locate-post-command-hook'."
291 (interactive
292 (list
293 (locate-prompt-for-search-string)
294 nil
295 current-prefix-arg))
296
297 (if (equal search-string "")
298 (error "Please specify a filename to search for"))
299 (let* ((locate-cmd-list (funcall locate-make-command-line search-string))
300 (locate-cmd (car locate-cmd-list))
301 (locate-cmd-args (cdr locate-cmd-list))
302 (run-locate-command
303 (or (and arg (not locate-prompt-for-command))
304 (and (not arg) locate-prompt-for-command))))
305
306 ;; Find the Locate buffer
307 (save-window-excursion
308 (set-buffer (get-buffer-create locate-buffer-name))
309 (locate-mode)
310 (let ((inhibit-read-only t)
311 (buffer-undo-list t))
312 (erase-buffer)
313
314 (setq locate-current-filter filter)
315 (set (make-local-variable 'locate-local-search) search-string)
316 (set (make-local-variable 'locate-local-filter) filter)
317 (set (make-local-variable 'locate-local-prompt) run-locate-command)
318
319 (if run-locate-command
320 (shell-command search-string locate-buffer-name)
321 (apply 'call-process locate-cmd nil t nil locate-cmd-args))
322
323 (and filter
324 (locate-filter-output filter))
325
326 (locate-do-setup search-string)))
327 (and (not (string-equal (buffer-name) locate-buffer-name))
328 (pop-to-buffer locate-buffer-name))
329
330 (run-hooks 'dired-mode-hook)
331 (dired-next-line 3) ;move to first matching file.
332 (run-hooks 'locate-post-command-hook)))
333
334 ;;;###autoload
335 (defun locate-with-filter (search-string filter &optional arg)
336 "Run the executable program `locate' with a filter.
337 This function is similar to the function `locate', which see.
338 The difference is that, when invoked interactively, the present function
339 prompts for both SEARCH-STRING and FILTER. It passes SEARCH-STRING
340 to the locate executable program. It produces a `*Locate*' buffer
341 that lists only those lines in the output of the locate program that
342 contain a match for the regular expression FILTER; this is often useful
343 to constrain a big search.
344
345 ARG is the interactive prefix arg, which has the same effect as in `locate'.
346
347 When called from Lisp, this function is identical with `locate',
348 except that FILTER is not optional."
349 (interactive
350 (list
351 (locate-prompt-for-search-string)
352 (read-from-minibuffer "Filter: " nil nil
353 nil 'locate-grep-history-list)
354 current-prefix-arg))
355 (locate search-string filter arg))
356
357 (defun locate-filter-output (filter)
358 "Filter output from the locate command."
359 (goto-char (point-min))
360 (keep-lines filter))
361
362 (defvar locate-mode-map
363 (let ((map (copy-keymap dired-mode-map)))
364 ;; Undefine Useless Dired Menu bars
365 (define-key map [menu-bar Dired] 'undefined)
366 (define-key map [menu-bar subdir] 'undefined)
367 (define-key map [menu-bar mark executables] 'undefined)
368 (define-key map [menu-bar mark directory] 'undefined)
369 (define-key map [menu-bar mark directories] 'undefined)
370 (define-key map [menu-bar mark symlinks] 'undefined)
371 (define-key map [M-mouse-2] 'locate-mouse-view-file)
372 (define-key map "\C-c\C-t" 'locate-tags)
373 (define-key map "l" 'locate-do-redisplay)
374 (define-key map "U" 'dired-unmark-all-files)
375 (define-key map "V" 'locate-find-directory)
376 map)
377 "Local keymap for Locate mode buffers.")
378
379 ;; This variable is used to indent the lines and then to search for
380 ;; the file name
381 (defconst locate-filename-indentation 4
382 "The amount of indentation for each file.")
383
384 (defun locate-get-file-positions ()
385 "Return list of start and end of the file name on the current line.
386 This is a list of two buffer positions.
387
388 You should only call this function on lines that contain a file name
389 listed by the locate program. Inside inserted subdirectories, or if
390 there is no file name on the current line, the return value is
391 meaningless. You can check whether the current line contains a file
392 listed by the locate program, using the function
393 `locate-main-listing-line-p'."
394 (list (+ locate-filename-indentation
395 (line-beginning-position))
396 ;; Assume names end at the end of the line.
397 (line-end-position)))
398
399 ;; From SQL-mode
400 (defun locate-current-line-number ()
401 "Return the current line number, as an integer."
402 (+ (count-lines (point-min) (point))
403 (if (eq (current-column) 0)
404 1
405 0)))
406
407 ;; You should only call this function on lines that contain a file name
408 ;; listed by the locate program. Inside inserted subdirectories, or if
409 ;; there is no file name on the current line, the return value is
410 ;; meaningless. You can check whether the current line contains a file
411 ;; listed by the locate program, using the function
412 ;; `locate-main-listing-line-p'.
413 (defun locate-get-filename ()
414 (let ((pos (locate-get-file-positions))
415 (lineno (locate-current-line-number)))
416 (and (not (eq lineno 1))
417 (not (eq lineno 2))
418 (buffer-substring (elt pos 0) (elt pos 1)))))
419
420 (defun locate-main-listing-line-p ()
421 "Return t if current line contains a file name listed by locate.
422 This function returns nil if the current line either contains no
423 file name or is inside a subdirectory."
424 (save-excursion
425 (forward-line 0)
426 (looking-at (concat "."
427 (make-string (1- locate-filename-indentation) ?\s)
428 "\\(/\\|[A-Za-z]:\\)"))))
429
430 (defun locate-mouse-view-file (event)
431 "In Locate mode, view a file, using the mouse."
432 (interactive "@e")
433 (save-excursion
434 (goto-char (posn-point (event-start event)))
435 (if (locate-main-listing-line-p)
436 (view-file (locate-get-filename))
437 (message "This command only works inside main listing."))))
438
439 ;; Define a mode for locate
440 ;; Default directory is set to "/" so that dired commands, which
441 ;; expect to be in a tree, will work properly
442 (defun locate-mode ()
443 "Major mode for the `*Locate*' buffer made by \\[locate].
444 \\<locate-mode-map>\
445 In that buffer, you can use almost all the usual dired bindings.
446 \\[locate-find-directory] visits the directory of the file on the current line.
447 This function runs `locate-mode-hook' before returning.
448
449 Operating on listed files works, but does not always
450 automatically update the buffer as in ordinary Dired.
451 This is true both for the main listing and for subdirectories.
452 Reverting the buffer using \\[revert-buffer] deletes all subdirectories.
453 Specific `locate-mode' commands, such as \\[locate-find-directory],
454 do not work in subdirectories.
455
456 \\{locate-mode-map}"
457 ;; Not to be called interactively.
458 (kill-all-local-variables)
459 ;; Avoid clobbering this variable
460 (make-local-variable 'dired-subdir-alist)
461 (use-local-map locate-mode-map)
462 (setq major-mode 'locate-mode
463 mode-name "Locate"
464 default-directory "/"
465 buffer-read-only t
466 selective-display t)
467 (dired-alist-add-1 default-directory (point-min-marker))
468 (set (make-local-variable 'dired-directory) "/")
469 (set (make-local-variable 'dired-subdir-switches) locate-ls-subdir-switches)
470 (setq dired-switches-alist nil)
471 (make-local-variable 'directory-listing-before-filename-regexp)
472 ;; This should support both Unix and Windoze style names
473 (setq directory-listing-before-filename-regexp
474 (concat "^."
475 (make-string (1- locate-filename-indentation) ?\s)
476 "\\(/\\|[A-Za-z]:\\)\\|"
477 (default-value 'directory-listing-before-filename-regexp)))
478 (make-local-variable 'dired-actual-switches)
479 (setq dired-actual-switches "")
480 (make-local-variable 'dired-permission-flags-regexp)
481 (setq dired-permission-flags-regexp
482 (concat "^.\\("
483 (make-string (1- locate-filename-indentation) ?\s)
484 "\\)\\|"
485 (default-value 'dired-permission-flags-regexp)))
486 (make-local-variable 'revert-buffer-function)
487 (setq revert-buffer-function 'locate-update)
488 (set (make-local-variable 'page-delimiter) "\n\n")
489 (run-mode-hooks 'locate-mode-hook))
490
491 (defun locate-do-setup (search-string)
492 (goto-char (point-min))
493 (save-excursion
494
495 ;; Nothing returned from locate command?
496 (and (eobp)
497 (progn
498 (kill-buffer locate-buffer-name)
499 (if locate-current-filter
500 (error "Locate: no match for %s in database using filter %s"
501 search-string locate-current-filter)
502 (error "Locate: no match for %s in database" search-string))))
503
504 (locate-insert-header search-string)
505
506 (while (not (eobp))
507 (insert-char ?\s locate-filename-indentation t)
508 (locate-set-properties)
509 (forward-line 1)))
510 (goto-char (point-min)))
511
512 (defun locate-set-properties ()
513 (save-excursion
514 (let ((pos (locate-get-file-positions)))
515 (dired-insert-set-properties (elt pos 0) (elt pos 1)))))
516
517 (defun locate-insert-header (search-string)
518 ;; There needs to be a space before `Matches, because otherwise,
519 ;; `*!" would erase the `M'. We can not use two spaces, or the line
520 ;; would mistakenly fit `dired-subdir-regexp'.
521 (let ((locate-format-string " /:\n Matches for %s")
522 (locate-regexp-match
523 (concat " *Matches for \\(" (regexp-quote search-string) "\\)"))
524 (locate-format-args (list search-string))
525 )
526
527 (and locate-fcodes-file
528 (setq locate-format-string
529 (concat locate-format-string " in %s")
530 locate-regexp-match
531 (concat locate-regexp-match
532 " in \\("
533 (regexp-quote locate-fcodes-file)
534 "\\)")
535 locate-format-args
536 (append (list locate-fcodes-file) locate-format-args)))
537
538 (and locate-current-filter
539 (setq locate-format-string
540 (concat locate-format-string " using filter %s")
541 locate-regexp-match
542 (concat locate-regexp-match
543 " using filter "
544 "\\("
545 (regexp-quote locate-current-filter)
546 "\\)")
547 locate-format-args
548 (append (list locate-current-filter) locate-format-args)))
549
550 (setq locate-format-string
551 (concat locate-format-string ":\n\n")
552 locate-regexp-match
553 (concat locate-regexp-match ":\n"))
554
555 (insert (apply 'format locate-format-string (reverse locate-format-args)))
556
557 (save-excursion
558 (goto-char (point-min))
559 (forward-line 1)
560 (if (not (looking-at locate-regexp-match))
561 nil
562 (add-text-properties (match-beginning 1) (match-end 1)
563 (list 'face locate-header-face))
564 (and (match-beginning 2)
565 (add-text-properties (match-beginning 2) (match-end 2)
566 (list 'face locate-header-face)))
567 (and (match-beginning 3)
568 (add-text-properties (match-beginning 3) (match-end 3)
569 (list 'face locate-header-face)))
570 ))))
571
572 (defun locate-tags ()
573 "Visit a tags table in `*Locate*' mode."
574 (interactive)
575 (if (locate-main-listing-line-p)
576 (let ((tags-table (locate-get-filename)))
577 (and (y-or-n-p (format "Visit tags table %s? " tags-table))
578 (visit-tags-table tags-table)))
579 (message "This command only works inside main listing.")))
580
581 ;; From Stephen Eglen <stephen@cns.ed.ac.uk>
582 (defun locate-update (ignore1 ignore2)
583 "Revert the *Locate* buffer.
584 If `locate-update-when-revert' is non-nil, offer to update the
585 locate database using the shell command in `locate-update-command'."
586 (let ((locate-buffer-name (buffer-name))
587 (locate-prompt-for-command locate-local-prompt))
588 (and locate-update-when-revert
589 (yes-or-no-p "Update locate database (may take a few seconds)? ")
590 ;; `expand-file-name' is used in order to autoload Tramp if
591 ;; necessary. It cannot be loaded when `default-directory'
592 ;; is remote.
593 (let ((default-directory (expand-file-name locate-update-path)))
594 (shell-command locate-update-command)))
595 (locate locate-local-search locate-local-filter)))
596
597 ;;; Modified three functions from `dired.el':
598 ;;; dired-find-directory,
599 ;;; dired-find-directory-other-window
600 ;;; dired-get-filename
601
602 (defun locate-find-directory ()
603 "Visit the directory of the file mentioned on this line."
604 (interactive)
605 (if (locate-main-listing-line-p)
606 (let ((directory-name (locate-get-dirname)))
607 (if (file-directory-p directory-name)
608 (find-file directory-name)
609 (if (file-symlink-p directory-name)
610 (error "Directory is a symlink to a nonexistent target")
611 (error "Directory no longer exists; run `updatedb' to update database"))))
612 (message "This command only works inside main listing.")))
613
614 (defun locate-find-directory-other-window ()
615 "Visit the directory of the file named on this line in other window."
616 (interactive)
617 (if (locate-main-listing-line-p)
618 (find-file-other-window (locate-get-dirname))
619 (message "This command only works inside main listing.")))
620
621 ;; You should only call this function on lines that contain a file name
622 ;; listed by the locate program. Inside inserted subdirectories, or if
623 ;; there is no file name on the current line, the return value is
624 ;; meaningless. You can check whether the current line contains a file
625 ;; listed by the locate program, using the function
626 ;; `locate-main-listing-line-p'.
627 (defun locate-get-dirname ()
628 "Return the directory name of the file mentioned on this line."
629 (let (file (filepos (locate-get-file-positions)))
630 (if (setq file (buffer-substring (nth 0 filepos) (nth 1 filepos)))
631 (progn
632 ;; Get rid of the mouse-face property that file names have.
633 (set-text-properties 0 (length file) nil file)
634 (setq file (file-name-directory file))
635 ;; Unquote names quoted by ls or by dired-insert-directory.
636 ;; Using read to unquote is much faster than substituting
637 ;; \007 (4 chars) -> ^G (1 char) etc. in a lisp loop.
638 (setq file
639 (read
640 (concat "\""
641 ;; some ls -b don't escape quotes, argh!
642 ;; This is not needed for GNU ls, though.
643 (or (dired-string-replace-match
644 "\\([^\\]\\|\\`\\)\"" file "\\1\\\\\"" nil t)
645 file)
646 "\"")))))
647 (and file buffer-file-coding-system
648 (not file-name-coding-system)
649 (setq file (encode-coding-string file buffer-file-coding-system)))
650 file))
651
652 ;; Only for GNU locate
653 (defun locate-in-alternate-database (search-string database)
654 "Run the GNU locate program, using an alternate database.
655
656 This command only works if you use GNU locate. It does not work
657 properly if `locate-prompt-for-command' is set to t. In that
658 case, you can just run the regular `locate' command and specify
659 the database on the command line."
660 (interactive
661 (list
662 (progn
663 ;; (require 'locate)
664 (read-from-minibuffer "Locate: " nil nil
665 nil 'locate-history-list))
666 (read-file-name "Locate using Database: " )
667 ))
668 (or (file-exists-p database)
669 (error "Database file %s does not exist" database))
670 (let ((locate-make-command-line
671 (function (lambda (string)
672 (cons locate-command
673 (list (concat "--database="
674 (expand-file-name database))
675 string))))))
676 (locate search-string)))
677
678 (defun locate-do-redisplay (&optional arg test-for-subdir)
679 "Like `dired-do-redisplay', but adapted for `*Locate*' buffers."
680 (interactive "P\np")
681 (if (string= (dired-current-directory) "/")
682 (message "This command only works in subdirectories.")
683 (let ((dired-actual-switches locate-ls-subdir-switches))
684 (dired-do-redisplay arg test-for-subdir))))
685
686 (provide 'locate)
687
688 ;;; locate.el ends here