(.module: lux (lux (control [monoid #+ Monoid] [equality #+ Eq] [order] [monad #+ do Monad] [codec #+ Codec] hash) (data (coll [list]) [maybe]))) ## [Functions] (def: #export (size x) (-> Text Nat) ("lux text size" x)) (def: #export (nth idx input) (-> Nat Text (Maybe Nat)) ("lux text char" input idx)) (def: #export (contains? sub text) (-> Text Text Bool) (case ("lux text index" text sub +0) (#.Some _) true _ false)) (def: #export (clip from to input) (-> Nat Nat Text (Maybe Text)) ("lux text clip" input from to)) (def: #export (clip' from input) (-> Nat Text (Maybe Text)) ("lux text clip" input from (size input))) (def: #export (replace-all pattern value template) (-> Text Text Text Text) ("lux text replace-all" template pattern value)) (def: #export (index-of' pattern from input) (-> Text Nat Text (Maybe Nat)) ("lux text index" input pattern from)) (def: #export (index-of pattern input) (-> Text Text (Maybe Nat)) ("lux text index" input pattern +0)) (def: (last-index-of'' part since text) (-> Text Nat Text (Maybe Nat)) (case ("lux text index" text part (inc since)) #.None (#.Some since) (#.Some since') (last-index-of'' part since' text))) (def: #export (last-index-of' part from text) (-> Text Nat Text (Maybe Nat)) (case ("lux text index" text part from) (#.Some since) (last-index-of'' part since text) #.None #.None)) (def: #export (last-index-of part text) (-> Text Text (Maybe Nat)) (case ("lux text index" text part +0) (#.Some since) (last-index-of'' part since text) #.None #.None)) (def: #export (starts-with? prefix x) (-> Text Text Bool) (case (index-of prefix x) (#.Some +0) true _ false)) (def: #export (ends-with? postfix x) (-> Text Text Bool) (case (last-index-of postfix x) (#.Some n) (n/= (size x) (n/+ (size postfix) n)) _ false)) (def: #export (split at x) (-> Nat Text (Maybe [Text Text])) (case [(clip +0 at x) (clip' at x)] [(#.Some pre) (#.Some post)] (#.Some [pre post]) _ #.None)) (def: #export (split-with token sample) (-> Text Text (Maybe [Text Text])) (do maybe.Monad [index (index-of token sample) [pre post'] (split index sample) [_ post] (split (size token) post')] (wrap [pre post]))) (def: #export (split-all-with token sample) (-> Text Text (List Text)) (case (split-with token sample) (#.Some [pre post]) (#.Cons pre (split-all-with token post)) #.None (#.Cons sample #.Nil))) (def: #export split-lines (split-all-with "\n")) ## [Structures] (struct: #export _ (Eq Text) (def: (= test subject) ("lux text =" subject test))) (struct: #export _ (order.Order Text) (def: eq Eq) (def: (< test subject) ("lux text <" subject test)) (def: (<= test subject) (or ("lux text <" subject test) ("lux text =" subject test))) (def: (> test subject) ("lux text <" test subject)) (def: (>= test subject) (or ("lux text <" test subject) ("lux text =" test subject))) ) (struct: #export _ (Monoid Text) (def: identity "") (def: (compose left right) ("lux text concat" left right))) (open: "text/" Monoid) (def: #export (encode original) (-> Text Text) (let [escaped (|> original (replace-all "\\" "\\\\") (replace-all "\t" "\\t") (replace-all "\v" "\\v") (replace-all "\b" "\\b") (replace-all "\n" "\\n") (replace-all "\r" "\\r") (replace-all "\f" "\\f") (replace-all "\"" "\\\"") )] ($_ text/compose "\"" escaped "\""))) (struct: #export _ (Hash Text) (def: eq Eq) (def: (hash input) ("lux text hash" input))) (def: #export concat (-> (List Text) Text) (let [(^open) list.Fold (^open) Monoid] (|>> list.reverse (fold text/compose identity)))) (def: #export (join-with sep texts) (-> Text (List Text) Text) (|> texts (list.interpose sep) concat)) (def: #export (empty? text) (-> Text Bool) (case text "" true _ false)) (def: #export (replace-once pattern value template) (-> Text Text Text Text) (maybe.default template (do maybe.Monad [[pre post] (split-with pattern template) #let [(^open) Monoid]] (wrap ($_ text/compose pre value post))))) (def: #export (enclose [left right] content) {#.doc "Surrounds the given content text with left and right side additions."} (-> [Text Text] Text Text) (let [(^open) Monoid] ($_ text/compose left content right))) (def: #export (enclose' boundary content) {#.doc "Surrounds the given content text with the same boundary text."} (-> Text Text Text) (enclose [boundary boundary] content)) (def: #export from-code (-> Nat Text) (|>> (:coerce Int) "lux int char")) (def: #export (space? char) {#.doc "Checks whether the character is white-space."} (-> Nat Bool) (case char (^or (^ (char "\t")) (^ (char "\v")) (^ (char " ")) (^ (char "\n")) (^ (char "\r")) (^ (char "\f"))) true _ false))