emacs/org/elpa/helm-20220423.1712/helm-find.el

171 lines
6.6 KiB
EmacsLisp
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; helm-find.el --- helm interface for find command. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2021 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program 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 3 of the License, or
;; (at your option) any later version.
;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'helm-files)
(require 'helm-external)
(defcustom helm-findutils-skip-boring-files t
"Ignore boring files in find command results."
:group 'helm-files
:type 'boolean)
(defcustom helm-findutils-search-full-path nil
"Search in full path with shell command find when non-nil.
I.e. use the -path/ipath arguments of find instead of
-name/iname."
:group 'helm-files
:type 'boolean)
(defcustom helm-find-noerrors nil
"Prevent showing error messages in helm buffer when non nil."
:group 'helm-files
:type 'boolean)
(defvar helm-find-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-generic-files-map)
(define-key map (kbd "DEL") 'helm-delete-backward-no-update)
map))
(defvar helm-source-findutils
(helm-build-async-source "Find"
:header-name (lambda (name)
(concat name " in [" (helm-default-directory) "]"))
:candidates-process 'helm-find-shell-command-fn
:filtered-candidate-transformer 'helm-findutils-transformer
:action-transformer 'helm-transform-file-load-el
:persistent-action 'helm-ff-kill-or-find-buffer-fname
:action 'helm-type-file-actions
:help-message 'helm-generic-file-help-message
:keymap helm-find-map
:candidate-number-limit 9999
:requires-pattern 3))
(defun helm-findutils-transformer (candidates _source)
(let (non-essential
(default-directory (helm-default-directory)))
(cl-loop for i in candidates
for abs = (expand-file-name
(helm-aif (file-remote-p default-directory)
(concat it i) i))
for type = (car (file-attributes abs))
for disp = (if (and helm-ff-transformer-show-only-basename
(not (string-match "[.]\\{1,2\\}$" i)))
(helm-basename abs) abs)
collect (cond ((eq t type)
(cons (propertize disp 'face 'helm-ff-directory)
abs))
((stringp type)
(cons (propertize disp 'face 'helm-ff-symlink)
abs))
(t (cons (propertize disp 'face 'helm-ff-file)
abs))))))
(defun helm-find--build-cmd-line ()
(require 'find-cmd)
(let* ((default-directory (or (file-remote-p default-directory 'localname)
default-directory))
(patterns+options (split-string helm-pattern "\\(\\`\\| +\\)\\* +"))
(fold-case (helm-set-case-fold-search (car patterns+options)))
(patterns (split-string (car patterns+options)))
(additional-options (and (cdr patterns+options)
(list (concat (cadr patterns+options) " "))))
(ignored-dirs ())
(ignored-files (when helm-findutils-skip-boring-files
(cl-loop for f in completion-ignored-extensions
if (string-match "/$" f)
do (push (replace-match "" nil t f)
ignored-dirs)
else collect (concat "*" f))))
(path-or-name (if helm-findutils-search-full-path
'(ipath path) '(iname name)))
(name-or-iname (if fold-case
(car path-or-name) (cadr path-or-name))))
(find-cmd (and ignored-dirs
`(prune (name ,@ignored-dirs)))
(and ignored-files
`(not (name ,@ignored-files)))
`(and ,@(mapcar
(lambda (pattern)
`(,name-or-iname ,(concat "*" pattern "*")))
patterns)
,@additional-options))))
(defun helm-find-shell-command-fn ()
"Asynchronously fetch candidates for `helm-find'.
Additional find options can be specified after a \"*\"
separator."
(let* (process-connection-type
non-essential
(cmd (concat (helm-find--build-cmd-line)
(if helm-find-noerrors "2> /dev/null" "")))
(proc (start-file-process-shell-command "hfind" helm-buffer cmd)))
(helm-log "Find command:\n%s" cmd)
(prog1 proc
(set-process-sentinel
proc
(lambda (process event)
(helm-process-deferred-sentinel-hook
process event (helm-default-directory))
(if (string= event "finished\n")
(helm-locate-update-mode-line "Find")
(helm-log "Error: Find %s"
(replace-regexp-in-string "\n" "" event))))))))
(defun helm-find-1 (dir)
(let ((default-directory (file-name-as-directory dir)))
(helm :sources 'helm-source-findutils
:buffer "*helm find*"
:ff-transformer-show-only-basename nil
:case-fold-search helm-file-name-case-fold-search)))
;;; Preconfigured commands
;;
;;
;;;###autoload
(defun helm-find (arg)
"Preconfigured `helm' for the find shell command.
Recursively find files whose names are matched by all specified
globbing PATTERNs under the current directory using the external
program specified in `find-program' (usually \"find\"). Every
input PATTERN is silently wrapped into two stars: *PATTERN*.
With prefix argument, prompt for a directory to search.
When user option `helm-findutils-search-full-path' is non-nil,
match against complete paths, otherwise, against file names
without directory part.
The (possibly empty) list of globbing PATTERNs can be followed by
the separator \"*\" plus any number of additional arguments that
are passed to \"find\" literally."
(interactive "P")
(let ((directory
(if arg
(file-name-as-directory
(read-directory-name "DefaultDirectory: "))
default-directory)))
(helm-find-1 directory)))
(provide 'helm-find)
;;; helm-find.el ends here