· 7 years ago · Oct 18, 2018, 08:02 AM
1;;; anything-c-yasnippet.el --- anything config for yasnippet.el
2
3;; Author: Kenji.I (Kenji Imakado) <ken.imakaado@gmail.com>
4;; Version: 0.6.1
5;; Keywords: anything yasnippet
6
7;; This file is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 2, or (at your option)
10;; any later version.
11
12;; This file is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs; see the file COPYING. If not, write to the
19;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20;; Boston, MA 02110-1301, USA.
21
22;;; Commentary:
23;; thans to grandVin for patch on his blog.
24
25;; anything-source name => anything-c-source-yasnippet
26;;
27;; Actions: Insert snippet, Open snippet file, Open snippet file other window
28;; C-z: execute-persistent-action
29
30;;; Changelog:
31;; 2010/11/23 fixed bug on yasnippet 0.7.0
32;; **edited by myuhe
33
34
35;;; Commands:
36;;
37;; Below are complete command list:
38;;
39;; `anything-c-yas-complete'
40;; List of yasnippet snippets using `anything' interface.
41;; `anything-c-yas-create-snippet-on-region'
42;; Create a snippet from region.
43;;
44;;; Customizable Options:
45;;
46;; Below are customizable option list:
47;;
48;; `anything-c-yas-not-display-dups'
49;; if non-nil not display duplicate snippet otherwise display all snippet
50;; default = t
51;; `anything-c-yas-display-msg-after-complete'
52;; if non-nil display snippet key message in minibuffer after Complete
53;; default = t
54;; `anything-c-yas-snippets-dir-list'
55;; list of directory used to find snippet file
56;; default = nil
57;; `anything-c-yas-space-match-any-greedy'
58;; if non-nil anything pattern space match anyword greedy.
59;; default = nil
60;; `anything-c-yas-display-key-on-candidate'
61;; if non-nil anything display candidate(snippet name) include key
62;; default = nil
63
64;; here's my yasnippet's configuration
65;; (require 'yasnippet)
66;; (require 'anything-c-yasnippet)
67;; (setq anything-c-yas-space-match-any-greedy t) ;[default: nil]
68;; (global-set-key (kbd "C-c y") 'anything-c-yas-complete)
69;; (yas/initialize)
70;; (yas/load-directory "<path>/<to>/snippets/")
71;; (add-to-list 'yas/extra-mode-hooks 'ruby-mode-hook)
72;; (add-to-list 'yas/extra-mode-hooks 'cperl-mode-hook)
73
74(require 'cl)
75(require 'anything)
76(require 'yasnippet)
77
78;;; Code
79(defvar anything-c-yas-version "0.6" "Version of anything-c-yasnippet")
80
81(defgroup anything-c-yasnippet nil
82 "anything config yasnippet"
83 :group 'anything)
84
85(defcustom anything-c-yas-not-display-dups t
86 "if non-nil not display duplicate snippet otherwise display all snippet"
87 :type 'boolean
88 :group 'anything-c-yasnippet)
89
90(defcustom anything-c-yas-display-msg-after-complete t
91 "if non-nil display snippet key message in minibuffer after Complete"
92 :type 'boolean
93 :group 'anything-c-yasnippet)
94
95(defcustom anything-c-yas-snippets-dir-list nil
96 "list of directory used to find snippet file"
97 :type '(repeat (directory
98 :tag "snippet-directory"))
99 :group 'anything-c-yasnippet)
100
101(defcustom anything-c-yas-space-match-any-greedy nil
102 "if non-nil anything pattern space match anyword greedy.
103pattern regexp: \"if else\" replace to \"if.*else\"
104match \"if (...) { ... } else { ... }\" and \"if, elsif, else ...\"
105quite convenience
106Default: nil"
107 :type 'boolean
108 :group 'anything-c-yasnippet)
109
110(defcustom anything-c-yas-display-key-on-candidate nil
111 "if non-nil anything display candidate(snippet name) include key
112ex. [for] for (...) { ... }
113otherwise display just name
114ex. for (...) { ... }"
115 :type 'boolean
116 :group 'anything-c-yasnippet)
117
118(defvar anything-c-yas-snippets-dir-list nil)
119(defadvice yas/load-directory-1 (around anything-yas-build-alist activate)
120 (let ((directory (ad-get-arg 0)))
121 (when (stringp directory)
122 (add-to-list 'anything-c-yas-snippets-dir-list directory)))
123 ad-do-it)
124
125
126(defun anything-c-yas-create-new-snippet (selected-text &optional snippet-file)
127 "Create snippet from SELECTED-TEXT into SNIPPET-FILE.
128If SNIPPET-FILE is nil, asks file name.
129If SNIPPET-FILE does not contain directory, it is placed in default snippet directory."
130 (let ((snippet-dir (anything-c-yas-find-recursively
131 (regexp-quote (symbol-name anything-c-yas-cur-major-mode))
132 (expand-file-name
133 (or (car-safe yas/root-directory) yas/root-directory))
134 'snippet-file)))
135 (setq snippet-file
136 (anything-aif snippet-file
137 (expand-file-name snippet-file snippet-dir)
138 (read-file-name "create snippet : " snippet-dir snippet-dir)))
139 (when (file-exists-p snippet-file)
140 (error "can't create file [%s] already exists" (file-name-nondirectory snippet-file)))
141 ;; create buffer, insert template
142 (find-file snippet-file)
143 (insert "#name : \n# --\n" selected-text)))
144
145(defun anything-c-yas-find-recursively (regexp &optional directory predicate)
146 (let ((directory (or directory default-directory))
147 (predfunc (case predicate
148 (dir 'file-directory-p)
149 (file 'file-regular-p)
150 (otherwise 'identity)))
151 (files (remove-if (lambda (s) (string-match "^\\." (file-name-nondirectory s))) (directory-files directory t)))
152 (found nil)
153 (result nil))
154 (loop for file in files
155 unless found
156 do (if (and (funcall predfunc file)
157 (string-match regexp file))
158 (progn (setq found t)
159 (return (file-name-as-directory file)))
160 (when (file-directory-p file)
161 (setq result (anything-c-yas-find-recursively regexp file predicate))))
162 finally (return result))))
163
164
165(defun anything-c-yas-build-cur-snippets-alist (&optional table)
166 (let ((yas/choose-keys-first nil)
167 (yas/choose-tables-first nil)
168 (yas/buffer-local-condition 'always))
169 (let* ((result-alist '((candidates) (transformed) (template-key-alist)(template-file-alist)))
170 (cur-tables
171 (if table
172 (list table)
173 (yas/get-snippet-tables)))
174 (hash-value-alist nil))
175 (let ((hashes (loop for table in cur-tables
176 collect (yas/table-hash table))))
177 (loop for hash in hashes
178 do (maphash (lambda (k v)
179 (let (a)
180 (maphash (lambda (n te)
181 (setq a (append (list (cons k te)) a)))
182 v)
183 (setq hash-value-alist (append a hash-value-alist))))
184 hash))
185 (loop with transformed
186 with templates
187 with template-key-alist
188 with template-file-alist
189 for lst in hash-value-alist
190 for key = (car lst)
191 for template-struct = (cdr lst)
192 for name = (yas/template-name template-struct) ;`yas/template-name'
193 for template = (yas/template-content template-struct) ;`yas/template-content'
194 for file = (yas/template-file template-struct) ;`yas/template-content'
195 do (progn (push template templates)
196 (push `(,name . ,template) transformed)
197 (push `(,template . ,key) template-key-alist)
198 (push `(,template . ,file) template-file-alist))
199 finally (progn (push `(candidates . ,templates) result-alist)
200 (push `(transformed . ,transformed) result-alist)
201 (push `(template-file-alist . ,template-file-alist) result-alist)
202 (push `(template-key-alist . ,template-key-alist) result-alist)))
203 result-alist)
204 )))
205
206(defun anything-c-yas-get-modes ()
207 (let ((cur-major-mode anything-c-yas-cur-major-mode))
208 (list cur-major-mode)))
209
210(defun anything-c-yas-get-cmp-context ()
211 "Return list (initial-input point-start point-end)
212like `yas/current-key'"
213 (let ((start (point))
214 (end (point))
215 (syntax "w_"))
216 (condition-case nil
217 (save-excursion
218 (when mark-active
219 (error ""))
220 (skip-syntax-backward syntax)
221 (setq start (point))
222 (values (buffer-substring-no-properties start end) start end))
223 (error (values "" (point) (point))))))
224
225(defun anything-c-yas-get-key-by-template (template alist) ;str template
226 "Return key"
227 (assoc-default template (assoc-default 'template-key-alist alist)))
228
229(defun anything-c-yas-get-candidates (alist)
230 "Return list of template"
231 (assoc-default 'candidates alist 'eq))
232
233(defun anything-c-yas-get-transformed-list (alist initial-input)
234 "Return list of dotlist, (DISPLAY . REAL) DISPLAY is name of snippet, REAL is template of snippet"
235 (let ((transformed-list (assoc-default 'transformed alist 'eq)))
236 (cond
237 ;; display key on candidate ex: [for] for (...) { ... }
238 (anything-c-yas-display-key-on-candidate
239 (setq transformed-list (remove-if-not (lambda (lst)
240 (string-match (concat "^" (regexp-quote initial-input)) (car lst)))
241 transformed-list))
242 (setq transformed-list (loop for dotlst in transformed-list
243 for name = (car dotlst)
244 for template = (cdr dotlst)
245 for key = (anything-c-yas-get-key-by-template template alist)
246 for name-inc-key = (concat "[" key "] " name)
247 collect `(,name-inc-key . ,template))))
248 ;; default ex: for (...) { ... }
249 (t
250 (setq transformed-list (remove-if-not (lambda (lst)
251 (string-match (concat "^" (regexp-quote initial-input)) (car lst)))
252 transformed-list))))
253 (when anything-c-yas-not-display-dups
254 (setq transformed-list (delete-dups transformed-list)))
255 ;; sort
256 (setq transformed-list (sort* transformed-list 'string< :key 'car))
257 transformed-list))
258
259(defun anything-c-yas-find-snippet-file-by-key (key)
260 (let ((modes (anything-c-yas-get-modes))
261 (snippet-dirs anything-c-yas-snippets-dir-list))
262 (let ((found-path (loop for mode in modes
263 for test-re = (concat (symbol-name mode) "/" key "$")
264 for path = (anything-c-yas-find-snippet-file-aux test-re snippet-dirs)
265 when path return path)))
266 ;; if not found in major-mode try to find in all dirs
267 (unless found-path
268 (setq found-path (anything-c-yas-find-snippet-file-aux (concat "/" key "$") snippet-dirs)))
269 found-path)))
270
271(defun anything-c-yas-find-snippet-file-aux (test-re dirs)
272 (loop with done
273 with path
274 for directory in dirs
275 for files = (directory-files directory t)
276 unless done
277 do (loop for file in files
278 when (string-match test-re file)
279 return (setq done t
280 path file))
281 finally return path))
282
283(defun anything-c-yas-find-file-snippet-by-template (template &optional other-window)
284 (let* ((path (assoc-default template (assoc-default 'template-file-alist anything-c-yas-cur-snippets-alist)))
285 (ff-func (if other-window 'find-file-other-window 'find-file)))
286 (if path
287 (funcall ff-func path)
288 (message "not found snippet file"))))
289
290
291(defun anything-c-yas-get-path-by-template (template)
292 (let* ((key (anything-c-yas-get-key-by-template template anything-c-yas-cur-snippets-alist))
293 (path (anything-c-yas-find-snippet-file-by-key key)))
294 path))
295
296(defun anything-c-yas-match (candidate)
297 "if customize variable `anything-c-yas-space-match-any-greedy' is non-nil
298space match anyword greedy"
299 (cond
300 (anything-c-yas-space-match-any-greedy
301 (let ((re (replace-regexp-in-string "[ \t]+" ".*" anything-pattern)))
302 (string-match re candidate)))
303 (t
304 (string-match anything-pattern candidate))))
305
306(defvar anything-c-yas-cur-snippets-alist nil)
307(defvar anything-c-yas-initial-input "")
308(defvar anything-c-yas-point-start nil)
309(defvar anything-c-yas-point-end nil)
310(defvar anything-c-yas-cur-major-mode nil)
311(defvar anything-c-yas-selected-text "" "region text if mark-active otherwise \"\"")
312(defvar anything-c-source-yasnippet
313 `((name . "Yasnippet")
314 (init . (lambda ()
315 (setq anything-c-yas-cur-major-mode major-mode)
316 (setq anything-c-yas-selected-text (if mark-active (buffer-substring-no-properties (region-beginning) (region-end)) ""))
317 (multiple-value-setq
318 (anything-c-yas-initial-input anything-c-yas-point-start anything-c-yas-point-end) (anything-c-yas-get-cmp-context)) ;return values(str point point)
319 (setq anything-c-yas-cur-snippets-alist (anything-c-yas-build-cur-snippets-alist))))
320 (candidates . (anything-c-yas-get-candidates anything-c-yas-cur-snippets-alist))
321 (candidate-transformer . (lambda (candidates)
322 (anything-c-yas-get-transformed-list anything-c-yas-cur-snippets-alist anything-c-yas-initial-input)))
323 (action . (("Insert snippet" . (lambda (template)
324 (yas/expand-snippet template anything-c-yas-point-start anything-c-yas-point-end)
325 (when anything-c-yas-display-msg-after-complete
326 (message "this snippet is bound to [ %s ]"
327 (anything-c-yas-get-key-by-template template anything-c-yas-cur-snippets-alist)))))
328 ("Open snippet file" . (lambda (template)
329 (anything-c-yas-find-file-snippet-by-template template)))
330 ("Open snippet file other window" . (lambda (template)
331 (anything-c-yas-find-file-snippet-by-template template t)))
332 ("Create new snippet on region" . (lambda (template)
333 (anything-c-yas-create-new-snippet anything-c-yas-selected-text)))
334 ("Reload All Snippts" . (lambda (template)
335 (yas/reload-all)
336 (message "Reload All Snippts done")))
337 ("Rename snippet file" . (lambda (template)
338 (let* ((path (or (anything-c-yas-get-path-by-template template) ""))
339 (dir (file-name-directory path))
340 (filename (file-name-nondirectory path))
341 (rename-to (read-string (concat "rename [" filename "] to: "))))
342 (rename-file path (concat dir rename-to))
343 (yas/reload-all))))
344 ("Delete snippet file" . (lambda (template)
345 (let ((path (or (anything-c-yas-get-path-by-template template) "")))
346 (when (y-or-n-p "really delete?")
347 (delete-file path)
348 (yas/reload-all)))))))
349 (persistent-action . (lambda (template)
350 (anything-c-yas-find-file-snippet-by-template template)))
351 (match . (anything-c-yas-match))))
352
353
354;;; visit template
355(defun anything-c-yas-all-templates ()
356 (let ((tables (yas/get-snippet-tables)))
357 (loop for table in tables
358 append (yas/snippet-table-templates table))))
359
360(defun anything-c-yas-flatten-templates (templates)
361 (loop for lot in templates ;lot is list of templates
362 append lot))
363
364(defun anything-c-yas-snippet-files-candidates ()
365 "called in `anything-c-source-yasnippet-snippet-files' candidates"
366 (let ((yas/choose-keys-first nil)
367 (yas/choose-tables-first nil)
368 (yas/buffer-local-condition 'always))
369 (with-current-buffer anything-current-buffer
370 (mapcar* 'yas/template-file
371 (mapcar 'cdr
372 (anything-c-yas-all-templates))))))
373
374;; (anything 'anything-c-source-yasnippet-snippet-files)
375(defvar anything-c-source-yasnippet-snippet-files
376 '((name . "yasnippet snippet files")
377 (candidates . anything-c-yas-snippet-files-candidates)
378 (type . file)
379 ))
380
381
382;;; Commands
383(defun anything-c-yas-complete ()
384 "List of yasnippet snippets using `anything' interface."
385 (interactive)
386 (anything 'anything-c-source-yasnippet))
387
388(defun anything-c-yas-visit-snippet-file ()
389 "List of yasnippet snippet files"
390 (interactive)
391 (anything 'anything-c-source-yasnippet-snippet-files))
392
393(defun anything-c-yas-create-snippet-on-region (&optional start end file-name)
394 "Create a snippet from region."
395 (interactive "r")
396 (let ((str (buffer-substring-no-properties start end)))
397 (anything-c-yas-create-new-snippet str file-name)))
398;; (anything-c-yas-create-snippet-on-region (region-beginning) (region-end) "aaaa")
399
400
401
402(provide 'anything-c-yasnippet)
403;; anything-c-yasnippet.el ends here