From 41f31ba9ce406c057732b9788a6d756953b9d759 Mon Sep 17 00:00:00 2001 From: theschmocker Date: Sat, 19 Aug 2023 21:00:15 -0500 Subject: [PATCH 1/4] fix(snippets): fix snippet uuid completion Rather than attempting to read the uuid from a text property on the selected completion -- which gets stripped by vertico (and possibly helm) -- grab it from a lookup alist of completion-candidat->uuid. Essentially the same as the proposed implementation by @jgrey4296 on #4127 Fix: #4127 --- modules/editor/snippets/autoload/snippets.el | 31 ++++++++------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/modules/editor/snippets/autoload/snippets.el b/modules/editor/snippets/autoload/snippets.el index 539a11b80..fdbb678ed 100644 --- a/modules/editor/snippets/autoload/snippets.el +++ b/modules/editor/snippets/autoload/snippets.el @@ -45,25 +45,20 @@ Finds correctly active snippets from parent modes (based on Yas' logic)." return it)) (defun +snippet--completing-read-uuid (prompt all-snippets &rest args) - (plist-get - (text-properties-at - 0 (apply #'completing-read prompt - (cl-loop for (_ . tpl) in (mapcan #'yas--table-templates (if all-snippets - (hash-table-values yas--tables) - (yas--get-snippet-tables))) + (let* ((completion-uuid-alist + (cl-loop for (_ . tpl) in (mapcan #'yas--table-templates + (if all-snippets + (hash-table-values yas--tables) + (yas--get-snippet-tables))) - for txt = (format "%-25s%-30s%s" - (yas--template-key tpl) - (yas--template-name tpl) - (abbreviate-file-name (yas--template-load-file tpl))) - collect - (progn - (set-text-properties 0 (length txt) `(uuid ,(yas--template-uuid tpl) - path ,(yas--template-load-file tpl)) - txt) - txt)) - args)) - 'uuid)) + for txt = (format "%-25s%-30s%s" + (yas--template-key tpl) + (yas--template-name tpl) + (abbreviate-file-name (yas--template-load-file tpl))) + collect + (cons txt (yas--template-uuid tpl)))) + (completion (apply #'completing-read prompt completion-uuid-alist args))) + (alist-get completion completion-uuid-alist nil nil #'string=))) (defun +snippet--abort () (interactive) From 464337626852d5462f61d3456b02255bf05e0757 Mon Sep 17 00:00:00 2001 From: theschmocker Date: Sat, 19 Aug 2023 21:12:05 -0500 Subject: [PATCH 2/4] fix(snippets): fix +snippets/new and +snippets/new-alias file creation When adding a snippet/alias to a mode for the first time, setting `default-directory` before calling `+snippet--ensure-dir` would cause an error due to the directory not existing. As a fix, return the dir from `+snippet--ensure-dir` and bind `default-directory` to that. Additionally, not having a file associated with the buffer caused issues with loading the snippet after using snippet-mode's C-c C-c binding, especially when other directories were added to yasnippet's load paths. As a solution for this, prompt the user for a snippet key and set the buffer's file name to it within the snippet dir. If an existing file would be overwritten, ask user for confirmation. As an additional convenience, set the snippet's key field to the entered value. Finally, replace %alias with doom-snippets-expand in the generated alias snippets. Not aware of any history here, but %alias did not work for me. --- modules/editor/snippets/autoload/snippets.el | 78 ++++++++++++-------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/modules/editor/snippets/autoload/snippets.el b/modules/editor/snippets/autoload/snippets.el index fdbb678ed..3566bab2c 100644 --- a/modules/editor/snippets/autoload/snippets.el +++ b/modules/editor/snippets/autoload/snippets.el @@ -33,7 +33,13 @@ ignored. This makes it easy to override built-in snippets with private ones." (unless (file-directory-p dir) (if (y-or-n-p (format "%S doesn't exist. Create it?" (abbreviate-file-name dir))) (make-directory dir t) - (error "%S doesn't exist" (abbreviate-file-name dir))))) + (error "%S doesn't exist" (abbreviate-file-name dir)))) + dir) + +(defun +snippets--use-snippet-file-name-p (snippet-file-name) + (or (not (file-exists-p snippet-file-name)) + (y-or-n-p (format "%s exists. Overwrite it?" + (abbreviate-file-name snippet-file-name))))) (defun +snippet--get-template-by-uuid (uuid &optional mode) "Look up the template by uuid in child-most to parent-most mode order. @@ -191,22 +197,25 @@ buggy behavior when is pressed in an empty field." (defun +snippets/new () "Create a new snippet in `+snippets-dir'." (interactive) - (let ((default-directory - (expand-file-name (symbol-name major-mode) - +snippets-dir))) - (+snippet--ensure-dir default-directory) - (with-current-buffer (switch-to-buffer "untitled-snippet") - (snippet-mode) - (erase-buffer) - (yas-expand-snippet (concat "# -*- mode: snippet -*-\n" - "# name: $1\n" - "# uuid: $2\n" - "# key: ${3:trigger-key}${4:\n" - "# condition: t}\n" - "# --\n" - "$0")) - (when (bound-and-true-p evil-local-mode) - (evil-insert-state))))) + (let* ((default-directory (+snippet--ensure-dir (expand-file-name + (symbol-name major-mode) + +snippets-dir))) + (snippet-key (read-string "Enter a key for the snippet: ")) + (snippet-file-name (expand-file-name snippet-key))) + (when (+snippets--use-snippet-file-name-p snippet-file-name) + (with-current-buffer (switch-to-buffer snippet-key) + (snippet-mode) + (erase-buffer) + (set-visited-file-name snippet-file-name) + (yas-expand-snippet (concat "# -*- mode: snippet -*-\n" + "# name: $1\n" + "# uuid: $2\n" + "# key: ${3:" snippet-key "}${4:\n" + "# condition: t}\n" + "# --\n" + "$0")) + (when (bound-and-true-p evil-local-mode) + (evil-insert-state)))))) ;;;###autoload (defun +snippets/new-alias (template-uuid) @@ -219,21 +228,26 @@ You will be prompted for a snippet to alias." current-prefix-arg))) (unless (require 'doom-snippets nil t) (user-error "This command requires the `doom-snippets' library bundled with Doom Emacs")) - (let ((default-directory (expand-file-name (symbol-name major-mode) +snippets-dir))) - (+snippet--ensure-dir default-directory) - (with-current-buffer (switch-to-buffer "untitled-snippet") - (snippet-mode) - (erase-buffer) - (yas-expand-snippet - (concat "# -*- mode: snippet -*-\n" - "# name: $1\n" - "# key: ${2:trigger-key}${3:\n" - "# condition: t}\n" - "# type: command\n" - "# --\n" - "(%alias \"${4:" (or template-uuid "uuid") "}\")")) - (when (bound-and-true-p evil-local-mode) - (evil-insert-state))))) + (let* ((default-directory (+snippet--ensure-dir (expand-file-name + (symbol-name major-mode) + +snippets-dir))) + (alias-key (read-string "Enter a key for the alias: ")) + (alias-file-name (expand-file-name alias-key))) + (when (+snippets--use-snippet-file-name-p alias-file-name) + (with-current-buffer (switch-to-buffer alias-key) + (snippet-mode) + (erase-buffer) + (set-visited-file-name alias-file-name) + (yas-expand-snippet + (concat "# -*- mode: snippet -*-\n" + "# name: $1\n" + "# key: ${2:" alias-key "}${3:\n" + "# condition: t}\n" + "# type: command\n" + "# --\n" + "(doom-snippets-expand :uuid \"${4:" (or template-uuid "uuid") "}\")")) + (when (bound-and-true-p evil-local-mode) + (evil-insert-state)))))) ;;;###autoload (defun +snippets/edit (template-uuid) From 363706744d72f11e3ac6de3a178ed56f2fd45480 Mon Sep 17 00:00:00 2001 From: theschmocker Date: Sat, 19 Aug 2023 21:46:32 -0500 Subject: [PATCH 3/4] feat(snippets): select mode for new snippet When there are extra yasnippet modes loaded in the current buffer, prompt user to select one for the new snippet. If a prefix arg is supplied when calling `+snippets/new`, prompt user to select any mode. --- modules/editor/snippets/autoload/snippets.el | 26 +++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/modules/editor/snippets/autoload/snippets.el b/modules/editor/snippets/autoload/snippets.el index 3566bab2c..b10101f87 100644 --- a/modules/editor/snippets/autoload/snippets.el +++ b/modules/editor/snippets/autoload/snippets.el @@ -66,6 +66,18 @@ Finds correctly active snippets from parent modes (based on Yas' logic)." (completion (apply #'completing-read prompt completion-uuid-alist args))) (alist-get completion completion-uuid-alist nil nil #'string=))) +(defun +snippets--snippet-mode-name-completing-read (&optional all-modes) + (if all-modes + (completing-read + "Select snippet mode: " + obarray + (lambda (sym) + (string-match-p "-mode\\'" (symbol-name sym)))) + (if (not (null yas--extra-modes)) + (completing-read "Select snippet mode: " + (cons major-mode yas--extra-modes)) + (symbol-name major-mode)))) + (defun +snippet--abort () (interactive) (set-buffer-modified-p nil) @@ -194,12 +206,14 @@ buggy behavior when is pressed in an empty field." (user-error "Cannot find template with UUID %S" template-uuid))) ;;;###autoload -(defun +snippets/new () - "Create a new snippet in `+snippets-dir'." - (interactive) - (let* ((default-directory (+snippet--ensure-dir (expand-file-name - (symbol-name major-mode) - +snippets-dir))) +(defun +snippets/new (&optional all-modes) + "Create a new snippet in `+snippets-dir'. + +If there are extra yasnippet modes active, or if ALL-MODES is non-nil, you will +be prompted for the mode for which to create the snippet." + (interactive "P") + (let* ((mode (+snippets--snippet-mode-name-completing-read all-modes)) + (default-directory (+snippet--ensure-dir (expand-file-name mode +snippets-dir))) (snippet-key (read-string "Enter a key for the snippet: ")) (snippet-file-name (expand-file-name snippet-key))) (when (+snippets--use-snippet-file-name-p snippet-file-name) From 406594b9af87bc0faae191161950887eaee65486 Mon Sep 17 00:00:00 2001 From: theschmocker Date: Sat, 19 Aug 2023 21:59:48 -0500 Subject: [PATCH 4/4] refactor(snippets): use cond instead of nested if --- modules/editor/snippets/autoload/snippets.el | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/modules/editor/snippets/autoload/snippets.el b/modules/editor/snippets/autoload/snippets.el index b10101f87..59c257dd6 100644 --- a/modules/editor/snippets/autoload/snippets.el +++ b/modules/editor/snippets/autoload/snippets.el @@ -67,16 +67,14 @@ Finds correctly active snippets from parent modes (based on Yas' logic)." (alist-get completion completion-uuid-alist nil nil #'string=))) (defun +snippets--snippet-mode-name-completing-read (&optional all-modes) - (if all-modes - (completing-read - "Select snippet mode: " - obarray - (lambda (sym) - (string-match-p "-mode\\'" (symbol-name sym)))) - (if (not (null yas--extra-modes)) - (completing-read "Select snippet mode: " - (cons major-mode yas--extra-modes)) - (symbol-name major-mode)))) + (cond (all-modes (completing-read + "Select snippet mode: " + obarray + (lambda (sym) + (string-match-p "-mode\\'" (symbol-name sym))))) + ((not (null yas--extra-modes)) (completing-read "Select snippet mode: " + (cons major-mode yas--extra-modes))) + (t (symbol-name major-mode)))) (defun +snippet--abort () (interactive)