+\f
+;; Search only in file names in the Dired buffer.
+
+(defcustom dired-isearch-filenames nil
+ "Non-nil to Isearch in file names only.
+If t, Isearch in Dired always matches only file names.
+If `dwim', Isearch matches file names when initial point position is on
+a file name. Otherwise, it searches the whole buffer without restrictions."
+ :type '(choice (const :tag "No restrictions" nil)
+ (const :tag "When point is on a file name initially, search file names" dwim)
+ (const :tag "Always search in file names" t))
+ :group 'dired
+ :version "23.1")
+
+(defvar dired-isearch-filter-predicate-orig nil)
+
+(defun dired-isearch-filenames-toggle ()
+ "Toggle file names searching on or off.
+When on, Isearch skips matches outside file names using the predicate
+`dired-isearch-filter-filenames' that matches only at file names.
+When off, it uses the original predicate."
+ (interactive)
+ (setq isearch-filter-predicate
+ (if (eq isearch-filter-predicate 'dired-isearch-filter-filenames)
+ dired-isearch-filter-predicate-orig
+ 'dired-isearch-filter-filenames))
+ (setq isearch-success t isearch-adjusted t)
+ (isearch-update))
+
+;;;###autoload
+(defun dired-isearch-filenames-setup ()
+ "Set up isearch to search in Dired file names.
+Intended to be added to `isearch-mode-hook'."
+ (when (or (eq dired-isearch-filenames t)
+ (and (eq dired-isearch-filenames 'dwim)
+ (get-text-property (point) 'dired-filename)))
+ (setq isearch-message-prefix-add "filename ")
+ (define-key isearch-mode-map "\M-sf" 'dired-isearch-filenames-toggle)
+ (setq dired-isearch-filter-predicate-orig
+ (default-value 'isearch-filter-predicate))
+ (setq-default isearch-filter-predicate 'dired-isearch-filter-filenames)
+ (add-hook 'isearch-mode-end-hook 'dired-isearch-filenames-end nil t)))
+
+(defun dired-isearch-filenames-end ()
+ "Clean up the Dired file name search after terminating isearch."
+ (setq isearch-message-prefix-add nil)
+ (define-key isearch-mode-map "\M-sf" nil)
+ (setq-default isearch-filter-predicate dired-isearch-filter-predicate-orig)
+ (remove-hook 'isearch-mode-end-hook 'dired-isearch-filenames-end t))
+
+(defun dired-isearch-filter-filenames (beg end)
+ "Test whether the current search hit is a visible file name.
+Return non-nil if the text from BEG to END is part of a file
+name (has the text property `dired-filename') and is visible."
+ (and (isearch-filter-visible beg end)
+ (if dired-isearch-filenames
+ (text-property-not-all (min beg end) (max beg end)
+ 'dired-filename nil)
+ t)))
+
+;;;###autoload
+(defun dired-isearch-filenames ()
+ "Search for a string using Isearch only in file names in the Dired buffer."
+ (interactive)
+ (let ((dired-isearch-filenames t))
+ (isearch-forward)))
+
+;;;###autoload
+(defun dired-isearch-filenames-regexp ()
+ "Search for a regexp using Isearch only in file names in the Dired buffer."
+ (interactive)
+ (let ((dired-isearch-filenames t))
+ (isearch-forward-regexp)))
+