112 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
| -- | Text.Tabular.AsciiArt from tabular-0.2.2.7, modified to treat
 | |
| -- wide characters as double width.
 | |
| 
 | |
| module Text.Tabular.AsciiWide where
 | |
| 
 | |
| import Data.List (intersperse, transpose)
 | |
| import Text.Tabular
 | |
| import Hledger.Utils.String
 | |
| 
 | |
| -- | for simplicity, we assume that each cell is rendered
 | |
| --   on a single line
 | |
| render :: Bool -- ^ pretty tables
 | |
|        -> (rh -> String)
 | |
|        -> (ch -> String)
 | |
|        -> (a -> String)
 | |
|        -> Table rh ch a
 | |
|        -> String
 | |
| render pretty fr fc f (Table rh ch cells) =
 | |
|   unlines $ [ bar SingleLine   -- +--------------------------------------+
 | |
|             , renderColumns pretty sizes ch2
 | |
|             , bar DoubleLine   -- +======================================+
 | |
|             ] ++
 | |
|             (renderRs $ fmap renderR $ zipHeader [] cells $ fmap fr rh) ++
 | |
|             [ bar SingleLine ] -- +--------------------------------------+
 | |
|  where
 | |
|   bar = concat . renderHLine pretty sizes ch2
 | |
|   -- ch2 and cell2 include the row and column labels
 | |
|   ch2 = Group DoubleLine [Header "", fmap fc ch]
 | |
|   cells2 = headerContents ch2
 | |
|          : zipWith (\h cs -> h : map f cs) rhStrings cells
 | |
|   --
 | |
|   renderR (cs,h) = renderColumns pretty sizes $ Group DoubleLine
 | |
|                     [ Header h
 | |
|                     , fmap fst $ zipHeader "" (map f cs) ch]
 | |
|   rhStrings = map fr $ headerContents rh
 | |
|   -- maximum width for each column
 | |
|   sizes   = map (maximum . map strWidth) . transpose $ cells2
 | |
|   renderRs (Header s)   = [s]
 | |
|   renderRs (Group p hs) = concat . intersperse sep . map renderRs $ hs
 | |
|     where sep = renderHLine pretty sizes ch2 p
 | |
| 
 | |
| verticalBar :: Bool -> Char
 | |
| verticalBar pretty = if pretty then '│' else '|'
 | |
| 
 | |
| leftBar :: Bool -> String
 | |
| leftBar pretty = verticalBar pretty : " "
 | |
| 
 | |
| rightBar :: Bool -> String
 | |
| rightBar pretty = " " ++ [verticalBar pretty]
 | |
| 
 | |
| midBar :: Bool -> String
 | |
| midBar pretty = " " ++ verticalBar pretty : " "
 | |
| 
 | |
| doubleMidBar :: Bool -> String
 | |
| doubleMidBar pretty = if pretty then " ║ " else " || "
 | |
| 
 | |
| horizontalBar :: Bool -> Char
 | |
| horizontalBar pretty = if pretty then '─' else '-'
 | |
| 
 | |
| doubleHorizontalBar :: Bool -> Char
 | |
| doubleHorizontalBar pretty = if pretty then '═' else '='
 | |
| 
 | |
| -- | We stop rendering on the shortest list!
 | |
| renderColumns :: Bool -- ^ pretty
 | |
|               -> [Int] -- ^ max width for each column
 | |
|               -> Header String
 | |
|               -> String
 | |
| renderColumns pretty is h = leftBar pretty ++ coreLine ++ rightBar pretty
 | |
|  where
 | |
|   coreLine = concatMap helper $ flattenHeader $ zipHeader 0 is h
 | |
|   helper = either hsep (uncurry padLeftWide)
 | |
|   hsep :: Properties -> String
 | |
|   hsep NoLine     = "  "
 | |
|   hsep SingleLine = midBar pretty
 | |
|   hsep DoubleLine = doubleMidBar pretty
 | |
| 
 | |
| renderHLine :: Bool -- ^ pretty
 | |
|             -> [Int] -- ^ width specifications
 | |
|             -> Header String
 | |
|             -> Properties
 | |
|             -> [String]
 | |
| renderHLine _ _ _ NoLine = []
 | |
| renderHLine pretty w h SingleLine = [renderHLine' pretty SingleLine w (horizontalBar pretty) h]
 | |
| renderHLine pretty w h DoubleLine = [renderHLine' pretty DoubleLine w (doubleHorizontalBar pretty) h]
 | |
| 
 | |
| doubleCross :: Bool -> String
 | |
| doubleCross pretty = if pretty then "╬" else "++"
 | |
| 
 | |
| doubleVerticalCross :: Bool -> String
 | |
| doubleVerticalCross pretty = if pretty then "╫" else "++"
 | |
| 
 | |
| cross :: Bool -> Char
 | |
| cross pretty = if pretty then '┼' else '+'
 | |
| 
 | |
| renderHLine' :: Bool -> Properties -> [Int] -> Char -> Header String -> String
 | |
| renderHLine' pretty prop is sep h = [ cross pretty, sep ] ++ coreLine ++ [sep, cross pretty]
 | |
|  where
 | |
|   coreLine        = concatMap helper $ flattenHeader $ zipHeader 0 is h
 | |
|   helper          = either vsep dashes
 | |
|   dashes (i,_)    = replicate i sep
 | |
|   vsep NoLine     = replicate 2 sep  -- match the double space sep in renderColumns
 | |
|   vsep SingleLine = sep : cross pretty : [sep]
 | |
|   vsep DoubleLine = sep : cross' ++ [sep]
 | |
|   cross' = case prop of
 | |
|      DoubleLine -> doubleCross pretty
 | |
|      _ -> doubleVerticalCross pretty
 | |
| 
 | |
| -- padLeft :: Int -> String -> String
 | |
| -- padLeft l s = padding ++ s
 | |
| --  where padding = replicate (l - length s) ' '
 | |
| 
 |