emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/emacsql 4a89bfaf44 044/427: Use a macro to greatly simplif


From: ELPA Syncer
Subject: [nongnu] elpa/emacsql 4a89bfaf44 044/427: Use a macro to greatly simplify expanders.
Date: Tue, 13 Dec 2022 02:59:26 -0500 (EST)

branch: elpa/emacsql
commit 4a89bfaf4487d82429944fb35893e16680483417
Author: Christopher Wellons <wellons@nullprogram.com>
Commit: Christopher Wellons <wellons@nullprogram.com>

    Use a macro to greatly simplify expanders.
---
 emacsql.el | 78 ++++++++++++++++++++++++++++++++------------------------------
 1 file changed, 40 insertions(+), 38 deletions(-)

diff --git a/emacsql.el b/emacsql.el
index dc27c69de1..ab39fa7c8d 100644
--- a/emacsql.el
+++ b/emacsql.el
@@ -355,53 +355,55 @@ KIND should be :value or :identifier."
               (:identifier (emacsql-escape thing))
               (otherwise thing))))
 
+(defvar emacsql--vars ()
+  "For use with `emacsql-with-vars'.")
+
+(defun emacsql-symbol-function (symbol)
+  "Like `symbol-function' but don't return an error."
+  (ignore-errors (symbol-function symbol)))
+
+(gv-define-setter emacsql-symbol-function (store symbol)
+  `(if ,store (fset ,symbol ,store) (fmakunbound ,symbol)))
+
+(defun emacsql--vars-collect (thing kind)
+  "Only use within `emacsql-with-vars'!"
+  (if (emacsql-var thing)
+      (prog1 "%s" (push (cons (emacsql-var thing) kind) emacsql--vars))
+    (ecase kind
+      ((:identifier :value) (emacsql-escape-format thing kind))
+      (:auto (emacsql-escape-format
+              thing (if (symbolp thing) :identifier :value))))))
+
+(defmacro emacsql-with-vars (prefix &rest body)
+  "Evaluate BODY, collecting variables with `var'.
+BODY should return a string, which will be combined with variable
+definitions for return from a `emacsql-defexpander'."
+  (declare (indent 1))
+  `(let ((emacsql--vars ()))
+     (cl-letf (((emacsql-symbol-function 'var)
+                (symbol-function 'emacsql--vars-collect)))
+       (cons (concat ,prefix (progn ,@body)) emacsql--vars))))
+
 ;; SQL Expansion Functions:
 
 (emacsql-defexpander :select (arg)
   "Expands to the SELECT keyword."
-  (let ((vars ()))
-    (cons
-     (concat
-      "SELECT "
-      (cond
-       ((eq '* arg) "*")
-       ((emacsql-var arg)
-        (push (cons (emacsql-var arg) :identifier) vars)
-        "%s")
-       ((symbolp arg)
-        (emacsql-escape-format arg :identifier))
-       ((vectorp arg)
-        (mapconcat
-         #'identity
-         (cl-loop for name elements of arg
-                  when (emacsql-var name)
-                  collect (prog1 "%s" (push (cons it :identifier) vars))
-                  else when (symbolp name)
-                  collect (emacsql-escape-format name :identifier)
-                  else do (error "Unknown format %S" name))
-         ", "))))
-     (nreverse vars))))
+  (emacsql-with-vars "SELECT "
+    (cond
+     ((eq '* arg) "*")
+     ((vectorp arg)
+      (mapconcat (lambda (s) (var s :identifier)) arg ", "))
+     ((var arg :identifier)))))
 
 (emacsql-defexpander :from (table)
   "Expands to the FROM keyword."
-  (if (emacsql-var table)
-      (list "FROM %s" (cons (emacsql-var table) :identifier))
-    (list (concat "FROM " (emacsql-escape-format table :identifier)))))
+  (emacsql-with-vars "FROM "
+    (var table :identifier)))
 
 (emacsql-defexpander :where (expr)
-  (let ((vars ()))
-    (cl-flet* ((collect (thing)
-                 (push (cons (emacsql-var thing) :auto) vars) "%s")
-               (handle (v)
-                 (cond ((emacsql-var v) (collect v))
-                       ((symbolp v) (emacsql-escape-format v :identifier))
-                       ((emacsql-escape-format v :value)))))
-      (cl-destructuring-bind (op a b) expr
-        (cons (format "WHERE %s %s %s"
-                      (handle a)
-                      op
-                      (handle b))
-              (nreverse vars))))))
+  (emacsql-with-vars "WHERE "
+    (cl-destructuring-bind (op a b) expr
+      (format "%s %s %s" (var a :auto) op (var b :auto)))))
 
 (provide 'emacsql)
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]