di 0.2 → 0.3
raw patch · 6 files changed
+58/−26 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Di: mkDiStringHandle :: (MonadIO m) => Handle -> m (Di String String String)
+ Di: mkDiStringHandle :: (MonadIO m) => Handle -> m (Di String [String] String)
- Di: mkDiStringStderr :: MonadIO m => m (Di String String String)
+ Di: mkDiStringStderr :: MonadIO m => m (Di String [String] String)
Files
- CHANGELOG.md +8/−0
- LICENSE.txt +1/−1
- README.md +1/−1
- di.cabal +2/−2
- src/Di/Backend.hs +43/−19
- src/Di/Core.hs +3/−3
CHANGELOG.md view
@@ -1,3 +1,11 @@+# Version 0.3++* BREAKING CHANGE: `mkDiTextStderr` and `mkDiStringHandle` return a `Di String+ [String] String` now.++* Made compatible with GHC 8.4.++ # Version 0.2 * BREAKING CHANGE: `Di` now takes a new type argument `level`.
LICENSE.txt view
@@ -1,4 +1,4 @@-Copyright (c) 2017, Renzo Carbonara+Copyright (c) 2017-2018, Renzo Carbonara All rights reserved.
README.md view
@@ -8,5 +8,5 @@ file to learn about the legal terms and conditions for this library. Find documentation for this library in the top-level-[`Di`](https://github.com/k0001/di/blob/master/di/src/Di.hs) module.+[`Di`](https://github.com/k0001/di/blob/master/src/Di.hs) module.
di.cabal view
@@ -1,8 +1,8 @@ name: di-version: 0.2+version: 0.3 author: Renzo Carbonara maintainer: renλren.zone-copyright: Renzo Carbonara 2017+copyright: Renzo Carbonara 2017-2018 license: BSD3 license-file: LICENSE.txt extra-source-files: README.md CHANGELOG.md
src/Di/Backend.hs view
@@ -6,56 +6,77 @@ ) where import Control.Monad.IO.Class (MonadIO, liftIO)-import Data.Monoid (mconcat, mappend, (<>))+import Data.Monoid (mconcat, mappend) import Data.String (IsString(fromString)) import qualified Data.Time as Time import Prelude hiding (log, filter) import qualified System.IO as IO+import Data.Semigroup (Semigroup(..)) import Di.Core (Di, mkDi, contrapath) -------------------------------------------------------------------------------- --- | Strings separated by a forward slash. Doesn't contain white space.+-- | Strings separated by a forward slash. --+-- The string doesn't contain any of @[\'/'\, \' \', \'\\n\', \'\\r\']@.+-- -- Use 'fromString' (GHC's @OverloadedStrings@ extension) to construct a -- 'StringPath'.-newtype StringPath = StringPath { unStringPath :: String }+newtype StringPath = UnsafeStringPath { unStringPath :: String } deriving (Eq, Ord, Show) instance IsString StringPath where fromString = stringPathSingleton {-# INLINE fromString #-} +-- | Ocurrences of one of @[\'/'\, \' \', \'\\n\', \'\\r\']@ in the given+-- 'String' will be replaced by @\'_\'@. stringPathSingleton :: String -> StringPath-stringPathSingleton = \s -> StringPath (map f s)+stringPathSingleton = \s -> UnsafeStringPath (map f s) where f :: Char -> Char- f = \case '/' -> '.'+ f = \case '/' -> '_' ' ' -> '_' '\n' -> '_' '\r' -> '_' c -> c -instance Monoid StringPath where- mempty = StringPath ""- mappend (StringPath "") b = b- mappend a (StringPath "") = a- mappend (StringPath a) (StringPath b) = StringPath (a <> "/" <> b)+instance Semigroup StringPath where+ UnsafeStringPath "" <> b = b+ a <> UnsafeStringPath "" = a+ UnsafeStringPath a <> UnsafeStringPath b = UnsafeStringPath (a <> "/" <> b) +instance Monoid StringPath where+ mempty = UnsafeStringPath ""+ {-# INLINE mempty #-}+ mappend = (<>)+ {-# INLINE mappend #-} -- | 'String's are written to 'IO.Handle' using the 'IO.Handle''s locale -- encoding.+--+-- The @level@ and @message@ are plain 'String's.+--+-- The @path@ is a list of 'String's which will be separated by @\'/\'@ when+-- rendered. Ocurrences of one of @[\'/'\, \' \', \'\\n\', \'\\r\']@ in those+-- 'String's will be replaced by @\'_\'@.+--+-- @+-- > 'log' ('push' [\"cuatro\"] ('push' [\"uno dos\", \"tres\"] di)) \"WARNING\" \"Hello!\"+-- WARNING 2018-05-03T09:15:54.819379740000Z uno_dos\/tres\/cuatro: Hello!+-- @ mkDiStringHandle :: (MonadIO m) => IO.Handle- -> m (Di String String String)+ -> m (Di String [String] String) mkDiStringHandle h = liftIO $ do IO.hSetBuffering h IO.LineBuffering- fmap (contrapath stringPathSingleton) $ mkDi $ \ts l p m -> do- IO.hPutStrLn h $ mconcat- [ l, " ", renderIso8601 ts- , if p == mempty then "" else (" " <> unStringPath p)- , ": ", noBreaks m ]- IO.hFlush h+ fmap (contrapath (mconcat . map stringPathSingleton)) $ do+ mkDi $ \ts l p m -> do+ IO.hPutStrLn h $ mconcat+ [ l, " ", renderIso8601 ts+ , if p == mempty then "" else (" " <> unStringPath p)+ , ": ", noBreaks m ]+ IO.hFlush h where noBreaks :: String -> String noBreaks = concatMap $ \case@@ -63,8 +84,11 @@ '\r' -> "\\r" c -> [c] --- | 'String' is written to 'IO.stderr' using the system's locale encoding.-mkDiStringStderr :: MonadIO m => m (Di String String String)+-- |+-- @+-- 'mkDiStringStderr' == 'mkDiStringHandle' 'IO.stderr'+-- @+mkDiStringStderr :: MonadIO m => m (Di String [String] String) mkDiStringStderr = mkDiStringHandle IO.stderr --------------------------------------------------------------------------------
src/Di/Core.hs view
@@ -47,7 +47,7 @@ -- type safety, as well as the composability of the @level@, @path@ and @msg@ -- values. In particular, all of @level@, @path@ and @msg@ are contravariant -- values, which in practice means including a precise 'Di' into a more general--- 'Di' is always possible (see the 'contralevel@, 'contrapath' and 'contramsg'+-- 'Di' is always possible (see the 'contralevel', 'contrapath' and 'contramsg' -- functions). -- -- Messages of undesired importance levels can be muted by using 'filter'.@@ -62,7 +62,7 @@ -- -- 'Di' is pronounced as \"dee" (not \"die" nor \"dye" nor \"day"). \"Di" is -- the spanish word for an imperative form of the verb \"decir", which in--- english means "to say".+-- english means "to say", which clearly has something to do with logging. data Di level path msg = Di { _diLog :: Time.UTCTime -> level -> path -> msg -> IO () -- ^ Low level logging function.@@ -124,7 +124,7 @@ -- | Block until all messages being logged have finished processing. ----- Mabually calling 'flush' is not usually necessary, but, if at some point you+-- Manually calling 'flush' is not usually necessary, but, if at some point you -- want to ensure that all messages logged until then have properly rendered to -- the underlying backend, then 'flush' will block until that happens. flush :: MonadIO m => Di level path msg -> m ()