module Text.Docvim.Optimize (optimize) where

import Control.Lens hiding (Empty)
import Text.Docvim.AST

-- | "Optimize" a Project's AST by eliminating empty paths.
optimize :: Node -> Node
optimize = transform prune

-- | Marks a node for pruning by returning Empty if it has no non-Empty
-- children.
prune :: Node -> Node
prune n | not (null (children n)) = checkChildren
        | container n = Empty
        | otherwise = n
  where
    checkChildren | all empty (children n) = Empty
                  | any empty (children n) = filterChildren n
                  | otherwise = n
    filterChildren (Project cs) = Project $ filter (not . empty) cs
    filterChildren (Unit cs) = Unit $ filter (not . empty) cs
    filterChildren (DocBlock cs) = DocBlock $ filter (not . empty) cs
    filterChildren _ = n

-- | Returns True if the supplied node is the Empty node.
empty :: Node -> Bool
empty Empty = True
empty _     = False

-- | Returns True if the supplied node is a (potentially) prunable container.
container :: Node -> Bool
container (Project _)  = True
container (Unit _)     = True
container (DocBlock _) = True
container _            = False

module Text.Docvim.Optimize (optimize) where

import Control.Lens (children, transform)
import Text.Docvim.AST

-- | "Optimize" a Project's AST by eliminating empty paths.
optimize :: Node -> Node
optimize = transform prune

-- | Marks a node for pruning by returning Empty if it has no non-Empty
-- children.
prune :: Node -> Node
prune n | not (null (children n)) = checkChildren
        | container n = Empty
        | otherwise = n
  where
    checkChildren | all empty (children n) = Empty
                  | any empty (children n) = filterChildren n
                  | otherwise = n
    filterChildren (Project cs) = Project $ filter (not . empty) cs
    filterChildren (Unit cs) = Unit $ filter (not . empty) cs
    filterChildren (DocBlock cs) = DocBlock $ filter (not . empty) cs
    filterChildren _ = n

-- | Returns True if the supplied node is the Empty node.
empty :: Node -> Bool
empty Empty = True
empty _     = False

-- | Returns True if the supplied node is a (potentially) prunable container.
container :: Node -> Bool
container (Project _)  = True
container (Unit _)     = True
container (DocBlock _) = True
container _            = False

Tweak Control.Lens import for better compatibility
Tweak Control.Lens import for better compatibility

One of the CI runs blowing up:

    /home/travis/build/wincent/docvim/lib/Text/Docvim/Optimize.hs:3:1: Warning:
        Module ‘Control.Lens’ does not export ‘Empty’
    <no location info>:
    Failing due to -Werror.

Source: https://travis-ci.org/wincent/docvim/jobs/138094062

I'm going to turn off `-Werror` in CI and keep it locally, but in the meantime I
think I can get compatibility with a wider range of Lens versions if I switch
the import to not mention `Empty`.

See also: https://github.com/wincent/docvim/issues/24
