From 1e6b143b8949e09c1231f860a7d9662010b7cb75 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Mon, 19 Feb 2018 10:27:32 +0100 Subject: Update all modes --- .emacs.d/lisp/php-mode.el | 225 ++++++++++++++------- .emacs.d/lisp/yaml-mode.el | 82 +++++--- .emacs.d/lisp/yasnippet.el | 489 +++++++++++++++++++++++++-------------------- 3 files changed, 477 insertions(+), 319 deletions(-) (limited to '.emacs.d/lisp') diff --git a/.emacs.d/lisp/php-mode.el b/.emacs.d/lisp/php-mode.el index 5cbc0d1..d568d90 100644 --- a/.emacs.d/lisp/php-mode.el +++ b/.emacs.d/lisp/php-mode.el @@ -5,18 +5,19 @@ ;; 2011, 2012, 2013, 2014, 2015, 2016, 2017 Eric James Michael Ritz ;; Author: Eric James Michael Ritz +;; Maintainer: USAMI Kenta ;; URL: https://github.com/ejmr/php-mode -;; Version: 1.18.3 +;; Keywords: languages php +;; Version: 1.18.4 ;; Package-Requires: ((emacs "24") (cl-lib "0.5")) +;; License: GPL-3.0-or-later -(defconst php-mode-version-number "1.18.3" +(defconst php-mode-version-number "1.18.4" "PHP Mode version number.") -(defconst php-mode-modified "2017-06-22" +(defconst php-mode-modified "2018-01-30" "PHP Mode build date.") -;;; License - ;; This file is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License ;; as published by the Free Software Foundation; either version 3 @@ -32,14 +33,24 @@ ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ;; 02110-1301, USA. -;;; Usage +;;; Commentary: -;; Put this file in your Emacs lisp path (eg. site-lisp) and add to +;; PHP Mode is a major mode for editing PHP source code. It's an +;; extension of C mode; thus it inherits all C mode's navigation +;; functionality. But it colors according to the PHP grammar and +;; indents according to the PEAR coding guidelines. It also includes +;; a couple handy IDE-type features such as documentation search and a +;; source and class browser. + +;; ## Usage + +;; Put this file in your Emacs Lisp path (eg. site-lisp) and add to ;; your .emacs file: -;; + ;; (require 'php-mode) ;; To use abbrev-mode, add lines like this: + ;; (add-hook 'php-mode-hook ;; '(lambda () (define-abbrev php-mode-abbrev-table "ex" "extends"))) @@ -47,19 +58,10 @@ ;; Many options available under Help:Customize ;; Options specific to php-mode are in -;; Programming/Languages/Php +;; Programming/Languages/PHP ;; Since it inherits much functionality from c-mode, look there too ;; Programming/Languages/C -;;; Commentary: - -;; PHP Mode is a major mode for editing PHP source code. It's an -;; extension of C mode; thus it inherits all C mode's navigation -;; functionality. But it colors according to the PHP grammar and -;; indents according to the PEAR coding guidelines. It also includes -;; a couple handy IDE-type features such as documentation search and a -;; source and class browser. - ;;; Code: (require 'cc-mode) @@ -79,8 +81,10 @@ (require 'flymake) (require 'etags) (require 'speedbar) +(require 'imenu) (require 'cl-lib) +(require 'mode-local) (eval-when-compile (require 'regexp-opt) @@ -114,7 +118,7 @@ ;; Local variables ;;;###autoload (defgroup php nil - "Major mode `php-mode' for editing PHP code." + "Major mode for editing PHP code." :tag "PHP" :prefix "php-" :group 'languages @@ -171,7 +175,7 @@ Turning this on will open it whenever `php-mode' is loaded." "\\)\\>[^_]?")) (defun php-mode-extra-constants-set(sym value) - "Apply the list of extra constant keywords VALUE. + "Apply the list of extra constant keywords `VALUE'. This function is called when the custom variable php-extra-constants is updated. The web-mode-extra-constants list is appended to the list @@ -187,7 +191,7 @@ of constants when set." (set sym value)) (defcustom php-lineup-cascaded-calls nil - "Indent chained method calls to the previous line" + "Indent chained method calls to the previous line." :type 'boolean) ;;;###autoload @@ -219,7 +223,7 @@ which will be the name of the method." "\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(")) (defun php-create-regexp-for-classlike (type) - "Accepts a `type' of a 'classlike' object as a string, such as + "Accepts a `TYPE' of a 'classlike' object as a string, such as 'class' or 'interface', and returns a regexp as a string which can be used to match against definitions for that classlike." (concat @@ -255,15 +259,25 @@ can be used to match against definitions for that classlike." "\\<\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*=\\s-*function\\s-*(" 1) ("Named Functions" "^\\s-*function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1)) - "Imenu generic expression for PHP Mode. See `imenu-generic-expression'.") + "Imenu generic expression for PHP Mode. See `imenu-generic-expression'.") -(defcustom php-site-url "http://php.net/" +(defcustom php-do-not-use-semantic-imenu t + "Customize `imenu-create-index-function' for `php-mode'. + +If using `semantic-mode' `imenu-create-index-function' will be +set to `semantic-create-imenu-index' due to `c-mode' being its +parent. Set this variable to t if you want to use +`imenu-default-create-index-function' even with `semantic-mode' +enabled." + :type 'boolean) + +(defcustom php-site-url "https://secure.php.net/" "Default PHP.net site URL. The URL to use open PHP manual and search word. You can find a mirror site closer to you." :type 'string - :link '(url-link :tag "List of Mirror Sites" "http://php.net/mirrors.php")) + :link '(url-link :tag "List of Mirror Sites" "https://secure.php.net/mirrors.php")) (defcustom php-manual-url 'en "URL at which to find PHP manual. @@ -335,7 +349,7 @@ Turning this on will force PEAR rules on all PHP files." mumamo-mode turned on. Detects if there are any HTML tags in the buffer before warning, but this is is not very smart; e.g. if you have any tags inside a PHP string, it will be fooled." - :type '(choice (const :tag "Warg" t) (const "Don't warn" nil))) + :type '(choice (const :tag "Warn" t) (const "Don't warn" nil))) (defcustom php-mode-coding-style 'pear "Select default coding style to use with php-mode. @@ -373,6 +387,31 @@ This variable can take one of the following symbol values: (message "PHP Mode %s of %s" php-mode-version-number php-mode-modified)) +(defvar php-available-project-root-files + '((projectile ".projectile") + (composer "composer.json" "composer.lock") + (git ".git") + (mercurial ".hg") + (subversion ".svn") + ;; NOTICE: This method does not detect the top level of .editorconfig + ;; However, we can integrate it by adding the editorconfig.el's API. + ;;(editorconfig . ".editorconfig") + )) + +;;;###autoload +(progn + (defvar php-project-root 'auto + "Method of searching for the top level directory. + +`auto' (default) + Try to search file in order of `php-available-project-root-files'. + +SYMBOL + Key of `php-available-project-root-files'.") + (make-variable-buffer-local 'php-project-root) + (put 'php-project-root 'safe-local-variable + #'(lambda (v) (assq v php-available-project-root-files)))) + (defvar php-mode-map (let ((map (make-sparse-keymap))) ;; (define-key map [menu-bar php] @@ -427,7 +466,7 @@ This variable can take one of the following symbol values: ;; choice. (define-key map [tab] 'indent-for-tab-command) map) - "Keymap for `php-mode'") + "Keymap for `php-mode'.") (c-lang-defconst c-mode-menu php (append '(["Complete function name" php-complete-function t] @@ -442,6 +481,16 @@ This variable can take one of the following symbol values: (c-lang-defconst c-vsemi-status-unknown-p-fn php 'php-c-vsemi-status-unknown-p) +(c-lang-defconst c-get-state-before-change-functions + php nil) + +(c-lang-defconst c-before-font-lock-functions + php (let (functions) + (when (fboundp #'c-change-expand-fl-region) + (cl-pushnew 'c-change-expand-fl-region functions)) + (when (fboundp #'c-depropertize-new-text) + (cl-pushnew 'c-depropertize-new-text functions)))) + ;; Make php-mode recognize opening tags as preprocessor macro's. ;; ;; This is a workaround, the tags must be recognized as something @@ -653,8 +702,7 @@ but only if the setting is enabled" (tab-width . 4))) (defun php-enable-pear-coding-style () - "Sets up php-mode to use the coding styles preferred for PEAR -code and modules." + "Set up php-mode to use the coding styles preferred for PEAR code and modules." (interactive) (php-set-style "pear")) @@ -668,8 +716,7 @@ code and modules." (php-style-delete-trailing-whitespace . t))) (defun php-enable-drupal-coding-style () - "Makes php-mode use coding styles that are preferable for -working with Drupal." + "Make php-mode use coding styles that are preferable for working with Drupal." (interactive) (php-set-style "drupal")) @@ -683,8 +730,7 @@ working with Drupal." (fill-column . 78))) (defun php-enable-wordpress-coding-style () - "Makes php-mode use coding styles that are preferable for -working with Wordpress." + "Make php-mode use coding styles that are preferable for working with Wordpress." (interactive) (php-set-style "wordpress")) @@ -697,8 +743,7 @@ working with Wordpress." (require-final-newline . t))) (defun php-enable-symfony2-coding-style () - "Makes php-mode use coding styles that are preferable for -working with Symfony2." + "Make php-mode use coding styles that are preferable for working with Symfony2." (interactive) (php-set-style "symfony2")) @@ -713,7 +758,7 @@ working with Symfony2." (php-style-delete-trailing-whitespace . t))) (defun php-enable-psr2-coding-style () - "Makes php-mode comply to the PSR-2 coding style" + "Make php-mode comply to the PSR-2 coding style." (interactive) (php-set-style "psr2")) @@ -882,7 +927,7 @@ This is was done due to the problem reported here: ) (defun php-lineup-string-cont (langelem) - "Line up string toward equal sign or dot + "Line up string toward equal sign or dot. e.g. $str = 'some' . 'string'; @@ -916,22 +961,19 @@ this ^ lineup" (beginning-of-line) (if (looking-at-p "\\s-*;\\s-*$") 0 '+))) -(defconst php-heredoc-start-re - "<<<\\(?:\\w+\\|'\\w+'\\)$" - "Regular expression for the start of a PHP heredoc.") +(eval-and-compile + (defconst php-heredoc-start-re + "<<<\\(?:\\w+\\|'\\w+'\\)$" + "Regular expression for the start of a PHP heredoc.")) (defun php-heredoc-end-re (heredoc-start) - "Build a regular expression for the end of a heredoc started by -the string HEREDOC-START." + "Build a regular expression for the end of a heredoc started by the string HEREDOC-START." ;; Extract just the identifier without <<< and quotes. (string-match "\\w+" heredoc-start) (concat "^\\(" (match-string 0 heredoc-start) "\\)\\W")) (defun php-syntax-propertize-function (start end) "Apply propertize rules from START to END." - ;; (defconst php-syntax-propertize-function - ;; (syntax-propertize-rules - ;; (php-heredoc-start-re (0 (ignore (php-heredoc-syntax)))))) (goto-char start) (while (and (< (point) end) (re-search-forward php-heredoc-start-re end t)) @@ -940,7 +982,12 @@ the string HEREDOC-START." (while (re-search-forward "['\"]" end t) (when (php-in-comment-p) (c-put-char-property (match-beginning 0) - 'syntax-table (string-to-syntax "_"))))) + 'syntax-table (string-to-syntax "_")))) + (funcall + (syntax-propertize-rules + ("\\(\"\\)\\(\\\\.\\|[^\"\n\\]\\)*\\(\"\\)" (1 "\"") (3 "\"")) + ("\\('\\)\\(\\\\.\\|[^'\n\\]\\)*\\('\\)" (1 "\"") (3 "\""))) + start end)) (defun php-heredoc-syntax () "Mark the boundaries of searched heredoc." @@ -953,8 +1000,7 @@ the string HEREDOC-START." (c-put-char-property (1- (point)) 'syntax-table (string-to-syntax "|"))) (defun php-syntax-propertize-extend-region (start end) - "Extend the propertize region if START or END falls inside a -PHP heredoc." + "Extend the propertize region if START or END falls inside a PHP heredoc." (let ((new-start) (new-end)) (goto-char start) @@ -1105,6 +1151,28 @@ After setting the stylevars run hooks according to STYLENAME (put 'php-set-style 'interactive-form (interactive-form 'c-set-style)) +(defun php-mode-debug () + "Display informations useful for debugging PHP Mode." + (interactive) + (message "--- PHP-MODE DEBUG BEGIN ---") + (message "versions: %s; %s" (emacs-version) (php-mode-version)) + (message "major-mode: %s" major-mode) + (message "minor-modes: %s" (cl-remove-if + (lambda (s) (string-match-p "global" (symbol-name s))) + minor-mode-list)) + (message "variables: %s" + (cl-loop for v in '(indent-tabs-mode tab-width) + collect (list v (symbol-value v)))) + (message "custom variables: %s" + (cl-loop for (v type) in (custom-group-members 'php nil) + if (eq type 'custom-variable) + collect (list v (symbol-value v)))) + (message "c-indentation-style: %s" c-indentation-style) + (message "c-style-variables: %s" (c-get-style-variables c-indentation-style nil)) + (message "--- PHP-MODE DEBUG END ---") + (switch-to-buffer "*Messages*") + (goto-char (point-max))) + ;;;###autoload (define-derived-mode php-mode c-mode "PHP" "Major mode for editing PHP code. @@ -1129,14 +1197,9 @@ After setting the stylevars run hooks according to STYLENAME (modify-syntax-entry ?\n "> b" php-mode-syntax-table) (modify-syntax-entry ?$ "'" php-mode-syntax-table) - (set (make-local-variable 'syntax-propertize-via-font-lock) - '(("\\(\"\\)\\(\\\\.\\|[^\"\n\\]\\)*\\(\"\\)" (1 "\"") (3 "\"")) - ("\\(\'\\)\\(\\\\.\\|[^\'\n\\]\\)*\\(\'\\)" (1 "\"") (3 "\"")))) - + (set (make-local-variable 'syntax-propertize-function) #'php-syntax-propertize-function) (add-to-list (make-local-variable 'syntax-propertize-extend-region-functions) #'php-syntax-propertize-extend-region) - (set (make-local-variable 'syntax-propertize-function) - #'php-syntax-propertize-function) (setq imenu-generic-expression php-imenu-generic-expression) @@ -1151,11 +1214,10 @@ After setting the stylevars run hooks according to STYLENAME (php-set-style (symbol-name php-mode-coding-style)) - (if (or php-mode-force-pear - (and (stringp buffer-file-name) - (string-match "PEAR\\|pear" - (buffer-file-name)) - (string-match "\\.php$" (buffer-file-name)))) + (when (or php-mode-force-pear + (and (stringp buffer-file-name) + (string-match "PEAR\\|pear" buffer-file-name) + (string-match "\\.php\\'" buffer-file-name))) (php-set-style "pear")) (setq indent-line-function 'php-cautious-indent-line) @@ -1191,6 +1253,13 @@ After setting the stylevars run hooks according to STYLENAME (save-excursion (php-syntax-propertize-function (point-min) (point-max)))))) +(defvar-mode-local php-mode imenu-create-index-function + (if php-do-not-use-semantic-imenu + #'imenu-default-create-index-function + (require 'semantic/imenu) + #'semantic-create-imenu-index) + "Imenu index function for PHP.") + ;; Define function name completion function (defvar php-completion-table nil @@ -1476,8 +1545,8 @@ a completion list." (defvar php-phpdoc-font-lock-keywords `((,(lambda (limit) - (c-font-lock-doc-comments "/\\*\\*" limit - php-phpdoc-font-lock-doc-comments))))) + (c-font-lock-doc-comments "/\\*\\*" limit + php-phpdoc-font-lock-doc-comments))))) (defconst php-font-lock-keywords-1 (c-lang-const c-matchers-1 php) "Basic highlighting for PHP Mode.") @@ -1515,9 +1584,13 @@ a completion list." ;; - when used as a type hint ;; - when used as a return type ("(\\(array\\))" 1 font-lock-type-face) - ("\\b\\(array\\)\\s-+\\$" 1 font-lock-type-face) + ("\\b\\(array\\)\\s-+&?\\$" 1 font-lock-type-face) (")\\s-*:\\s-*\\??\\(array\\)\\b" 1 font-lock-type-face) + ;; namespaces + ("\\(\\([a-zA-Z0-9_]+\\\\\\)+[a-zA-Z0-9_]+\\|\\(\\\\[a-zA-Z0-9_]+\\)+\\)[^:a-zA-Z0-9_\\\\]" 1 'font-lock-type-face) + ("\\(\\([a-zA-Z0-9_]+\\\\\\)+[a-zA-Z0-9_]+\\|\\(\\\\[a-zA-Z0-9_]+\\)+\\)::" 1 'php-constant) + ;; Support the ::class constant in PHP5.6 ("\\sw+\\(::\\)\\(class\\)\\b" (1 'php-paamayim-nekudotayim) (2 'php-constant))) @@ -1610,7 +1683,7 @@ Look at the `php-executable' variable instead of the constant \"php\" command." (defun php-send-region (start end) - "Send the region between `start' and `end' to PHP for execution. + "Send the region between `START' and `END' to PHP for execution. The output will appear in the buffer *PHP*." (interactive "r") (let ((php-buffer (get-buffer-create "*PHP*")) @@ -1658,20 +1731,6 @@ The output will appear in the buffer *PHP*." (delete-char 1)))) (ad-activate 'fixup-whitespace) - -;; Advice `font-lock-fontify-keywords-region' to support namespace -;; separators in class names. Use word syntax for backslashes when -;; doing keyword fontification, but not when doing syntactic -;; fontification because that breaks \ as escape character in strings. -;; -;; Special care is taken to restore the original syntax, because we -;; want \ not to be word for functions like forward-word. -(defadvice font-lock-fontify-keywords-region (around backslash-as-word activate) - "Fontify keywords with backslash as word character." - (let ((old-syntax (string (char-syntax ?\\)))) - (modify-syntax-entry ?\\ "w") - ad-do-it - (modify-syntax-entry ?\\ old-syntax))) (defcustom php-class-suffix-when-insert "::" @@ -1696,6 +1755,18 @@ The output will appear in the buffer *PHP*." (when (re-search-backward re-pattern nil t) (match-string-no-properties 1)))) +;;;###autoload +(defun php-project-get-root-dir () + "Return path to current PHP project." + (let ((detect-method (if (stringp php-project-root) + (list php-project-root) + (if (eq php-project-root 'auto) + (cl-loop for m in php-available-project-root-files + append (cdr m)) + (cdr-safe (assq php-project-root php-available-project-root-files)))))) + (cl-loop for m in detect-method + thereis (locate-dominating-file default-directory m)))) + ;;;###autoload (defun php-current-class () "Insert current class name if cursor in class context." diff --git a/.emacs.d/lisp/yaml-mode.el b/.emacs.d/lisp/yaml-mode.el index e257379..c3416dd 100644 --- a/.emacs.d/lisp/yaml-mode.el +++ b/.emacs.d/lisp/yaml-mode.el @@ -234,18 +234,19 @@ that key is pressed to begin a block literal." ;; Font-lock support (defvar yaml-font-lock-keywords - `((,yaml-constant-scalars-re . (1 font-lock-constant-face)) + `((yaml-font-lock-block-literals 0 font-lock-string-face) + (,yaml-constant-scalars-re . (1 font-lock-constant-face)) (,yaml-tag-re . (0 font-lock-type-face)) (,yaml-node-anchor-alias-re . (0 font-lock-function-name-face)) (,yaml-hash-key-re . (1 font-lock-variable-name-face)) (,yaml-document-delimiter-re . (0 font-lock-comment-face)) (,yaml-directive-re . (1 font-lock-builtin-face)) - (yaml-font-lock-block-literals 0 font-lock-string-face) ("^[\t]+" 0 'yaml-tab-face t)) "Additional expressions to highlight in YAML mode.") (defun yaml-mode-syntax-propertize-function (beg end) - "Unhighlight foo#bar tokens between BEG and END." + "Override buffer's syntax table for special syntactic constructs." + ;; Unhighlight foo#bar tokens between BEG and END. (save-excursion (goto-char beg) (while (search-forward "#" end t) @@ -255,7 +256,27 @@ that key is pressed to begin a block literal." (when (and (not (bolp)) (not (memq (preceding-char) '(?\s ?\t)))) (put-text-property (point) (1+ (point)) - 'syntax-table (string-to-syntax "_"))))))) + 'syntax-table (string-to-syntax "_")))))) + + ;; If quote is detected as a syntactic string start but appeared + ;; after a non-whitespace character, then mark it as syntactic word. + (save-excursion + (goto-char beg) + (while (re-search-forward "['\"]" end t) + (when (get-text-property (point) 'yaml-block-literal) + (put-text-property (1- (point)) (point) + 'syntax-table (string-to-syntax "w"))) + (when (nth 8 (syntax-ppss)) + (save-excursion + (forward-char -1) + (cond ((and (char-equal ?' (char-before (point))) + (char-equal ?' (char-after (point))) + (put-text-property (1- (point)) (1+ (point)) + 'syntax-table (string-to-syntax "w")))) + ((and (not (bolp)) + (char-equal ?w (char-syntax (char-before (point))))) + (put-text-property (point) (1+ (point)) + 'syntax-table (string-to-syntax "w"))))))))) (defun yaml-font-lock-block-literals (bound) "Find lines within block literals. @@ -272,29 +293,36 @@ artificially limitted to the value of (let ((begin (point)) (end (min (1+ (point-at-eol)) bound))) (goto-char (point-at-bol)) - (while (and (looking-at yaml-blank-line-re) (not (bobp))) + (while (and (looking-at yaml-blank-line-re) + (not (bobp))) (forward-line -1)) (let ((nlines yaml-block-literal-search-lines) (min-level (current-indentation))) - (forward-line -1) - (while (and (/= nlines 0) - (/= min-level 0) - (not (looking-at yaml-block-literal-re)) - (not (bobp))) - (set 'nlines (1- nlines)) - (unless (looking-at yaml-blank-line-re) - (set 'min-level (min min-level (current-indentation)))) - (forward-line -1)) - (cond - ((and (< (current-indentation) min-level) - (looking-at yaml-block-literal-re)) - (goto-char end) (set-match-data (list begin end)) t) + (forward-line -1) + (while (and (/= nlines 0) + (/= min-level 0) + (not (looking-at yaml-block-literal-re)) + (not (bobp))) + (setq nlines (1- nlines)) + (unless (looking-at yaml-blank-line-re) + (setq min-level (min min-level (current-indentation)))) + (forward-line -1)) + (cond + ((and (< (current-indentation) min-level) + (looking-at yaml-block-literal-re)) + (goto-char end) + (put-text-property begin end 'yaml-block-literal t) + (set-match-data (list begin end)) + t) ((progn (goto-char begin) (re-search-forward (concat yaml-block-literal-re " *\\(.*\\)\n") bound t)) - (set-match-data (nthcdr 2 (match-data))) t)))))) + (let ((range (nthcdr 2 (match-data)))) + (put-text-property (car range) (cadr range) 'yaml-block-literal t) + (set-match-data range)) + t)))))) ;; Indentation and electric keys @@ -329,8 +357,8 @@ back-dent the line by `yaml-indent-offset' spaces. On reaching column (if (and (equal last-command this-command) (/= ci 0)) (indent-to (* (/ (- ci 1) yaml-indent-offset) yaml-indent-offset)) (indent-to need))) - (if (< (current-column) (current-indentation)) - (forward-to-indentation 0)))) + (if (< (current-column) (current-indentation)) + (forward-to-indentation 0)))) (defun yaml-electric-backspace (arg) "Delete characters or back-dent the current line. @@ -374,8 +402,8 @@ margin." (self-insert-command (prefix-numeric-value arg)) (save-excursion (beginning-of-line) - (if (and (not arg) (looking-at yaml-document-delimiter-re)) - (delete-horizontal-space)))) + (when (and (not arg) (looking-at yaml-document-delimiter-re)) + (delete-horizontal-space)))) (defun yaml-narrow-to-block-literal () "Narrow the buffer to block literal if the point is in it, @@ -393,13 +421,13 @@ otherwise do nothing." (/= min-level 0) (not (looking-at-p yaml-block-literal-re)) (not (bobp))) - (set 'nlines (1- nlines)) + (setq nlines (1- nlines)) (unless (looking-at-p yaml-blank-line-re) - (set 'min-level (min min-level (current-indentation)))) + (setq min-level (min min-level (current-indentation)))) (forward-line -1)) (when (and (< (current-indentation) min-level) - (looking-at-p yaml-block-literal-re)) - (set 'min-level (current-indentation)) + (looking-at-p yaml-block-literal-re)) + (setq min-level (current-indentation)) (forward-line) (setq beg (point)) (while (and (not (eobp)) diff --git a/.emacs.d/lisp/yasnippet.el b/.emacs.d/lisp/yasnippet.el index b3c5c90..69b880a 100644 --- a/.emacs.d/lisp/yasnippet.el +++ b/.emacs.d/lisp/yasnippet.el @@ -157,16 +157,14 @@ (file-name-directory (or load-file-name buffer-file-name)) "Directory that yasnippet was loaded from.") -(defvar yas-installed-snippets-dir nil) -(setq yas-installed-snippets-dir - (expand-file-name "snippets" yas--loaddir)) +(defconst yas-installed-snippets-dir (expand-file-name "snippets" yas--loaddir)) +(make-obsolete-variable 'yas-installed-snippets-dir "\ +Yasnippet no longer comes with installed snippets" "0.13") (defconst yas--default-user-snippets-dir (expand-file-name "snippets" user-emacs-directory)) -(defcustom yas-snippet-dirs (remove nil - (list yas--default-user-snippets-dir - 'yas-installed-snippets-dir)) +(defcustom yas-snippet-dirs (list yas--default-user-snippets-dir) "List of top-level snippet directories. Each element, a string or a symbol whose value is a string, @@ -398,18 +396,26 @@ It must be set to nil before loading yasnippet to take effect." ;;; User-visible variables +(defconst yas-maybe-skip-and-clear-field + '(menu-item "" yas-skip-and-clear-field + :filter yas--maybe-clear-field-filter) + "A conditional key definition. +This can be used as a key definition in keymaps to bind a key to +`yas-skip-and-clear-field' only when at the beginning of an +unmodified snippey field.") + (defvar yas-keymap (let ((map (make-sparse-keymap))) (define-key map [(tab)] 'yas-next-field-or-maybe-expand) (define-key map (kbd "TAB") 'yas-next-field-or-maybe-expand) (define-key map [(shift tab)] 'yas-prev-field) (define-key map [backtab] 'yas-prev-field) (define-key map (kbd "C-g") 'yas-abort-snippet) - (define-key map (kbd "C-d") 'yas-skip-and-clear-or-delete-char) + (define-key map (kbd "C-d") yas-maybe-skip-and-clear-field) map) "The active keymap while a snippet expansion is in progress.") -(defvar yas-key-syntaxes (list "w" "w_" "w_." "w_.()" - #'yas-try-key-from-whitespace) +(defvar yas-key-syntaxes (list #'yas-try-key-from-whitespace + "w_.()" "w_." "w_" "w") "Syntaxes and functions to help look for trigger keys before point. Each element in this list specifies how to skip buffer positions @@ -953,14 +959,25 @@ Honour `yas-dont-activate-functions', which see." "The keymap used when `snippet-mode' is active.") -;;;###autoload -(define-derived-mode snippet-mode text-mode "Snippet" - "A mode for editing yasnippets" - (setq font-lock-defaults '(yas--font-lock-keywords)) - (set (make-local-variable 'require-final-newline) nil) - (set (make-local-variable 'comment-start) "#") - (set (make-local-variable 'comment-start-skip) "#+[\t ]*") - (add-hook 'after-save-hook #'yas-maybe-load-snippet-buffer nil t)) + +;;;###autoload(autoload 'snippet-mode "yasnippet" "A mode for editing yasnippets" t nil) +(eval-and-compile + (if (fboundp 'prog-mode) + ;; `prog-mode' is new in 24.1. + (define-derived-mode snippet-mode prog-mode "Snippet" + "A mode for editing yasnippets" + (setq font-lock-defaults '(yas--font-lock-keywords)) + (set (make-local-variable 'require-final-newline) nil) + (set (make-local-variable 'comment-start) "#") + (set (make-local-variable 'comment-start-skip) "#+[\t ]*") + (add-hook 'after-save-hook #'yas-maybe-load-snippet-buffer nil t)) + (define-derived-mode snippet-mode fundamental-mode "Snippet" + "A mode for editing yasnippets" + (setq font-lock-defaults '(yas--font-lock-keywords)) + (set (make-local-variable 'require-final-newline) nil) + (set (make-local-variable 'comment-start) "#") + (set (make-local-variable 'comment-start-skip) "#+[\t ]*") + (add-hook 'after-save-hook #'yas-maybe-load-snippet-buffer nil t)))) (defun yas-snippet-mode-buffer-p () "Return non-nil if current buffer should be in `snippet-mode'. @@ -1493,7 +1510,7 @@ Here's a list of currently recognized directives: expand-env binding uuid) - (if (re-search-forward "^# --\n" nil t) + (if (re-search-forward "^# --\\s-*\n" nil t) (progn (setq template (buffer-substring-no-properties (point) (point-max))) @@ -1938,12 +1955,19 @@ prefix argument." (yas-direct-keymaps-reload) (run-hooks 'yas-after-reload-hook) - (yas--message (if errors 2 3) - (if no-jit "Snippets loaded %s." - "Prepared just-in-time loading of snippets %s.") - (if errors - "with some errors. Check *Messages*" - "successfully"))))) + (let ((no-snippets + (cl-every (lambda (table) (= (hash-table-count table) 0)) + (list yas--scheduled-jit-loads + yas--parents yas--tables)))) + (yas--message (if (or no-snippets errors) 2 3) + (if no-jit "Snippets loaded %s." + "Prepared just-in-time loading of snippets %s.") + (cond (errors + "with some errors. Check *Messages*") + (no-snippets + "(but no snippets found)") + (t + "successfully"))))))) (defvar yas-after-reload-hook nil "Hooks run after `yas-reload-all'.") @@ -2388,18 +2412,17 @@ Honours `yas-choose-tables-first', `yas-choose-keys-first' and :key #'yas--template-name :test #'string=))) (defun yas-lookup-snippet (name &optional mode noerror) - "Get the snippet content for the snippet NAME in MODE's tables. + "Get the snippet named NAME in MODE's tables. MODE defaults to the current buffer's `major-mode'. If NOERROR is non-nil, then don't signal an error if there isn't any snippet called NAME. Honours `yas-buffer-local-condition'." - (let ((snippet (yas--lookup-snippet-1 name mode))) - (cond - (snippet (yas--template-content snippet)) - (noerror nil) - (t (error "No snippet named: %s" name))))) + (cond + ((yas--lookup-snippet-1 name mode)) + (noerror nil) + (t (error "No snippet named: %s" name)))) (defun yas-insert-snippet (&optional no-condition) "Choose a snippet to expand, pop-up a list of choices according @@ -2495,10 +2518,11 @@ where snippets of table might exist." (tables (if table (list table) (yas--get-snippet-tables)))) ;; HACK! the snippet table created here is actually registered! - ;; - (unless (or table (gethash major-mode yas--tables)) - (push (yas--table-get-create major-mode) - tables)) + (unless table + ;; The major mode is probably the best guess, put it first. + (let ((major-mode-table (yas--table-get-create major-mode))) + (cl-callf2 delq major-mode-table tables) + (push major-mode-table tables))) (mapcar #'(lambda (table) (cons table @@ -2689,8 +2713,11 @@ and `kill-buffer' instead." (save-buffer))) (quit-window kill))) +(declare-function yas-debug-snippets "yasnippet-debug") + (defun yas-tryout-snippet (&optional debug) - "Test current buffer's snippet template in other buffer." + "Test current buffer's snippet template in other buffer. +DEBUG is for debugging the YASnippet engine itself." (interactive "P") (let* ((major-mode-and-parent (yas--compute-major-mode-and-parents buffer-file-name)) (parsed (yas--parse-template)) @@ -2720,9 +2747,9 @@ and `kill-buffer' instead." (point-max) (yas--template-expand-env yas--current-template)) (when (and debug - (require 'yasnippet-debug nil t) - (fboundp 'yas-debug-snippet-vars)) - (add-hook 'post-command-hook #'yas-debug-snippet-vars nil t)))) + (require 'yasnippet-debug nil t)) + (yas-debug-snippets "*YASnippet trace*" 'snippet-navigation) + (display-buffer "*YASnippet trace*")))) (t (yas--message 1 "Cannot test snippet for unknown major mode"))))) @@ -3527,22 +3554,37 @@ holds the keymap." (overlay-put overlay 'yas--snippet snippet) overlay)) +(defun yas-current-field () + "Return the currently active field." + (and yas--active-field-overlay + (overlay-buffer yas--active-field-overlay) + (overlay-get yas--active-field-overlay 'yas--field))) + +(defun yas--maybe-clear-field-filter (cmd) + "Return CMD if at start of unmodified snippet field. +Use as a `:filter' argument for a conditional keybinding." + (let ((field (yas-current-field))) + (when (and field + (not (yas--field-modified-p field)) + (eq (point) (marker-position (yas--field-start field)))) + cmd))) + +(defun yas-skip-and-clear-field (&optional field) + "Clears unmodified FIELD if at field start, skips to next tab." + (interactive) + (yas--skip-and-clear (or field (yas-current-field))) + (yas-next-field 1)) + (defun yas-skip-and-clear-or-delete-char (&optional field) "Clears unmodified field if at field start, skips to next tab. Otherwise deletes a character normally by calling `delete-char'." (interactive) - (let ((field (or field - (and yas--active-field-overlay - (overlay-buffer yas--active-field-overlay) - (overlay-get yas--active-field-overlay 'yas--field))))) - (cond ((and field - (not (yas--field-modified-p field)) - (eq (point) (marker-position (yas--field-start field)))) - (yas--skip-and-clear field) - (yas-next-field 1)) - (t - (call-interactively 'delete-char))))) + (declare (obsolete "Bind to `yas-maybe-skip-and-clear-field' instead." "0.13")) + (cond ((yas--maybe-clear-field-filter t) + (yas--skip-and-clear (or field (yas-current-field))) + (yas-next-field 1)) + (t (call-interactively 'delete-char)))) (defun yas--skip-and-clear (field &optional from) "Deletes the region of FIELD and sets it's modified state to t. @@ -3740,124 +3782,100 @@ Move the overlays, or create them if they do not exit." ;; running, but if managed correctly (including overlay priorities) ;; they should account for all situations... -(defvar yas--first-indent-undo nil - "Internal variable for indent undo entries. -Used to pass info from `yas--indent-region' to `yas-expand-snippet'.") -(defvar yas--get-indent-undo-pos nil - "Record undo info for line beginning at given position. -We bind this when first creating a snippet. See also -`yas--first-indent-undo'.") - -(defun yas-expand-snippet (content &optional start end expand-env) - "Expand snippet CONTENT at current point. +(defun yas-expand-snippet (snippet &optional start end expand-env) + "Expand SNIPPET at current point. Text between START and END will be deleted before inserting -template. EXPAND-ENV is a list of (SYM VALUE) let-style dynamic bindings -considered when expanding the snippet." +template. EXPAND-ENV is a list of (SYM VALUE) let-style dynamic +bindings considered when expanding the snippet. If omitted, use +SNIPPET's expand-env field. + +SNIPPET may be a snippet structure (e.g., as returned by +`yas-lookup-snippet'), or just a snippet body (which is a string +for normal snippets, and a list for command snippets)." (cl-assert (and yas-minor-mode (memq 'yas--post-command-handler post-command-hook)) nil "[yas] `yas-expand-snippet' needs properly setup `yas-minor-mode'") (run-hooks 'yas-before-expand-snippet-hook) - ;; - (let* ((yas-selected-text (or yas-selected-text - (and (region-active-p) - (buffer-substring-no-properties (region-beginning) - (region-end))))) - (start (or start - (and (region-active-p) - (region-beginning)) - (point))) - (end (or end - (and (region-active-p) - (region-end)) - (point))) - (to-delete (and start - end + (let* ((clear-field + (let ((field (and yas--active-field-overlay + (overlay-buffer yas--active-field-overlay) + (overlay-get yas--active-field-overlay 'yas--field)))) + (and field (yas--skip-and-clear-field-p + field (point) (point) 0) + field))) + (start (cond (start) + ((region-active-p) + (region-beginning)) + (clear-field + (yas--field-start clear-field)) + (t (point)))) + (end (cond (end) + ((region-active-p) + (region-end)) + (clear-field + (yas--field-end clear-field)) + (t (point)))) + (to-delete (and (> end start) (buffer-substring-no-properties start end))) - (yas--first-indent-undo nil) - snippet) + (yas-selected-text + (cond (yas-selected-text) + ((and (region-active-p) + (not clear-field)) + to-delete)))) (goto-char start) (setq yas--indent-original-column (current-column)) ;; Delete the region to delete, this *does* get undo-recorded. - ;; - (when (and to-delete - (> end start)) + (when to-delete (delete-region start end)) - (cond ((listp content) - ;; x) This is a snippet-command - ;; - (yas--eval-for-effect content)) - (t - ;; x) This is a snippet-snippet :-) - ;; - ;; Narrow the region down to the content, shoosh the - ;; `buffer-undo-list', and create the snippet, the new - ;; snippet updates its mirrors once, so we are left with - ;; some plain text. The undo action for deleting this - ;; plain text will get recorded at the end. - ;; - ;; stacked expansion: also shoosh the overlay modification hooks - (let ((buffer-undo-list t) - (yas--get-indent-undo-pos (line-beginning-position))) - ;; snippet creation might evaluate users elisp, which - ;; might generate errors, so we have to be ready to catch - ;; them mostly to make the undo information - ;; + (let ((content (if (yas--template-p snippet) + (yas--template-content snippet) + snippet))) + (when (and (not expand-env) (yas--template-p snippet)) + (setq expand-env (yas--template-expand-env snippet))) + (cond ((listp content) + ;; x) This is a snippet-command. + (yas--eval-for-effect content)) + (t + ;; x) This is a snippet-snippet :-) (setq yas--start-column (current-column)) + ;; Stacked expansion: also shoosh the overlay modification hooks. (let ((yas--inhibit-overlay-hooks t)) - (insert content) (setq snippet - (yas--snippet-create expand-env start (point))))) - - ;; stacked-expansion: This checks for stacked expansion, save the - ;; `yas--previous-active-field' and advance its boundary. - ;; - (let ((existing-field (and yas--active-field-overlay - (overlay-buffer yas--active-field-overlay) - (overlay-get yas--active-field-overlay 'yas--field)))) - (when existing-field - (setf (yas--snippet-previous-active-field snippet) existing-field) - (yas--advance-end-maybe existing-field (overlay-end yas--active-field-overlay)))) - - ;; Exit the snippet immediately if no fields - ;; - (unless (yas--snippet-fields snippet) - (yas-exit-snippet snippet)) - - ;; Undo actions from indent of snippet's 1st line. - (setq buffer-undo-list - (nconc yas--first-indent-undo buffer-undo-list)) - ;; Undo action for the expand snippet contents. - (push (cons (overlay-start (yas--snippet-control-overlay snippet)) - (overlay-end (yas--snippet-control-overlay snippet))) - buffer-undo-list) - ;; Follow up with `yas--take-care-of-redo' on the newly - ;; inserted snippet boundaries. - (push `(apply yas--take-care-of-redo ,start - ,(overlay-end (yas--snippet-control-overlay snippet)) - ,snippet) - buffer-undo-list) - - ;; Now, schedule a move to the first field - ;; - (let ((first-field (car (yas--snippet-fields snippet)))) - (when first-field - (sit-for 0) ;; fix issue 125 - (yas--letenv (yas--snippet-expand-env snippet) - (yas--move-to-field snippet first-field)) - (when (and (eq (yas--field-number first-field) 0) - (> (length (yas--field-text-for-display - first-field)) - 0)) - ;; Keep region for ${0:exit text}. - (setq deactivate-mark nil)))) - (yas--message 4 "snippet %d expanded." (yas--snippet-id snippet)) - t)))) - -(defun yas--take-care-of-redo (_beg _end snippet) + (yas--snippet-create content expand-env start (point)))) + + ;; Stacked-expansion: This checks for stacked expansion, save the + ;; `yas--previous-active-field' and advance its boundary. + (let ((existing-field (and yas--active-field-overlay + (overlay-buffer yas--active-field-overlay) + (overlay-get yas--active-field-overlay 'yas--field)))) + (when existing-field + (setf (yas--snippet-previous-active-field snippet) existing-field) + (yas--advance-end-maybe existing-field (overlay-end yas--active-field-overlay)))) + + ;; Exit the snippet immediately if no fields. + (unless (yas--snippet-fields snippet) + (yas-exit-snippet snippet)) + + ;; Now, schedule a move to the first field. + (let ((first-field (car (yas--snippet-fields snippet)))) + (when first-field + (sit-for 0) ;; fix issue 125 + (yas--letenv (yas--snippet-expand-env snippet) + (yas--move-to-field snippet first-field)) + (when (and (eq (yas--field-number first-field) 0) + (> (length (yas--field-text-for-display + first-field)) + 0)) + ;; Keep region for ${0:exit text}. + (setq deactivate-mark nil)))) + (yas--message 4 "snippet %d expanded." (yas--snippet-id snippet)) + t))))) + +(defun yas--take-care-of-redo (snippet) "Commits SNIPPET, which in turn pushes an undo action for reviving it. Meant to exit in the `buffer-undo-list'." @@ -3882,19 +3900,37 @@ After revival, push the `yas--take-care-of-redo' in the (when (yas--maybe-move-to-active-field snippet) (setf (yas--snippet-control-overlay snippet) (yas--make-control-overlay snippet beg end)) (overlay-put (yas--snippet-control-overlay snippet) 'yas--snippet snippet) - (push `(apply yas--take-care-of-redo ,beg ,end ,snippet) + (push `(apply yas--take-care-of-redo ,snippet) buffer-undo-list))) -(defun yas--snippet-create (expand-env begin end) +(defun yas--snippet-create (content expand-env begin end) "Create a snippet from a template inserted at BEGIN to END. Returns the newly created snippet." (save-restriction - (narrow-to-region begin end) (let ((snippet (yas--make-snippet expand-env))) (yas--letenv expand-env - (goto-char begin) - (yas--snippet-parse-create snippet) + ;; Put a single undo action for the expanded snippet's + ;; content. + (let ((buffer-undo-list t)) + ;; Some versions of cc-mode fail when inserting snippet + ;; content in a narrowed buffer. + (goto-char begin) + (insert content) + (setq end (+ end (length content))) + (narrow-to-region begin end) + (goto-char (point-min)) + (yas--snippet-parse-create snippet)) + (push (cons (point-min) (point-max)) + buffer-undo-list) + + ;; Indent, collecting undo information normally. + (yas--indent snippet) + + ;; Follow up with `yas--take-care-of-redo' on the newly + ;; inserted snippet boundaries. + (push `(apply yas--take-care-of-redo ,snippet) + buffer-undo-list) ;; Sort and link each field (yas--snippet-sort-fields snippet) @@ -3991,22 +4027,27 @@ has to be called before the $-constructs are deleted." (when soup (cl-reduce link-foms soup))))) -(defun yas--calculate-mirrors-in-fields (snippet mirror) - "Attempt to assign a parent field of SNIPPET to the mirror MIRROR. +(defun yas--calculate-simple-fom-parentage (snippet fom) + "Discover if FOM is parented by some field in SNIPPET. Use the tightest containing field if more than one field contains the mirror. Intended to be called *before* the dollar-regions are deleted." (let ((min (point-min)) (max (point-max))) - (dolist (field (yas--snippet-fields snippet)) - (when (and (<= (yas--field-start field) (yas--mirror-start mirror)) - (<= (yas--mirror-end mirror) (yas--field-end field)) + (dolist (field (remq fom (yas--snippet-fields snippet))) + (when (and (<= (yas--field-start field) (yas--fom-start fom)) + (<= (yas--fom-end fom) (yas--field-end field)) (< min (yas--field-start field)) (< (yas--field-end field) max)) (setq min (yas--field-start field) max (yas--field-end field)) - (setf (yas--mirror-parent-field mirror) field))))) + (cond ((yas--field-p fom) + (setf (yas--field-parent-field fom) field)) + ((yas--mirror-p fom) + (setf (yas--mirror-parent-field fom) field)) + (t ; it's an exit, so noop + nil )))))) (defun yas--advance-end-maybe (fom newend) "Maybe advance FOM's end to NEWEND if it needs it. @@ -4050,11 +4091,6 @@ next FOM. Works its way up recursively for parents of parents." "When expanding the snippet the \"parse-create\" functions add cons cells to this var.") -(defvar yas--backquote-markers-and-strings nil - "List of (MARKER . STRING) marking where the values from -backquoted Lisp expressions should be inserted at the end of -expansion.") - (defvar yas--indent-markers nil "List of markers for manual indentation.") @@ -4063,21 +4099,22 @@ expansion.") necessary fields, mirrors and exit points. Meant to be called in a narrowed buffer, does various passes" - (let ((parse-start (point))) + (let ((saved-quotes nil) + (parse-start (point))) ;; Avoid major-mode's syntax propertizing function, since we ;; change the syntax-table while calling `scan-sexps'. (let ((syntax-propertize-function nil)) (setq yas--dollar-regions nil) ; Reset the yas--dollar-regions. (yas--protect-escapes nil '(?`)) ; Protect just the backquotes. (goto-char parse-start) - (yas--save-backquotes) ; Replace all backquoted expressions. - (yas--protect-escapes) ; Protect escaped characters. + (setq saved-quotes (yas--save-backquotes)) ; `expressions`. + (yas--protect-escapes) ; Protect escaped characters. (goto-char parse-start) (yas--indent-parse-create) ; Parse indent markers: `$>'. (goto-char parse-start) (yas--field-parse-create snippet) ; Parse fields with {}. (goto-char parse-start) - (yas--simple-mirror-parse-create snippet) ; Parse simple mirrors & fields. + (yas--simple-fom-create snippet) ; Parse simple mirrors & fields. (goto-char parse-start) (yas--transform-mirror-parse-create snippet) ; Parse mirror transforms. ;; Invalidate any syntax-propertizing done while @@ -4101,12 +4138,11 @@ Meant to be called in a narrowed buffer, does various passes" (get-register yas-wrap-around-region)) (insert (prog1 (get-register yas-wrap-around-region) (set-register yas-wrap-around-region nil))))) - (yas--restore-backquotes) ; Restore backquoted expression values. + (yas--restore-backquotes saved-quotes) ; Restore `expression` values. (goto-char parse-start) (yas--restore-escapes) ; Restore escapes. (yas--update-mirrors snippet) ; Update mirrors for the first time. - (goto-char parse-start)) - (yas--indent snippet)) ; Indent the best we can. + (goto-char parse-start))) ;; HACK: Some implementations of `indent-line-function' (called via ;; `indent-according-to-mode') delete text before they insert (like @@ -4246,12 +4282,7 @@ The SNIPPET's markers are preserved." remarkers))) (unwind-protect (progn (back-to-indentation) - (if (eq yas--get-indent-undo-pos bol) - (let ((buffer-undo-list nil)) - (indent-according-to-mode) - (setq yas--first-indent-undo - (delq nil buffer-undo-list))) - (indent-according-to-mode))) + (indent-according-to-mode)) (save-restriction (narrow-to-region bol (line-end-position)) (mapc #'yas--restore-marker-location remarkers)))) @@ -4322,9 +4353,11 @@ With optional string TEXT do it in string instead of the buffer." changed-text)) (defun yas--save-backquotes () - "Save all the \"\\=`(lisp-expression)\\=`\"-style expressions -with their evaluated value into `yas--backquote-markers-and-strings'." - (let* ((yas--snippet-buffer (current-buffer)) + "Save all \"\\=`(lisp-expression)\\=`\"-style expressions. +Return a list of (MARKER . STRING) entires for each backquoted +Lisp expression." + (let* ((saved-quotes nil) + (yas--snippet-buffer (current-buffer)) (yas--change-detected nil) (detect-change (lambda (_beg _end) (when (eq (current-buffer) yas--snippet-buffer) @@ -4347,29 +4380,28 @@ with their evaluated value into `yas--backquote-markers-and-strings'." (insert "Y") ;; quite horrendous, I love it :) (set-marker marker (point)) (insert "Y")) - (push (cons marker transformed) yas--backquote-markers-and-strings))))) + (push (cons marker transformed) saved-quotes))))) (when yas--change-detected (lwarn '(yasnippet backquote-change) :warning "`%s' modified buffer in a backquote expression. To hide this warning, add (yasnippet backquote-change) to `warning-suppress-types'." (if yas--current-template (yas--template-name yas--current-template) - "Snippet"))))) - -(defun yas--restore-backquotes () - "Replace markers in `yas--backquote-markers-and-strings' with their values." - (while yas--backquote-markers-and-strings - (let* ((marker-and-string (pop yas--backquote-markers-and-strings)) - (marker (car marker-and-string)) - (string (cdr marker-and-string))) - (save-excursion - (goto-char marker) - (save-restriction - (widen) - (delete-char -1) - (insert string) - (delete-char 1)) - (set-marker marker nil))))) + "Snippet"))) + saved-quotes)) + +(defun yas--restore-backquotes (saved-quotes) + "Replace markers in SAVED-QUOTES with their values. +SAVED-QUOTES is the in format returned by `yas--save-backquotes'." + (cl-loop for (marker . string) in saved-quotes do + (save-excursion + (goto-char marker) + (save-restriction + (widen) + (delete-char -1) + (insert string) + (delete-char 1)) + (set-marker marker nil)))) (defun yas--scan-sexps (from count) (ignore-errors @@ -4488,10 +4520,10 @@ When multiple expressions are found, only the last one counts." (when brand-new-mirror (push brand-new-mirror (yas--field-mirrors field)) - (yas--calculate-mirrors-in-fields snippet brand-new-mirror) + (yas--calculate-simple-fom-parentage snippet brand-new-mirror) (push (cons (match-beginning 0) real-match-end-0) yas--dollar-regions))))) -(defun yas--simple-mirror-parse-create (snippet) +(defun yas--simple-fom-create (snippet) "Parse the simple \"$n\" fields/mirrors/exitmarkers in SNIPPET." (while (re-search-forward yas--simple-mirror-regexp nil t) (let ((number (string-to-number (match-string-no-properties 1)))) @@ -4501,20 +4533,22 @@ When multiple expressions are found, only the last one counts." (push (cons (match-beginning 0) (yas--exit-marker (yas--snippet-exit snippet))) yas--dollar-regions)) (t - (let ((field (yas--snippet-find-field snippet number))) + (let ((field (yas--snippet-find-field snippet number)) + (fom)) (if field - (let ((brand-new-mirror (yas--make-mirror - (yas--make-marker (match-beginning 0)) - (yas--make-marker (match-beginning 0)) - nil))) - (push brand-new-mirror - (yas--field-mirrors field)) - (yas--calculate-mirrors-in-fields snippet brand-new-mirror)) - (push (yas--make-field number - (yas--make-marker (match-beginning 0)) - (yas--make-marker (match-beginning 0)) - nil) - (yas--snippet-fields snippet)))) + (push + (setq fom (yas--make-mirror + (yas--make-marker (match-beginning 0)) + (yas--make-marker (match-beginning 0)) + nil)) + (yas--field-mirrors field)) + (push + (setq fom (yas--make-field number + (yas--make-marker (match-beginning 0)) + (yas--make-marker (match-beginning 0)) + nil)) + (yas--snippet-fields snippet))) + (yas--calculate-simple-fom-parentage snippet fom)) (push (cons (match-beginning 0) (match-end 0)) yas--dollar-regions)))))) @@ -4737,7 +4771,7 @@ object satisfying `yas--field-p' to restrict the expansion to."))) "Log level for `yas--message' 4 means trace most anything, 0 means nothing.") (defun yas--message (level message &rest args) - "When LEVEL is at or below `yas-verbosity-level', log MESSAGE and ARGS." + "When LEVEL is at or below `yas-verbosity', log MESSAGE and ARGS." (when (>= yas-verbosity level) (message "%s" (apply #'yas--format message args)))) @@ -4805,6 +4839,31 @@ and return the directory. Return nil if not found." (directory-file-name file)))) (setq file nil)))) root)))) + +;;; Unloading + +(defvar unload-function-defs-list) ; loadhist.el + +(defun yasnippet-unload-function () + "Disable minor modes when calling `unload-feature'." + ;; Disable `yas-minor-mode' everywhere it's enabled. + (yas-global-mode -1) + (save-current-buffer + (dolist (buffer (buffer-list)) + (set-buffer buffer) + (when yas-minor-mode + (yas-minor-mode -1)))) + ;; Remove symbol properties of all our functions, this avoids + ;; Bug#25088 in Emacs 25.1, where the compiler macro on + ;; `cl-defstruct' created functions hang around in the symbol plist + ;; and cause errors when loading again (we don't *need* to clean + ;; *all* symbol plists, but it's easier than being precise). + (dolist (def unload-function-defs-list) + (when (eq (car-safe def) 'defun) + (setplist (cdr def) nil))) + ;; Return nil so that `unload-feature' will take of undefining + ;; functions, and changing any buffers using `snippet-mode'. + nil) ;;; Backward compatibility to yasnippet <= 0.7 -- cgit v1.3