mirror of https://github.com/Chizi123/.emacs.d.git

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