mirror of
https://github.com/joaotavora/yasnippet.git
synced 2025-10-13 21:13:04 +00:00
fix: oops, big bug, mirrors and fields have to be made then initialized
This commit is contained in:
parent
21986d92fd
commit
0919fa6575
116
snippet.el
116
snippet.el
@ -27,22 +27,56 @@
|
|||||||
(eval-when-compile (require 'cl))
|
(eval-when-compile (require 'cl))
|
||||||
|
|
||||||
|
|
||||||
(cl-defstruct (snippet--field (:constructor snippet--make-field (name mirrors parent-field start end)))
|
(cl-defstruct (snippet--field (:constructor snippet--make-field (name mirrors parent-field start end next-field prev-field)))
|
||||||
name
|
name
|
||||||
start end
|
start end
|
||||||
parent-field
|
parent-field
|
||||||
(mirrors '())
|
(mirrors '())
|
||||||
(transform nil)
|
(transform nil)
|
||||||
(modified-p nil)
|
(modified-p nil)
|
||||||
next)
|
next-field
|
||||||
|
prev-field)
|
||||||
|
|
||||||
(cl-defstruct (snippet--mirror (:constructor snippet--make-mirror (source transform parent-field start end)))
|
(cl-defstruct (snippet--mirror (:constructor snippet--make-mirror (source transform parent-field start end)))
|
||||||
source
|
source
|
||||||
start end
|
start end
|
||||||
(transform nil)
|
(transform nil)
|
||||||
parent-field
|
parent-field)
|
||||||
next
|
|
||||||
depth)
|
(defgroup snippet nil
|
||||||
|
"Customize snippet features"
|
||||||
|
:group 'convenience)
|
||||||
|
|
||||||
|
(defface snippet-field-face
|
||||||
|
'((t (:inherit 'region)))
|
||||||
|
"Face used to highlight the currently active field of a snippet"
|
||||||
|
:group 'snippet)
|
||||||
|
|
||||||
|
(defvar snippet-field-keymap
|
||||||
|
(let ((map (make-sparse-keymap)))
|
||||||
|
(define-key map [(tab)] 'snippet-next-field)
|
||||||
|
(define-key map [backtab] 'snippet-prev-field)
|
||||||
|
map)
|
||||||
|
"The active keymap while a snippet expansion is in progress.")
|
||||||
|
|
||||||
|
(defvar snippet--field-overlay nil)
|
||||||
|
|
||||||
|
(defun snippet-next-field (&optional prev)
|
||||||
|
(interactive)
|
||||||
|
(let ((field (overlay-get snippet--field-overlay 'field)))
|
||||||
|
(cond (prev
|
||||||
|
(if (snippet--field-prev-field field)
|
||||||
|
(snippet--move-to-field (snippet--field-prev-field field))
|
||||||
|
(goto-char (snippet--field-start field))
|
||||||
|
(snippet-exit-snippet)))
|
||||||
|
(t
|
||||||
|
(if (snippet--field-next-field field)
|
||||||
|
(snippet--move-to-field (snippet--field-next-field field))
|
||||||
|
(goto-char (snippet--field-end field))
|
||||||
|
(snippet-exit-snippet))))))
|
||||||
|
|
||||||
|
(defun snippet-exit-snippet ()
|
||||||
|
(delete-overlay snippet--field-overlay))
|
||||||
|
|
||||||
(defun snippet--make-marker ()
|
(defun snippet--make-marker ()
|
||||||
(let ((marker (make-marker)))
|
(let ((marker (make-marker)))
|
||||||
@ -53,17 +87,17 @@
|
|||||||
(declare (indent defun))
|
(declare (indent defun))
|
||||||
`(snippet--call-with-current-object ,object #'(lambda () ,@body)))
|
`(snippet--call-with-current-object ,object #'(lambda () ,@body)))
|
||||||
|
|
||||||
(defun snippet--object-start-marker (o)
|
(defun snippet--object-start-marker (field-or-mirror)
|
||||||
(cond ((snippet--field-p o)
|
(cond ((snippet--field-p field-or-mirror)
|
||||||
(snippet--field-start o))
|
(snippet--field-start field-or-mirror))
|
||||||
((snippet--mirror-p o)
|
((snippet--mirror-p field-or-mirror)
|
||||||
(snippet--mirror-start o))))
|
(snippet--mirror-start field-or-mirror))))
|
||||||
|
|
||||||
(defun snippet--object-end-marker (o)
|
(defun snippet--object-end-marker (field-or-mirror)
|
||||||
(cond ((snippet--field-p o)
|
(cond ((snippet--field-p field-or-mirror)
|
||||||
(snippet--field-end o))
|
(snippet--field-end field-or-mirror))
|
||||||
((snippet--mirror-p o)
|
((snippet--mirror-p field-or-mirror)
|
||||||
(snippet--mirror-end o))))
|
(snippet--mirror-end field-or-mirror))))
|
||||||
|
|
||||||
(defun snippet--call-with-current-object (object fn)
|
(defun snippet--call-with-current-object (object fn)
|
||||||
(let* ((start (snippet--object-start-marker object))
|
(let* ((start (snippet--object-start-marker object))
|
||||||
@ -84,9 +118,26 @@
|
|||||||
(insert text))))
|
(insert text))))
|
||||||
|
|
||||||
(defun snippet--insert-mirror (mirror)
|
(defun snippet--insert-mirror (mirror)
|
||||||
|
(snippet--update-mirror mirror))
|
||||||
|
|
||||||
|
(defun snippet--update-mirror (mirror)
|
||||||
(snippet--with-current-object mirror
|
(snippet--with-current-object mirror
|
||||||
|
(delete-region (snippet--object-start-marker mirror)
|
||||||
|
(snippet--object-end-marker mirror))
|
||||||
(insert (funcall (snippet--mirror-transform mirror)))))
|
(insert (funcall (snippet--mirror-transform mirror)))))
|
||||||
|
|
||||||
|
(defun snippet--move-to-field (field)
|
||||||
|
(goto-char (snippet--object-start-marker field))
|
||||||
|
(move-overlay snippet--field-overlay
|
||||||
|
(point)
|
||||||
|
(snippet--object-end-marker field))
|
||||||
|
(overlay-put snippet--field-overlay 'snippet--field field))
|
||||||
|
|
||||||
|
(defun snippet--field-overlay-changed (overlay after? _beg _end &optional _length)
|
||||||
|
(when after?
|
||||||
|
(let ((field (overlay-get overlay 'snippet--field)))
|
||||||
|
(mapc #'snippet--update-mirror (snippet--field-mirrors field)))))
|
||||||
|
|
||||||
(defun snippet--field-text (field)
|
(defun snippet--field-text (field)
|
||||||
(buffer-substring-no-properties (snippet--field-start field)
|
(buffer-substring-no-properties (snippet--field-start field)
|
||||||
(snippet--field-end field)))
|
(snippet--field-end field)))
|
||||||
@ -204,7 +255,8 @@ I would need these somewhere in the let* form
|
|||||||
`(snippet--make-marker))))))
|
`(snippet--make-marker))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defun snippet--first-field-sym (tuples)
|
||||||
|
(first (cl-find-if #'snippet--form-field-p tuples :key #'second)))
|
||||||
|
|
||||||
|
|
||||||
(defun snippet--make-object-sym-tuples (tuples)
|
(defun snippet--make-object-sym-tuples (tuples)
|
||||||
@ -237,13 +289,17 @@ I would need these somewhere in the let* form
|
|||||||
;; complete lists of mirror symbols.
|
;; complete lists of mirror symbols.
|
||||||
;;
|
;;
|
||||||
(make-field-forms
|
(make-field-forms
|
||||||
(loop for (sym form parent-sym) in tuples
|
(loop with field-tuples = (cl-remove-if-not #'snippet--form-field-p tuples :key #'second)
|
||||||
when (snippet--form-field-p form)
|
for (prev-sym) in (cons nil field-tuples)
|
||||||
|
for (sym form parent-sym) in field-tuples
|
||||||
|
for (next-sym) in (append field-tuples (list nil))
|
||||||
collect `(,sym (snippet--make-field ,(second form)
|
collect `(,sym (snippet--make-field ,(second form)
|
||||||
(list ,@(gethash sym field-mirrors))
|
(list ,@(gethash sym field-mirrors))
|
||||||
,parent-sym
|
,parent-sym
|
||||||
,(snippet--start-marker-name sym)
|
,(snippet--start-marker-name sym)
|
||||||
,(snippet--end-marker-name sym))))))
|
,(snippet--end-marker-name sym)
|
||||||
|
,prev-sym
|
||||||
|
,next-sym)))))
|
||||||
|
|
||||||
(append make-field-forms
|
(append make-field-forms
|
||||||
make-mirror-forms)))
|
make-mirror-forms)))
|
||||||
@ -296,13 +352,12 @@ can be:
|
|||||||
options is currently unimplemented."
|
options is currently unimplemented."
|
||||||
(let* ((sym-tuples (snippet--form-sym-tuples body))
|
(let* ((sym-tuples (snippet--form-sym-tuples body))
|
||||||
(marker-init-forms (snippet--make-marker-init-forms sym-tuples))
|
(marker-init-forms (snippet--make-marker-init-forms sym-tuples))
|
||||||
(make-object-forms (snippet--make-object-sym-tuples sym-tuples)))
|
(make-object-forms (snippet--make-object-sym-tuples sym-tuples))
|
||||||
|
(first-field-sym (snippet--first-field-sym sym-tuples)))
|
||||||
`(let ((insert-snippet-fn
|
`(let ((insert-snippet-fn
|
||||||
#'(lambda ()
|
#'(lambda ()
|
||||||
(let* (,@(mapcar #'list (remove 'ignore (mapcar #'car sym-tuples)))
|
(let* (,@(mapcar #'list (remove 'ignore (mapcar #'car sym-tuples)))
|
||||||
,@marker-init-forms
|
,@marker-init-forms)
|
||||||
(start (point))
|
|
||||||
overlay)
|
|
||||||
|
|
||||||
,(if make-object-forms
|
,(if make-object-forms
|
||||||
`(setq ,@(loop for (sym form) in make-object-forms
|
`(setq ,@(loop for (sym form) in make-object-forms
|
||||||
@ -320,8 +375,19 @@ can be:
|
|||||||
((functionp form)
|
((functionp form)
|
||||||
`(insert (funcall ,form)))))
|
`(insert (funcall ,form)))))
|
||||||
|
|
||||||
(setq overlay (make-overlay start (point)))
|
(setq snippet--field-overlay
|
||||||
overlay
|
(make-overlay (point) (point) nil nil t))
|
||||||
|
(overlay-put snippet--field-overlay
|
||||||
|
'face
|
||||||
|
'snippet-field-face)
|
||||||
|
(overlay-put snippet--field-overlay
|
||||||
|
'modification-hooks
|
||||||
|
'(snippet--field-overlay-changed))
|
||||||
|
(overlay-put snippet--field-overlay
|
||||||
|
'keymap
|
||||||
|
snippet-field-keymap)
|
||||||
|
,(if first-field-sym
|
||||||
|
`(snippet--move-to-field ,first-field-sym))
|
||||||
))))
|
))))
|
||||||
(defun ,name ()
|
(defun ,name ()
|
||||||
(funcall insert-snippet-fn)))))
|
(funcall insert-snippet-fn)))))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user