Skip to content

Commit

Permalink
(consult-yasnippet): Cleanup and refactor implementation
Browse files Browse the repository at this point in the history
See #173.
  • Loading branch information
mohkale committed Jan 20, 2021
1 parent b5798b8 commit 18e4b37
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 85 deletions.
6 changes: 3 additions & 3 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ variables and functions with their descriptions.
lines again. If the input begins with "! SPC", the filter matches the
complement. In contrast to =consult-keep-lines= this function does not edit
the buffer.
- =consult-yasnippet=: Expand [[https://github.com/joaotavora/yasnippet][yasnippet]] snippets in the current buffer.
This command is available from the additional =consult-yasnippet.el=
package.

** Navigation
:properties:
Expand Down Expand Up @@ -237,9 +240,6 @@ variables and functions with their descriptions.
components.
- =consult-flymake=: Jump to Flymake diagnostic, like
=consult-flycheck=.
- =consult-yasnippet=: Expand [[https://github.com/joaotavora/yasnippet][yasnippet]] snippets in the current buffer.
This command is available from the additional =consult-yasnippet.el=
package.

** Histories
:properties:
Expand Down
149 changes: 67 additions & 82 deletions consult-yasnippet.el
Original file line number Diff line number Diff line change
Expand Up @@ -37,36 +37,19 @@
(require 'consult)
(require 'yasnippet)

(defgroup consult-yasnippet nil
"Consulting `completing-read' for yasnippet snippets."
:group 'consult
:prefix "consult-yasnippet-")

(defvar consult-yasnippet--snippets nil
"Snippet collection for current `consult-snippet' session.")

(defvar consult-yasnippet--buffer nil
"The buffer in which `consult-yasnippet' was begun")

(defvar consult-yasnippet--region nil
"The position (a cons of the start and end `point's) of where `consult-yasnippet' was begun")

(defvar consult-yasnippet--region-contents ""
"The original contents of `consult-yasnippet--region'.")

(defun consult-yasnippet--expand-template (template)
(defun consult-yasnippet--expand-template (template region region-contents)
"Expand the yasnippet template TEMPLATE at point."
(deactivate-mark)
(goto-char (car consult-yasnippet--region))
(when (not (string-equal "" consult-yasnippet--region-contents))
(goto-char (car region))
(when (not (string-equal "" region-contents))
(push-mark (point))
(push-mark (cdr consult-yasnippet--region) nil t))
(push-mark (cdr region) nil t))

(yas-expand-snippet (yas--template-content template)
nil nil
(yas--template-expand-env template)))

(defun consult-yasnippet--preview (template _)
(defun consult-yasnippet--preview ()
"Previewer for `consult--read'.
This function expands TEMPLATE at point in the buffer
`consult-yasnippet--read-snippet' was started in. This includes
Expand All @@ -75,51 +58,49 @@ previews that're already active.
When TEMPLATE is not given, this function essentially just resets
the state of the current buffer to before any snippets were previewed."
(with-current-buffer consult-yasnippet--buffer
(let ((yas-verbosity 0)
(inhibit-redisplay t)
(inhibit-read-only t)
(orig-offset (- (point-max) (cdr consult-yasnippet--region)))
(yas-prompt-functions '(yas-no-prompt)))

;; We always undo any snippet previews before maybe setting up
;; some new previews.
(delete-region (car consult-yasnippet--region)
(cdr consult-yasnippet--region))
(goto-char (car consult-yasnippet--region))
(setcar consult-yasnippet--region (point))
(insert consult-yasnippet--region-contents)
(setcdr consult-yasnippet--region (point))

(when template
(unwind-protect
(consult-yasnippet--expand-template template)
(unwind-protect
(mapc #'yas--commit-snippet
(yas-active-snippets (point-min) (point-max)))
(setcdr consult-yasnippet--region (- (point-max) orig-offset))))
(redisplay)))))

(defmacro consult-yasnippet--setup (&rest body)
"Setup the local variables and environment for `consult-yasnippet'.
This environment is used both in `consult-yasnippet--preview'and
`consult-yasnippet--expand-template'."
`(progn
(barf-if-buffer-read-only)
(unless (bound-and-true-p yas-minor-mode)
(error "`yas-minor-mode' not enabled in current buffer"))

(let* ((consult-yasnippet--snippets
(mapcar (lambda (template)
(cons (yas--template-name template) template))
(yas--all-templates (yas--get-snippet-tables))))
(consult-yasnippet--buffer (current-buffer))
(consult-yasnippet--region (if (region-active-p)
(cons (region-beginning) (region-end))
(cons (point) (point))))
(consult-yasnippet--region-contents (buffer-substring (car consult-yasnippet--region)
(cdr consult-yasnippet--region))))
,@body)))
(let* ((buf (current-buffer))
(region (if (region-active-p)
(cons (region-beginning) (region-end))
(cons (point) (point))))
(region-contents (buffer-substring (car region) (cdr region))))
(lambda (template _restore)
(with-current-buffer buf
(let ((yas-verbosity 0)
(inhibit-redisplay t)
(inhibit-read-only t)
(orig-offset (- (point-max) (cdr region)))
(yas-prompt-functions '(yas-no-prompt)))

;; We always undo any snippet previews before maybe setting up
;; some new previews.
(delete-region (car region) (cdr region))
(goto-char (car region))
(setcar region (point))
(insert region-contents)
(setcdr region (point))

(when template
(unwind-protect
(consult-yasnippet--expand-template template region region-contents)
(unwind-protect
(mapc #'yas--commit-snippet
(yas-active-snippets (point-min) (point-max)))
(setcdr region (- (point-max) orig-offset))))
(redisplay)))))))

(defun consult-yasnippet--candidates (&rest body)
"Retrieve the list of available snippets in the current buffer."
(unless (bound-and-true-p yas-minor-mode)
(error "`yas-minor-mode' not enabled in current buffer"))

(cl-loop for template in (yas--all-templates (yas--get-snippet-tables))
with annotation = nil
;; TODO: custom face
do (setq annotation
(propertize (yas--template-key template) 'face 'font-lock-type-face))
collect (cons (concat (yas--template-name template)
(propertize " " 'display (concat " [" annotation "]")))
template)))

(defun consult-yasnippet--read-snippet ()
"Backend implementation of `consult-yasnippet'.
Expand All @@ -130,28 +111,32 @@ replacing the active region with the snippet expansion.
This function doesn't actually expand the snippet, it only reads and then
returns a snippet template from the user."
(consult-yasnippet--setup
(let ((buffer-undo-list t)) ; Prevent querying user (and showing previews) from updating the undo-history
(unwind-protect
(consult--read
"Choose a snippet: "
consult-yasnippet--snippets
:lookup 'consult--lookup-cdr
:require-match t
:preview #'consult-yasnippet--preview
:category 'yasnippet)
(consult-yasnippet--preview nil t))))) ; Restore contents of region from before preview (while still ignoring undo history).
(barf-if-buffer-read-only)

(let* ((buffer-undo-list t) ; Prevent querying user (and showing previews) from updating the undo-history
(previewer (consult-yasnippet--preview)))
(unwind-protect
(consult--read
"Choose a snippet: "
(consult-yasnippet--candidates)
:lookup 'consult--lookup-cdr
:require-match t
:preview previewer
:category 'yasnippet)
(funcall previewer nil t))))

(defun consult-yasnippet-visit-snippet-file (snippet)
(interactive (list (consult-yasnippet--read-snippet)))
(yas--visit-snippet-file-1 snippet))

(defun consult-yasnippet (template)
(interactive (list (consult-yasnippet--read-snippet)))
;; We need to first restore the local environment for
;; `consult-yasnippet--expand-template' to work.
(consult-yasnippet--setup
(consult-yasnippet--expand-template template)))
(barf-if-buffer-read-only)
(let* ((region (if (region-active-p)
(cons (region-beginning) (region-end))
(cons (point) (point))))
(region-contents (buffer-substring (car region) (cdr region))))
(consult-yasnippet--expand-template template region region-contents)))

(provide 'consult-yasnippet)

Expand Down

0 comments on commit 18e4b37

Please sign in to comment.