Display an outline as a nested table: Difference between revisions

→‎{{header|Haskell}}: Added a draft in Haskell
(→‎{{header|Haskell}}: Added a draft in Haskell)
Line 500:
| |
| |
|}
 
=={{header|Haskell}}==
<lang haskell>{-# LANGUAGE TupleSections #-}
 
module OutlineTree where
 
import Data.Bifunctor (first)
import Data.Bool (bool)
import Data.Char (isSpace)
import Data.List (find, intercalate)
import Data.Tree (Tree (..), foldTree, levels)
 
 
---------------- NESTED TABLE FROM OUTLINE ---------------
 
wikiTableFromOutline :: [String] -> String -> String
wikiTableFromOutline colorSwatch =
wikiTableFromRows
. levels
. paintedTree colorSwatch
. widthLabelledTree
. (paddedTree [] =<< treeDepth)
. treeFromOutline
 
 
--------------------------- TEST -------------------------
main :: IO ()
main =
( putStrLn
. wikiTableFromOutline
[ "#ffffe6",
"#ffebd2",
"#f0fff0",
"#e6ffff",
"#ffeeff"
]
)
"Display an outline as a nested table.\n\
\ Parse the outline to a tree,\n\
\ measuring the indent of each line,\n\
\ translating the indentation to a nested structure,\n\
\ and padding the tree to even depth.\n\
\ count the leaves descending from each node,\n\
\ defining the width of a leaf as 1,\n\
\ and the width of a parent node as a sum.\n\
\ (The sum of the widths of its children)\n\
\ and write out a table with 'colspan' values\n\
\ either as a wiki table,\n\
\ or as HTML."
 
 
------------- TREE STRUCTURE FROM NESTED TEXT ------------
 
treeFromOutline :: String -> Tree String
treeFromOutline s =
head
. forestFromLineIndents
. indentLevelsFromLines
$ lines s
 
forestFromLineIndents :: [(Int, String)] -> [Tree String]
forestFromLineIndents = go
where
go [] = []
go ((n, s) : xs) =
let (subOutline, rest) = span ((n <) . fst) xs
in Node s (go subOutline) : go rest
 
indentLevelsFromLines :: [String] -> [(Int, String)]
indentLevelsFromLines xs =
let pairs = first length . span isSpace <$> xs
indentUnit = maybe 1 fst (find ((0 <) . fst) pairs)
in first (`div` indentUnit) <$> pairs
 
 
---------------- TREE PADDED TO EVEN DEPTH ---------------
 
paddedTree :: a -> Int -> Tree a -> Tree a
paddedTree padValue = go
where
go n tree
| 1 >= n = tree
| otherwise =
Node
(rootLabel tree)
( go (pred n)
<$> bool nest [Node padValue []] (null nest)
)
where
nest = subForest tree
 
treeDepth :: Tree a -> Int
treeDepth = foldTree go
where
go _ [] = 1
go _ xs = (succ . maximum) xs
 
 
----------------- SUBTREE WIDTHS MEASURED ----------------
 
widthLabelledTree :: Tree a -> Tree (a, Int)
widthLabelledTree = foldTree go
where
go x [] = Node (x, 1) []
go x xs =
Node
(x, foldr ((+) . snd . rootLabel) 0 xs)
xs
 
 
------------------- COLOR SWATCH APPLIED -----------------
 
paintedTree :: [String] -> Tree a -> Tree (String, a)
paintedTree [] tree = fmap ("",) tree
paintedTree (color : colors) tree =
Node
(color, rootLabel tree)
( zipWith
(fmap . (,))
(cycle $ colors <> [""])
(subForest tree)
)
 
 
-------------------- WIKITABLE RENDERED ------------------
 
wikiTableFromRows :: [[(String, (String, Int))]] -> String
wikiTableFromRows rows =
let wikiRow = unlines . fmap cellText
cellText (color, (txt, width))
| null txt = "| |"
| otherwise = "| " <> cw color width <> "| " <> txt
cw color width =
let go w
| 1 < w = " colspan=" <> show w
| otherwise = ""
in "style=\"background:"
<> color
<> "; \""
<> go width
<> " "
in "{| class=\"wikitable\" "
<> "style=\"text-align: center;\"\n|-\n"
<> intercalate "|-\n" (wikiRow <$> rows)
<> "|}"
</lang>
{{Out}}
{| class="wikitable" style="text-align: center;"
|-
| style="background:#ffffe6; " colspan=7 | Display an outline as a nested table.
|-
| style="background:#ffebd2; " colspan=3 | Parse the outline to a tree,
| style="background:#f0fff0; " colspan=2 | count the leaves descending from each node,
| style="background:#e6ffff; " colspan=2 | and write out a table with 'colspan' values
|-
| style="background:#ffebd2; " | measuring the indent of each line,
| style="background:#ffebd2; " | translating the indentation to a nested structure,
| style="background:#ffebd2; " | and padding the tree to even depth.
| style="background:#f0fff0; " | defining the width of a leaf as 1,
| style="background:#f0fff0; " | and the width of a parent node as a sum.
| style="background:#e6ffff; " | either as a wiki table,
| style="background:#e6ffff; " | or as HTML.
|-
| |
| |
| |
| |
| style="background:#f0fff0; " | (The sum of the widths of its children)
| |
| |
|}
 
9,655

edits