Show

------------------------------------------------------------------------
-- The Agda standard library
--
-- 1 dimensional pretty printing of rose trees
------------------------------------------------------------------------

{-# OPTIONS --without-K --safe #-}

module Data.Tree.Rose.Show where

open import Data.Bool.Base using (Bool; true; false; if_then_else_; _∧_)
open import Data.DifferenceList as DList
   using (_++_; fromList; toList)
   renaming (DiffList to DList; [] to []ᴰ; _∷_ to _∷ᴰ_)
open import Data.List.Base as List using (List; []; _∷_; [_])
open import Data.List.NonEmpty.Base as List⁺ using (List⁺; _∷_; _∷⁺_)
open import Data.String.Base as String using (String)
open import Data.Tree.Rose using (Rose; node; map)
open import Function.Base using (_∘′_; id; _$_)
open import Level using (Level)

private
  variable
    a : Level
    A : Set a


------------------------------------------------------------------------
-- Main recursive definition

display : Rose (List String) → List String
display t = toList $ goTree [] t []ᴰ
  where
  padding : Bool → List Bool → String → String
  padding dir? []       = id
  padding dir? (b ∷ bs) =
    ((if dir? ∧ List.null bs
     then if b then " ├ " else " └ "
     else if b then " │ " else "   ")
    String.++_) ∘′ padding dir? bs

  nodePrefix : List Bool → List String → DList String
  nodePrefix bs []       = []ᴰ
  nodePrefix bs (s ∷ ss) = let bsᵒ = List.reverse bs in
    padding true bsᵒ s ∷ᴰ fromList (List.map (padding false bsᵒ) ss)

  childrenPrefixes : List A → List⁺ Bool
  childrenPrefixes []       = false ∷ []
  childrenPrefixes (x ∷ xs) = true ∷⁺ childrenPrefixes xs

  goTree : List Bool → Rose (List String) → DList String → DList String
  goTree bs (node ss ts) dl = nodePrefix bs ss ++ goList ts ++ dl
    where
    goZip : List (List Bool) → List (Rose (List String)) → DList String
    goZip (bs ∷ bss) (t ∷ ts) = goTree bs t $ goZip bss ts
    goZip [] _ = []ᴰ
    goZip _ [] = []ᴰ

    goList : List (Rose (List String)) → DList String
    goList []       = []ᴰ
    goList (t ∷ ts) =
      let bs′ ∷ bss′ = List⁺.map (_∷ bs) (childrenPrefixes ts)
      in goTree bs′ t $ goZip bss′ ts

------------------------------------------------------------------------
-- Corollaries

show : (A → List String) → Rose A → List String
show toString = display ∘′ map toString

showSimple : (A → String) → Rose A → List String
showSimple toString = show ([_] ∘′ toString)