(chapter-start ‘string-manipulation “utilities for manipulating strings”)
; return a new string with leading and trailing whitespace removed (def string-strip (txt)
(string-replace "(\\A\\s+|\\s+\\z)" "" txt))
;; flatten ‘things into a single list (ie unnest lists) ;; convert each item to a string ;; return a single string which is the concatenation of each ;; stringified item, with given ’txt inserted in between ;; each item (def joinstr (txt . things)
(let joinables (flatten things) (apply + (to-string:car joinables) (flatten (map (fn (x) (list txt x)) (cdr joinables))))))
;; stringify join all the things and join them with no separator, like (joinstr “” things) (def j things
(apply + "" (flatmap to-string things)))
;; string-interpolation syntax emits this form. Default implementation ;; is to delegate to ‘j , but containing forms may use macros that ;; override this in order to provide specific interpolation behaviour ;; (for example, formatting numbers or stripping HTML tags) (def string-pieces pieces
(j pieces))
; return the first ‘length chars of string ’str (def string-truncate (str length)
(string-replace "(.{~|length|}).*" "\\1" str))
;; returns a function with args ‘args whose body is ’str. ‘str should be a string, ;; ’args should correspond to interpolations within ‘str ;; ;; example: (string-eval-fn “hello ~u.firstname” ’u) ;; returns (fn (u) (string-pieces “hello ” u.firstname)) (defmemo string-eval-fn (str args)
(eval `(fn ,args ,(parse-in-string str))))
;; assigns ‘args respectively to ’arg-names and evals ‘str in that context. ;; Assumes ’str contains interpolations which reference ‘arg-names. ;; Useful for evaluating user-supplied strings ; dangerous for the same reason. ;; ;; example: (string/eval-with-args “~x + ~y is ~(+ x y)” ’(x y) 2 3) ;; returns “2 + 3 is 5” ;; (def string/eval-with-args (str arg-names . args)
(on-err (error (j "error evaluating " (inspect str) "\nwith arg names " (inspect arg-names) "\nand args " (inspect args))) (apply (string-eval-fn str arg-names) args)))
;; if txt is not blank/empty, return concatenation of before, txt, after (def maybe-wrap-text (txt before after)
(if (nb txt) (j before txt after) txt))