{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-} -- | "Control.Lens" based extractors for 'Layout' module System.Directory.Layout.Lens ( -- * Usage -- $setup text, name, names, next, file, directory, node ) where import Control.Applicative ((<$>), (<*>), pure) import Control.Lens import Data.Text (Text) import System.Directory.Layout.Internal (Node(..), Layout) -- $setup -- -- >>> :set -XOverloadedStrings -- >>> import Control.Lens -- >>> let layout = F "foo" (T "not empty" ()) (D "bar" (F "baz" (E ()) (F "quux" (T "something" ()) (E ()))) (F "swaks" (E ()) (E ()))) -- | Target 'Text' from the current 'Layout' top (if possible) -- -- >>> layout ^? text -- Nothing -- >>> layout ^? file "foo" . text -- Just "not empty" -- >>> layout ^? directory "bar" . file "quux" . text -- Just "something" text :: Prism' Layout Text text = prism' (\t -> T t ()) $ \s -> case s of T t _ -> Just t _ -> Nothing {-# INLINE text #-} -- | Target 'FilePath' from the current 'Layout' top (if possible) -- -- >>> layout ^? name -- Just "foo" -- >>> layout ^? directory "bar" . name -- Just "baz" -- >>> layout ^? directory "quux" . name -- Nothing -- >>> layout & name .~ "boo" -- F "boo" (T "not empty" ()) (D "bar" (F "baz" (E ()) (F "quux" (T "something" ()) (E ()))) (F "swaks" (E ()) (E ()))) name :: Traversal' Layout FilePath name f = go where go (E x) = pure (E x) go (T t x) = pure (T t x) go (F n l x) = f n <&> \n' -> F n' l x go (D n l x) = f n <&> \n' -> D n' l x {-# INLINE name #-} -- | Target all 'Filpath's from current 'Layout' layer -- -- >>> layout ^? names -- Just "foo" -- >>> layout ^.. names -- ["foo","bar","swaks"] -- >>> layout ^.. directory "bar" . names -- ["baz","quux"] -- >>> layout & directory "bar" . names %~ reverse -- F "foo" (T "not empty" ()) (D "bar" (F "zab" (E ()) (F "xuuq" (T "something" ()) (E ()))) (F "swaks" (E ()) (E ()))) names :: Traversal' Layout FilePath names f = go where go (E x) = pure (E x) go (T t x) = pure (T t x) go (F n l x) = (\n' x' -> F n' l x') <$> f n <*> go x go (D n l x) = (\n' x' -> D n' l x') <$> f n <*> go x {-# INLINE names #-} -- | Target next 'Node' -- -- >>> layout ^? name -- Just "foo" -- >>> layout ^? next . name -- Just "bar" -- >>> layout ^? next . next . name -- Just "swaks" -- >>> layout ^? next . next . next . name -- Nothing next :: Traversal' Layout Layout next f = go where go (E x) = pure (E x) go (T t x) = pure (T t x) go (F n l x) = f x <&> \x' -> F n l x' go (D n l x) = f x <&> \x' -> D n l x' {-# INLINE next #-} -- | Target 'Layout' under the current 'Layout' top if it happens to be a file -- -- >>> layout ^? file "biz" -- Nothing -- >>> layout ^? file "swaks" -- Just (E ()) -- >>> layout ^? directory "bar" . file "baz" -- Just (E ()) file :: FilePath -> IndexedTraversal' FilePath Layout Layout file k f = go where go (E x) = pure (E x) go (T t x) = pure (T t x) go (F k' l x) | k == k' = indexed f k l <&> \l' -> F k' l' x | otherwise = go x <&> \x' -> F k' l x' go (D n l x) = go x <&> \x' -> D n l x' {-# INLINE file #-} -- | Target 'Layout' under the current 'Layout' top if it happens to be a directory -- -- >>> layout ^? directory "foo" -- Nothing -- >>> layout ^? directory "bar" -- Just (F "baz" (E ()) (F "quux" (T "something" ()) (E ()))) directory :: FilePath -> IndexedTraversal' FilePath Layout Layout directory k f = go where go (E x) = pure (E x) go (T t x) = pure (T t x) go (F n l x) = go x <&> \x' -> F n l x' go (D k' l x) | k == k' = indexed f k l <&> \l' -> D k' l' x | otherwise = go x <&> \x' -> D k' l x' {-# INLINE directory #-} -- | Target 'Layout' under the current 'Layout' top -- -- >>> layout ^? node "foo" -- Just (T "not empty" ()) -- >>> layout ^? node "bar" -- Just (F "baz" (E ()) (F "quux" (T "something" ()) (E ()))) -- >>> layout ^? node "what" -- Nothing node :: FilePath -> IndexedTraversal' FilePath Layout Layout node k f = go where go (E x) = pure (E x) go (T t x) = pure (T t x) go (F k' l x) | k == k' = indexed f k l <&> \l' -> F k' l' x | otherwise = go x <&> \x' -> F k' l x' go (D k' l x) | k == k' = indexed f k l <&> \l' -> D k' l' x | otherwise = go x <&> \x' -> D k' l x' {-# INLINE node #-}