@@ -3,7 +3,8 @@ This module introduces our pretty printing monad.
33-}
44module Vatras.Show.Lines where
55
6- open import Data.Bool using (true; false; if_then_else_)
6+ open import Data.Bool using (true; false; if_then_else_; _∧_)
7+ open import Data.Char as Char using (Char)
78open import Data.Nat using (ℕ; _*_; _∸_; ⌊_/2⌋; ⌈_/2⌉; _≤ᵇ_)
89open import Data.List as List using (List; _∷_; [_]; concat; splitAt; _∷ʳ_)
910open import Data.Maybe using (nothing; just)
@@ -34,11 +35,40 @@ open Line public
3435manipulate : (String → String) → Line → Line
3536manipulate f l = record l { content = f (content l) }
3637
37- align : ℕ → Line → Line
38- align width line = manipulate (fromAlignment (alignment line) width) line
38+ -- Rough approximation for how monospaced fonts are typically rendered.
39+ -- Only currently used characters are included so this will need to be extended
40+ -- if more/different symbols/emojis are used.
41+ charWidth : Char → ℕ
42+ charWidth c =
43+ -- All the symbols starting at the Emoticons block.
44+ if (0x1f300 ≤ᵇ codePoint) ∧ (codePoint ≤ᵇ 0x1fbff)
45+ then 2
46+ else 1
47+ where
48+ codePoint = Char.toℕ c
49+
50+ stringLength : String → ℕ
51+ stringLength line = List.sum (List.map charWidth (Data.String.toList line))
3952
4053length : Line → ℕ
41- length line = Data.String.length (content line)
54+ length line = stringLength (content line)
55+
56+ -- Align the given line to have the given width.
57+ -- This will add spaces before and/or after the line depending on the line's alignment.
58+ -- also see: Data.String.Base.fromAlignment
59+ align : ℕ → Line → Line
60+ align width line =
61+ manipulate
62+ (fromAlignment
63+ (alignment line)
64+ -- We use the fromAlignment function of the standard library,
65+ -- which considers all characters to have width 1.
66+ -- If the line contains characters with width > 1 (e.g., emojis),
67+ -- then fromAlignment would add too much padding. So we have to
68+ -- decrease the padding value accordingly.
69+ (width ∸ (length line ∸ Data.String.length (content line)))
70+ )
71+ line
4272
4373{-|
4474Lines monad.
@@ -126,7 +156,7 @@ infix 1 >_
126156infix 1 >∷_
127157
128158phantom : String → String
129- phantom s = replicate (Data.String.length s) ' '
159+ phantom s = replicate (stringLength s) ' '
130160
131161mantle : String → String → Lines → Lines
132162mantle prefix suffix = map (manipulate (λ s → prefix ++ s ++ suffix))
@@ -188,7 +218,7 @@ boxed width title content =
188218 tr = '╮'
189219 br = '╯'
190220
191- total-titlebar-len = width ∸ (Data.String.length title) ∸ 4 -- 2x whitespace + 2x corners
221+ total-titlebar-len = width ∸ (stringLength title) ∸ 4 -- 2x whitespace + 2x corners
192222 left-titlebar-len = ⌊ total-titlebar-len /2⌋
193223 right-titlebar-len = ⌈ total-titlebar-len /2⌉
194224
@@ -198,7 +228,7 @@ boxed width title content =
198228
199229 title-spacing = fromChar (if (title == "" ) then h else ' ' )
200230 header = (replicate left-titlebar-len h) ++ title-spacing ++ title ++ title-spacing ++ (replicate right-titlebar-len h)
201- footer = replicate (Data.String.length header) h
231+ footer = replicate (stringLength header) h
202232 in do
203233 -- print the header of the box
204234 > (fromChar tl) ++ header ++ (fromChar tr)
0 commit comments