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