All files / src/draw/tree atoms.ts

100% Statements 56/56
100% Branches 5/5
100% Functions 2/2
100% Lines 56/56

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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 891x 1x   1x 1x 1x 1x                 1x 1x           1x 1x 1x 1x 1x           1x 1x 1x 1x 1x   268x 268x 268x 268x 268x 268x 540x 540x 540x 540x 540x 540x 540x 540x 540x 540x   540x 540x 540x 540x 540x 540x 540x 540x 540x 540x 268x           1x           1x   268x 268x 419x 419x 419x 419x 419x 419x 268x  
import {String} from '#util'
import {mapHeadTail} from '#Array'
import type {EndoOf} from '#Function'
import {flow, pipe} from 'effect'
import * as Part from '../part.js'
import {Struts, HStrut, VStrut} from '../struts.js'
import {
  addSpacingAfter,
  getGlyph,
  indentGlyphPart,
  type GlyphRole,
  type Theme,
  type ThemedPart,
} from './theme.js'
 
const childTee: ThemedPart = indentGlyphPart('rightTee', 'indent')
const childElbow: ThemedPart = indentGlyphPart('elbow', 'indent')
 
/**
 * @category drawing
 * @function
 */
export const leafLabel: (label: string) => ThemedPart = label(
  'hLine',
  'leafBullet',
  'space',
)
 
/**
 * @category drawing
 * @function
 */
export const branchLabel: (label: string) => ThemedPart = label(
  'tee',
  'branchBullet',
  'vLine',
)
 
function label(
  prefixRole: GlyphRole,
  bulletRole: GlyphRole,
  spaceRole: GlyphRole,
) {
  return (label: string): ThemedPart =>
    theme => {
      const glyph = getGlyph(theme),
        [before, bullet, space] = [
          glyph(prefixRole),
          glyph(bulletRole),
          glyph(spaceRole),
        ],
        prefixBullet = before + bullet,
        prefixPad =
          String.repeat(String.stringWidth(prefixBullet))(space) + bullet
 
      return pipe(
        theme,
        addSpacingAfter(label),
        mapHeadTail(
          flow(String.prefix(prefixBullet), Part.text),
          flow(String.prefix(prefixPad), Part.text),
        ),
        Part.column.left,
      )
    }
}
 
/**
 * @category drawing
 * @function
 */
export const headBranch = parent(childTee, 'vLine')
 
/**
 * @category drawing
 * @function
 */
export const tailBranch = parent(childElbow, 'space')
 
function parent(branch: ThemedPart, glyphRole: GlyphRole) {
  return (theme: Theme): EndoOf<Part.Part> => {
    const glyph = getGlyph(theme)
    return Part.after.top.left(
      branch(theme),
      Struts(VStrut.empty, HStrut([glyph('space')], glyph(glyphRole))),
    )
  }
}