Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 line
6.7 KiB

5 年之前
  1. ;;; helm-find.el --- helm interface for find command. -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2012 ~ 2019 Thierry Volpiatto <thierry.volpiatto@gmail.com>
  3. ;; This program is free software; you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation, either version 3 of the License, or
  6. ;; (at your option) any later version.
  7. ;; This program is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. ;; GNU General Public License for more details.
  11. ;; You should have received a copy of the GNU General Public License
  12. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ;;; Code:
  14. (require 'helm-files)
  15. (require 'helm-external)
  16. (defcustom helm-findutils-skip-boring-files t
  17. "Ignore boring files in find command results."
  18. :group 'helm-files
  19. :type 'boolean)
  20. (defcustom helm-findutils-search-full-path nil
  21. "Search in full path with shell command find when non--nil.
  22. I.e use the -path/ipath arguments of find instead of -name/iname."
  23. :group 'helm-files
  24. :type 'boolean)
  25. (defcustom helm-find-noerrors nil
  26. "Prevent showing error messages in helm buffer when non nil."
  27. :group 'helm-files
  28. :type 'boolean)
  29. (defvar helm-find-map
  30. (let ((map (make-sparse-keymap)))
  31. (set-keymap-parent map helm-generic-files-map)
  32. (define-key map (kbd "DEL") 'helm-delete-backward-no-update)
  33. map))
  34. (defvar helm-source-findutils
  35. (helm-build-async-source "Find"
  36. :header-name (lambda (name)
  37. (concat name " in [" (helm-default-directory) "]"))
  38. :candidates-process 'helm-find-shell-command-fn
  39. :filtered-candidate-transformer 'helm-findutils-transformer
  40. :action-transformer 'helm-transform-file-load-el
  41. :persistent-action 'helm-ff-kill-or-find-buffer-fname
  42. :action 'helm-type-file-actions
  43. :help-message 'helm-generic-file-help-message
  44. :keymap helm-find-map
  45. :candidate-number-limit 9999
  46. :requires-pattern 3))
  47. (defun helm-findutils-transformer (candidates _source)
  48. (let (non-essential
  49. (default-directory (helm-default-directory)))
  50. (cl-loop for i in candidates
  51. for abs = (expand-file-name
  52. (helm-aif (file-remote-p default-directory)
  53. (concat it i) i))
  54. for type = (car (file-attributes abs))
  55. for disp = (if (and helm-ff-transformer-show-only-basename
  56. (not (string-match "[.]\\{1,2\\}$" i)))
  57. (helm-basename abs) abs)
  58. collect (cond ((eq t type)
  59. (cons (propertize disp 'face 'helm-ff-directory)
  60. abs))
  61. ((stringp type)
  62. (cons (propertize disp 'face 'helm-ff-symlink)
  63. abs))
  64. (t (cons (propertize disp 'face 'helm-ff-file)
  65. abs))))))
  66. (defun helm-find--build-cmd-line ()
  67. (require 'find-cmd)
  68. (let* ((default-directory (or (file-remote-p default-directory 'localname)
  69. default-directory))
  70. (patterns+options (split-string helm-pattern "\\(\\`\\| +\\)\\* +"))
  71. (fold-case (helm-set-case-fold-search (car patterns+options)))
  72. (patterns (split-string (car patterns+options)))
  73. (additional-options (and (cdr patterns+options)
  74. (list (concat (cadr patterns+options) " "))))
  75. (ignored-dirs ())
  76. (ignored-files (when helm-findutils-skip-boring-files
  77. (cl-loop for f in completion-ignored-extensions
  78. if (string-match "/$" f)
  79. do (push (replace-match "" nil t f)
  80. ignored-dirs)
  81. else collect (concat "*" f))))
  82. (path-or-name (if helm-findutils-search-full-path
  83. '(ipath path) '(iname name)))
  84. (name-or-iname (if fold-case
  85. (car path-or-name) (cadr path-or-name))))
  86. (find-cmd (and ignored-dirs
  87. `(prune (name ,@ignored-dirs)))
  88. (and ignored-files
  89. `(not (name ,@ignored-files)))
  90. `(and ,@(mapcar
  91. (lambda (pattern)
  92. `(,name-or-iname ,(concat "*" pattern "*")))
  93. patterns)
  94. ,@additional-options))))
  95. (defun helm-find-shell-command-fn ()
  96. "Asynchronously fetch candidates for `helm-find'.
  97. Additional find options can be specified after a \"*\"
  98. separator."
  99. (let* (process-connection-type
  100. non-essential
  101. (cmd (concat (helm-find--build-cmd-line)
  102. (if helm-find-noerrors "2> /dev/null" "")))
  103. (proc (start-file-process-shell-command "hfind" helm-buffer cmd)))
  104. (helm-log "Find command:\n%s" cmd)
  105. (prog1 proc
  106. (set-process-sentinel
  107. proc
  108. (lambda (process event)
  109. (helm-process-deferred-sentinel-hook
  110. process event (helm-default-directory))
  111. (if (string= event "finished\n")
  112. (helm-locate-update-mode-line "Find")
  113. (helm-log "Error: Find %s"
  114. (replace-regexp-in-string "\n" "" event))))))))
  115. (defun helm-find-1 (dir)
  116. (let ((default-directory (file-name-as-directory dir)))
  117. (helm :sources 'helm-source-findutils
  118. :buffer "*helm find*"
  119. :ff-transformer-show-only-basename nil
  120. :case-fold-search helm-file-name-case-fold-search)))
  121. ;;; Preconfigured commands
  122. ;;
  123. ;;
  124. ;;;###autoload
  125. (defun helm-find (arg)
  126. "Preconfigured `helm' for the find shell command.
  127. Recursively find files whose names are matched by all specified
  128. globbing PATTERNs under the current directory using the external
  129. program specified in `find-program' (usually \"find\"). Every
  130. input PATTERN is silently wrapped into two stars: *PATTERN*.
  131. With prefix argument, prompt for a directory to search.
  132. When user option `helm-findutils-search-full-path' is non-nil,
  133. match against complete paths, otherwise, against file names
  134. without directory part.
  135. The (possibly empty) list of globbing PATTERNs can be followed by
  136. the separator \"*\" plus any number of additional arguments that
  137. are passed to \"find\" literally."
  138. (interactive "P")
  139. (let ((directory
  140. (if arg
  141. (file-name-as-directory
  142. (read-directory-name "DefaultDirectory: "))
  143. default-directory)))
  144. (helm-find-1 directory)))
  145. (provide 'helm-find)
  146. ;; Local Variables:
  147. ;; byte-compile-warnings: (not obsolete)
  148. ;; coding: utf-8
  149. ;; indent-tabs-mode: nil
  150. ;; End:
  151. ;;; helm-find.el ends here