packages feed

hydrogen-prelude 0.9 → 0.10

raw patch · 5 files changed

+168/−15 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Hydrogen.Prelude: firstJust :: [a -> Maybe b] -> a -> Maybe b
+ Hydrogen.Prelude: safeHeadAndTail :: a -> [a] -> (a, [a])
+ Hydrogen.Prelude: safeHeadAndTail2 :: a -> a -> [a] -> (a, a, [a])
+ Hydrogen.Prelude.System: escapeFileName :: String -> String
+ Hydrogen.Prelude.System: findFilesRecursively :: (FilePath -> IO Bool) -> FilePath -> IO [FilePath]
+ Hydrogen.Prelude.System: findFilesRecursivelyWithContext :: (c -> FilePath -> [FilePath] -> IO c) -> (FilePath -> IO Bool) -> c -> FilePath -> IO [(FilePath, c)]
+ Hydrogen.Prelude.System: unescapeFileName :: String -> Maybe String

Files

CHANGELOG.md view
@@ -61,3 +61,8 @@ + Added `class Container (Contained, (?))` + `fmap` is exported as `map` +## v0.10++ Added `safeHeadAndTail`, `safeHeadAndTail2`, `firstJust`++ Little documentation improvements++ Added `findFilesRecursively` and `findFilesRecursivelyWithContext`+  in `Hydrogen.Prelude.System`
README.md view
@@ -138,7 +138,7 @@  The Hydrogen Prelude offers you the functions and datatypes from these modules, all with one import: -+ from `base`++ from [`base`](http://hackage.haskell.org/package/base)   + `module Prelude`   + `module Control.Applicative`   + `module Control.Arrow`@@ -168,44 +168,79 @@   + `module Numeric`   + `module Text.Printf` -+ from `array`++ from [`array`](http://hackage.haskell.org/package/array)   + `module Data.Array` -+ from `cereal`++ from [`cereal`](http://hackage.haskell.org/package/cereal)   + `module Data.Serialize` -+ from `containers`++ from [`containers`](http://hackage.haskell.org/package/containers)   + `Data.Set`, `Data.Map`, and `Data.Seq` -+ from `hashable`++ from [`hashable`](http://hackage.haskell.org/package/hashable)   + `module Data.Hashable` -+ form `hydrogen-multimap`++ form [`hydrogen-multimap`](http://hackage.haskell.org/package/hydrogen-multimap)   + `Hydrogen.MultiMap` -+ from `hydrogen-version`++ from [`hydrogen-version`](http://hackage.haskell.org/package/hydrogen-version)   + `module Hydrogen.Version` -+ from `regex-tdfa`++ from [`regex-tdfa`](http://hackage.haskell.org/package/regex-tdfa)   + `module Text.Regex.TDFA` -+ from `time`++ from [`time`](http://hackage.haskell.org/package/time)   + `module Data.Time` -+ from `transformers`++ from [`transformers`](http://hackage.haskell.org/package/transformers)   + `module Data.Functor.Identity`   + `module Data.Functor.Reverse` -+ from `uuid`++ from [`uuid`](http://hackage.haskell.org/package/uuid)   + `Data.UUID`   + `Data.UUID.fromString` as `uuidFromString`   + `Data.UUID.V4.nextRandom` as `randomUUID` + ### Hydrogen.Prelude.IO ++ from [`base`](http://hackage.haskell.org/package/base)+  + `module Data.IORef`+  + `module Control.Concurret`+  + `module Control.Exception`+  + `module System.IO`+  + `module System.Timeout`+++ from [`strict`](http://hackage.haskell.org/package/strict)+  + strict IO functions `hGetContents'`, `getContents'`, `readFile'`, `interact'`++ ### Hydrogen.Prelude.System ++ from [`base`](http://hackage.haskell.org/package/base)+  + `module System.CPUTime`+  + `module System.Environment`+  + `module System.Exit`+  + `module System.Info`+++ from [`directory`](http://hackage.haskell.org/package/directory)+  + `module System.Directory`+++ from [`filepath`](http://hackage.haskell.org/package/filepath)+  + `module System.FilePath`+++ from [`process`](http://hackage.haskell.org/package/process)+  + `module System.Process`+++ from [`random`](http://hackage.haskell.org/package/random)+  + `module System.Random`++ ### Hydrogen.Prelude.Network+++ from [`network`](http://hackage.haskell.org/package/network)+  + `module Network`+  FAQ ===
hydrogen-prelude.cabal view
@@ -1,5 +1,5 @@ name:                 hydrogen-prelude-version:              0.9+version:              0.10 homepage:             http://scravy.de/hydrogen-prelude/ synopsis:             Hydrogen Prelude license:              MIT
src/Hydrogen/Prelude.hs view
@@ -27,6 +27,7 @@   , module Data.Serialize   , module Data.String   , module Data.Time+  , module Data.Time.Calendar.OrdinalDate   , module Data.Traversable   , module Data.Tuple   , module Data.Typeable@@ -43,6 +44,9 @@   , uuidFromString   , randomUUID   , safeHead+  , safeHeadAndTail+  , safeHeadAndTail2+  , firstJust   , map   , UUID   , Generic@@ -142,6 +146,7 @@ import "cereal" Data.Serialize import "base" Data.String import "time" Data.Time+import "time" Data.Time.Calendar.OrdinalDate import "base" Data.Traversable import "base" Data.Tuple import "base" Data.Typeable@@ -211,23 +216,51 @@ f .^ g = \x -> f x /= g x  (|>) :: a -> (a -> b) -> b+-- ^ @flip ('$')@ (|>) = flip ($)  __ :: a+-- ^ A shorthand for 'undefined'. __ = error "Hydrogen.Prelude.undefined"  uuidFromString :: String -> Maybe UUID uuidFromString = Data.UUID.fromString  randomUUID :: IO UUID+-- ^ Produces a random V4 UUID (alias for 'Data.UUID.V4.nextRandom'). randomUUID = Data.UUID.V4.nextRandom -safeHead :: a -> [a] -> a-safeHead d = \case+safeHead+    :: a   -- ^ The default value for the case of the empty list.+    -> [a] -- ^ The list.+    -> a+-- ^ Returns the head of the list or the default value.+safeHead def = \case     x : _ -> x-    _     -> d+    _     -> def +safeHeadAndTail :: a -> [a] -> (a, [a])+safeHeadAndTail def = \case+    x : xs -> (x, xs)+    _ -> (def, [])++safeHeadAndTail2 :: a -> a -> [a] -> (a, a, [a])+safeHeadAndTail2 d1 d2 = \case+    x : y : xs -> (x, y, xs)+    x : xs -> (x, d2, xs)+    xs -> (d1, d2, xs)++firstJust :: [a -> Maybe b] -> a -> Maybe b+-- ^ Applies a bunch of functions on a given value,+--   returns the first result that is not Nothing+--   (or 'Nothing' if no 'Just' value was produced).+firstJust (f : fs) v = case f v of+    Nothing -> firstJust fs v+    x -> x+firstJust [] _ = Nothing+ map :: Functor f => (a -> b) -> f a -> f b+-- ^ map as it should be: 'fmap'. map = fmap  class TMap a where
src/Hydrogen/Prelude/System.hs view
@@ -1,3 +1,5 @@+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+ module Hydrogen.Prelude.System (     module Hydrogen.Prelude.IO   , module System.CPUTime@@ -8,6 +10,10 @@   , module System.Info   , module System.Process   , module System.Random+  , findFilesRecursively+  , findFilesRecursivelyWithContext+  , escapeFileName+  , unescapeFileName ) where  import Hydrogen.Prelude.IO@@ -20,4 +26,78 @@ import "base" System.Info import "process" System.Process import "random" System.Random++import qualified Data.Set as Set+++findFilesRecursively :: (FilePath -> IO Bool) -> FilePath -> IO [FilePath]+findFilesRecursively f dir =+    map fst <$> findFilesRecursivelyWithContext (\c _ _ -> return c) f () dir+++findFilesRecursivelyWithContext+    :: forall c.+       (c -> FilePath -> [FilePath] -> IO c)  -- ^ update function for current context+    -> (FilePath -> IO Bool)                  -- ^ predicate to filter files+    -> c                                      -- ^ current context+    -> FilePath -> IO [(FilePath, c)]+findFilesRecursivelyWithContext updater predicate context dir = do++    cwd <- getCurrentDirectory+    snd <$> find Set.empty context (cwd </> dir)++  where++    find :: Set FilePath -> c -> FilePath -> IO (Set FilePath, [(FilePath, c)])+    find visited context dir = do++      thisDirectory <- canonicalizePath dir+      if | Set.member thisDirectory visited -> return (Set.empty, [])+         | otherwise -> do++            allFiles <- map (dir </>) <$> getDirectoryContents dir+            theFiles <- filterFiles allFiles+            theDirs  <- filterM isDir allFiles+            context' <- updater context dir theFiles++            let visited' = Set.insert thisDirectory visited+                f (visited, files) dir = do+                    (visited', files') <- find visited context' dir+                    return (visited', files' : files)++            (visited'', files') <- foldM f (visited', []) theDirs+            +            return (visited'', concat (zip theFiles (repeat context') : files'))++    filterFiles = filterM (\x -> liftM2 (&&) (doesFileExist x) (predicate x))+    isDir x = liftM2 (&&) (doesDirectoryExist x) (return (head (takeFileName x) /= '.'))+++escapeFileName :: String -> String+escapeFileName s = case s of+    ('/' : xs)+        -> '_' : escapeFileName xs+    (x : xs) ->+      if | isSafeChar x -> x : escapeFileName xs+         | ord x <= 255 -> '$' : printf "%02X" (ord x) ++ escapeFileName xs+         | otherwise    -> "$$" ++ printf "%04X" (ord x) ++ escapeFileName xs+    [] -> []+  where+    isSafeChar x = isAscii x && isAlphaNum x || x `elem` ".-"+++unescapeFileName :: String -> Maybe String+unescapeFileName s = case s of+    ('$' : '$' : a : b : c : d : xs)+        -> (chr <$> hexnum (a : b : c : [d])) `cons` unescapeFileName xs+    ('$' : a : b : xs)+        -> (chr <$> hexnum (a : [b])) `cons` unescapeFileName xs+    ('_' : xs)+        -> pure '/' `cons` unescapeFileName xs+    (x : xs)+        -> pure x `cons` unescapeFileName xs+    [] -> return []+  where+    cons = liftA2 (:)+    hexnum = fmap fst . listToMaybe . readHex