diff options
| author | Richard M. Stallman | 1996-12-30 04:22:22 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1996-12-30 04:22:22 +0000 |
| commit | 6aea3b07e8a9453f5d99d211e23803d3124d199f (patch) | |
| tree | 9f013b4118d3d1a194f780ebcdfb2928a08ad8ac | |
| parent | ececcbec2a29bb7e2ef8b1059d3f6d060781525c (diff) | |
| download | emacs-6aea3b07e8a9453f5d99d211e23803d3124d199f.tar.gz emacs-6aea3b07e8a9453f5d99d211e23803d3124d199f.zip | |
Initial revision
| -rw-r--r-- | lisp/locate.el | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/lisp/locate.el b/lisp/locate.el new file mode 100644 index 00000000000..ed9c6a7eb6d --- /dev/null +++ b/lisp/locate.el | |||
| @@ -0,0 +1,385 @@ | |||
| 1 | ;; Locate.el: interface to the locate command | ||
| 2 | |||
| 3 | ;; Copyright (C) 1996 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Peter Breton <pbreton@i-kinetics.com> | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | |||
| 9 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;; any later version. | ||
| 13 | |||
| 14 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | |||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;; Boston, MA 02111-1307, USA. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | |||
| 26 | ;; Search a database of files and use dired commands on | ||
| 27 | ;; the result. | ||
| 28 | ;; | ||
| 29 | |||
| 30 | ;; Installation: | ||
| 31 | ;; | ||
| 32 | ;; Place the following in your .emacs file: | ||
| 33 | ;; | ||
| 34 | ;; ;; redefines dired-get-filename as a switch function | ||
| 35 | ;; | ||
| 36 | ;; (require 'advice) | ||
| 37 | ;; (defadvice dired-get-filename (around check-mode activate) | ||
| 38 | ;; "Use an alternative function in Locate mode" | ||
| 39 | ;; (cond ((eq major-mode 'locate-mode) | ||
| 40 | ;; (setq ad-return-value (locate-get-filename))) | ||
| 41 | ;; (t | ||
| 42 | ;; ad-do-it))) | ||
| 43 | ;; | ||
| 44 | ;; DOS and WINDOWS Users: | ||
| 45 | ;; | ||
| 46 | ;;;;; Building a database of files ;;;;;;;;; | ||
| 47 | ;; | ||
| 48 | ;; You can create a simple files database with a port of the Unix find command | ||
| 49 | ;; and one of the various Windows NT various scheduling utilities, | ||
| 50 | ;; for example the AT command from the NT Resource Kit, WinCron which is | ||
| 51 | ;; included with Microsoft FrontPage, or the shareware NTCron program. | ||
| 52 | ;; | ||
| 53 | ;; To set up a function which searches the files database, do something | ||
| 54 | ;; like this: | ||
| 55 | ;; | ||
| 56 | ;; (defvar locate-fcodes-file (concat my-home "/fcodes")) | ||
| 57 | ;; (defvar locate-make-command-line 'nt-locate-make-command-line) | ||
| 58 | ;; | ||
| 59 | ;; (defun nt-locate-make-command-line (arg) | ||
| 60 | ;; (cons "grep" | ||
| 61 | ;; (mapconcat 'identity | ||
| 62 | ;; (list "-i" arg locate-fcodes-file) | ||
| 63 | ;; " "))) | ||
| 64 | ;; | ||
| 65 | ;;;;;;;; ADVICE For dired-make-relative: ;;;;;;;;; | ||
| 66 | ;; | ||
| 67 | ;; For certain dired commands to work right, you should also include the | ||
| 68 | ;; following in your _emacs/.emacs: | ||
| 69 | ;; | ||
| 70 | ;; (defadvice dired-make-relative (before set-no-error activate) | ||
| 71 | ;; "For locate mode and Windows, don't return errors" | ||
| 72 | ;; (if (and (eq major-mode 'locate-mode) | ||
| 73 | ;; (memq system-type (list 'windows-nt 'ms-dos))) | ||
| 74 | ;; (ad-set-arg 2 t) | ||
| 75 | ;; )) | ||
| 76 | ;; | ||
| 77 | ;; Otherwise, dired-make-relative will give error messages like | ||
| 78 | ;; "FILENAME: not in directory tree growing at /" | ||
| 79 | |||
| 80 | ;;; Commentary: | ||
| 81 | ;; | ||
| 82 | ;; Locate.el provides an interface to a program which searches a | ||
| 83 | ;; database of file names. By default, this program is the GNU locate | ||
| 84 | ;; command, but it could also be the BSD-style find command, or even a | ||
| 85 | ;; user specified command. | ||
| 86 | ;; | ||
| 87 | ;; To use the BSD-style "fast find", or any other shell command of the | ||
| 88 | ;; form | ||
| 89 | ;; | ||
| 90 | ;; SHELLPROGRAM Name-to-find | ||
| 91 | ;; | ||
| 92 | ;; set the variable locate-command in your .emacs file. | ||
| 93 | ;; | ||
| 94 | ;; To use a more complicated expression, create a function which | ||
| 95 | ;; takes a string (the name to find) as input and returns a cons | ||
| 96 | ;; pair: the car should be the command to be executed, the cdr | ||
| 97 | ;; should be the arguments, concatenated into a string (including | ||
| 98 | ;; the name to find). Then do | ||
| 99 | ;; | ||
| 100 | ;; (setq locate-make-command-line 'my-locate-command-line) | ||
| 101 | ;; | ||
| 102 | ;; in your .emacs, using the name of your function in place of | ||
| 103 | ;; my-locate-command-line | ||
| 104 | ;; | ||
| 105 | ;; You should make sure that whichever command you use works correctly | ||
| 106 | ;; from a shell prompt. GNU locate and BSD find expect the file databases | ||
| 107 | ;; to either be in standard places or located via environment variables. | ||
| 108 | ;; If the latter, make sure these environment variables are set in | ||
| 109 | ;; your emacs process | ||
| 110 | ;; | ||
| 111 | ;; Locate-mode assumes that each line output from the locate-command | ||
| 112 | ;; consists exactly of a file name, possibly preceded or trailed by | ||
| 113 | ;; whitespace. If your file database has other information on the line (for | ||
| 114 | ;; example, the file size), you will need to redefine the function | ||
| 115 | ;; locate-get-file-positions to return a list consisting of the first | ||
| 116 | ;; character in the file name and the last character in the file name. | ||
| 117 | ;; | ||
| 118 | ;; To use locate-mode, simply type M-x locate and then the string | ||
| 119 | ;; you wish to find. You can use almost all of the dired commands in | ||
| 120 | ;; the resulting *Locate* buffer. It is worth noting that your commands | ||
| 121 | ;; do not, of course, affect the file database. For example, if you | ||
| 122 | ;; compress a file in the locate buffer, the actual file will be | ||
| 123 | ;; compressed, but the entry in the file database will not be | ||
| 124 | ;; affected. Consequently, the database and the filesystem will be out | ||
| 125 | ;; of sync until the next time the database is updated | ||
| 126 | ;; | ||
| 127 | ;; The command locate-with-filter keeps only lines matching a | ||
| 128 | ;; regular expression; this is often useful to constrain a big search. | ||
| 129 | ;; | ||
| 130 | |||
| 131 | ;;; Code: | ||
| 132 | |||
| 133 | (eval-when-compile | ||
| 134 | (require 'dired)) | ||
| 135 | |||
| 136 | ;; Variables | ||
| 137 | (defvar locate-command "locate" | ||
| 138 | "*The executable program used to search a database of files.") | ||
| 139 | |||
| 140 | (defvar locate-history-list nil | ||
| 141 | "The history list used by the \\[locate] command.") | ||
| 142 | |||
| 143 | (defvar locate-make-command-line 'locate-default-make-command-line | ||
| 144 | "*Function used to create the locate command line.") | ||
| 145 | |||
| 146 | (defvar locate-buffer-name "*Locate*" | ||
| 147 | "*Name of the buffer to show results from the \\[locate] command.") | ||
| 148 | |||
| 149 | (defvar locate-fcodes-file nil | ||
| 150 | "*Database of filenames.") | ||
| 151 | |||
| 152 | (defvar locate-mouse-face 'highlight | ||
| 153 | "*Face used to highlight locate entries.") | ||
| 154 | |||
| 155 | (defvar locate-header-face 'region | ||
| 156 | "*Face used to highlight the locate header.") | ||
| 157 | |||
| 158 | (defvar locate-current-filter nil) | ||
| 159 | |||
| 160 | ;; Functions | ||
| 161 | |||
| 162 | (defun locate-default-make-command-line (search-string) | ||
| 163 | (cons locate-command search-string)) | ||
| 164 | |||
| 165 | ;;;### autoload | ||
| 166 | (defun locate (search-string &optional filter) | ||
| 167 | "Run the \\[locate] command, putting results in `*Locate*' buffer." | ||
| 168 | (interactive | ||
| 169 | (list (read-from-minibuffer "Locate: " nil nil | ||
| 170 | nil 'locate-history-list))) | ||
| 171 | (let* ((pop-up-windows 1) | ||
| 172 | (locate-cmd-list (funcall locate-make-command-line search-string)) | ||
| 173 | (locate-cmd (car locate-cmd-list)) | ||
| 174 | (locate-cmd-args (cdr locate-cmd-list)) | ||
| 175 | (locate-proc) | ||
| 176 | ) | ||
| 177 | |||
| 178 | ;; Find the Locate buffer | ||
| 179 | (if (not (string-equal (buffer-name) locate-buffer-name)) | ||
| 180 | (switch-to-buffer-other-window locate-buffer-name)) | ||
| 181 | |||
| 182 | (locate-mode) | ||
| 183 | (erase-buffer) | ||
| 184 | |||
| 185 | (setq locate-current-filter filter) | ||
| 186 | |||
| 187 | (call-process locate-cmd nil t nil locate-cmd-args) | ||
| 188 | (if filter | ||
| 189 | (locate-filter-output filter)) | ||
| 190 | |||
| 191 | (locate-do-setup) | ||
| 192 | ) | ||
| 193 | ) | ||
| 194 | |||
| 195 | ;;;### autoload | ||
| 196 | (defun locate-with-filter (search-string filter) | ||
| 197 | "Run the locate command with a filter." | ||
| 198 | (interactive | ||
| 199 | (list (read-from-minibuffer "Locate: " nil nil | ||
| 200 | nil 'locate-history-list) | ||
| 201 | (read-from-minibuffer "Filter: " nil nil | ||
| 202 | nil 'grep-history))) | ||
| 203 | (locate search-string filter)) | ||
| 204 | |||
| 205 | (defun locate-filter-output (filter) | ||
| 206 | "Filter output from the locate command." | ||
| 207 | (goto-char (point-min)) | ||
| 208 | (delete-non-matching-lines (regexp-quote filter))) | ||
| 209 | |||
| 210 | (defvar locate-mode-map nil | ||
| 211 | "Local keymap for Locate mode buffers.") | ||
| 212 | (if locate-mode-map | ||
| 213 | nil | ||
| 214 | |||
| 215 | (require 'dired) | ||
| 216 | |||
| 217 | (setq locate-mode-map (copy-keymap dired-mode-map)) | ||
| 218 | |||
| 219 | ;; Undefine Useless Dired Menu bars | ||
| 220 | (define-key locate-mode-map [menu-bar Dired] 'undefined) | ||
| 221 | (define-key locate-mode-map [menu-bar subdir] 'undefined) | ||
| 222 | |||
| 223 | (define-key locate-mode-map [menu-bar mark executables] 'undefined) | ||
| 224 | (define-key locate-mode-map [menu-bar mark directory] 'undefined) | ||
| 225 | (define-key locate-mode-map [menu-bar mark directories] 'undefined) | ||
| 226 | (define-key locate-mode-map [menu-bar mark symlinks] 'undefined) | ||
| 227 | |||
| 228 | (define-key locate-mode-map [mouse-2] 'mouse-locate-view-file) | ||
| 229 | (define-key locate-mode-map "\C-ct" 'locate-tags) | ||
| 230 | |||
| 231 | (define-key locate-mode-map "U" 'dired-unmark-all-files-no-query) | ||
| 232 | ) | ||
| 233 | |||
| 234 | ;; This variable is used to indent the lines and then to search for | ||
| 235 | ;; the file name | ||
| 236 | (defconst locate-filename-indentation 4 | ||
| 237 | "The amount of indentation for each file.") | ||
| 238 | |||
| 239 | ;; 32 is the ASCII code for SPACE character | ||
| 240 | (defconst locate-indentation-string | ||
| 241 | (make-string locate-filename-indentation 32) | ||
| 242 | "The indentation string for each file.") | ||
| 243 | |||
| 244 | (defun locate-get-file-positions () | ||
| 245 | (save-excursion | ||
| 246 | (end-of-line) | ||
| 247 | (let ((eol (point))) | ||
| 248 | (beginning-of-line) | ||
| 249 | |||
| 250 | ;; Assumes names end at the end of the line | ||
| 251 | (forward-char locate-filename-indentation) | ||
| 252 | (list (point) eol)))) | ||
| 253 | |||
| 254 | ;; From SQL-mode | ||
| 255 | (defun current-line () | ||
| 256 | "Return the current line number, as an integer." | ||
| 257 | (interactive) | ||
| 258 | (+ (count-lines (point-min) (point)) | ||
| 259 | (if (eq (current-column) 0) | ||
| 260 | 1 | ||
| 261 | 0))) | ||
| 262 | |||
| 263 | (defun locate-get-filename () | ||
| 264 | (let ((pos (locate-get-file-positions)) | ||
| 265 | (lineno (current-line))) | ||
| 266 | (and (not (eq lineno 1)) | ||
| 267 | (not (eq lineno 2)) | ||
| 268 | (buffer-substring (elt pos 0) (elt pos 1))))) | ||
| 269 | |||
| 270 | (defun mouse-locate-view-file (event) | ||
| 271 | "In Locate mode, view a file, using the mouse." | ||
| 272 | (interactive "@e") | ||
| 273 | (save-excursion | ||
| 274 | (goto-char (posn-point (event-start event))) | ||
| 275 | (view-file (locate-get-filename)))) | ||
| 276 | |||
| 277 | ;; Define a mode for locate | ||
| 278 | ;; Default directory is set to "/" so that dired commands, which | ||
| 279 | ;; expect to be in a tree, will work properly | ||
| 280 | (defun locate-mode () | ||
| 281 | "Major mode for the `*Locate*' buffer made by \\[locate]." | ||
| 282 | (kill-all-local-variables) | ||
| 283 | (use-local-map locate-mode-map) | ||
| 284 | (setq major-mode 'locate-mode | ||
| 285 | mode-name "Locate" | ||
| 286 | default-directory "/" | ||
| 287 | dired-subdir-alist (list (cons "/" (point-min-marker)))) | ||
| 288 | (run-hooks 'locate-mode-hook)) | ||
| 289 | |||
| 290 | (defun locate-do-setup () | ||
| 291 | (let ((search-string (car locate-history-list))) | ||
| 292 | (goto-char (point-min)) | ||
| 293 | (save-excursion | ||
| 294 | |||
| 295 | ;; Nothing returned from locate command? | ||
| 296 | (if (eobp) | ||
| 297 | (progn | ||
| 298 | (kill-buffer locate-buffer-name) | ||
| 299 | (delete-window) | ||
| 300 | (if locate-current-filter | ||
| 301 | (error "Locate: no match for %s in database using filter %s" | ||
| 302 | search-string locate-current-filter) | ||
| 303 | (error "Locate: no match for %s in database" search-string)))) | ||
| 304 | |||
| 305 | (locate-insert-header search-string) | ||
| 306 | |||
| 307 | (while (progn | ||
| 308 | (locate-set-indentation) | ||
| 309 | (locate-set-properties) | ||
| 310 | (zerop (forward-line))))))) | ||
| 311 | |||
| 312 | (defun locate-set-indentation () | ||
| 313 | (save-excursion | ||
| 314 | (beginning-of-line) | ||
| 315 | (insert locate-indentation-string))) | ||
| 316 | |||
| 317 | (defun locate-set-properties () | ||
| 318 | (save-excursion | ||
| 319 | (let ((pos (locate-get-file-positions))) | ||
| 320 | (add-text-properties (elt pos 0) (elt pos 1) | ||
| 321 | (list 'mouse-face locate-mouse-face))))) | ||
| 322 | |||
| 323 | (defun locate-insert-header (search-string) | ||
| 324 | (let ((locate-format-string "Matches for %s") | ||
| 325 | (locate-regexp-match | ||
| 326 | (concat " *Matches for \\(" (regexp-quote search-string) "\\)")) | ||
| 327 | (locate-format-args (list search-string)) | ||
| 328 | ) | ||
| 329 | |||
| 330 | (if locate-fcodes-file | ||
| 331 | (setq locate-format-string | ||
| 332 | (concat locate-format-string " in %s") | ||
| 333 | locate-regexp-match | ||
| 334 | (concat locate-regexp-match | ||
| 335 | " in \\(" | ||
| 336 | (regexp-quote locate-fcodes-file) | ||
| 337 | "\\)") | ||
| 338 | locate-format-args | ||
| 339 | (append (list locate-fcodes-file) locate-format-args))) | ||
| 340 | |||
| 341 | (if locate-current-filter | ||
| 342 | (setq locate-format-string | ||
| 343 | (concat locate-format-string " using filter %s") | ||
| 344 | locate-regexp-match | ||
| 345 | (concat locate-regexp-match | ||
| 346 | " using filter " | ||
| 347 | "\\(" | ||
| 348 | (regexp-quote locate-current-filter) | ||
| 349 | "\\)") | ||
| 350 | locate-format-args | ||
| 351 | (append (list locate-current-filter) locate-format-args))) | ||
| 352 | |||
| 353 | (setq locate-format-string | ||
| 354 | (concat locate-format-string ": \n\n") | ||
| 355 | locate-regexp-match | ||
| 356 | (concat locate-regexp-match ": \n")) | ||
| 357 | |||
| 358 | (insert locate-indentation-string | ||
| 359 | (apply 'format locate-format-string (reverse locate-format-args))) | ||
| 360 | |||
| 361 | (save-excursion | ||
| 362 | (goto-char (point-min)) | ||
| 363 | (if (not (looking-at locate-regexp-match)) | ||
| 364 | nil | ||
| 365 | (add-text-properties (match-beginning 1) (match-end 1) | ||
| 366 | (list 'face locate-header-face)) | ||
| 367 | (and (match-beginning 2) | ||
| 368 | (add-text-properties (match-beginning 2) (match-end 2) | ||
| 369 | (list 'face locate-header-face))) | ||
| 370 | (and (match-beginning 3) | ||
| 371 | (add-text-properties (match-beginning 3) (match-end 3) | ||
| 372 | (list 'face locate-header-face))) | ||
| 373 | )))) | ||
| 374 | |||
| 375 | (defun locate-tags () | ||
| 376 | "Visit a tags table in `*Locate*' mode." | ||
| 377 | (interactive) | ||
| 378 | (let ((tags-table (locate-get-filename))) | ||
| 379 | (if (y-or-n-p (format "Visit tags table %s? " tags-table)) | ||
| 380 | (visit-tags-table tags-table) | ||
| 381 | nil))) | ||
| 382 | |||
| 383 | (provide 'locate) | ||
| 384 | |||
| 385 | ;;; locate.el ends here | ||