packages feed

nyan-0.2: src/Main.hs

{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
-- | Main entry point.

module Main where

import           Control.Concurrent
import           Control.Monad.Trans
import qualified Data.ByteString      as B
import           Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString.Lazy as L
import           Data.Char
import           Data.Int
import           Data.Monoid
import           Data.Text            (Text)
import qualified Data.Text            as T
import           Data.Text.Encoding
import           Data.Word
import           System.IO
import           UI.NCurses

-- | Main entry point.
main :: IO ()
main = do
  hSetBinaryMode stdin True
  hSetBuffering stdin NoBuffering
  runCurses $ do
    w <- defaultWindow
    garbage <- getGarbage mempty
    showScene w garbage 0

-- | Render nyan cat flying through space.
showScene :: Window -> ByteString -> Int -> Curses ()
showScene w garbage sceneIndex = do
  updateWindow w $ do
    moveCursor 0 0
    drawText $ (decodeUtf8 $ B.concat . L.toChunks . L.pack $
             L.zipWith paint (L.cycle garbage) $ frames !! sceneIndex)
             `mappend` "\n\n"
  render
  io $ threadDelay $ 1000 * 200
  newGarbage <- getGarbage garbage
  showScene w
            newGarbage
            (if sceneIndex == length frames - 1 then 0 else sceneIndex + 1)

-- | Get garbage input from stdin to be used for the rainbow.
getGarbage :: ByteString -> Curses ByteString
getGarbage previous = io $ do
  bytes <- fmap (L.filter (isAllowedChar.enumToEnum)) $ L.hGetNonBlocking stdin 100
  return $ L.take 100 $
    bytes `mappend`
    previous `mappend`
    L.repeat (fromIntegral $ fromEnum '=')

-- | Is an allowed byte?
isAllowedChar :: Char -> Bool
isAllowedChar c = elem c asciiChars

-- | Allowed bytes from input.
asciiChars :: [Char]
asciiChars = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ" ++
             "KLMNOPQRSTUVWXYZ[\\]^`abcdefghijklmnopqrstuvwxyz{|}~"

-- | "Paint" the garbage input onto the rainbow part of the frame.
paint :: Word8 -> Word8 -> Word8
paint garbageChar (enumToEnum -> '=')
  | isLatin1 (enumToEnum garbageChar) = garbageChar
  | otherwise = enumToEnum $ ';'
paint _           c   = c

-- | Convert one enum to another enum type.
enumToEnum :: (Enum a,Enum b) => a -> b
enumToEnum = toEnum . fromEnum

-- | Madness.
io :: MonadIO m => IO a -> m a
io = liftIO

frames :: [ByteString]
frames = map (L.fromChunks.return.encodeUtf8) $ T.splitOn ("\n\n") $ 
         ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;________________________;;;;;;;;;;;;;;;;;;;;;;\n================/                        \\;;;;;;;;;;;;;;;;;;;;;\n================|  '@'''''''@'''''@_''''  |;;;;;;;;;;;;;;;;;;;;\n================| ''''''''''''''''| \\'@'' |;/ |;;;;;;;;;;;;;;;;\n================| ''''''''''''''''|  \\_____/  |';;;;;;;;;;;;;;;\n==========_=====| ''''@''''@'''''|             ;;;;;;;;;;;;;;;;\n=========| \\____| ''''''''''''''|     _|    _|  \\;;;;;;;;;;;;;;\n==========\\_____| ''@''''''''''@| ##       #   ##|;;;;;;;;;;;;;\n================| '''''''@'''''''\\     |___,__| /;;;;;;;;;;;;;;\n================|  ''@'''''''''''`\\___________;;;;;;;;;;;;;;;;;\n================ \\_________________________/; \\;;;;;;;;;;;;;;;;\n=================\\_\\;\\_\\;;;;;;;;;;;;;;;\\_\\;;;\\_\\;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;________________________;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;/                        \\;;;;;;;;;;;;;;;;;;;;;\n================| ''''''''''''''''| \\'@'' |;/ |;;;;;;;;;;;;;;;;\n================| ''''''''''''''''|  \\_____/  |';;;;;;;;;;;;;;;\n================| ''''@''''@'''''|             ;;;;;;;;;;;;;;;;\n=========_______| ''''''''''''''|     _|    _|  \\;;;;;;;;;;;;;;\n=========\\______| ''@''''''''''@| ##       #   ##|;;;;;;;;;;;;;\n================| '''''''@'''''''\\     |___,__| /;;;;;;;;;;;;;;\n================|  ''@'''''''''''`\\___________;;;;;;;;;;;;;;;;;\n================|  ''''''''''''''''          /;;;;;;;;;;;;;;;;;\n===============| \\_________________________/ |;;;;;;;;;;;;;;;;;\n===============|_|;;|_/;;;;;;;;;;;;;;|_|;;|_|;;;;;;;;;;;;;;;;;;\n===============;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;________________________;;;;;;;;;;;;;;;;;;;;;;\n================/                        \\;;;;;;;;;;;;;;;;;;;;;\n================|  '@'''''''@'''''@_''''  |;;;;;;;;;;;;;;;;;;;;\n================| ''''''''''''''''| \\'@'' |;/ |;;;;;;;;;;;;;;;;\n================| ''''''''''''''''|  \\_____/  |';;;;;;;;;;;;;;;\n================| ''''@''''@'''''|             ;;;;;;;;;;;;;;;;\n=============___| ''''''''''''''|     _|    _|  \\;;;;;;;;;;;;;;\n=========/```___| ''@''''''''''@| ##       #   ##|;;;;;;;;;;;;;\n=========|/``===| '''''''@'''''''\\     |___,__| /;;;;;;;;;;;;;;\n================|  ''@'''''''''''`\\___________;;;;;;;;;;;;;;;;;\n==============/  \\________________________//;;;;;;;;;;;;;;;;;;;\n=============/_/;/_/;;;;;;;;;;;;;;/_/;;;/_/;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"