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.

308 lines
12 KiB

4 years ago
  1. ;;; helm-for-files.el --- helm-for-files and related. -*- 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. (require 'helm-bookmark)
  17. (defcustom helm-multi-files-toggle-locate-binding "C-c p"
  18. "Default binding to switch back and forth locate in `helm-multi-files'."
  19. :group 'helm-files
  20. :type 'string)
  21. (defcustom helm-for-files-preferred-list
  22. '(helm-source-buffers-list
  23. helm-source-recentf
  24. helm-source-bookmarks
  25. helm-source-file-cache
  26. helm-source-files-in-current-dir
  27. helm-source-locate)
  28. "Your preferred sources for `helm-for-files' and `helm-multi-files'.
  29. When adding a source here it is up to you to ensure the library of
  30. this source is accessible and properly loaded."
  31. :type '(repeat (choice symbol))
  32. :group 'helm-files)
  33. (defcustom helm-for-files-tramp-not-fancy t
  34. "Colorize remote files when non nil.
  35. Be aware that a nil value will make tramp display very slow."
  36. :group 'helm-files
  37. :type 'boolean)
  38. ;;; File Cache
  39. ;;
  40. ;;
  41. (defvar file-cache-alist)
  42. (defclass helm-file-cache (helm-source-in-buffer helm-type-file)
  43. ((init :initform (lambda () (require 'filecache)))))
  44. (defun helm-file-cache-get-candidates ()
  45. (cl-loop for item in file-cache-alist append
  46. (cl-destructuring-bind (base &rest dirs) item
  47. (cl-loop for dir in dirs collect
  48. (concat dir base)))))
  49. (defvar helm-source-file-cache nil)
  50. (defcustom helm-file-cache-fuzzy-match nil
  51. "Enable fuzzy matching in `helm-source-file-cache' when non--nil."
  52. :group 'helm-files
  53. :type 'boolean
  54. :set (lambda (var val)
  55. (set var val)
  56. (setq helm-source-file-cache
  57. (helm-make-source "File Cache" 'helm-file-cache
  58. :fuzzy-match helm-file-cache-fuzzy-match
  59. :data 'helm-file-cache-get-candidates))))
  60. (cl-defun helm-file-cache-add-directory-recursively
  61. (dir &optional match (ignore-dirs t))
  62. (require 'filecache)
  63. (cl-loop for f in (helm-walk-directory
  64. dir
  65. :path 'full
  66. :directories nil
  67. :match match
  68. :skip-subdirs ignore-dirs)
  69. do (file-cache-add-file f)))
  70. (defun helm-transform-file-cache (actions _candidate)
  71. (let ((source (helm-get-current-source)))
  72. (if (string= (assoc-default 'name source) "File Cache")
  73. (append actions
  74. '(("Remove marked files from file-cache"
  75. . helm-ff-file-cache-remove-file)))
  76. actions)))
  77. ;;; Recentf files
  78. ;;
  79. ;;
  80. (defvar helm-recentf--basename-flag nil)
  81. (defun helm-recentf-pattern-transformer (pattern)
  82. (let ((pattern-no-flag (replace-regexp-in-string " -b" "" pattern)))
  83. (cond ((and (string-match " " pattern-no-flag)
  84. (string-match " -b\\'" pattern))
  85. (setq helm-recentf--basename-flag t)
  86. pattern-no-flag)
  87. ((string-match "\\([^ ]*\\) -b\\'" pattern)
  88. (prog1 (match-string 1 pattern)
  89. (setq helm-recentf--basename-flag t)))
  90. (t (setq helm-recentf--basename-flag nil)
  91. pattern))))
  92. (defcustom helm-turn-on-recentf t
  93. "Automatically turn on `recentf-mode' when non-nil."
  94. :group 'helm-files
  95. :type 'boolean)
  96. (defclass helm-recentf-source (helm-source-sync helm-type-file)
  97. ((init :initform (lambda ()
  98. (require 'recentf)
  99. (when helm-turn-on-recentf (recentf-mode 1))))
  100. (candidates :initform (lambda () recentf-list))
  101. (pattern-transformer :initform 'helm-recentf-pattern-transformer)
  102. (match-part :initform (lambda (candidate)
  103. (if (or helm-ff-transformer-show-only-basename
  104. helm-recentf--basename-flag)
  105. (helm-basename candidate) candidate)))
  106. (migemo :initform t)
  107. (persistent-action :initform 'helm-ff-kill-or-find-buffer-fname)))
  108. (defmethod helm--setup-source :after ((source helm-recentf-source))
  109. (setf (slot-value source 'action)
  110. (append (symbol-value (helm-actions-from-type-file))
  111. '(("Delete file(s) from recentf" .
  112. (lambda (_candidate)
  113. (cl-loop for file in (helm-marked-candidates)
  114. do (setq recentf-list (delete file recentf-list)))))))))
  115. (defvar helm-source-recentf nil
  116. "See (info \"(emacs)File Conveniences\").
  117. Set `recentf-max-saved-items' to a bigger value if default is too small.")
  118. (defcustom helm-recentf-fuzzy-match nil
  119. "Enable fuzzy matching in `helm-source-recentf' when non--nil."
  120. :group 'helm-files
  121. :type 'boolean
  122. :set (lambda (var val)
  123. (set var val)
  124. (let ((helm-fuzzy-sort-fn 'helm-fuzzy-matching-sort-fn-preserve-ties-order))
  125. (setq helm-source-recentf
  126. (helm-make-source "Recentf" 'helm-recentf-source
  127. :fuzzy-match helm-recentf-fuzzy-match)))))
  128. ;;; Files in current dir
  129. ;;
  130. ;;
  131. (defun helm-highlight-files (files _source)
  132. "A basic transformer for helm files sources.
  133. Colorize only symlinks, directories and files."
  134. (cl-loop with mp-fn = (or (assoc-default
  135. 'match-part (helm-get-current-source))
  136. 'identity)
  137. for i in files
  138. for disp = (if (and helm-ff-transformer-show-only-basename
  139. (not (helm-dir-is-dot i))
  140. (not (and helm--url-regexp
  141. (string-match helm--url-regexp i)))
  142. (not (string-match helm-ff-url-regexp i)))
  143. (helm-basename i) (abbreviate-file-name i))
  144. for isremote = (or (file-remote-p i)
  145. (helm-file-on-mounted-network-p i))
  146. ;; Call file-attributes only if:
  147. ;; - file is not remote
  148. ;; - helm-for-files--tramp-not-fancy is nil and file is remote AND
  149. ;; connected. (Issue #1679)
  150. for type = (and (or (null isremote)
  151. (and (null helm-for-files-tramp-not-fancy)
  152. (file-remote-p i nil t)))
  153. (car (file-attributes i)))
  154. collect
  155. (cond ((and (null type) isremote) (cons disp i))
  156. ((stringp type)
  157. (cons (propertize disp
  158. 'face 'helm-ff-symlink
  159. 'match-part (funcall mp-fn disp)
  160. 'help-echo (expand-file-name i))
  161. i))
  162. ((eq type t)
  163. (cons (propertize disp
  164. 'face 'helm-ff-directory
  165. 'match-part (funcall mp-fn disp)
  166. 'help-echo (expand-file-name i))
  167. i))
  168. (t (cons (propertize disp
  169. 'face 'helm-ff-file
  170. 'match-part (funcall mp-fn disp)
  171. 'help-echo (expand-file-name i))
  172. i)))))
  173. (defclass helm-files-in-current-dir-source (helm-source-sync helm-type-file)
  174. ((candidates :initform (lambda ()
  175. (with-helm-current-buffer
  176. (let ((dir (helm-current-directory)))
  177. (when (file-accessible-directory-p dir)
  178. (directory-files dir t))))))
  179. (pattern-transformer :initform 'helm-recentf-pattern-transformer)
  180. (match-part :initform (lambda (candidate)
  181. (if (or helm-ff-transformer-show-only-basename
  182. helm-recentf--basename-flag)
  183. (helm-basename candidate) candidate)))
  184. (fuzzy-match :initform t)
  185. (migemo :initform t)))
  186. (defvar helm-source-files-in-current-dir
  187. (helm-make-source "Files from Current Directory"
  188. 'helm-files-in-current-dir-source))
  189. ;;;###autoload
  190. (defun helm-for-files ()
  191. "Preconfigured `helm' for opening files.
  192. Run all sources defined in `helm-for-files-preferred-list'."
  193. (interactive)
  194. (require 'helm-x-files)
  195. (unless helm-source-buffers-list
  196. (setq helm-source-buffers-list
  197. (helm-make-source "Buffers" 'helm-source-buffers)))
  198. (helm :sources helm-for-files-preferred-list
  199. :ff-transformer-show-only-basename nil
  200. :buffer "*helm for files*"
  201. :truncate-lines helm-buffers-truncate-lines))
  202. (defun helm-multi-files-toggle-to-locate ()
  203. (interactive)
  204. (with-helm-alive-p
  205. (with-helm-buffer
  206. (if (setq helm-multi-files--toggle-locate
  207. (not helm-multi-files--toggle-locate))
  208. (progn
  209. (helm-set-sources (unless (memq 'helm-source-locate
  210. helm-sources)
  211. (cons 'helm-source-locate helm-sources)))
  212. (helm-set-source-filter '(helm-source-locate)))
  213. (helm-kill-async-processes)
  214. (helm-set-sources (remove 'helm-source-locate
  215. helm-for-files-preferred-list))
  216. (helm-set-source-filter nil)))))
  217. (put 'helm-multi-files-toggle-to-locate 'helm-only t)
  218. ;;;###autoload
  219. (defun helm-multi-files ()
  220. "Preconfigured helm like `helm-for-files' but running locate only on demand.
  221. Allow toggling back and forth from locate to others sources with
  222. `helm-multi-files-toggle-locate-binding' key.
  223. This avoid launching needlessly locate when what you search is already
  224. found."
  225. (interactive)
  226. (require 'helm-x-files)
  227. (unless helm-source-buffers-list
  228. (setq helm-source-buffers-list
  229. (helm-make-source "Buffers" 'helm-source-buffers)))
  230. (setq helm-multi-files--toggle-locate nil)
  231. (helm-locate-set-command)
  232. (helm-set-local-variable 'helm-async-outer-limit-hook
  233. (list (lambda ()
  234. (when (and helm-locate-fuzzy-match
  235. (not (string-match-p
  236. "\\s-" helm-pattern)))
  237. (helm-redisplay-buffer)))))
  238. (let ((sources (remove 'helm-source-locate helm-for-files-preferred-list))
  239. (helm-locate-command
  240. (if helm-locate-fuzzy-match
  241. (unless (string-match-p "\\`locate -b" helm-locate-command)
  242. (replace-regexp-in-string
  243. "\\`locate" "locate -b" helm-locate-command))
  244. helm-locate-command))
  245. (old-key (lookup-key
  246. helm-map
  247. (read-kbd-macro helm-multi-files-toggle-locate-binding))))
  248. (with-helm-temp-hook 'helm-after-initialize-hook
  249. (define-key helm-map (kbd helm-multi-files-toggle-locate-binding)
  250. 'helm-multi-files-toggle-to-locate))
  251. (unwind-protect
  252. (helm :sources sources
  253. :ff-transformer-show-only-basename nil
  254. :buffer "*helm multi files*"
  255. :truncate-lines helm-buffers-truncate-lines)
  256. (define-key helm-map (kbd helm-multi-files-toggle-locate-binding)
  257. old-key))))
  258. ;;;###autoload
  259. (defun helm-recentf ()
  260. "Preconfigured `helm' for `recentf'."
  261. (interactive)
  262. (helm :sources 'helm-source-recentf
  263. :ff-transformer-show-only-basename nil
  264. :buffer "*helm recentf*"))
  265. (provide 'helm-for-files)
  266. ;; Local Variables:
  267. ;; byte-compile-warnings: (not obsolete)
  268. ;; coding: utf-8
  269. ;; indent-tabs-mode: nil
  270. ;; End:
  271. ;;; helm-for-files.el ends here