diff --git a/README.md b/README.md index 573af3c..ba5917e 100644 --- a/README.md +++ b/README.md @@ -887,8 +887,9 @@ A case-like macro that works with strings (CL case's test function is Example: ~~~lisp -(str:string-case input - ("foo" (do something)) +(str:string-case "hello" + ("foo" 1) + (("hello" "test") 5) (nil (print "input is nil")) (otherwise (print "non of the previous forms was caught."))) ~~~ diff --git a/str.lisp b/str.lisp index c010918..6273ce3 100644 --- a/str.lisp +++ b/str.lisp @@ -711,11 +711,13 @@ Returns the string written to file." (defmacro string-case (str &body forms) "A case-like macro that works with strings (case works only with symbols). + You can either supply single-item clauses, multiple-items clauses, or otherwise. Example: (str:string-case input (\"foo\" (do something)) + ((\"hello\" \"test\") 5) (nil (print \"input is nil\") (otherwise (print \"none of the previous forms was caught\"))) @@ -729,7 +731,12 @@ Returns the string written to file." (cond ,@(loop :for (s . f) :in forms :if (stringp s) :collect `((string= ,test ,s) ,@f) - :else :if (string= s 'otherwise) :collect `(t ,@f) + :else :if (consp s) + :append (loop for element :in s + :if (stringp element) + :collect `((string= ,test ,element) ,@f) + :else :collect `((eql ,test ,s) ,@f)) + :else :if (string= s 'otherwise) :collect `(t ,@f) :else :collect `((eql ,test ,s) ,@f)))))) (defun expand-match-branch (str block patterns forms) diff --git a/test/test-str.lisp b/test/test-str.lisp index 932fa93..b0cbbb7 100644 --- a/test/test-str.lisp +++ b/test/test-str.lisp @@ -695,6 +695,11 @@ ("hello" (format nil "yes")) (otherwise nil)) "string-case base case") + (is (string-case "two-forms" + ("first" nil) + (("hello" "two-forms") t) + (otherwise nil)) + "multiple-item clause") (is (string= nil (string-case "no" ("hello" t) (otherwise nil)))