All files / src/draw/tree layout.ts

100% Statements 46/46
100% Branches 9/9
100% Functions 5/5
100% Lines 46/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 631x 1x 1x 1x   1x 1x 1x                   1x 1x 1x   536x 536x 536x 536x 536x 536x 536x 536x 536x 536x   1x 1x 536x 208x 208x 208x 208x   208x 208x   1x 1x 208x 208x   208x 208x 208x 208x 208x 208x 208x 208x 208x   208x 208x 208x 208x  
import {Function, flow, Array, pipe} from '#util'
import {type ForestOf, type Tree, match} from '#tree'
import {mapInitLast} from '#Array'
import {flipCurried} from '#Function'
import type {NonEmptyReadonlyArray} from 'effect/Array'
import {type Part, column as columnPart} from '../part.js'
import {type Theme, type ThemedPart} from './theme.js'
import {branchLabel, headBranch, leafLabel, tailBranch} from './atoms.js'
 
/**
 * Convert a tree into a themed part.
 *
 * You can find a flipped version under the key `flip`.
 * @param tree The string tree to draw.
 * @category drawing
 * @function
 */
export const treeLayout = Object.assign(_treeLayout, {
  flip: flipCurried(_treeLayout),
})
 
function _treeLayout(tree: Tree<string>): ThemedPart {
  return (theme: Theme) =>
    pipe(
      tree,
      match({
        onLeaf: node => leafLabel(node)(theme),
        onBranch: parentLayout(theme),
      }),
    )
}
 
const parentLayout =
  (theme: Theme) =>
  (value: string, nodes: ForestOf<string>): Part => {
    const parts: NonEmptyReadonlyArray<ThemedPart> = [
      branchLabel(value),
      forestLayout(nodes),
    ]
 
    return pipe(parts, foreachThemed, Function.apply(theme), columnPart.left)
  }
 
const forestLayout =
  (trees: NonEmptyReadonlyArray<Tree<string>>): ThemedPart =>
  (theme: Theme) => {
    const treePart = flow(treeLayout, Function.apply(theme))
 
    return pipe(
      trees,
      mapInitLast(
        flow(treePart, headBranch(theme)),
        flow(treePart, tailBranch(theme)),
      ),
      columnPart.left,
    )
  }
 
function foreachThemed(xs: Array.NonEmptyReadonlyArray<ThemedPart>) {
  return (theme: Theme): Array.NonEmptyArray<Part> =>
    Array.map(xs, Function.apply(theme))
}