module System.Nemesis where
import Prelude ()
import Air.Env hiding (lookup)
import Air.TH hiding (get)
import Control.Monad.State hiding (State, join)
import Data.List (sort)
import Data.Map (Map, insert, lookup, elems)
import System.Environment
import Text.Printf
newtype ShowIO = ShowIO {unShowIO :: IO () }
instance Show ShowIO where
show _ = "IO"
instance Default ShowIO where
def = ShowIO (return ())
data Task = Task
{
name :: String
, action :: ShowIO
, deps :: [String]
, description :: Maybe String
, namespace :: [String]
}
deriving (Show)
mkDefault ''Task
data Nemesis = Nemesis
{
tasks :: Map String Task
, target :: String
, current_desc :: Maybe String
, current_namespace :: [String]
}
deriving (Show)
mkDefault ''Nemesis
full_name :: Task -> String
full_name t = (t.name : t.namespace).reverse.join "/"
display_name :: Task -> String
display_name t = (t.name : t.namespace).reverse.map (printf "%-10s") .join " "
show_task :: Task -> String
show_task = show_with_ljust 44
instance Eq Task where
a == b = a.name == b.name
instance Ord Task where
compare = compare_by full_name
type Unit = StateT Nemesis IO ()
show_with_ljust :: Int -> Task -> String
show_with_ljust n task=
case task.description of
Nothing -> task.full_name
Just x -> task.full_name.ljust n ' ' + x
run :: Unit -> IO ()
run unit = do
args <- getArgs
case args of
[] -> help
_target:_ -> execStateT unit def {target = _target} >>= run_nemesis
where
help = execStateT unit def >>= list_task
list_task n = do
let _tasks = n.tasks.elems
_task_len = _tasks.map (full_name > length) .maximum + 5
br
n.tasks.elems.sort.map (show_with_ljust _task_len) .mapM_ putStrLn
br
br = puts ""
insert_task :: Task -> Unit
insert_task t = do
n <- get
let description = n.current_desc
namespace = n.current_namespace
deps' = t.deps.map (with_current namespace)
task = t {deps = deps', description, namespace}
tasks' = n.tasks.insert (task.full_name) task
put n {tasks = tasks', current_desc = Nothing}
where
with_current namespace x
| x.starts_with "/" = x.tail
| otherwise = (x : namespace).reverse.join "/"
run_nemesis :: Nemesis -> IO ()
run_nemesis n = run' (n.target)
where
run' :: String -> IO ()
run' s = case (n.tasks.lookup s) of
Nothing -> bye
Just x -> run_task x
where
bye = do
printf "%s does not exist!" s
run_task :: Task -> IO ()
run_task t = t.deps.mapM_ run' >> t.action.unShowIO