diff --git a/snippets/cc-mode/c++-mode/beginend b/text-mode/cc-mode/c++-mode/beginend similarity index 100% rename from snippets/cc-mode/c++-mode/beginend rename to text-mode/cc-mode/c++-mode/beginend diff --git a/snippets/cc-mode/c++-mode/class b/text-mode/cc-mode/c++-mode/class similarity index 100% rename from snippets/cc-mode/c++-mode/class rename to text-mode/cc-mode/c++-mode/class diff --git a/snippets/cc-mode/c++-mode/using b/text-mode/cc-mode/c++-mode/using similarity index 100% rename from snippets/cc-mode/c++-mode/using rename to text-mode/cc-mode/c++-mode/using diff --git a/snippets/cc-mode/c-mode/fopen b/text-mode/cc-mode/c-mode/fopen similarity index 100% rename from snippets/cc-mode/c-mode/fopen rename to text-mode/cc-mode/c-mode/fopen diff --git a/snippets/cc-mode/do b/text-mode/cc-mode/do similarity index 100% rename from snippets/cc-mode/do rename to text-mode/cc-mode/do diff --git a/snippets/cc-mode/for b/text-mode/cc-mode/for similarity index 100% rename from snippets/cc-mode/for rename to text-mode/cc-mode/for diff --git a/snippets/cc-mode/if b/text-mode/cc-mode/if similarity index 100% rename from snippets/cc-mode/if rename to text-mode/cc-mode/if diff --git a/snippets/cc-mode/inc b/text-mode/cc-mode/inc similarity index 100% rename from snippets/cc-mode/inc rename to text-mode/cc-mode/inc diff --git a/snippets/cc-mode/inc.1 b/text-mode/cc-mode/inc.1 similarity index 100% rename from snippets/cc-mode/inc.1 rename to text-mode/cc-mode/inc.1 diff --git a/snippets/cc-mode/main b/text-mode/cc-mode/main similarity index 100% rename from snippets/cc-mode/main rename to text-mode/cc-mode/main diff --git a/snippets/cc-mode/once b/text-mode/cc-mode/once similarity index 100% rename from snippets/cc-mode/once rename to text-mode/cc-mode/once diff --git a/snippets/cc-mode/struct b/text-mode/cc-mode/struct similarity index 100% rename from snippets/cc-mode/struct rename to text-mode/cc-mode/struct diff --git a/snippets/cperl-mode/eval b/text-mode/cperl-mode/eval similarity index 100% rename from snippets/cperl-mode/eval rename to text-mode/cperl-mode/eval diff --git a/snippets/cperl-mode/for b/text-mode/cperl-mode/for similarity index 100% rename from snippets/cperl-mode/for rename to text-mode/cperl-mode/for diff --git a/snippets/cperl-mode/fore b/text-mode/cperl-mode/fore similarity index 100% rename from snippets/cperl-mode/fore rename to text-mode/cperl-mode/fore diff --git a/snippets/cperl-mode/if b/text-mode/cperl-mode/if similarity index 100% rename from snippets/cperl-mode/if rename to text-mode/cperl-mode/if diff --git a/snippets/cperl-mode/ife b/text-mode/cperl-mode/ife similarity index 100% rename from snippets/cperl-mode/ife rename to text-mode/cperl-mode/ife diff --git a/snippets/cperl-mode/ifee b/text-mode/cperl-mode/ifee similarity index 100% rename from snippets/cperl-mode/ifee rename to text-mode/cperl-mode/ifee diff --git a/snippets/cperl-mode/sub b/text-mode/cperl-mode/sub similarity index 100% rename from snippets/cperl-mode/sub rename to text-mode/cperl-mode/sub diff --git a/snippets/cperl-mode/unless b/text-mode/cperl-mode/unless similarity index 100% rename from snippets/cperl-mode/unless rename to text-mode/cperl-mode/unless diff --git a/snippets/cperl-mode/while b/text-mode/cperl-mode/while similarity index 100% rename from snippets/cperl-mode/while rename to text-mode/cperl-mode/while diff --git a/snippets/cperl-mode/xfore b/text-mode/cperl-mode/xfore similarity index 100% rename from snippets/cperl-mode/xfore rename to text-mode/cperl-mode/xfore diff --git a/snippets/cperl-mode/xif b/text-mode/cperl-mode/xif similarity index 100% rename from snippets/cperl-mode/xif rename to text-mode/cperl-mode/xif diff --git a/snippets/cperl-mode/xunless b/text-mode/cperl-mode/xunless similarity index 100% rename from snippets/cperl-mode/xunless rename to text-mode/cperl-mode/xunless diff --git a/snippets/cperl-mode/xwhile b/text-mode/cperl-mode/xwhile similarity index 100% rename from snippets/cperl-mode/xwhile rename to text-mode/cperl-mode/xwhile diff --git a/snippets/css-mode/background b/text-mode/css-mode/background similarity index 100% rename from snippets/css-mode/background rename to text-mode/css-mode/background diff --git a/snippets/css-mode/background.1 b/text-mode/css-mode/background.1 similarity index 100% rename from snippets/css-mode/background.1 rename to text-mode/css-mode/background.1 diff --git a/snippets/css-mode/border b/text-mode/css-mode/border similarity index 100% rename from snippets/css-mode/border rename to text-mode/css-mode/border diff --git a/snippets/email b/text-mode/email similarity index 100% rename from snippets/email rename to text-mode/email diff --git a/snippets/html-mode/div b/text-mode/html-mode/div similarity index 100% rename from snippets/html-mode/div rename to text-mode/html-mode/div diff --git a/snippets/html-mode/doctype b/text-mode/html-mode/doctype similarity index 100% rename from snippets/html-mode/doctype rename to text-mode/html-mode/doctype diff --git a/snippets/html-mode/doctype.xhml1 b/text-mode/html-mode/doctype.xhml1 similarity index 100% rename from snippets/html-mode/doctype.xhml1 rename to text-mode/html-mode/doctype.xhml1 diff --git a/snippets/html-mode/doctype.xhtml1_1 b/text-mode/html-mode/doctype.xhtml1_1 similarity index 100% rename from snippets/html-mode/doctype.xhtml1_1 rename to text-mode/html-mode/doctype.xhtml1_1 diff --git a/snippets/html-mode/doctype.xhtml1_strict b/text-mode/html-mode/doctype.xhtml1_strict similarity index 100% rename from snippets/html-mode/doctype.xhtml1_strict rename to text-mode/html-mode/doctype.xhtml1_strict diff --git a/snippets/html-mode/doctype.xhtml1_transitional b/text-mode/html-mode/doctype.xhtml1_transitional similarity index 100% rename from snippets/html-mode/doctype.xhtml1_transitional rename to text-mode/html-mode/doctype.xhtml1_transitional diff --git a/snippets/objc-mode/prop b/text-mode/objc-mode/prop similarity index 100% rename from snippets/objc-mode/prop rename to text-mode/objc-mode/prop diff --git a/snippets/python-mode/__ b/text-mode/python-mode/__ similarity index 100% rename from snippets/python-mode/__ rename to text-mode/python-mode/__ diff --git a/snippets/python-mode/for b/text-mode/python-mode/for similarity index 100% rename from snippets/python-mode/for rename to text-mode/python-mode/for diff --git a/snippets/python-mode/ifmain b/text-mode/python-mode/ifmain similarity index 100% rename from snippets/python-mode/ifmain rename to text-mode/python-mode/ifmain diff --git a/snippets/python-mode/while b/text-mode/python-mode/while similarity index 100% rename from snippets/python-mode/while rename to text-mode/python-mode/while diff --git a/snippets/ruby-mode/# b/text-mode/ruby-mode/# similarity index 100% rename from snippets/ruby-mode/# rename to text-mode/ruby-mode/# diff --git a/snippets/ruby-mode/=b b/text-mode/ruby-mode/=b similarity index 100% rename from snippets/ruby-mode/=b rename to text-mode/ruby-mode/=b diff --git a/snippets/ruby-mode/Comp b/text-mode/ruby-mode/Comp similarity index 100% rename from snippets/ruby-mode/Comp rename to text-mode/ruby-mode/Comp diff --git a/snippets/ruby-mode/all b/text-mode/ruby-mode/all similarity index 100% rename from snippets/ruby-mode/all rename to text-mode/ruby-mode/all diff --git a/snippets/ruby-mode/am b/text-mode/ruby-mode/am similarity index 100% rename from snippets/ruby-mode/am rename to text-mode/ruby-mode/am diff --git a/snippets/ruby-mode/any b/text-mode/ruby-mode/any similarity index 100% rename from snippets/ruby-mode/any rename to text-mode/ruby-mode/any diff --git a/snippets/ruby-mode/app b/text-mode/ruby-mode/app similarity index 100% rename from snippets/ruby-mode/app rename to text-mode/ruby-mode/app diff --git a/snippets/ruby-mode/bm b/text-mode/ruby-mode/bm similarity index 100% rename from snippets/ruby-mode/bm rename to text-mode/ruby-mode/bm diff --git a/snippets/ruby-mode/case b/text-mode/ruby-mode/case similarity index 100% rename from snippets/ruby-mode/case rename to text-mode/ruby-mode/case diff --git a/snippets/ruby-mode/cla b/text-mode/ruby-mode/cla similarity index 100% rename from snippets/ruby-mode/cla rename to text-mode/ruby-mode/cla diff --git a/snippets/ruby-mode/classify b/text-mode/ruby-mode/classify similarity index 100% rename from snippets/ruby-mode/classify rename to text-mode/ruby-mode/classify diff --git a/snippets/ruby-mode/cls b/text-mode/ruby-mode/cls similarity index 100% rename from snippets/ruby-mode/cls rename to text-mode/ruby-mode/cls diff --git a/snippets/ruby-mode/collect b/text-mode/ruby-mode/collect similarity index 100% rename from snippets/ruby-mode/collect rename to text-mode/ruby-mode/collect diff --git a/snippets/ruby-mode/dee b/text-mode/ruby-mode/dee similarity index 100% rename from snippets/ruby-mode/dee rename to text-mode/ruby-mode/dee diff --git a/snippets/ruby-mode/deli b/text-mode/ruby-mode/deli similarity index 100% rename from snippets/ruby-mode/deli rename to text-mode/ruby-mode/deli diff --git a/snippets/ruby-mode/det b/text-mode/ruby-mode/det similarity index 100% rename from snippets/ruby-mode/det rename to text-mode/ruby-mode/det diff --git a/snippets/ruby-mode/ea b/text-mode/ruby-mode/ea similarity index 100% rename from snippets/ruby-mode/ea rename to text-mode/ruby-mode/ea diff --git a/snippets/ruby-mode/eac b/text-mode/ruby-mode/eac similarity index 100% rename from snippets/ruby-mode/eac rename to text-mode/ruby-mode/eac diff --git a/snippets/ruby-mode/eai b/text-mode/ruby-mode/eai similarity index 100% rename from snippets/ruby-mode/eai rename to text-mode/ruby-mode/eai diff --git a/snippets/ruby-mode/eav b/text-mode/ruby-mode/eav similarity index 100% rename from snippets/ruby-mode/eav rename to text-mode/ruby-mode/eav diff --git a/snippets/ruby-mode/eawi b/text-mode/ruby-mode/eawi similarity index 100% rename from snippets/ruby-mode/eawi rename to text-mode/ruby-mode/eawi diff --git a/snippets/ruby-mode/forin b/text-mode/ruby-mode/forin similarity index 100% rename from snippets/ruby-mode/forin rename to text-mode/ruby-mode/forin diff --git a/snippets/ruby-mode/if b/text-mode/ruby-mode/if similarity index 100% rename from snippets/ruby-mode/if rename to text-mode/ruby-mode/if diff --git a/snippets/ruby-mode/ife b/text-mode/ruby-mode/ife similarity index 100% rename from snippets/ruby-mode/ife rename to text-mode/ruby-mode/ife diff --git a/snippets/ruby-mode/inject b/text-mode/ruby-mode/inject similarity index 100% rename from snippets/ruby-mode/inject rename to text-mode/ruby-mode/inject diff --git a/snippets/ruby-mode/mm b/text-mode/ruby-mode/mm similarity index 100% rename from snippets/ruby-mode/mm rename to text-mode/ruby-mode/mm diff --git a/snippets/ruby-mode/r b/text-mode/ruby-mode/r similarity index 100% rename from snippets/ruby-mode/r rename to text-mode/ruby-mode/r diff --git a/snippets/ruby-mode/rb b/text-mode/ruby-mode/rb similarity index 100% rename from snippets/ruby-mode/rb rename to text-mode/ruby-mode/rb diff --git a/snippets/ruby-mode/reject b/text-mode/ruby-mode/reject similarity index 100% rename from snippets/ruby-mode/reject rename to text-mode/ruby-mode/reject diff --git a/snippets/ruby-mode/req b/text-mode/ruby-mode/req similarity index 100% rename from snippets/ruby-mode/req rename to text-mode/ruby-mode/req diff --git a/snippets/ruby-mode/rreq b/text-mode/ruby-mode/rreq similarity index 100% rename from snippets/ruby-mode/rreq rename to text-mode/ruby-mode/rreq diff --git a/snippets/ruby-mode/rw b/text-mode/ruby-mode/rw similarity index 100% rename from snippets/ruby-mode/rw rename to text-mode/ruby-mode/rw diff --git a/snippets/ruby-mode/select b/text-mode/ruby-mode/select similarity index 100% rename from snippets/ruby-mode/select rename to text-mode/ruby-mode/select diff --git a/snippets/ruby-mode/w b/text-mode/ruby-mode/w similarity index 100% rename from snippets/ruby-mode/w rename to text-mode/ruby-mode/w diff --git a/snippets/ruby-mode/y b/text-mode/ruby-mode/y similarity index 100% rename from snippets/ruby-mode/y rename to text-mode/ruby-mode/y diff --git a/snippets/ruby-mode/zip b/text-mode/ruby-mode/zip similarity index 100% rename from snippets/ruby-mode/zip rename to text-mode/ruby-mode/zip diff --git a/snippets/time b/text-mode/time similarity index 100% rename from snippets/time rename to text-mode/time diff --git a/yasnippet.el b/yasnippet.el index 9665308..26fea5b 100644 --- a/yasnippet.el +++ b/yasnippet.el @@ -3,7 +3,7 @@ ;; Copyright 2008 pluskid ;; ;; Author: pluskid -;; Version: 0.1.1 +;; Version: 0.2.0 ;; X-URL: http://code.google.com/p/yasnippet/ ;; This file is free software; you can redistribute it and/or modify @@ -79,7 +79,7 @@ mode will be listed under the menu \"yasnippet\".") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Internal variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defvar yas/version "0.1") +(defvar yas/version "0.2.0") (defvar yas/snippet-tables (make-hash-table) "A hash table of snippet tables corresponding to each major-mode.") @@ -144,12 +144,17 @@ mode will be listed under the menu \"yasnippet\".") (next nil) (prev nil) snippet) -(defstruct (yas/field (:constructor yas/make-field (overlay number value transform))) +(defstruct (yas/field + (:constructor yas/make-field (overlay number value transform))) "A field in a snippet." overlay number transform value) +(defstruct (yas/snippet-table (:constructor yas/make-snippet-table ())) + "A table to store snippets for a perticular mode." + (hash (make-hash-table :test 'equal)) + (parent nil)) (defun yas/snippet-add-field (snippet field) "Add FIELD to SNIPPET." @@ -198,6 +203,25 @@ have, compare through the start point of the overlay." (< (overlay-start (yas/field-overlay field1)) (overlay-start (yas/field-overlay field2))))))) +(defun yas/snippet-table-fetch (table key) + "Fetch a snippet binding to KEY from TABLE. If not found, +fetch from parent if any." + (let ((templates (gethash key (yas/snippet-table-hash table)))) + (when (and (null templates) + (not (null (yas/snippet-table-parent table)))) + (setq templates (yas/snippet-table-fetch + (yas/snippet-table-parent table) + key))) + templates)) +(defun yas/snippet-table-store (table full-key key template) + "Store a snippet template in the table." + (puthash key + (yas/modify-alist (gethash key + (yas/snippet-table-hash table)) + full-key + template) + (yas/snippet-table-hash table))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Internal functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -226,7 +250,7 @@ unmodified." "Get the snippet table corresponding to MODE." (let ((table (gethash mode yas/snippet-tables))) (unless table - (setq table (make-hash-table :test 'equal)) + (setq table (yas/make-snippet-table)) (puthash mode table yas/snippet-tables)) table)) (defsubst yas/current-snippet-table () @@ -253,8 +277,9 @@ the template of a snippet in the current snippet-table." (setq syntaxes (cdr syntaxes)) (save-excursion (skip-syntax-backward syntax) - (when (gethash (buffer-substring-no-properties (point) end) - (yas/current-snippet-table)) + (when (yas/snippet-table-fetch + (yas/current-snippet-table) + (buffer-substring-no-properties (point) end)) (setq done t) (setq start (point))))) (list (buffer-substring-no-properties start end) @@ -636,20 +661,23 @@ t is returned simply." ;; no window system, simply select the first one (cdar templates))) -(defun yas/load-directory-1 (directory) +(defun yas/load-directory-1 (directory &optional parent) "Really do the job of loading snippets from a directory hierarchy." - (with-temp-buffer - (dolist (mode (yas/directory-files directory nil)) - (let ((mode-sym (intern (file-name-nondirectory mode)))) - (dolist (file (yas/directory-files mode t)) - (when (file-readable-p file) - (insert-file-contents file nil nil nil t) - (multiple-value-bind - (key template name) - (cons (file-name-nondirectory file) + (let ((mode-sym (intern (file-name-nondirectory directory))) + (snippets nil)) + (with-temp-buffer + (dolist (file (yas/directory-files directory t)) + (when (file-readable-p file) + (insert-file-contents file nil nil nil t) + (push (cons (file-name-nondirectory file) (yas/parse-template)) - (yas/define mode-sym key template name)))))))) + snippets)))) + (yas/define-snippets mode-sym + snippets + parent) + (dolist (subdir (yas/directory-files directory nil)) + (yas/load-directory-1 subdir mode-sym)))) (defun yas/quote-string (string) "Escape and quote STRING. @@ -734,7 +762,8 @@ content of the file is the template." (interactive "DSelect the root directory: ") (unless yas/root-directory (setq yas/root-directory directory)) - (yas/load-directory-1 directory) + (dolist (dir (yas/directory-files directory nil)) + (yas/load-directory-1 dir)) (when (interactive-p) (message "done."))) @@ -748,33 +777,62 @@ content of the file is the template." (cons "YASnippet" yas/menu-keymap) 'buffer))) +(defun yas/define-snippets (mode snippets &optional parent-mode) + "Define snippets for MODE. SNIPPETS is a list of +snippet definition, of the following form: + (KEY TEMPLATE NAME) +or the NAME may be omitted. The optional 3rd parameter +can be used to specify the parent mode of MODE. That is, +when looking a snippet in MODE failed, it can refer to +its parent mode. The PARENT-MODE may not need to be a +real mode." + (let ((snippet-table (yas/snippet-table mode)) + (parent-table (if parent-mode + (yas/snippet-table parent-mode) + nil)) + (keymap (if yas/use-menu + (yas/menu-keymap-for-mode mode) + nil))) + (when parent-table + (setf (yas/snippet-table-parent snippet-table) + parent-table) + (when yas/use-menu + (define-key keymap (vector 'parent-mode) + `(menu-item "parent mode" + ,(yas/menu-keymap-for-mode parent-mode))))) + (when yas/use-menu + (define-key yas/menu-keymap (vector mode) + `(menu-item ,(symbol-name mode) ,keymap))) + (dolist (snippet snippets) + (let* ((full-key (car snippet)) + (key (file-name-sans-extension full-key)) + (name (caddr snippet)) + (template (yas/make-template (cadr snippet) + (or name key)))) + (yas/snippet-table-store snippet-table + full-key + key + template) + (when yas/use-menu + (define-key keymap (vector (make-symbol full-key)) + `(menu-item ,(yas/template-name template) + ,(yas/make-menu-binding (yas/template-content template)) + :keys ,(concat key yas/trigger-symbol)))))))) + (defun yas/define (mode key template &optional name) "Define a snippet. Expanding KEY into TEMPLATE. NAME is a description to this template. Also update the menu if `yas/use-menu' is `t'." - (let* ((full-key key) - (key (file-name-sans-extension full-key)) - (template (yas/make-template template (or name key))) - (snippet-table (yas/snippet-table mode))) - (puthash key - (yas/modify-alist (gethash key snippet-table) - full-key - template) - snippet-table) - (when yas/use-menu - (let ((keymap (yas/menu-keymap-for-mode mode))) - (define-key yas/menu-keymap (vector mode) - `(menu-item ,(symbol-name mode) ,keymap)) - (define-key keymap (vector (make-symbol full-key)) - `(menu-item ,(yas/template-name template) - ,(yas/make-menu-binding (yas/template-content template)) - :keys ,(concat key yas/trigger-symbol))))))) + (yas/define-snippets mode + (list key template name))) + (defun yas/expand () "Expand a snippet." (interactive) (multiple-value-bind (key start end) (yas/current-key) - (let ((templates (gethash key (yas/current-snippet-table)))) + (let ((templates (yas/snippet-table-fetch (yas/current-snippet-table) + key))) (if templates (let ((template (if (null (cdr templates)) ; only 1 template (yas/template-content (cdar templates))