Skip to content

Instantly share code, notes, and snippets.

@teppix
Created January 3, 2019 21:33
Show Gist options
  • Select an option

  • Save teppix/7a3aa73b84b16ee08b9dc8a6cd08eadf to your computer and use it in GitHub Desktop.

Select an option

Save teppix/7a3aa73b84b16ee08b9dc8a6cd08eadf to your computer and use it in GitHub Desktop.
Ascii random filetree generator in haskell
import System.Random
import System.IO
import System.Posix.Unistd (usleep)
import System.Console.ANSI (clearScreen, hideCursor, showCursor)
data Prefix = Root
| Single | First | Middle
| Last
deriving (Show, Eq)
type Name = String
data Node = File Name
| Folder Name [Node]
deriving (Show)
prefix :: Prefix -> String
prefix Single = "---"
prefix First = "-+-"
prefix Middle = " |-"
prefix Last = " `-"
prefix Root = ""
spacer :: Prefix -> String
spacer Single = " "
spacer First = " | "
spacer Middle = " | "
spacer Last = " "
spacer Root = ""
blank :: String -> String
blank s = replicate (length s) ' '
positions :: [a] -> [Prefix]
positions items
| n==0 = []
| n==1 = [Single]
| otherwise = [First] ++ (replicate (n-2) Middle) ++ [Last]
where n = length items
showNode :: Prefix -> Node -> [String]
showNode pos (File name) = [(prefix pos) ++ name]
showNode pos (Folder name []) = [ (prefix pos) ++ name ++ (prefix Single) ]
showNode pos (Folder name items) =
zipWith (++) prefixes $ concat $ zipWith showNode (positions items) items
where
prefix' = (prefix pos) ++ name
prefixes = [prefix'] ++ repeat ((spacer pos) ++ (blank name))
showTree :: Node -> String
showTree node = unlines $ showNode Root node
printTree :: Node -> IO ()
printTree t = clearScreen >> putStr (showTree t) >> hFlush stdout
randomNodes :: StdGen -> Float -> Int -> [Node]
randomNodes gen0 ratio maxfiles = (n : ns)
where (gen1, gen2) = split gen0
n = randomTree gen1 ratio maxfiles
ns = randomNodes gen2 ratio maxfiles
randomFolder :: StdGen -> Float -> Int -> Node
randomFolder gen0 ratio maxfiles =
Folder "mapp" childNodes
where
(rnd, gen1) = random gen0 :: (Float, StdGen)
childCount = round (rnd * fromIntegral maxfiles)
childNodes = take childCount $ randomNodes gen1 ratio maxfiles
randomTree :: StdGen -> Float -> Int -> Node
randomTree gen0 ratio maxfiles =
if x1 < ratio then randomFolder gen1 (ratio * 0.8) maxfiles
else File "fil"
where (x1, gen1) = random gen0 :: (Float, StdGen)
mainLoop :: StdGen -> IO ()
mainLoop gen = do
let (gen1, gen2) = split gen
printTree $ randomFolder gen1 0.5 5
getLine >> mainLoop gen2
setup :: IO ()
setup = hSetBuffering stdout $ BlockBuffering (Just 2048)
main :: IO ()
main = setup >> getStdGen >>= mainLoop
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment