root/lang/elisp/anything-c-yasnippet/anything-c-yasnippet.el @ 8674

Revision 8674, 15.9 kB (checked in by imakado, 7 years ago)

lang/elisp/anything-c-yasnippet/anything-c-yasnippet.el:
カスタマイズ可能な変数 `anything-c-yas-display-key-on-candidate'を追加
non-nilで補完候補表示の際に先頭にkey(snippetのファイル名)も含めるようになる。

RevLine 
[8348]1;;; anything-c-yasnippet.el --- anything config for yasnippet.el
2
[8612]3;; Author: Kenji.I (Kenji Imakado) <ken.imakaado@gmail.com>
[8674]4;; Version: 0.4
[8612]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
[8348]22;;; Commentary:
23
24;; anything-source name  => anything-c-source-yasnippet
25;;
26;; Actions: Insert snippet, Open snippet file, Open snippet file other window
27;; C-z: execute-persistent-action
28
[8388]29;; here's my yasnippet's configuration
30;; (require 'yasnippet)
31;; (require 'anything-c-yasnippet)
32;; (setq anything-c-yas-space-match-any-greedy t) ;[default: nil]
33;; (global-set-key (kbd "C-c y") 'anything-c-yas-complete)
34;; (yas/initialize)
35;; (yas/load-directory "<path>/<to>/snippets/")
36;; (add-to-list 'yas/extra-mode-hooks 'ruby-mode-hook)
37;; (add-to-list 'yas/extra-mode-hooks 'cperl-mode-hook)
38
[8348]39(require 'cl)
40(require 'anything)
41(require 'yasnippet)
42
43;;; Compatibility code
44;; written by rubikitch see http://d.hatena.ne.jp/rubikitch/20071228/anythingpersistent (japanese)
45(unless (fboundp 'anything-execute-persistent-action)
46  (defun anything-execute-persistent-action ()
47    "If a candidate was selected then perform the associated action without quitting anything."
48    (interactive)
49    (save-selected-window
50      (select-window (get-buffer-window anything-buffer))
51      (select-window (setq minibuffer-scroll-window
52                           (if (one-window-p t) (split-window) (next-window (selected-window) 1))))
53      (let* ((anything-window (get-buffer-window anything-buffer))
54             (selection (if anything-saved-sources
55                            ;; the action list is shown
56                            anything-saved-selection
57                          (anything-get-selection)))
58             (default-action (anything-get-action))
59             (action (assoc-default 'persistent-action (anything-get-current-source))))
60        (setq action (or action default-action))
61        (if (and (listp action)
62                 (not (functionp action))) ; lambda
63            ;; select the default action
64            (setq action (cdar action)))
65        (set-window-dedicated-p anything-window t)
66        (unwind-protect
67            (and action selection (funcall action selection))
68          (set-window-dedicated-p anything-window nil))))))
69
70(define-key anything-map "\C-z" 'anything-execute-persistent-action)
71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
72
[8612]73;;; Code
[8674]74(defvar anything-c-yas-version "0.4" "Version of anything-c-yasnippet")
[8612]75
76(defgroup anything-c-yasnippet nil
77  "anything config yasnippet")
78
79(defcustom anything-c-yas-not-display-dups t
80  "if non-nil not display duplicate snippet otherwise display all snippet"
81  :type 'boolean
82  :group 'anything-c-yasnippet)
83
84(defcustom anything-c-yas-display-msg-after-complete t
85  "if non-nil display snippet key message in minibuffer after Complete"
86  :type 'boolean
87  :group 'anything-c-yasnippet)
88
89(defcustom anything-c-yas-snippets-dir-list nil
90  "list of directory used to find snippet file"
91  :type '(repeat (directory
92                  :tag "snippet-directory"))
93  :group 'anything-c-yasnippet)
94
95(defcustom anything-c-yas-space-match-any-greedy nil
96  "if non-nil anything pattern space match anyword greedy.
[8388]97pattern regexp: \"if else\" replace to \"if.*else\"
[8612]98match \"if (...) { ... } else { ... }\" and \"if, elsif, else ...\"
99quite convenience
100Default: nil"
101  :type 'boolean
102  :group 'anything-c-yasnippet)
[8348]103
[8674]104(defcustom anything-c-yas-display-key-on-candidate nil
105  "if non-nil anything display candidate(snippet name) include key
106ex. [for] for (...) { ... }
107otherwise display just name
108ex. for (...) { ... }"
109  :type 'boolean
110  :group 'anything-c-yasnippet)
[8388]111
[8674]112
[8388]113(defvar anything-c-yas-snippets-dir-list nil)
[8348]114(defadvice yas/load-directory-1 (around anything-yas-build-alist activate)
[8388]115  (let ((directory (ad-get-arg 0)))
116    (when (stringp directory)
117      (add-to-list 'anything-c-yas-snippets-dir-list directory)))
[8348]118  ad-do-it)
119
[8612]120
121(defun anything-c-yas-create-new-snippet (selected-text)
122  (let* ((mode-name (symbol-name anything-c-yas-cur-major-mode))
123         (root-dir (expand-file-name yas/root-directory))
124         (default-snippet-dir (anything-c-yas-find-recursively mode-name root-dir 'dir))
125         (dir (read-file-name "create snippet : " default-snippet-dir default-snippet-dir)))
126    (condition-case e
127        (progn (when (file-exists-p dir)
128                 (error "can't create file [%s] already exists" (file-name-nondirectory dir)))
129               ;; create buffer, insert template
130               (find-file dir)
131               (insert "#name : \n# --\n " selected-text))
132      (message "%s" (error-message-string e)))))
[8348]133
[8612]134(defun anything-c-yas-find-recursively (regexp &optional directory predicate)
135  (let ((directory (or directory default-directory))
136        (predfunc (case predicate
137                    (dir 'file-directory-p)
138                    (file 'file-regular-p)
139                    (otherwise 'identity)))
140        (files (remove-if (lambda (s) (string-match "^\\." (file-name-nondirectory  s))) (directory-files directory t)))
141        (found nil)
142        (result nil))
143    (loop for file in files
144          unless found
145          do (if (and (funcall predfunc file)
146                      (string-match regexp file))
147                 (progn (setq found t)
148                        (return (file-name-as-directory file)))
149               (when (file-directory-p file)
150                 (setq result (anything-c-yas-find-recursively regexp file predicate))))
151          finally (return result))))
152
[8388]153(defun anything-c-yas-build-cur-snippets-alist (&optional table)
154  (let* ((result-alist '((candidates) (transformed) (template-key-alist)))
155         (hash-value-alist nil)
156         (cur-table (or table (yas/snippet-table anything-c-yas-cur-major-mode)))
157         (parent-table (yas/snippet-table-parent cur-table)) ;`yas/snippet-table-parent'
158         (hash-table (yas/snippet-table-hash cur-table))) ;`yas/snippet-table-hash'
159    (maphash (lambda (k v) (setq hash-value-alist (append v hash-value-alist))) hash-table)
[8348]160    (loop with transformed
161          with templates
[8388]162          with template-key-alist
163          for lst in hash-value-alist
164          for key = (car lst)
165          for template-struct = (cdr lst)
166          for name = (yas/template-name template-struct) ;`yas/template-name'
167          for template = (yas/template-content template-struct) ;`yas/template-content'
[8348]168          do (progn (push template templates)
[8388]169                    (push `(,name . ,template) transformed)
170                    (push `(,template . ,key) template-key-alist))
[8348]171          finally (progn (push `(candidates . ,templates) result-alist)
172                         (push `(transformed . ,transformed) result-alist)
[8388]173                         (push `(template-key-alist . ,template-key-alist) result-alist)))
174    ;; if cur-table has parent build recursively
175    (when parent-table
176      (let ((rec-ret (anything-c-yas-build-cur-snippets-alist parent-table))
177            (alist-keys '(candidates transformed template-key-alist)))
178        (mapc (lambda (key)
179                (let ((res-list (assq key result-alist))
180                      (rec-val (assoc-default key rec-ret)))
181                  (setcdr res-list (nconc rec-val (cdr res-list)))))
182              alist-keys)))
[8348]183    result-alist))
184
185(defun anything-c-yas-get-modes ()
186  (let ((cur-major-mode anything-c-yas-cur-major-mode))
[8612]187    (list cur-major-mode)))
[8348]188
189(defun anything-c-yas-get-cmp-context ()
190  "Return list (initial-input point-start point-end)
191like `yas/current-key'"
192  (let ((start (point))
193        (end (point))
194        (syntax "w_"))
195    (condition-case nil
196        (save-excursion
[8612]197          (when mark-active
198            (error ""))
[8348]199          (skip-syntax-backward syntax)
200          (setq start (point))
201          (values (buffer-substring-no-properties start end) start end))
202      (error (values "" (point) (point))))))
203
204(defun anything-c-yas-get-key-by-template (template alist) ;str template
205  "Return key"
[8388]206  (assoc-default template (assoc-default 'template-key-alist alist)))
[8348]207
208(defun anything-c-yas-get-candidates (alist)
209  "Return list of template"
210  (assoc-default 'candidates alist 'eq))
211
212(defun anything-c-yas-get-transformed-list (alist initial-input)
213  "Return list of dotlist, (DISPLAY . REAL) DISPLAY is name of snippet, REAL is template of snippet"
214  (let ((transformed-list (assoc-default 'transformed alist 'eq)))
[8674]215    (cond
216     ;; display key on candidate ex: [for] for (...) { ... }
217     (anything-c-yas-display-key-on-candidate
218      (setq transformed-list (remove-if-not (lambda (lst)
219                                              (string-match (concat "^" (regexp-quote initial-input)) (car lst)))
220                                            transformed-list))
221      (setq transformed-list (loop for dotlst in transformed-list
222                                   for name = (car dotlst)
223                                   for template = (cdr dotlst)
224                                   for key = (anything-c-yas-get-key-by-template template alist)
225                                   for name-inc-key = (concat "[" key "] " name)
226                                   collect `(,name-inc-key . ,template))))
227     ;; default ex: for (...) { ... }
228     (t
229      (setq transformed-list (remove-if-not (lambda (lst)
230                                              (string-match (concat "^" (regexp-quote initial-input)) (car lst)))
231                                            transformed-list))))
[8348]232    (when anything-c-yas-not-display-dups
233      (setq transformed-list (delete-dups transformed-list)))
234    ;; sort
235    (setq transformed-list (sort* transformed-list 'string< :key 'car))
236    transformed-list))
237
238(defun anything-c-yas-find-snippet-file-by-key (key)
239  (let ((modes (anything-c-yas-get-modes))
[8388]240        (snippet-dirs (add-to-list 'anything-c-yas-snippets-dir-list yas/root-directory)))
241    (let ((found-path (loop for mode in modes
242                            for test-re = (concat (symbol-name mode) "/" key "$")
243                            for path =  (anything-c-yas-find-snippet-file-aux test-re snippet-dirs)
244                            when path return path)))
245      ;; if not found in major-mode try to find in all dirs
246      (unless found-path
247        (setq found-path (anything-c-yas-find-snippet-file-aux (concat "/" key "$") snippet-dirs)))
248      found-path)))
[8348]249
[8388]250(defun anything-c-yas-find-snippet-file-aux (test-re dirs)
251  (loop with done
252        with path
253        for directory in dirs
254        for files = (directory-files directory t)
255        unless done
256        do (loop for file in files
257                 when (string-match test-re file)
258                 return (setq done t
259                              path file))
260        finally return path))
261
[8348]262(defun anything-c-yas-find-file-snippet-by-template (template &optional other-window)
[8612]263  (let* ((path (anything-c-yas-get-path-by-template template))
[8348]264         (ff-func (if other-window 'find-file-other-window 'find-file)))
[8612]265    (if path
266        (funcall ff-func path)
267      (message "not found snippet file"))))
[8348]268
[8612]269(defun anything-c-yas-get-path-by-template (template)
270  (let* ((key (anything-c-yas-get-key-by-template template anything-c-yas-cur-snippets-alist))
271         (path (anything-c-yas-find-snippet-file-by-key key)))
272    path))
273
[8388]274(defun anything-c-yas-match (candidate)
275  "if customize variable `anything-c-yas-space-match-any-greedy' is non-nil
276space match anyword greedy"
277  (cond
278   (anything-c-yas-space-match-any-greedy
279    (let ((re (replace-regexp-in-string "[ \t]+" ".*" anything-pattern)))
280      (string-match re candidate)))
281   (t
282    (string-match anything-pattern candidate))))
[8348]283
284(defvar anything-c-yas-cur-snippets-alist nil)
285(defvar anything-c-yas-initial-input "")
286(defvar anything-c-yas-point-start nil)
287(defvar anything-c-yas-point-end nil)
288(defvar anything-c-yas-cur-major-mode nil)
[8612]289(defvar anything-c-yas-selected-text "" "region text if mark-active otherwise \"\"")
[8348]290(defvar anything-c-source-yasnippet
291  `((name . "Yasnippet")
292    (init . (lambda ()
293              (setq anything-c-yas-cur-major-mode major-mode)
[8612]294              (setq anything-c-yas-selected-text (if mark-active (buffer-substring-no-properties (region-beginning) (region-end)) ""))
295              (multiple-value-setq
296                  (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)
[8348]297              (setq anything-c-yas-cur-snippets-alist (anything-c-yas-build-cur-snippets-alist))))
[8612]298    (candidates . (anything-c-yas-get-candidates anything-c-yas-cur-snippets-alist))
[8348]299    (candidate-transformer . (lambda (candidates)
300                               (anything-c-yas-get-transformed-list anything-c-yas-cur-snippets-alist anything-c-yas-initial-input)))
301    (action . (("Insert snippet" . (lambda (template)
302                                     (yas/expand-snippet anything-c-yas-point-start anything-c-yas-point-end template)
303                                     (when anything-c-yas-display-msg-after-complete
304                                       (message "this snippet is bound to [ %s ]"
305                                                (anything-c-yas-get-key-by-template template anything-c-yas-cur-snippets-alist)))))
306               ("Open snippet file" . (lambda (template)
[8612]307                                        (anything-c-yas-find-file-snippet-by-template template)))
[8348]308               ("Open snippet file other window" . (lambda (template)
[8612]309                                                     (anything-c-yas-find-file-snippet-by-template template t)))
310               ("Create new snippet on region" . (lambda (template)
311                                                   (anything-c-yas-create-new-snippet anything-c-yas-selected-text)))
312               ("Reload All Snippts" . (lambda (template)
313                                         (yas/reload-all)
314                                         (message "Reload All Snippts done")))
315               ("Rename snippet file" . (lambda (template)
316                                       (let* ((path (or (anything-c-yas-get-path-by-template template) ""))
317                                              (dir (file-name-directory path))
318                                              (filename (file-name-nondirectory path))
319                                              (rename-to (read-string (concat "rename [" filename "] to: "))))
320                                         (rename-file path (concat dir rename-to))
321                                         (yas/reload-all))))
322               ("Delete snippet file" . (lambda (template)
323                                          (let ((path (or (anything-c-yas-get-path-by-template template) "")))
324                                            (when (y-or-n-p "really delete?")
325                                              (delete-file path)
326                                              (yas/reload-all)))))))
[8348]327    (persistent-action . (lambda (template)
[8388]328                           (anything-c-yas-find-file-snippet-by-template template)))
329    (match . (anything-c-yas-match))))
[8348]330
[8612]331
332;;; Commands
[8348]333(defun anything-c-yas-complete ()
334  (interactive)
335  (let ((anything-sources (list anything-c-source-yasnippet)))
336    (anything)))
337
[8612]338(defun anything-c-yas-create-snippet-on-regin (&optional start end)
339  (interactive "r")
340  (let ((str (buffer-substring-no-properties start end)))
341    (anything-c-yas-create-new-snippet str)))
342 
343
[8348]344(provide 'anything-c-yasnippet)
345;; anything-c-yasnippet.el ends here
Note: See TracBrowser for help on using the browser.