gnu-emacs-sources
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: globalff.el --- Global find file


From: spamfilteraccount
Subject: Re: globalff.el --- Global find file
Date: 9 Mar 2006 02:54:44 -0800
User-agent: G2/0.2

Here's new version which doesn't use electric, so the pattern editing
is more natural.

;;; globalff.el --- Global find file

;; Copyright (C) 2006  Free Software Foundation, Inc.

;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;;; Commentary:

;; Start with M-x globallff and type in any substring of any path on
;; your system to display the matching files. The displayed list is
;; updated dynamically as you type more characters or delete some.
;;
;; Needs an up-to-date locate database for file name searching.
;;
;; Since the searching is based on locate you can use any globbing
;; characters allowed by the locate command.
;;
;; You can move up/down the list with the cursor keys (I know these
;; bindings are not very Emacsian, but I happen to like them) and
;; select a file to open with Enter.
;;
;; You can quit with C-g.
;;

;;; Code:

;;
;; User configurable variables
;;

(defvar globalff-databases nil
  "List of database files separated with colon to be used by the locate
command.
If nil then the system default database is used.")

(defvar globalff-minimum-input-length 3
  "The minimum number of characters needed to start file searching.")

(defvar globalff-search-delay 0.5
  "Idle time after last input event, before starting the search.")

(defvar globalff-idle-timer nil
  "Idle timer for monitoring typed characters.")

(defconst globalff-buffer "*globalff*"
  "Buffer used for finding files.")

(defvar globalff-previous-input ""
  "The previous input substring used for searching.")

(defvar globalff-overlay nil
  "Overlay used to highlight the current selection.")


(defun globalff-output-filter (process string)
  "Avoid moving of point if the buffer is empty."
  (with-current-buffer globalff-buffer
    (let* ((empty (= (buffer-size) 0))
           (moving (and (not empty)
                        (= (point) (process-mark process)))))
      (save-excursion
        ;; Insert the text, advancing the process marker.
        (goto-char (process-mark process))
        (insert string)
        (set-marker (process-mark process) (point)))

      (if empty
          (globalff-mark-current-line))

      (if moving (goto-char (process-mark process))))))


(defun globalff-mark-current-line ()
  "Mark current line with a distinctive color."
  (setq globalff-overlay (make-overlay (point-at-bol) (point-at-eol)))
  (overlay-put globalff-overlay 'face 'region))



(defun globalff-previous-line ()
  "Move mark to the previous line."
  (interactive)
  (unless (with-current-buffer globalff-buffer
            (= (point-min) (line-beginning-position)))
    (globalff-move-mark -1)))


(defun globalff-next-line ()
  "Move mark to the next line."
  (interactive)
  (unless (with-current-buffer globalff-buffer
            (save-excursion
              (forward-line)
              (eobp)))
    (globalff-move-mark +1)))


(defun globalff-move-mark (direction)
  (let ((old-window (selected-window)))
    (select-window (get-buffer-window globalff-buffer))

    (when globalff-overlay
      (delete-overlay globalff-overlay))
    (next-line direction)
    (globalff-mark-current-line)

    (select-window old-window)))


(defun globalff-process-sentinel (process event)
  "Prevent printing of process status messages into the output buffer."
  )


(defun globalff-check-input ()
  "Check input string and start/stop search if necessary."
  (let ((input (minibuffer-contents)))
    (unless (equal input globalff-previous-input)
    (setq globalff-previous-input input)

    (globalff-kill-process)
    (with-current-buffer globalff-buffer
      (erase-buffer))
    (setq globalff-overlay nil)

    (unless (or (equal input "")
                (< (length input) globalff-minimum-input-length))
      (let ((process (start-process "globalff-process" globalff-buffer
                                    "locate"
                                    (if globalff-databases
                                        (concat "--database="
globalff-databases)
                                      ;; -i is used as a placeholder
                                      ;; since I don't know how to
                                      ;; skip an argument
                                      "-i")
                                    "-i"
                                    input)))
        (set-process-filter process 'globalff-output-filter)
        (set-process-sentinel process 'globalff-process-sentinel))))))


(defun globalff-kill-process ()
  "Kill find process."
  (if (eq 'run (process-status globalff-buffer))
      (delete-process globalff-buffer)))


(defun globalff ()
  "Start global find file."
  (interactive)
  (let ((winconfig (current-window-configuration)))
    (pop-to-buffer globalff-buffer)
    (erase-buffer)

    (setq globalff-overlay nil)
    (setq globalff-previous-input "")
    (setq globalff-idle-timer
          (run-with-idle-timer globalff-search-delay t
'globalff-check-input))

    (define-key minibuffer-local-map (kbd "<down>")
'globalff-next-line)
    (define-key minibuffer-local-map (kbd "<up>")
'globalff-previous-line)

    (with-current-buffer globalff-buffer
      (setq cursor-type nil))

    (unwind-protect
        (read-string "substring: ")

      (define-key minibuffer-local-map (kbd "<down>")
'next-history-element)
      (define-key minibuffer-local-map (kbd "<up>")
'previous-history-element)

      (globalff-kill-process)
      (cancel-timer globalff-idle-timer)

      (with-current-buffer globalff-buffer
        (setq cursor-type t))

      (set-window-configuration winconfig)))

  (unless (= (buffer-size (get-buffer globalff-buffer)) 0)
    (assert globalff-overlay)
    (find-file
     (with-current-buffer globalff-buffer
       (buffer-substring-no-properties (overlay-start globalff-overlay)
                                       (overlay-end
globalff-overlay))))))
 
 
(provide 'globalff)
;;; globalff.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]