Skip to content

Instantly share code, notes, and snippets.

@Gavinok
Last active May 14, 2022 07:54
Show Gist options
  • Save Gavinok/250a0394e1025a0d96a8dacc9dd832a3 to your computer and use it in GitHub Desktop.
Save Gavinok/250a0394e1025a0d96a8dacc9dd832a3 to your computer and use it in GitHub Desktop.
The basis of porting yasnippets to tempel
(defvar *snippet-funcs*
'((any . (tabstop placeholder choice variable ;; text
))
(tabstop . (("$" int) ("${" int "}")))
(placeholder . (("${" int ":" any "}")))
(choice . ("${" int "|" text ("," text)* "|}"))
(variable . (("$" var) ("${" var "}")
("${" var ":" any "}")
("${" var "/" regex "/" (format | text)+ "/" options "}")))
(format . (("$" int) ("${" int "}")
("${" int ":" "/upcase") "/downcase"( "/capitalize" "}")
("${" int ":+" if "}")
("${" int ":?" if ":" else "}")
("${" int ":-" else "}") ("${" int ":" else "}")))
(regex . (JavaScript Regular Expression value (ctor-string)))
(options . (JavaScript Regular Expression option (ctor-options)))
(var . "[_a-zA-Z] [_a-zA-Z0-9]*")
(int . "[0-9]+")
(text . ".*")))
(defun parse-this (test-string remaining-string)
"Treats a given string TEST-STRING and compairs it to
REMAINING-STRING returns the matched substring starting at the 0th index and nil
if it failed to find a match.
Parse-this assumes the TEST-STRING passed was regex if it starts with a [ or ."
;; Regex Needed
(let ((start-of-sexp (aref test-string 0)))
(if (cl-some (lambda (x) (equal start-of-sexp x)) '(?\[ ?.))
(progn
(string-match (concat "\\(" test-string "\\)") remaining-string)
(match-string 1 remaining-string))
;; No regex needed
(let ((matched-string (cl-loop for i in (string-to-list test-string)
for j in (string-to-list remaining-string)
;; counter to determin the last index matched
for counter from 0
if (char-equal i j)
collect j
else
return nil)))
(if matched-string
(seq-concatenate 'string matched-string)
matched-string)))))
;; TODO implement this
(defun try-different-variations (options remaining-string)
"Try each option one at a time and go with the first match
return nil if all fail to match."
)
(defun parse-by-type (current-element remaining-element remaining-string)
"Parse the REMAINING-STRING against the CURRENT-ELEMENT the
CURRENT-ELEMENT can be a `list' of alternative formats, a
symbolwith a `sexp' location in the `*snippet-funcs*', and finally a
`string'.
parse-by-type returns nil if it was unable to match the
CURRENT-ELEMENT with the REMAINING-STRING using any of the above
methods."
(cl-check-type remaining-string string)
(print current-element)
(cl-typecase current-element
(null nil)
;; we have hit text we can match against
(string (print (parse-this current-element remaining-string)))
;; Find the definition of this symbol
(symbol (cons current-element
(parse-by-type (alist-get current-element
,*snippet-funcs*)
remaining-string)))
;; Fork in the road we go down one of 2 paths
;; first we will go down the first path
(cons (or
(handle-sexps current-element remaining-string)
(handle-sexps remaining-element remaining-string)))
(t (handle-sexps current-element remaining-string))))
;; This should return the section of the string that
;; was matched or nil if it did not match
(defun handle-sexps (current-sexp remaining-string)
"Takes a given sexp called CURRENT-SEXP tokenizes the string
named REMAINING-STRING using it's contents."
(let* ((next-element (cdr current-sexp))
(matched-result (parse-by-type
(car current-sexp)
(cdr current-sexp)
remaining-string))
;; handle when a (key . value) is returned
(matched-string (if (consp matched-result)
(cdr matched-result) matched-result)))
(cons matched-result
(if next-element
(handle-sexps next-element
(substring remaining-string
(length matched-string)
(length remaining-string)))
nil))))
(ert-deftest test/parse-this-no-regex ()
(should (equal (parse-this "$" "$l") "$"))
(should (equal (parse-this "hel" "hello") "hel"))
(should (equal (parse-this "$" "$l") "$"))
(should (equal (parse-this "ello" "hello") nil)))
(ert-deftest test/parse-this-with-regex ()
(should (equal (parse-this "[0-9]+" "10") "10"))
(should (equal (parse-this "[0-9]+" "$") nil)))
(ert-deftest test/handle-sexps-single-level-list ()
(should (equal (handle-sexps '("[0-9]+") "10") "10"))
(should (equal (handle-sexps '("[0-9]") "$") nil))
(should (equal (handle-sexps '("10") "10") "10")))
(ert-deftest test/handle-sexps-nested-lists ()
(should (equal (handle-sexps '("[0-9]+" "$") "10$")
'("10" "$")))
(should (equal (handle-sexps '("[0-9]+" ("${" int "}")) "10${1}")
'("10" ("${" "1" "}")))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment