@@ -9,6 +9,10 @@ import ProjectM36.Attribute hiding (null)
9import qualified Data.List as L
9import qualified Data.List as L
10import qualified Data.Text as T
10import qualified Data.Text as T
11import Control.Arrow hiding (left)
11import Control.Arrow hiding (left)
13+import Data.Char.WCWidth --guess the width that the character will appear as in the terminal
13boxV :: StringType
17boxV :: StringType
@@ -77,7 +81,7 @@ cellSizes (header, body) = map (map maxRowWidth &&& map (length . breakLines)) a
79 L.maximum (lengths row)
83 L.maximum (lengths row)
80− lengths row = map T.length (breakLines row)
84+ lengths row = map stringDisplayLength (breakLines row)
81 allRows = header : body
85 allRows = header : body
83relationAsTable :: Relation -> Table
87relationAsTable :: Relation -> Table
@@ -102,6 +106,7 @@ showParens predicate f = if predicate then
102showAtom :: Int -> Atom -> StringType
106showAtom :: Int -> Atom -> StringType
103showAtom _ (RelationAtom rel) = renderTable $ relationAsTable rel
107showAtom _ (RelationAtom rel) = renderTable $ relationAsTable rel
104showAtom level (ConstructedAtom dConsName _ atoms) = showParens (level >= 1 && not (null atoms)) $ T.concat (L.intersperse " " (dConsName : map (showAtom 1) atoms))
108showAtom level (ConstructedAtom dConsName _ atoms) = showParens (level >= 1 && not (null atoms)) $ T.concat (L.intersperse " " (dConsName : map (showAtom 1) atoms))
109+showAtom _ (TextAtom t) = "\"" <> t <> "\""
105showAtom _ atom = atomToText atom
110showAtom _ atom = atomToText atom
107renderTable :: Table -> StringType
112renderTable :: Table -> StringType
@@ -120,13 +125,14 @@ renderHeader (header, body) columnLocations = renderTopBar `T.append` renderHead
120renderHBar :: StringType -> StringType -> StringType -> [Int] -> StringType
125renderHBar :: StringType -> StringType -> StringType -> [Int] -> StringType
121renderHBar left middle end columnLocations = left `T.append` T.concat (L.intersperse middle (map (`repeatString` boxH) columnLocations)) `T.append` end
126renderHBar left middle end columnLocations = left `T.append` T.concat (L.intersperse middle (map (`repeatString` boxH) columnLocations)) `T.append` end
128+--pad a block of potentially multi-lined text
123leftPaddedString :: Int -> Int -> StringType -> StringType
129leftPaddedString :: Int -> Int -> StringType -> StringType
124leftPaddedString lineNum size str = if lineNum > length paddedLines -1 then
130leftPaddedString lineNum size str = if lineNum > length paddedLines -1 then
125 repeatString size " "
131 repeatString size " "
127 paddedLines !! lineNum
133 paddedLines !! lineNum
129− paddedLines = map (\line -> line `T.append` repeatString (size - T.length line) " ") (breakLines str)
135+ paddedLines = map (\line -> line `T.append` repeatString (size - stringDisplayLength line) " ") (breakLines str)
131renderRow :: [Cell] -> [Int] -> Int -> StringType -> StringType
137renderRow :: [Cell] -> [Int] -> Int -> StringType -> StringType
132renderRow cells columnLocations rowHeight interspersed = T.unlines $ map renderOneLine [0..rowHeight-1]
138renderRow cells columnLocations rowHeight interspersed = T.unlines $ map renderOneLine [0..rowHeight-1]
@@ -147,3 +153,14 @@ repeatString c s = T.concat (replicate c s)
148showRelation :: Relation -> StringType
154showRelation :: Relation -> StringType
149showRelation rel = renderTable (relationAsTable rel)
155showRelation rel = renderTable (relationAsTable rel)
157+--use wcwidth to guess the string width in the terminal- many CJK characters can take multiple columns in a fixed width font
158+stringDisplayLength :: StringType -> Int
159+stringDisplayLength = T.foldr charSize 0
161+ charSize char accum = let w = wcwidth char in
162+ accum + if w < 0 then