module Numeric.LAPACK.Output ( Output (text, above, beside, formatRow, formatColumn, formatAligned, formatSeparateTriangle), (/+/), (<+>), hyper, ) where import qualified Hyper import qualified Text.Blaze.Html4.Transitional as Html import qualified Text.Blaze.Html4.Transitional.Attributes as Attr import qualified Text.Blaze.Html.Renderer.Text as RenderHtml import Text.Blaze.Html ((!)) import qualified Text.PrettyPrint.Boxes as TextBox import Text.PrettyPrint.Boxes (Box) import qualified Data.Text.Lazy as TextLazy import qualified Data.Foldable as Fold import qualified Data.List.HT as ListHT import qualified Data.List as List import Data.Foldable (Foldable) import Data.String (fromString) import Data.Maybe.HT (toMaybe) import Data.Maybe (fromMaybe) class Output out where text :: String -> out above :: out -> out -> out beside :: out -> out -> out formatRow, formatColumn :: [out] -> out formatAligned :: (Foldable f) => [[f out]] -> out formatSeparateTriangle :: (Foldable f) => [[f out]] -> out (/+/) :: (Output out) => out -> out -> out (/+/) = above (<+>) :: (Output out) => out -> out -> out (<+>) = beside newtype Html = Html {unHtml :: Html.Html} hyper :: Html -> Hyper.Graphic hyper = Hyper.html . TextLazy.toStrict . RenderHtml.renderHtml . unHtml instance Output Html where text = Html . Html.toHtml above (Html a) (Html b) = Html $ a >> Html.br >> b beside (Html a) (Html b) = Html $ a >> Html.string " " >> b formatRow = Html . Html.table . Html.tr . mapM_ (td . unHtml) formatColumn = Html . Html.table . mapM_ (Html.tr . td . unHtml) formatAligned = Html . Html.table . mapM_ (Html.tr . mapM_ (td . unHtml) . concatMap Fold.toList) formatSeparateTriangle = Html . Html.table . mapM_ (Html.tr . mapM_ td . concat) . zipWith (zipWith $ \it -> map (it . unHtml) . Fold.toList) (iterate (Html.i:) (repeat id)) td :: Html.Html -> Html.Html td = Html.td ! Attr.align (fromString "right") instance Output Box where text = TextBox.text above = (TextBox./+/) beside = (TextBox.<+>) formatRow = TextBox.hsep 1 TextBox.right formatColumn = TextBox.vsep 1 TextBox.right formatAligned = alignSeparated . map (concatMap (attachSeparators Space)) formatSeparateTriangle = alignSeparated . map concat . zipWith (zipWith attachSeparators) (ListHT.outerProduct (\row col -> if row==col then Bar else Space) [(0::Int)..] [0..]) data Separator = Empty | Space | Bar deriving (Eq, Ord, Show) alignSeparated :: [[(Separator, Box)]] -> Box alignSeparated = TextBox.hcat TextBox.top . map (TextBox.vcat TextBox.right) . concatMap ((\(seps,column) -> [map (TextBox.text . formatSeparator) seps, column]) . unzip) . List.unfoldr (viewLAll (Empty, TextBox.text "")) viewLAll :: a -> [[a]] -> Maybe ([a], [[a]]) viewLAll x0 xs = toMaybe (any (not.null) xs) (unzip $ map (fromMaybe (x0,[]) . ListHT.viewL) xs) formatSeparator :: Separator -> String formatSeparator sep = case sep of Empty -> ""; Space -> " "; Bar -> "|" attachSeparators :: (Foldable f) => Separator -> f str -> [(Separator, str)] attachSeparators sep = zip (sep:repeat Empty) . Fold.toList