branch: master
commit 975da4bc12d61cbc8e233c6a1c90d0741d0a4180
Author: Ian D <[email protected]>
Commit: Ian D <[email protected]>
Improved org-bat-parse-form to handle new argument types
Includes quoted arguments, nested parentheses, and arguments with spaces.
* org-bat.el (org-bat-parse-form): Rewrote to use `read-from-string'.
---
org-bat.el | 46 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 39 insertions(+), 7 deletions(-)
diff --git a/org-bat.el b/org-bat.el
index e3ca976..d360732 100644
--- a/org-bat.el
+++ b/org-bat.el
@@ -13,13 +13,45 @@
(require 'subr-x)
(defun org-bat-parse-form (form)
- "Form should be KEY(ARGS)."
- (when (string-match "^\\([!]\\)?\\([a-zA-Z-]+\\)\\(?:(\\([^)]+\\))\\)?" form)
- (list (intern (match-string 2 form))
- (when-let (args (match-string 3 form))
- (save-match-data (split-string args ",")))
- (match-string 1 form)
- (match-end 0))))
+ (pcase-let* ((`(,token . ,pos) (read-from-string form))
+ (modifier nil)
+ (args nil))
+ (unless token
+ (signal 'invalid-read-syntax (substring form pos)))
+ ;; Check for either end of string or an opening parenthesis
+ (unless (or (equal pos (length form))
+ (equal (string-match-p "(" form pos) pos))
+ (signal 'invalid-read-syntax (substring form pos 1)))
+ ;; Parse arguments if we have any
+ (when (equal (string-match-p "(" form pos) pos)
+ ;; Move past the parenthesis
+ (cl-incf pos)
+ (while (and (< pos (length form))
+ (not (= (string-match-p ")" form pos) pos)))
+ (pcase-let* ((`(,arg . ,new-pos) (read-from-string form pos)))
+ (unless arg
+ (signal 'invalid-read-syntax (substring form pos)))
+ (let ((new-arg (if (stringp arg) arg (symbol-name arg))))
+ (push new-arg args))
+ (setq pos new-pos)
+ ;; Move past whitespace
+ (when (eq (string-match "\\w+" form pos) pos)
+ (setq pos (match-end 0)))
+ ;; The next character should either be a ',' or a ')'
+ (unless (equal (string-match-p "[,)]" form pos) pos)
+ (signal 'invalid-read-syntax (substring form pos 1)))
+ ;; Move past a comma if there is one
+ (when (equal (string-match-p "," form pos) pos)
+ (cl-incf pos))))
+ (unless (equal (string-match-p ")" form pos) pos)
+ (signal 'invalid-read-syntax (substring form pos 1)))
+ (setq args (seq-reverse args))
+ ;; Move past the closing parenthesis
+ (cl-incf pos))
+ (when (string-match "^\\([!]\\)\\(.*\\)" (symbol-name token))
+ (setq modifier (intern (match-string 1 (symbol-name token))))
+ (setq token (intern (match-string 2 (symbol-name token)))))
+ (list token args modifier pos)))
(defconst org-bat--types
'(finder action condition)