aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/data/text/format.lux
blob: cf4b3e2d46ec305c2db2adb42a9f9e36650d2d05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
(.module:
  [library
   [lux (#- list nat int rev type)
    [abstract
     [monad (#+ do)]
     [functor
      ["." contravariant]]]
    [control
     ["<>" parser
      ["<c>" code (#+ Parser)]]]
    [data
     ["." bit]
     ["." name]
     ["." text]
     [format
      ["." xml]
      ["." json]]
     [collection
      ["." list ("#\." monad)]]]
    ["." time
     ["." instant]
     ["." duration]
     ["." date]
     ["." day]
     ["." month]]
    [math
     ["." modular]
     [number
      ["." nat]
      ["." int]
      ["." rev]
      ["." frac]
      ["." ratio]]]
    [macro
     [syntax (#+ syntax:)]
     ["." code]
     ["." template]]
    [meta
     ["." location]]
    ["." type]]])

(type: #export (Format a)
  {#.doc "A way to produce readable text from values."}
  (-> a Text))

(implementation: #export functor
  (contravariant.Functor Format)
  
  (def: (map f fb)
    (|>> f fb)))

(syntax: #export (format {fragments (<>.many <c>.any)})
  {#.doc (doc "Text interpolation."
              (format "Static part " (text static) " does not match URI: " uri))}
  (in (.list (` ($_ "lux text concat" (~+ fragments))))))

(template [<name> <type> <formatter>]
  [(def: #export <name>
     (Format <type>)
     <formatter>)]

  [bit      Bit               (\ bit.codec encode)]
  [nat      Nat               (\ nat.decimal encode)]
  [int      Int               (\ int.decimal encode)]
  [rev      Rev               (\ rev.decimal encode)]
  [frac     Frac              (\ frac.decimal encode)]
  [text     Text              text.format]
  
  [ratio    ratio.Ratio       (\ ratio.codec encode)]
  [name     Name              (\ name.codec encode)]
  [location Location          location.format]
  [code     Code              code.format]
  [type     Type              type.format]
  
  [instant  instant.Instant   (\ instant.codec encode)]
  [duration duration.Duration (\ duration.codec encode)]
  [date     date.Date         (\ date.codec encode)]
  [time     time.Time         (\ time.codec encode)]
  [day      day.Day           (\ day.codec encode)]
  [month    month.Month       (\ month.codec encode)]
  
  [xml      xml.XML           (\ xml.codec encode)]
  [json     json.JSON         (\ json.codec encode)]
  )

(template [<type> <format>,<codec>]
  [(`` (template [<format> <codec>]
         [(def: #export <format>
            (Format <type>)
            (\ <codec> encode))]

         (~~ (template.spliced <format>,<codec>))))]

  [Nat
   [[nat/2 nat.binary]
    [nat/8 nat.octal]
    [nat/10 nat.decimal]
    [nat/16 nat.hex]]]
  [Int
   [[int/2 int.binary]
    [int/8 int.octal]
    [int/10 int.decimal]
    [int/16 int.hex]]]
  [Rev
   [[rev/2 rev.binary]
    [rev/8 rev.octal]
    [rev/10 rev.decimal]
    [rev/16 rev.hex]]]
  [Frac
   [[frac/2 frac.binary]
    [frac/8 frac.octal]
    [frac/10 frac.decimal]
    [frac/16 frac.hex]]]
  )

(def: #export (mod modular)
  (All [m] (Format (modular.Mod m)))
  (let [codec (modular.codec (modular.modulus modular))]
    (\ codec encode modular)))

(def: #export (list formatter)
  (All [a] (-> (Format a) (Format (List a))))
  (|>> (list\map (|>> formatter (format " ")))
       (text.join_with "")
       (text.enclosed ["(list" ")"])))

(def: #export (maybe format)
  (All [a] (-> (Format a) (Format (Maybe a))))
  (function (_ value)
    (case value
      #.None
      "#.None"

      (#.Some value)
      (..format "(#.Some " (format value) ")"))))