popup menu works like a charm

This commit is contained in:
Zhang Chiyuan 2008-03-06 12:55:21 +00:00
parent c9dd0b38ef
commit 83659ba159
2 changed files with 55 additions and 36 deletions

View File

@ -0,0 +1,3 @@
#name : background-image: ...
# --
background-image: url($1);

View File

@ -63,7 +63,7 @@ mode will be listed under the menu \"yasnippet\".")
"A hash table of snippet tables corresponding to each major-mode.") "A hash table of snippet tables corresponding to each major-mode.")
(defvar yas/menu-table (make-hash-table) (defvar yas/menu-table (make-hash-table)
"A hash table of menus of corresponding major-mode.") "A hash table of menus of corresponding major-mode.")
(defvar yas/menu-keymap (make-sparse-keymap)) (defvar yas/menu-keymap (make-sparse-keymap "YASnippet"))
;; empty menu will cause problems, so we insert some items ;; empty menu will cause problems, so we insert some items
(define-key yas/menu-keymap [yas/about] (define-key yas/menu-keymap [yas/about]
'(menu-item "About" yas/about)) '(menu-item "About" yas/about))
@ -202,13 +202,9 @@ have, compare through the start point of the overlay."
"Get the menu keymap correspondong to MODE." "Get the menu keymap correspondong to MODE."
(let ((keymap (gethash mode yas/menu-table))) (let ((keymap (gethash mode yas/menu-table)))
(unless keymap (unless keymap
(setq table (make-sparse-keymap)) (setq keymap (make-sparse-keymap))
(puthash mode keymap yas/menu-table)) (puthash mode keymap yas/menu-table))
table)) keymap))
(defsubst yas/template (key snippet-table)
"Get template for KEY in SNIPPET-TABLE."
(gethash key snippet-table))
(defun yas/current-key () (defun yas/current-key ()
"Get the key under current position. A key is used to find "Get the key under current position. A key is used to find
@ -538,6 +534,33 @@ an example:
(point) (point)
template)))) template))))
(defun yas/modify-alist (alist key value)
"Modify ALIST to map KEY to VALUE. return the new alist."
(let ((pair (assoc key alist)))
(if (null pair)
(cons (cons key value)
alist)
(setcdr pair value)
alist)))
(defun yas/fake-keymap-for-popup (templates)
"Create a fake keymap for popup menu usage."
(cons 'keymap
(cons "Select a template:"
(mapcar (lambda (pair)
(let* ((template (cdr pair))
(name (yas/template-name template))
(content (yas/template-content template)))
(list content 'menu-item name t)))
templates))))
(defun yas/popup-for-template (templates)
"Show a popup menu listing templates to let the user select one."
(if window-system
(car (x-popup-menu t (yas/fake-keymap-for-popup templates)))
;; no window system, simply select the first one
(cdar templates)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User level functions ;; User level functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -559,15 +582,20 @@ an example:
"Define a snippet. Expanding KEY into TEMPLATE. "Define a snippet. Expanding KEY into TEMPLATE.
NAME is a description to this template. Also update NAME is a description to this template. Also update
the menu if `yas/use-menu' is `t'." the menu if `yas/use-menu' is `t'."
(let ((template (yas/make-template template (or name key)))) (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 (puthash key
template (yas/modify-alist (gethash key snippet-table)
(yas/snippet-table mode)) full-key
template)
snippet-table)
(when yas/use-menu (when yas/use-menu
(let ((keymap (yas/menu-keymap-for-mode mode))) (let ((keymap (yas/menu-keymap-for-mode mode)))
(define-key yas/menu-keymap (vector mode) (define-key yas/menu-keymap (vector mode)
`(menu-item ,(symbol-name mode) ,keymap)) `(menu-item ,(symbol-name mode) ,keymap))
(define-key keymap (vector (make-symbol key)) (define-key keymap (vector (make-symbol full-key))
`(menu-item ,(yas/template-name template) `(menu-item ,(yas/template-name template)
,(yas/make-menu-binding (yas/template-content template)) ,(yas/make-menu-binding (yas/template-content template))
:keys ,(concat key yas/trigger-symbol))))))) :keys ,(concat key yas/trigger-symbol)))))))
@ -577,9 +605,13 @@ the menu if `yas/use-menu' is `t'."
otherwise, nil returned." otherwise, nil returned."
(interactive) (interactive)
(multiple-value-bind (key start end) (yas/current-key) (multiple-value-bind (key start end) (yas/current-key)
(let ((template (yas/template key (yas/current-snippet-table)))) (let ((templates (gethash key (yas/current-snippet-table))))
(if template (if templates
(yas/expand-snippet start end (yas/template-content template)) (let ((template (if (null (cdr templates)) ; only 1 template
(cdar templates)
(yas/popup-for-template templates))))
(when template
(yas/expand-snippet start end template)))
(when yas/trigger-fallback (when yas/trigger-fallback
(call-interactively yas/trigger-fallback)))))) (call-interactively yas/trigger-fallback))))))
@ -644,30 +676,14 @@ of a snippet. The file name is the trigger key and the
content of the file is the template." content of the file is the template."
(with-temp-buffer (with-temp-buffer
(dolist (mode (yas/directory-files directory nil)) (dolist (mode (yas/directory-files directory nil))
(let* ((mode-sym (intern (file-name-nondirectory mode))) (let ((mode-sym (intern (file-name-nondirectory mode))))
(snippet-table (yas/snippet-table mode-sym)) (dolist (file (yas/directory-files mode t))
(keymap (if yas/use-menu (when (file-readable-p file)
(yas/menu-keymap-for-mode mode-sym) (insert-file-contents file nil nil nil t)
nil)))
(dolist (key (yas/directory-files mode t))
(when (file-readable-p key)
(insert-file-contents key nil nil nil t)
(multiple-value-bind (multiple-value-bind
(key template name) (key template name)
(cons (file-name-sans-extension (cons (file-name-nondirectory file)
(file-name-nondirectory key))
(yas/parse-template)) (yas/parse-template))
(puthash key (yas/define mode-sym key template name))))))))
(yas/make-template
template
(or name key))
snippet-table)
(when yas/use-menu
(define-key yas/menu-keymap (vector mode-sym)
`(menu-item ,(symbol-name mode-sym) ,keymap))
(define-key keymap (vector (make-symbol key))
`(menu-item ,(or name key)
,(yas/make-menu-binding template)
:keys ,(concat key yas/trigger-symbol)))))))))))
(provide 'yasnippet) (provide 'yasnippet)