packages feed

nemesis (empty) → 2009.6.12

raw patch · 7 files changed

+271/−0 lines, 7 filesdep +basedep +containersdep +data-defaultsetup-changed

Dependencies added: base, containers, data-default, haskell98, mps, mtl, process

Files

+ LICENSE view
@@ -0,0 +1,9 @@+Copyright (c) <YEAR>, <OWNER>+All rights reserved.++Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:++Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.+Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,4 @@+#! /usr/bin/env runhaskell++> import Distribution.Simple+> main = defaultMain
+ changelog.md view
@@ -0,0 +1,4 @@+2009.6.12+---------++Init
+ nemesis.cabal view
@@ -0,0 +1,30 @@+Name:                 nemesis+Version:              2009.6.12+Build-type:           Simple+Synopsis:             a rake like task management tool+Description:+        +    a rake like task management tool++License:              BSD3+License-file:         LICENSE+Author:               Wang, Jinjing+Maintainer:           Wang, Jinjing <nfjinjing@gmail.com>+Build-Depends:        base+Cabal-version:        >= 1.2+category:             Web+homepage:             http://github.com/nfjinjing/nemesis+data-files:           readme.md, changelog.md++library+  ghc-options: -Wall+  build-depends: base >= 4 && < 5, haskell98, mtl, process, containers, data-default, mps >= 2009.5.13+  hs-source-dirs: src/+  exposed-modules:  +                      System.Nemesis++Executable            nemesis+  ghc-options:        -Wall+  build-depends:      base >= 4 && < 5, haskell98, mtl, process, containers, data-default, mps >= 2009.5.13+  hs-source-dirs:     src/+  main-is:            Runner.hs
+ readme.md view
@@ -0,0 +1,74 @@+Nemesis: a rake like task management tool for haskell+=====================================================++Tutorial+--------++### DSL++in `nem.hs`++    nemesis = do+      task "clean: hello-world" (print "cleaning")++      task "hello-world: ls" $ do+        sh "echo HELLO"++      task "ls" $ do+        sh "ls"++run `nemesis`++It will generate a bin `nem` inside your current folder.++### Run++run `./nem`++          clean: hello-world ls+    hello-world: ls+             ls:+    ++run `./nem ls`+++Advance usage+-------------++### Use LANGUAGEW++Use a separator below language extensions, e.g.++    {-# LANGUAGE QuasiQuotes #-}++    -- Nem++    nemesis = do++      task "dist" $ do+        sh "cabal clean"+        sh "cabal configure"+        sh "cabal sdist"++      task "i" (sh "ghci -isrc src/System/Nemesis.hs")++      task "manifest" $ do+        sh "find . | grep 'hs$' > manifest"++currently the separator `-- Nem` is hard coded++### Build it yourself++Example:++    module Main where+    +    import System.Nemesis++    nemesis = do+      task "i" (sh "ghci -isrc src/System/Nemesis.hs")+        +    main = nemesis++
+ src/Runner.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE QuasiQuotes #-}++import MPS+import Prelude hiding ((.), (>), (^))+import System.Cmd+++start, end :: String+start = [$here|+module Main where+import System.Nemesis+++|]++end = [$here|+++main = run nemesis+|]++main :: IO ()+main = do+  dir <- ls "."+  src <- readFile $ dir.filter (belongs_to possible_source) .get_name+  let h = src.lines.takeWhile (lower > starts_with sep > not) .unlines+      t = src.lines.dropWhile (lower > starts_with sep > not) .unlines+  if t.null+    then output $ start ++ h ++ end+    else output $ h ++ start ++ t ++ end+  +  system $ "ghc --make " ++ tmp_name ++ " -o " ++ bin+  system $ "rm " ++ tmp_name+  return ()+  +  where+    get_name [] = error "nem.hs does not exists"+    get_name xs = xs.first+    possible_source = ["Nem.hs", "nem.hs", "nemesis.hs", "Nemesis.hs"]+    sep = "-- nem"+    output = writeFile tmp_name+    tmp_name = "nemesis-tmp.hs"+    bin = "nem"+ 
+ src/System/Nemesis.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE NamedFieldPuns #-}++module System.Nemesis (run, sh, task) where++import MPS hiding (empty)+import Prelude hiding ((.), (>), (^), lookup)+import Control.Monad.State hiding (State, join)+import Data.Default+import Data.Map (Map, insert, empty, lookup, elems)+import System.Cmd (system)+import System+import GHC.IOBase hiding (liftIO)++data Task = Task+  {+    name :: String+  , action :: IO ()+  , deps :: [String]+  }++data Nemesis = Nemesis+  {+    tasks :: Map String Task+  , target :: String+  }+  deriving (Show)++instance Default Nemesis where+  def = Nemesis empty def++instance Default Task where+  def = Task def (return ()) def++instance Show Task where+  show x +    | x.deps.null = title+    | otherwise = +      [+        title+      , x.deps.join " "+      , ""+      ] .concat+    where+      title = x.name.ljust 20 ' ' ++ ": "++instance Eq Task where+  a == b = a.name == b.name++instance Ord Task where+  compare = compare_by name++type Unit = StateT Nemesis IO ()++-- sh :: String -> IO GHC.IOBase.ExitCode+sh :: String -> IO ()+sh s = do+  status <- system s+  case status of +    ExitSuccess -> return ()+    ExitFailure code -> error $ s ++ " failed with status code" ++ show code++run :: Unit -> IO ()+run unit = do+  args <- getArgs+  if args.null+    then help+    else execStateT unit def {target = args.first} >>= run_nemesis+  +  where+    help = execStateT unit def >>= list_task+    list_task n = do+      br+      n.tasks.elems.mapM_ print+      br+    br = putStrLn ""++task :: String -> IO () -> Unit+task s action = +  let x:xs = s.split "\\s*:\\s*"+  in+  task' x (xs.join'.words)+  where+    task' name deps = insert_task Task {name, deps, action}++insert_task :: Task -> Unit+insert_task t = do+  n <- get+  let tasks' = n.tasks.insert (t.name) t+  put n {tasks = tasks'}++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 -> revenge x+      where+        bye = error $ s ++  " does not exist!"++    revenge :: Task -> IO ()+    revenge t = t.deps.to_list.mapM_ run' >> revenge_and_say+      where+        revenge_and_say = do+          -- putStrLn $ "running: " ++ t.name+          t.action