/vendor/yasnippet/yasnippet.el

http://github.com/rejeep/emacs · Emacs Lisp · 3676 lines · 2704 code · 437 blank · 535 comment · 79 complexity · b772cd5ccc2eb9cb7294e279dfa92b89 MD5 · raw file

Large files are truncated click here to view the full file

  1. ;;; Yasnippet.el --- Yet another snippet extension for Emacs.
  2. ;; Copyright 2008 pluskid
  3. ;; 2009 pluskid, joaotavora
  4. ;; Authors: pluskid <pluskid@gmail.com>, joaotavora <joaotavora@gmail.com>
  5. ;; Version: 0.6.1
  6. ;; Package-version: 0.6.1c
  7. ;; X-URL: http://code.google.com/p/yasnippet/
  8. ;; Keywords: convenience, emulation
  9. ;; URL: http://code.google.com/p/yasnippet/
  10. ;; EmacsWiki: YaSnippetMode
  11. ;; This file is free software; you can redistribute it and/or modify
  12. ;; it under the terms of the GNU General Public License as published by
  13. ;; the Free Software Foundation; either version 2, or (at your option)
  14. ;; any later version.
  15. ;; This file is distributed in the hope that it will be useful,
  16. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. ;; GNU General Public License for more details.
  19. ;; You should have received a copy of the GNU General Public License
  20. ;; along with GNU Emacs; see the file COPYING. If not, write to
  21. ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  22. ;; Boston, MA 02111-1307, USA.
  23. ;;; Commentary:
  24. ;; Basic steps to setup:
  25. ;;
  26. ;; 1. In your .emacs file:
  27. ;; (add-to-list 'load-path "/dir/to/yasnippet.el")
  28. ;; (require 'yasnippet)
  29. ;; 2. Place the `snippets' directory somewhere. E.g: ~/.emacs.d/snippets
  30. ;; 3. In your .emacs file
  31. ;; (setq yas/root-directory "~/.emacs/snippets")
  32. ;; (yas/load-directory yas/root-directory)
  33. ;; 4. To enable the YASnippet menu and tab-trigger expansion
  34. ;; M-x yas/minor-mode
  35. ;; 5. To globally enable the minor mode in *all* buffers
  36. ;; M-x yas/global-mode
  37. ;;
  38. ;; Steps 4. and 5. are optional, you don't have to use the minor
  39. ;; mode to use YASnippet.
  40. ;;
  41. ;; Interesting variables are:
  42. ;;
  43. ;; `yas/root-directory'
  44. ;;
  45. ;; The directory where user-created snippets are to be
  46. ;; stored. Can also be a list of directories that
  47. ;; `yas/reload-all' will use for bulk-reloading snippets. In
  48. ;; that case the first directory the default for storing new
  49. ;; snippets.
  50. ;;
  51. ;; `yas/mode-symbol'
  52. ;;
  53. ;; A local variable that you can set in a hook to override
  54. ;; snippet-lookup based on major mode. It is a a symbol (or
  55. ;; list of symbols) that correspond to subdirectories of
  56. ;; `yas/root-directory' and is used for deciding which
  57. ;; snippets to consider for the active buffer.
  58. ;;
  59. ;; Major commands are:
  60. ;;
  61. ;; M-x yas/expand
  62. ;;
  63. ;; Try to expand snippets before point. In `yas/minor-mode',
  64. ;; this is bound to `yas/trigger-key' which you can customize.
  65. ;;
  66. ;; M-x yas/load-directory
  67. ;;
  68. ;; Prompts you for a directory hierarchy of snippets to load.
  69. ;;
  70. ;; M-x yas/insert-snippet
  71. ;;
  72. ;; Prompts you for possible snippet expansion if that is
  73. ;; possible according to buffer-local and snippet-local
  74. ;; expansion conditions. With prefix argument, ignore these
  75. ;; conditions.
  76. ;;
  77. ;; M-x yas/find-snippets
  78. ;;
  79. ;; Lets you find the snippet files in the correct
  80. ;; subdirectory of `yas/root-directory', according to the
  81. ;; active major mode (if it exists) like
  82. ;; `find-file-other-window'.
  83. ;;
  84. ;; M-x yas/visit-snippet-file
  85. ;;
  86. ;; Prompts you for possible snippet expansions like
  87. ;; `yas/insert-snippet', but instead of expanding it, takes
  88. ;; you directly to the snippet definition's file, if it
  89. ;; exists.
  90. ;;
  91. ;; M-x yas/new-snippet
  92. ;;
  93. ;; Lets you create a new snippet file in the correct
  94. ;; subdirectory of `yas/root-directory', according to the
  95. ;; active major mode.
  96. ;;
  97. ;; M-x yas/load-snippet-buffer
  98. ;;
  99. ;; When editing a snippet, this loads the snippet. This is
  100. ;; bound to "C-c C-c" while in the `snippet-mode' editing
  101. ;; mode.
  102. ;;
  103. ;; M-x yas/tryout-snippet
  104. ;;
  105. ;; When editing a snippet, this opens a new empty buffer,
  106. ;; sets it to the appropriate major mode and inserts the
  107. ;; snippet there, so you can see what it looks like. This is
  108. ;; bound to "C-c C-t" while in `snippet-mode'.
  109. ;;
  110. ;; The `dropdown-list.el' extension is bundled with YASnippet, you
  111. ;; can optionally use it the preferred "prompting method", puting in
  112. ;; your .emacs file, for example:
  113. ;;
  114. ;; (require 'dropdown-list)
  115. ;; (setq yas/prompt-functions '(yas/dropdown-prompt
  116. ;; yas/ido-prompt
  117. ;; yas/completing-prompt))
  118. ;;
  119. ;; Also check out the customization group
  120. ;;
  121. ;; M-x customize-group RET yasnippet RET
  122. ;;
  123. ;; If you use the customization group to set variables
  124. ;; `yas/root-directory' or `yas/global-mode', make sure the path to
  125. ;; "yasnippet.el" is present in the `load-path' *before* the
  126. ;; `custom-set-variables' is executed in your .emacs file.
  127. ;;
  128. ;; For more information and detailed usage, refer to the project page:
  129. ;; http://code.google.com/p/yasnippet/
  130. ;;; Code:
  131. (require 'cl)
  132. (require 'assoc)
  133. (require 'easymenu)
  134. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  135. ;; User customizable variables
  136. (defgroup yasnippet nil
  137. "Yet Another Snippet extension"
  138. :group 'editing)
  139. ;;;###autoload
  140. (defcustom yas/root-directory nil
  141. "Root directory that stores the snippets for each major mode.
  142. If you set this from your .emacs, can also be a list of strings,
  143. for multiple root directories. If you make this a list, the first
  144. element is always the user-created snippets directory. Other
  145. directories are used for bulk reloading of all snippets using
  146. `yas/reload-all'"
  147. :type '(choice (string :tag "Single directory (string)")
  148. (repeat :args (string) :tag "List of directories (strings)"))
  149. :group 'yasnippet
  150. :require 'yasnippet
  151. :set #'(lambda (symbol new)
  152. (let ((old (and (boundp symbol)
  153. (symbol-value symbol))))
  154. (set-default symbol new)
  155. (unless (or (not (fboundp 'yas/reload-all))
  156. (equal old new))
  157. (yas/reload-all)))))
  158. (defcustom yas/prompt-functions '(yas/x-prompt
  159. yas/dropdown-prompt
  160. yas/completing-prompt
  161. yas/ido-prompt
  162. yas/no-prompt)
  163. "Functions to prompt for keys, templates, etc interactively.
  164. These functions are called with the following arguments:
  165. - PROMPT: A string to prompt the user
  166. - CHOICES: a list of strings or objects.
  167. - optional DISPLAY-FN : A function that, when applied to each of
  168. the objects in CHOICES will return a string.
  169. The return value of any function you put here should be one of
  170. the objects in CHOICES, properly formatted with DISPLAY-FN (if
  171. that is passed).
  172. - To signal that your particular style of prompting is
  173. unavailable at the moment, you can also have the function return
  174. nil.
  175. - To signal that the user quit the prompting process, you can
  176. signal `quit' with
  177. (signal 'quit \"user quit!\")."
  178. :type '(repeat function)
  179. :group 'yasnippet)
  180. (defcustom yas/indent-line 'auto
  181. "Controls indenting applied to a recent snippet expansion.
  182. The following values are possible:
  183. - `fixed' Indent the snippet to the current column;
  184. - `auto' Indent each line of the snippet with `indent-according-to-mode'
  185. Every other value means don't apply any snippet-side indendation
  186. after expansion (the manual per-line \"$>\" indentation still
  187. applies)."
  188. :type '(choice (const :tag "Nothing" nothing)
  189. (const :tag "Fixed" fixed)
  190. (const :tag "Auto" auto))
  191. :group 'yasnippet)
  192. (defcustom yas/also-auto-indent-first-line nil
  193. "Non-nil means also auto indent first line according to mode.
  194. Naturally this is only valid when `yas/indent-line' is `auto'"
  195. :type 'boolean
  196. :group 'yasnippet)
  197. (defcustom yas/snippet-revival t
  198. "Non-nil means re-activate snippet fields after undo/redo."
  199. :type 'boolean
  200. :group 'yasnippet)
  201. (defcustom yas/trigger-key "TAB"
  202. "The key bound to `yas/expand' when function `yas/minor-mode' is active.
  203. Value is a string that is converted to the internal Emacs key
  204. representation using `read-kbd-macro'."
  205. :type 'string
  206. :group 'yasnippet
  207. :set #'(lambda (symbol key)
  208. (let ((old (and (boundp symbol)
  209. (symbol-value symbol))))
  210. (set-default symbol key)
  211. ;; On very first loading of this defcustom,
  212. ;; `yas/trigger-key' is *not* loaded.
  213. (if (fboundp 'yas/trigger-key-reload)
  214. (yas/trigger-key-reload old)))))
  215. (defcustom yas/next-field-key '("TAB" "<tab>")
  216. "The key to navigate to next field when a snippet is active.
  217. Value is a string that is converted to the internal Emacs key
  218. representation using `read-kbd-macro'.
  219. Can also be a list of strings."
  220. :type '(choice (string :tag "String")
  221. (repeat :args (string) :tag "List of strings"))
  222. :group 'yasnippet
  223. :set #'(lambda (symbol val)
  224. (set-default symbol val)
  225. (if (fboundp 'yas/init-yas-in-snippet-keymap)
  226. (yas/init-yas-in-snippet-keymap))))
  227. (defcustom yas/prev-field-key '("<backtab>" "<S-tab>")
  228. "The key to navigate to previous field when a snippet is active.
  229. Value is a string that is converted to the internal Emacs key
  230. representation using `read-kbd-macro'.
  231. Can also be a list of strings."
  232. :type '(choice (string :tag "String")
  233. (repeat :args (string) :tag "List of strings"))
  234. :group 'yasnippet
  235. :set #'(lambda (symbol val)
  236. (set-default symbol val)
  237. (if (fboundp 'yas/init-yas-in-snippet-keymap)
  238. (yas/init-yas-in-snippet-keymap))))
  239. (defcustom yas/skip-and-clear-key "C-d"
  240. "The key to clear the currently active field.
  241. Value is a string that is converted to the internal Emacs key
  242. representation using `read-kbd-macro'.
  243. Can also be a list of strings."
  244. :type '(choice (string :tag "String")
  245. (repeat :args (string) :tag "List of strings"))
  246. :group 'yasnippet
  247. :set #'(lambda (symbol val)
  248. (set-default symbol val)
  249. (if (fboundp 'yas/init-yas-in-snippet-keymap)
  250. (yas/init-yas-in-snippet-keymap))))
  251. (defcustom yas/triggers-in-field nil
  252. "If non-nil, `yas/next-field-key' can trigger stacked expansions.
  253. Otherwise, `yas/next-field-key' just tries to move on to the next
  254. field"
  255. :type 'boolean
  256. :group 'yasnippet)
  257. (defcustom yas/fallback-behavior 'call-other-command
  258. "How to act when `yas/trigger-key' does *not* expand a snippet.
  259. - `call-other-command' means try to temporarily disable YASnippet
  260. and call the next command bound to `yas/trigger-key'.
  261. - nil or the symbol `return-nil' mean do nothing. (and
  262. `yas/expand-returns' nil)
  263. - A lisp form (apply COMMAND . ARGS) means interactively call
  264. COMMAND, if ARGS is non-nil, call COMMAND non-interactively
  265. with ARGS as arguments."
  266. :type '(choice (const :tag "Call previous command" call-other-command)
  267. (const :tag "Do nothing" return-nil))
  268. :group 'yasnippet)
  269. (make-variable-buffer-local 'yas/fallback-behavior)
  270. (defcustom yas/choose-keys-first nil
  271. "If non-nil, prompt for snippet key first, then for template.
  272. Otherwise prompts for all possible snippet names.
  273. This affects `yas/insert-snippet' and `yas/visit-snippet-file'."
  274. :type 'boolean
  275. :group 'yasnippet)
  276. (defcustom yas/choose-tables-first nil
  277. "If non-nil, and multiple eligible snippet tables, prompts user for tables first.
  278. Otherwise, user chooses between the merging together of all
  279. eligible tables.
  280. This affects `yas/insert-snippet', `yas/visit-snippet-file'"
  281. :type 'boolean
  282. :group 'yasnippet)
  283. (defcustom yas/use-menu 'real-modes
  284. "Display a YASnippet menu in the menu bar.
  285. When non-nil, submenus for each snippet table will be listed
  286. under the menu \"Yasnippet\".
  287. - If set to `real-modes' only submenus whose name more or less
  288. corresponds to a major mode are listed.
  289. - If set to `abbreviate', only the current major-mode
  290. menu and the modes set in `yas/mode-symbol' are listed.
  291. Any other non-nil value, every submenu is listed."
  292. :type '(choice (const :tag "Full" t)
  293. (const :tag "Real modes only" real-modes)
  294. (const :tag "Abbreviate" abbreviate))
  295. :group 'yasnippet)
  296. (defcustom yas/trigger-symbol " =>"
  297. "The text that will be used in menu to represent the trigger."
  298. :type 'string
  299. :group 'yasnippet)
  300. (defcustom yas/wrap-around-region nil
  301. "If non-nil, snippet expansion wraps around selected region.
  302. The wrapping occurs just before the snippet's exit marker. This
  303. can be overriden on a per-snippet basis."
  304. :type 'boolean
  305. :group 'yasnippet)
  306. (defcustom yas/good-grace t
  307. "If non-nil, don't raise errors in inline elisp evaluation.
  308. An error string \"[yas] error\" is returned instead."
  309. :type 'boolean
  310. :group 'yasnippet)
  311. (defcustom yas/ignore-filenames-as-triggers nil
  312. "If non-nil, don't derive tab triggers from filenames.
  313. This means a snippet without a \"# key:'\ directive wont have a
  314. tab trigger."
  315. :type 'boolean
  316. :group 'yasnippet)
  317. (defcustom yas/visit-from-menu nil
  318. "If non-nil visit snippets's files from menu, instead of expanding them.
  319. This cafn only work when snippets are loaded from files."
  320. :type 'boolean
  321. :group 'yasnippet)
  322. (defface yas/field-highlight-face
  323. '((((class color) (background light)) (:background "DarkSeaGreen1"))
  324. (t (:background "DimGrey")))
  325. "The face used to highlight the currently active field of a snippet"
  326. :group 'yasnippet)
  327. (defface yas/field-debug-face
  328. '()
  329. "The face used for debugging some overlays normally hidden"
  330. :group 'yasnippet)
  331. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  332. ;; User can also customize the next defvars
  333. (defun yas/define-some-keys (keys keymap definition)
  334. "Bind KEYS to DEFINITION in KEYMAP, read with `read-kbd-macro'."
  335. (let ((keys (or (and (listp keys) keys)
  336. (list keys))))
  337. (dolist (key keys)
  338. (define-key keymap (read-kbd-macro key) definition))))
  339. (defvar yas/keymap
  340. (let ((map (make-sparse-keymap)))
  341. (mapc #'(lambda (binding)
  342. (yas/define-some-keys (car binding) map (cdr binding)))
  343. `((,yas/next-field-key . yas/next-field-or-maybe-expand)
  344. (,yas/prev-field-key . yas/prev-field)
  345. ("C-g" . yas/abort-snippet)
  346. (,yas/skip-and-clear-key . yas/skip-and-clear-or-delete-char)))
  347. map)
  348. "The keymap active while a snippet expansion is in progress.")
  349. (defvar yas/key-syntaxes (list "w" "w_" "w_." "^ ")
  350. "A list of syntax of a key. This list is tried in the order
  351. to try to find a key. For example, if the list is '(\"w\" \"w_\").
  352. And in emacs-lisp-mode, where \"-\" has the syntax of \"_\":
  353. foo-bar
  354. will first try \"bar\", if not found, then \"foo-bar\" is tried.")
  355. (defvar yas/after-exit-snippet-hook
  356. '()
  357. "Hooks to run after a snippet exited.
  358. The hooks will be run in an environment where some variables bound to
  359. proper values:
  360. `yas/snippet-beg' : The beginning of the region of the snippet.
  361. `yas/snippet-end' : Similar to beg.
  362. Attention: These hooks are not run when exiting nested/stackd snippet expansion!")
  363. (defvar yas/before-expand-snippet-hook
  364. '()
  365. "Hooks to run just before expanding a snippet.")
  366. (defvar yas/buffer-local-condition
  367. '(if (and (not (bobp))
  368. (or (equal 'font-lock-comment-face
  369. (get-char-property (1- (point))
  370. 'face))
  371. (equal 'font-lock-string-face
  372. (get-char-property (1- (point))
  373. 'face))))
  374. '(require-snippet-condition . force-in-comment)
  375. t)
  376. "Snippet expanding condition.
  377. This variable is a lisp form:
  378. * If it evaluates to nil, no snippets can be expanded.
  379. * If it evaluates to the a cons (require-snippet-condition
  380. . REQUIREMENT)
  381. * Snippets bearing no \"# condition:\" directive are not
  382. considered
  383. * Snippets bearing conditions that evaluate to nil (or
  384. produce an error) won't be onsidered.
  385. * If the snippet has a condition that evaluates to non-nil
  386. RESULT:
  387. * If REQUIREMENT is t, the snippet is considered
  388. * If REQUIREMENT is `eq' RESULT, the snippet is
  389. considered
  390. * Otherwise, the snippet is not considered.
  391. * If it evaluates to the symbol 'always, all snippets are
  392. considered for expansion, regardless of any conditions.
  393. * If it evaluates to t or some other non-nil value
  394. * Snippet bearing no conditions, or conditions that
  395. evaluate to non-nil, are considered for expansion.
  396. * Otherwise, the snippet is not considered.
  397. Here's an example preventing snippets from being expanded from
  398. inside comments, in `python-mode' only, with the exception of
  399. snippets returning the symbol 'force-in-comment in their
  400. conditions.
  401. (add-hook 'python-mode-hook
  402. '(lambda ()
  403. (setq yas/buffer-local-condition
  404. '(if (python-in-string/comment)
  405. '(require-snippet-condition . force-in-comment)
  406. t))))
  407. The default value is similar, it filters out potential snippet
  408. expansions inside comments and string literals, unless the
  409. snippet itself contains a condition that returns the symbol
  410. `force-in-comment'.")
  411. (make-variable-buffer-local 'yas/buffer-local-condition)
  412. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  413. ;; Internal variables
  414. (defvar yas/version "0.6.1b")
  415. (defvar yas/menu-table (make-hash-table)
  416. "A hash table of MAJOR-MODE symbols to menu keymaps.")
  417. (defvar yas/active-keybindings nil
  418. "A list of cons (KEYMAP . KEY) setup from defining snippets.")
  419. (defvar yas/known-modes
  420. '(ruby-mode rst-mode markdown-mode)
  421. "A list of mode which is well known but not part of emacs.")
  422. (defvar yas/escaped-characters
  423. '(?\\ ?` ?' ?$ ?} )
  424. "List of characters which *might* need to be escaped.")
  425. (defconst yas/field-regexp
  426. "${\\([0-9]+:\\)?\\([^}]*\\)}"
  427. "A regexp to *almost* recognize a field.")
  428. (defconst yas/multi-dollar-lisp-expression-regexp
  429. "$+[ \t\n]*\\(([^)]*)\\)"
  430. "A regexp to *almost* recognize a \"$(...)\" expression.")
  431. (defconst yas/backquote-lisp-expression-regexp
  432. "`\\([^`]*\\)`"
  433. "A regexp to recognize a \"`lisp-expression`\" expression." )
  434. (defconst yas/transform-mirror-regexp
  435. "${\\(?:\\([0-9]+\\):\\)?$\\([ \t\n]*([^}]*\\)"
  436. "A regexp to *almost* recognize a mirror with a transform.")
  437. (defconst yas/simple-mirror-regexp
  438. "$\\([0-9]+\\)"
  439. "A regexp to recognize a simple mirror.")
  440. (defvar yas/snippet-id-seed 0
  441. "Contains the next id for a snippet.")
  442. (defun yas/snippet-next-id ()
  443. (let ((id yas/snippet-id-seed))
  444. (incf yas/snippet-id-seed)
  445. id))
  446. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  447. ;; Minor mode stuff
  448. ;; XXX: `last-buffer-undo-list' is somehow needed in Carbon Emacs for MacOSX
  449. (defvar last-buffer-undo-list nil)
  450. (defvar yas/minor-mode-menu nil
  451. "Holds the YASnippet menu")
  452. (defun yas/init-minor-keymap ()
  453. (let ((map (make-sparse-keymap)))
  454. (easy-menu-define yas/minor-mode-menu
  455. map
  456. "Menu used when YAS/minor-mode is active."
  457. '("YASnippet"
  458. "----"
  459. ["Expand trigger" yas/expand
  460. :help "Possibly expand tab trigger before point"]
  461. ["Insert at point..." yas/insert-snippet
  462. :help "Prompt for an expandable snippet and expand it at point"]
  463. ["New snippet..." yas/new-snippet
  464. :help "Create a new snippet in an appropriate directory"]
  465. ["Visit snippet file..." yas/visit-snippet-file
  466. :help "Prompt for an expandable snippet and find its file"]
  467. ["Find snippets..." yas/find-snippets
  468. :help "Invoke `find-file' in the appropriate snippet directory"]
  469. "----"
  470. ("Snippet menu behaviour"
  471. ["Visit snippets" (setq yas/visit-from-menu t)
  472. :help "Visit snippets from the menu"
  473. :active t :style radio :selected yas/visit-from-menu]
  474. ["Expand snippets" (setq yas/visit-from-menu nil)
  475. :help "Expand snippets from the menu"
  476. :active t :style radio :selected (not yas/visit-from-menu)]
  477. "----"
  478. ["Show \"Real\" modes only" (setq yas/use-menu 'real-modes)
  479. :help "Show snippet submenus for modes that appear to be real major modes"
  480. :active t :style radio :selected (eq yas/use-menu 'real-modes)]
  481. ["Show all modes" (setq yas/use-menu 't)
  482. :help "Show one snippet submenu for each loaded table"
  483. :active t :style radio :selected (eq yas/use-menu 't)]
  484. ["Abbreviate according to current mode" (setq yas/use-menu 'abbreviate)
  485. :help "Show only snippet submenus for the current active modes"
  486. :active t :style radio :selected (eq yas/use-menu 'abbreviate)])
  487. ("Indenting"
  488. ["Auto" (setq yas/indent-line 'auto)
  489. :help "Indent each line of the snippet with `indent-according-to-mode'"
  490. :active t :style radio :selected (eq yas/indent-line 'auto)]
  491. ["Fixed" (setq yas/indent-line 'fixed)
  492. :help "Indent the snippet to the current column"
  493. :active t :style radio :selected (eq yas/indent-line 'fixed)]
  494. ["None" (setq yas/indent-line 'none)
  495. :help "Don't apply any particular snippet indentation after expansion"
  496. :active t :style radio :selected (not (member yas/indent-line '(fixed auto)))]
  497. "----"
  498. ["Also auto indent first line" (setq yas/also-auto-indent-first-line
  499. (not yas/also-auto-indent-first-line))
  500. :help "When auto-indenting also, auto indent the first line menu"
  501. :active (eq yas/indent-line 'auto)
  502. :style toggle :selected yas/also-auto-indent-first-line]
  503. )
  504. ("Prompting method"
  505. ["System X-widget" (setq yas/prompt-functions
  506. (cons 'yas/x-prompt
  507. (remove 'yas/x-prompt
  508. yas/prompt-functions)))
  509. :help "Use your windowing system's (gtk, mac, windows, etc...) default menu"
  510. :active t :style radio :selected (eq (car yas/prompt-functions)
  511. 'yas/x-prompt)]
  512. ["Dropdown-list" (setq yas/prompt-functions
  513. (cons 'yas/dropdown-prompt
  514. (remove 'yas/dropdown-prompt
  515. yas/prompt-functions)))
  516. :help "Use a special dropdown list"
  517. :active t :style radio :selected (eq (car yas/prompt-functions)
  518. 'yas/dropdown-prompt)]
  519. ["Ido" (setq yas/prompt-functions
  520. (cons 'yas/ido-prompt
  521. (remove 'yas/ido-prompt
  522. yas/prompt-functions)))
  523. :help "Use an ido-style minibuffer prompt"
  524. :active t :style radio :selected (eq (car yas/prompt-functions)
  525. 'yas/ido-prompt)]
  526. ["Completing read" (setq yas/prompt-functions
  527. (cons 'yas/completing-prompt
  528. (remove 'yas/completing-prompt-prompt
  529. yas/prompt-functions)))
  530. :help "Use a normal minibuffer prompt"
  531. :active t :style radio :selected (eq (car yas/prompt-functions)
  532. 'yas/completing-prompt-prompt)]
  533. )
  534. ("Misc"
  535. ["Wrap region in exit marker"
  536. (setq yas/wrap-around-region
  537. (not yas/wrap-around-region))
  538. :help "If non-nil automatically wrap the selected text in the $0 snippet exit"
  539. :style toggle :selected yas/wrap-around-region]
  540. ["Allow stacked expansions "
  541. (setq yas/triggers-in-field
  542. (not yas/triggers-in-field))
  543. :help "If non-nil allow snippets to be triggered inside other snippet fields"
  544. :style toggle :selected yas/triggers-in-field]
  545. ["Revive snippets on undo "
  546. (setq yas/snippet-revival
  547. (not yas/snippet-revival))
  548. :help "If non-nil allow snippets to become active again after undo"
  549. :style toggle :selected yas/snippet-revival]
  550. ["Good grace "
  551. (setq yas/good-grace
  552. (not yas/good-grace))
  553. :help "If non-nil don't raise errors in bad embedded eslip in snippets"
  554. :style toggle :selected yas/good-grace]
  555. ["Ignore filenames as triggers"
  556. (setq yas/ignore-filenames-as-triggers
  557. (not yas/ignore-filenames-as-triggers))
  558. :help "If non-nil don't derive tab triggers from filenames"
  559. :style toggle :selected yas/ignore-filenames-as-triggers]
  560. )
  561. "----"
  562. ["Load snippets..." yas/load-directory
  563. :help "Load snippets from a specific directory"]
  564. ["Reload everything" yas/reload-all
  565. :help "Cleanup stuff, reload snippets, rebuild menus"]
  566. ["About" yas/about
  567. :help "Display some information about YASsnippet"]))
  568. ;; Now for the stuff that has direct keybindings
  569. ;;
  570. (define-key map "\C-c&\C-s" 'yas/insert-snippet)
  571. (define-key map "\C-c&\C-n" 'yas/new-snippet)
  572. (define-key map "\C-c&\C-v" 'yas/visit-snippet-file)
  573. (define-key map "\C-c&\C-f" 'yas/find-snippets)
  574. map))
  575. (defvar yas/minor-mode-map (yas/init-minor-keymap)
  576. "The keymap used when `yas/minor-mode' is active.")
  577. (defun yas/trigger-key-reload (&optional unbind-key)
  578. "Rebind `yas/expand' to the new value of `yas/trigger-key'.
  579. With optional UNBIND-KEY, try to unbind that key from
  580. `yas/minor-mode-map'."
  581. (when (and unbind-key
  582. (stringp unbind-key)
  583. (not (string= unbind-key "")))
  584. (define-key yas/minor-mode-map (read-kbd-macro unbind-key) nil))
  585. (when (and yas/trigger-key
  586. (stringp yas/trigger-key)
  587. (not (string= yas/trigger-key "")))
  588. (define-key yas/minor-mode-map (read-kbd-macro yas/trigger-key) 'yas/expand)))
  589. ;;;###autoload
  590. (define-minor-mode yas/minor-mode
  591. "Toggle YASnippet mode.
  592. When YASnippet mode is enabled, the `tas/trigger-key' key expands
  593. snippets of code depending on the mode.
  594. With no argument, this command toggles the mode.
  595. positive prefix argument turns on the mode.
  596. Negative prefix argument turns off the mode.
  597. You can customize the key through `yas/trigger-key'.
  598. Key bindings:
  599. \\{yas/minor-mode-map}"
  600. nil
  601. ;; The indicator for the mode line.
  602. " yas"
  603. :group 'yasnippet
  604. (when yas/minor-mode
  605. (yas/trigger-key-reload)
  606. ;; load all snippets definitions unless we still don't have a
  607. ;; root-directory or some snippets have already been loaded.
  608. (unless (or (null yas/root-directory)
  609. (> (hash-table-count yas/snippet-tables) 0))
  610. (yas/reload-all))))
  611. (defvar yas/dont-activate #'(lambda ()
  612. (and yas/root-directory
  613. (null (yas/get-snippet-tables))))
  614. "If non-nil don't let `yas/minor-mode-on' active yas for this buffer.
  615. `yas/minor-mode-on' is usually called by `yas/global-mode' so
  616. this effectively lets you define exceptions to the \"global\"
  617. behaviour.")
  618. (make-variable-buffer-local 'yas/dont-activate)
  619. (defun yas/minor-mode-on ()
  620. "Turn on YASnippet minor mode.
  621. Do this unless `yas/dont-activate' is t or the function
  622. `yas/get-snippet-tables' (which see), returns an empty list."
  623. (interactive)
  624. (unless (or (and (functionp yas/dont-activate)
  625. (funcall yas/dont-activate))
  626. (and (not (functionp yas/dont-activate))
  627. yas/dont-activate))
  628. (yas/minor-mode 1)))
  629. (defun yas/minor-mode-off ()
  630. "Turn off YASnippet minor mode."
  631. (interactive)
  632. (yas/minor-mode -1))
  633. (define-globalized-minor-mode yas/global-mode yas/minor-mode yas/minor-mode-on
  634. :group 'yasnippet
  635. :require 'yasnippet)
  636. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  637. ;; Major mode stuff
  638. ;;
  639. (defvar yas/font-lock-keywords
  640. (append '(("^#.*$" . font-lock-comment-face))
  641. lisp-font-lock-keywords
  642. lisp-font-lock-keywords-1
  643. lisp-font-lock-keywords-2
  644. '(("$\\([0-9]+\\)"
  645. (0 font-lock-keyword-face)
  646. (1 font-lock-string-face t))
  647. ("${\\([0-9]+\\):?"
  648. (0 font-lock-keyword-face)
  649. (1 font-lock-warning-face t))
  650. ("${" font-lock-keyword-face)
  651. ("$[0-9]+?" font-lock-preprocessor-face)
  652. ("\\(\\$(\\)" 1 font-lock-preprocessor-face)
  653. ("}"
  654. (0 font-lock-keyword-face)))))
  655. (defun yas/init-major-keymap ()
  656. (let ((map (make-sparse-keymap)))
  657. (easy-menu-define nil
  658. map
  659. "Menu used when snippet-mode is active."
  660. (cons "Snippet"
  661. (mapcar #'(lambda (ent)
  662. (when (third ent)
  663. (define-key map (third ent) (second ent)))
  664. (vector (first ent) (second ent) t))
  665. (list
  666. (list "Load this snippet" 'yas/load-snippet-buffer "\C-c\C-c")
  667. (list "Try out this snippet" 'yas/tryout-snippet "\C-c\C-t")))))
  668. map))
  669. (defvar snippet-mode-map
  670. (yas/init-major-keymap)
  671. "The keymap used when `snippet-mode' is active")
  672. (define-derived-mode snippet-mode text-mode "Snippet"
  673. "A mode for editing yasnippets"
  674. (set-syntax-table (standard-syntax-table))
  675. (setq font-lock-defaults '(yas/font-lock-keywords))
  676. (set (make-local-variable 'require-final-newline) nil)
  677. (use-local-map snippet-mode-map))
  678. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  679. ;; Internal structs for template management
  680. (defstruct (yas/template (:constructor yas/make-template
  681. (content name condition expand-env file keybinding)))
  682. "A template for a snippet."
  683. content
  684. name
  685. condition
  686. expand-env
  687. file
  688. keybinding)
  689. (defvar yas/snippet-tables (make-hash-table)
  690. "A hash table of MAJOR-MODE symbols to `yas/snippet-table' objects.")
  691. (defstruct (yas/snippet-table (:constructor yas/make-snippet-table (name)))
  692. "A table to store snippets for a particular mode.
  693. Has the following fields:
  694. `yas/snippet-table-name'
  695. A symbol normally corresponding to a major mode, but can also be
  696. a pseudo major-mode to be referenced in `yas/mode-symbol', for
  697. example.
  698. `yas/snippet-table-hash'
  699. A hash table the key is a string (the snippet key) and the
  700. value is yet another hash of (NAME TEMPLATE), where NAME is the
  701. snippet name and TEMPLATE is a `yas/template' object name.
  702. `yas/snippet-table-parents'
  703. A list of tables considered parents of this table: i.e. when
  704. searching for expansions they are searched as well."
  705. name
  706. (hash (make-hash-table :test 'equal))
  707. (parents nil))
  708. (defvar yas/better-guess-for-replacements nil
  709. "If non-nil `yas/store' better guess snippet replacements.")
  710. (defun yas/store (table name key template)
  711. "Store a snippet template in the TABLE."
  712. ;; This is dones by searching twice:
  713. ;;
  714. ;; * Try to get the existing namehash from TABLE using key.
  715. ;;
  716. ;; * Try to get the existing namehash from by searching the *whole*
  717. ;; snippet table for NAME. This is becuase they user might have
  718. ;; changed the key and that can no longer be used to locate the
  719. ;; previous `yas/template-structure'.
  720. ;;
  721. ;; * If that returns nothing, oh well...
  722. ;;
  723. (dolist (existing-namehash (remove nil (list (gethash key (yas/snippet-table-hash table))
  724. (when yas/better-guess-for-replacements
  725. (let (a)
  726. (maphash #'(lambda (key namehash)
  727. (when (gethash name namehash)
  728. (setq a namehash)))
  729. (yas/snippet-table-hash table))
  730. a)))))
  731. (let ((existing-template (gethash name existing-namehash)))
  732. (when existing-template
  733. ;; Remove the existing keybinding
  734. (when (yas/template-keybinding existing-template)
  735. (define-key
  736. (symbol-value (first (yas/template-keybinding existing-template)))
  737. (second (yas/template-keybinding existing-template))
  738. nil)
  739. (setq yas/active-keybindings
  740. (delete (yas/template-keybinding existing-template)
  741. yas/active-keybindings)))
  742. ;; Remove the (name . template) mapping from existing-namehash.
  743. (remhash name existing-namehash))))
  744. ;; Now store the new template independent of the previous steps.
  745. ;;
  746. (puthash name
  747. template
  748. (or (gethash key
  749. (yas/snippet-table-hash table))
  750. (puthash key
  751. (make-hash-table :test 'equal)
  752. (yas/snippet-table-hash table)))))
  753. (defun yas/fetch (table key)
  754. "Fetch a snippet binding to KEY from TABLE."
  755. (let* ((keyhash (yas/snippet-table-hash table))
  756. (namehash (and keyhash (gethash key keyhash))))
  757. (when namehash
  758. (yas/filter-templates-by-condition
  759. (let (alist)
  760. (maphash #'(lambda (k v)
  761. (push (cons k v) alist))
  762. namehash)
  763. alist)))))
  764. ;; Filtering/condition logic
  765. (defun yas/eval-condition (condition)
  766. (condition-case err
  767. (save-excursion
  768. (save-restriction
  769. (save-match-data
  770. (eval condition))))
  771. (error (progn
  772. (message (format "[yas] error in condition evaluation: %s"
  773. (error-message-string err)))
  774. nil))))
  775. (defun yas/filter-templates-by-condition (templates)
  776. "Filter the templates using the applicable condition.
  777. TEMPLATES is a list of cons (NAME . TEMPLATE) where NAME is a
  778. string and TEMPLATE is a `yas/template' structure.
  779. This function implements the rules described in
  780. `yas/buffer-local-condition'. See that variables documentation."
  781. (let ((requirement (yas/require-template-specific-condition-p)))
  782. (if (eq requirement 'always)
  783. templates
  784. (remove-if-not #'(lambda (pair)
  785. (yas/template-can-expand-p (yas/template-condition (cdr pair)) requirement))
  786. templates))))
  787. (defun yas/require-template-specific-condition-p ()
  788. "Decides if this buffer requests/requires snippet-specific
  789. conditions to filter out potential expansions."
  790. (if (eq 'always yas/buffer-local-condition)
  791. 'always
  792. (let ((local-condition (or (and (consp yas/buffer-local-condition)
  793. (yas/eval-condition yas/buffer-local-condition))
  794. yas/buffer-local-condition)))
  795. (when local-condition
  796. (if (eq local-condition t)
  797. t
  798. (and (consp local-condition)
  799. (eq 'require-snippet-condition (car local-condition))
  800. (symbolp (cdr local-condition))
  801. (cdr local-condition)))))))
  802. (defun yas/template-can-expand-p (condition &optional requirement)
  803. "Evaluates CONDITION and REQUIREMENT and returns a boolean"
  804. (let* ((requirement (or requirement
  805. (yas/require-template-specific-condition-p)))
  806. (result (or (null condition)
  807. (yas/eval-condition
  808. (condition-case err
  809. (read condition)
  810. (error (progn
  811. (message (format "[yas] error reading condition: %s"
  812. (error-message-string err))))
  813. nil))))))
  814. (cond ((eq requirement t)
  815. result)
  816. (t
  817. (eq requirement result)))))
  818. (defun yas/snippet-table-get-all-parents (table)
  819. (let ((parents (yas/snippet-table-parents table)))
  820. (when parents
  821. (append (copy-list parents)
  822. (mapcan #'yas/snippet-table-get-all-parents parents)))))
  823. (defun yas/snippet-table-templates (table)
  824. (when table
  825. (let ((acc (list)))
  826. (maphash #'(lambda (key namehash)
  827. (maphash #'(lambda (name template)
  828. (push (cons name template) acc))
  829. namehash))
  830. (yas/snippet-table-hash table))
  831. (yas/filter-templates-by-condition acc))))
  832. (defun yas/current-key ()
  833. "Get the key under current position. A key is used to find
  834. the template of a snippet in the current snippet-table."
  835. (let ((start (point))
  836. (end (point))
  837. (syntaxes yas/key-syntaxes)
  838. syntax
  839. done
  840. templates)
  841. (while (and (not done) syntaxes)
  842. (setq syntax (car syntaxes))
  843. (setq syntaxes (cdr syntaxes))
  844. (save-excursion
  845. (skip-syntax-backward syntax)
  846. (setq start (point)))
  847. (setq templates
  848. (mapcan #'(lambda (table)
  849. (yas/fetch table (buffer-substring-no-properties start end)))
  850. (yas/get-snippet-tables)))
  851. (if templates
  852. (setq done t)
  853. (setq start end)))
  854. (list templates
  855. start
  856. end)))
  857. (defun yas/snippet-table-all-keys (table)
  858. (when table
  859. (let ((acc))
  860. (maphash #'(lambda (key templates)
  861. (when (yas/filter-templates-by-condition templates)
  862. (push key acc)))
  863. (yas/snippet-table-hash table))
  864. acc)))
  865. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  866. ;; Internal functions
  867. (defun yas/real-mode? (mode)
  868. "Try to find out if MODE is a real mode. The MODE bound to
  869. a function (like `c-mode') is considered real mode. Other well
  870. known mode like `ruby-mode' which is not part of Emacs might
  871. not bound to a function until it is loaded. So yasnippet keeps
  872. a list of modes like this to help the judgement."
  873. (or (fboundp mode)
  874. (find mode yas/known-modes)))
  875. (defun yas/read-and-eval-string (string)
  876. ;; TODO: This is a possible optimization point, the expression could
  877. ;; be stored in cons format instead of string,
  878. "Evaluate STRING and convert the result to string."
  879. (let ((retval (catch 'yas/exception
  880. (condition-case err
  881. (save-excursion
  882. (save-restriction
  883. (save-match-data
  884. (widen)
  885. (let ((result (eval (read string))))
  886. (when result
  887. (format "%s" result))))))
  888. (error (if yas/good-grace
  889. "[yas] elisp error!"
  890. (error (format "[yas] elisp error: %s"
  891. (error-message-string err)))))))))
  892. (when (and (consp retval)
  893. (eq 'yas/exception (car retval)))
  894. (error (cdr retval)))
  895. retval))
  896. (defvar yas/mode-symbol nil
  897. "If non-nil, lookup snippets using this instead of `major-mode'.")
  898. (make-variable-buffer-local 'yas/mode-symbol)
  899. (defun yas/snippet-table-get-create (mode)
  900. "Get the snippet table corresponding to MODE.
  901. Optional DIRECTORY gets recorded as the default directory to
  902. search for snippet files if the retrieved/created table didn't
  903. already have such a property."
  904. (let ((table (gethash mode
  905. yas/snippet-tables)))
  906. (unless table
  907. (setq table (yas/make-snippet-table (symbol-name mode)))
  908. (puthash mode table yas/snippet-tables))
  909. table))
  910. (defun yas/get-snippet-tables (&optional mode-symbol dont-search-parents)
  911. "Get snippet tables for current buffer.
  912. Return a list of 'yas/snippet-table' objects indexed by mode.
  913. The modes are tried in this order: optional MODE-SYMBOL, then
  914. `yas/mode-symbol', then `major-mode' then, unless
  915. DONT-SEARCH-PARENTS is non-nil, the guessed parent mode of either
  916. MODE-SYMBOL or `major-mode'.
  917. Guessing is done by looking up the MODE-SYMBOL's
  918. `derived-mode-parent' property, see also `derived-mode-p'."
  919. (let ((mode-tables
  920. (mapcar #'(lambda (mode)
  921. (gethash mode yas/snippet-tables))
  922. (append (list mode-symbol)
  923. (if (listp yas/mode-symbol)
  924. yas/mode-symbol
  925. (list yas/mode-symbol))
  926. (list major-mode
  927. (and (not dont-search-parents)
  928. (get (or mode-symbol major-mode)
  929. 'derived-mode-parent))))))
  930. (all-tables))
  931. (dolist (table (remove nil mode-tables))
  932. (push table all-tables)
  933. (nconc all-tables (yas/snippet-table-get-all-parents table)))
  934. (remove-duplicates all-tables)))
  935. (defun yas/menu-keymap-get-create (mode)
  936. "Get the menu keymap correspondong to MODE."
  937. (or (gethash mode yas/menu-table)
  938. (puthash mode (make-sparse-keymap) yas/menu-table)))
  939. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  940. ;;; Template-related and snippet loading functions
  941. (defun yas/parse-template (&optional file)
  942. "Parse the template in the current buffer.
  943. Optional FILE is the absolute file name of the file being
  944. parsed.
  945. Return a snippet-definition, i.e. a list
  946. (KEY TEMPLATE NAME CONDITION GROUP VARS FILE KEYBINDING)
  947. If the buffer contains a line of \"# --\" then the contents
  948. above this line are ignored. Variables can be set above this
  949. line through the syntax:
  950. #name : value
  951. Here's a list of currently recognized variables:
  952. * name
  953. * contributor
  954. * condition
  955. * key
  956. * group
  957. * expand-env
  958. #name: #include \"...\"
  959. # --
  960. #include \"$1\""
  961. ;;
  962. ;;
  963. (goto-char (point-min))
  964. (let* ((name (and file
  965. (file-name-nondirectory file)))
  966. (key (unless yas/ignore-filenames-as-triggers
  967. (and name
  968. (file-name-sans-extension name))))
  969. template
  970. bound
  971. condition
  972. (group (and file
  973. (yas/calculate-group file)))
  974. expand-env
  975. binding)
  976. (if (re-search-forward "^# --\n" nil t)
  977. (progn (setq template
  978. (buffer-substring-no-properties (point)
  979. (point-max)))
  980. (setq bound (point))
  981. (goto-char (point-min))
  982. (while (re-search-forward "^# *\\([^ ]+?\\) *: *\\(.*\\)$" bound t)
  983. (when (string= "name" (match-string-no-properties 1))
  984. (setq name (match-string-no-properties 2)))
  985. (when (string= "condition" (match-string-no-properties 1))
  986. (setq condition (match-string-no-properties 2)))
  987. (when (string= "group" (match-string-no-properties 1))
  988. (setq group (match-string-no-properties 2)))
  989. (when (string= "expand-env" (match-string-no-properties 1))
  990. (setq expand-env (match-string-no-properties 2)))
  991. (when (string= "key" (match-string-no-properties 1))
  992. (setq key (match-string-no-properties 2)))
  993. (when (string= "binding" (match-string-no-properties 1))
  994. (setq binding (match-string-no-properties 2)))))
  995. (setq template
  996. (buffer-substring-no-properties (point-min) (point-max))))
  997. (list key template name condition group expand-env file binding)))
  998. (defun yas/calculate-group (file)
  999. "Calculate the group for snippet file path FILE."
  1000. (let* ((dominating-dir (locate-dominating-file file
  1001. ".yas-make-groups"))
  1002. (extra-path (and dominating-dir
  1003. (replace-regexp-in-string (concat "^"
  1004. (expand-file-name dominating-dir))
  1005. ""
  1006. (expand-file-name file))))
  1007. (extra-dir (and extra-path
  1008. (file-name-directory extra-path)))
  1009. (group (and extra-dir
  1010. (replace-regexp-in-string "/"
  1011. "."
  1012. (directory-file-name extra-dir)))))
  1013. group))
  1014. ;; (defun yas/glob-files (directory &optional recurse-p append)
  1015. ;; "Returns files under DIRECTORY ignoring dirs and hidden files.
  1016. ;; If RECURSE in non-nil, do that recursively."
  1017. ;; (let (ret
  1018. ;; (default-directory directory))
  1019. ;; (dolist (entry (directory-files "."))
  1020. ;; (cond ((or (string-match "^\\."
  1021. ;; (file-name-nondirectory entry))
  1022. ;; (string-match "~$"
  1023. ;; (file-name-nondirectory entry)))
  1024. ;; nil)
  1025. ;; ((and recurse-p
  1026. ;; (file-directory-p entry))
  1027. ;; (setq ret (nconc ret
  1028. ;; (yas/glob-files (expand-file-name entry)
  1029. ;; recurse-p
  1030. ;; (if append
  1031. ;; (concat append "/" entry)
  1032. ;; entry)))))
  1033. ;; ((file-directory-p entry)
  1034. ;; nil)
  1035. ;; (t
  1036. ;; (push (if append
  1037. ;; (concat append "/" entry)
  1038. ;; entry) ret))))
  1039. ;; ret))
  1040. (defun yas/subdirs (directory &optional file?)
  1041. "Return subdirs or files of DIRECTORY according to FILE?."
  1042. (remove-if (lambda (file)
  1043. (or (string-match "^\\."
  1044. (file-name-nondirectory file))
  1045. (string-match "~$"
  1046. (file-name-nondirectory file))
  1047. (if file?
  1048. (file-directory-p file)
  1049. (not (file-directory-p file)))))
  1050. (directory-files directory t)))
  1051. (defun yas/make-menu-binding (template)
  1052. `(lambda () (interactive) (yas/expand-or-visit-from-menu ,template)))
  1053. (defun yas/expand-or-visit-from-menu (template)
  1054. (if yas/visit-from-menu
  1055. (yas/visit-snippet-file-1 template)
  1056. (let ((where (if mark-active
  1057. (cons (region-beginning) (region-end))
  1058. (cons (point) (point)))))
  1059. (yas/expand-snippet (yas/template-content template)
  1060. (car where)
  1061. (cdr where)))))
  1062. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1063. ;; Popping up for keys and templates
  1064. ;;
  1065. (defun yas/prompt-for-template (templates &optional prompt)
  1066. "Interactively choose a template from the list TEMPLATES.
  1067. TEMPLATES is a list of `yas/template'."
  1068. (when templates
  1069. (some #'(lambda (fn)
  1070. (funcall fn (or prompt "Choose a snippet: ")
  1071. templates
  1072. #'yas/template-name))
  1073. yas/prompt-functions)))
  1074. (defun yas/prompt-for-keys (keys &optional prompt)
  1075. "Interactively choose a template key from the list KEYS."
  1076. (when keys
  1077. (some #'(lambda (fn)
  1078. (funcall fn (or prompt "Choose a snippet key: ") keys))
  1079. yas/prompt-functions)))
  1080. (defun yas/prompt-for-table (tables &optional prompt)
  1081. (when tables
  1082. (some #'(lambda (fn)
  1083. (funcall fn (or prompt "Choose a snippet table: ")
  1084. tables
  1085. #'yas/snippet-table-name))
  1086. yas/prompt-functions)))
  1087. (defun yas/x-prompt (prompt choices &optional display-fn)
  1088. (when (and window-system choices)
  1089. (let ((keymap (cons 'keymap
  1090. (cons
  1091. prompt
  1092. (mapcar (lambda (choice)
  1093. (list choice
  1094. 'menu-item
  1095. (if display-fn
  1096. (funcall display-fn choice)
  1097. choice)
  1098. t))
  1099. choices)))))
  1100. (when (cdr keymap)
  1101. (car (x-popup-menu (if (fboundp 'posn-at-point)
  1102. (let ((x-y (posn-x-y (posn-at-point (point)))))
  1103. (list (list (+ (car x-y) 10)
  1104. (+ (cdr x-y) 20))
  1105. (selected-window)))
  1106. t)
  1107. keymap))))))
  1108. (defun yas/ido-prompt (prompt choices &optional display-fn)
  1109. (when (and (featurep 'ido)
  1110. ido-mode)
  1111. (let* ((formatted-choices (or (and display-fn
  1112. (mapcar display-fn choices))
  1113. choices))
  1114. (chosen (and formatted-choices
  1115. (ido-completing-read prompt
  1116. formatted-choices
  1117. nil
  1118. 'require-match
  1119. nil
  1120. nil))))
  1121. (when chosen
  1122. (nth (position chosen formatted-choices :test #'string=) choices)))))
  1123. (eval-when-compile (require 'dropdown-list nil t))
  1124. (defun yas/dropdown-promp