packages feed

diagrams-lib 1.4.7 → 1.5

raw patch · 3 files changed

+18/−139 lines, 3 filesdep −fsnotifydep ~basedep ~monoid-extrasdep ~optparse-applicativePVP ok

version bump matches the API change (PVP)

Dependencies removed: fsnotify

Dependency ranges changed: base, monoid-extras, optparse-applicative

API changes (from Hackage documentation)

- Diagrams.Backend.CmdLine: DiagramLoopOpts :: Bool -> Maybe FilePath -> DiagramLoopOpts
- Diagrams.Backend.CmdLine: [_loop] :: DiagramLoopOpts -> Bool
- Diagrams.Backend.CmdLine: [_src] :: DiagramLoopOpts -> Maybe FilePath
- Diagrams.Backend.CmdLine: data DiagramLoopOpts
- Diagrams.Backend.CmdLine: defaultLoopRender :: DiagramLoopOpts -> IO ()
- Diagrams.Backend.CmdLine: diagramLoopOpts :: Parser DiagramLoopOpts
- Diagrams.Backend.CmdLine: instance Diagrams.Backend.CmdLine.Parseable Diagrams.Backend.CmdLine.DiagramLoopOpts
- Diagrams.Backend.CmdLine: loop :: Lens' DiagramLoopOpts Bool
- Diagrams.Backend.CmdLine: src :: Lens' DiagramLoopOpts (Maybe FilePath)
+ Diagrams.Prelude: classIdFields :: LensRules
+ Diagrams.Prelude: classIdNamer :: FieldNamer
+ Diagrams.Prelude: makeFieldsId :: Name -> DecsQ
- Diagrams.Segment: oeEnvelope :: forall v_aUvv n_aUvw. Lens' (OffsetEnvelope v_aUvv n_aUvw) (Envelope v_aUvv n_aUvw)
+ Diagrams.Segment: oeEnvelope :: forall v_aUlO n_aUlP. Lens' (OffsetEnvelope v_aUlO n_aUlP) (Envelope v_aUlO n_aUlP)
- Diagrams.Segment: oeOffset :: forall v_aUvv n_aUvw. Lens' (OffsetEnvelope v_aUvv n_aUvw) (TotalOffset v_aUvv n_aUvw)
+ Diagrams.Segment: oeOffset :: forall v_aUlO n_aUlP. Lens' (OffsetEnvelope v_aUlO n_aUlP) (TotalOffset v_aUlO n_aUlP)
- Diagrams.ThreeD.Camera: horizontalFieldOfView :: forall n_aJgA. Lens' (PerspectiveLens n_aJgA) (Angle n_aJgA)
+ Diagrams.ThreeD.Camera: horizontalFieldOfView :: forall n_aJ6T. Lens' (PerspectiveLens n_aJ6T) (Angle n_aJ6T)
- Diagrams.ThreeD.Camera: orthoHeight :: forall n_aJjn. Lens' (OrthoLens n_aJjn) n_aJjn
+ Diagrams.ThreeD.Camera: orthoHeight :: forall n_aJ9G. Lens' (OrthoLens n_aJ9G) n_aJ9G
- Diagrams.ThreeD.Camera: orthoWidth :: forall n_aJjn. Lens' (OrthoLens n_aJjn) n_aJjn
+ Diagrams.ThreeD.Camera: orthoWidth :: forall n_aJ9G. Lens' (OrthoLens n_aJ9G) n_aJ9G
- Diagrams.ThreeD.Camera: verticalFieldOfView :: forall n_aJgA. Lens' (PerspectiveLens n_aJgA) (Angle n_aJgA)
+ Diagrams.ThreeD.Camera: verticalFieldOfView :: forall n_aJ6T. Lens' (PerspectiveLens n_aJ6T) (Angle n_aJ6T)
- Diagrams.Transform.ScaleInv: scaleInvDir :: forall t_aCpT. Lens' (ScaleInv t_aCpT) (Vn t_aCpT)
+ Diagrams.Transform.ScaleInv: scaleInvDir :: forall t_aCgc. Lens' (ScaleInv t_aCgc) (Vn t_aCgc)
- Diagrams.Transform.ScaleInv: scaleInvLoc :: forall t_aCpT. Lens' (ScaleInv t_aCpT) (Point (V t_aCpT) (N t_aCpT))
+ Diagrams.Transform.ScaleInv: scaleInvLoc :: forall t_aCgc. Lens' (ScaleInv t_aCgc) (Point (V t_aCgc) (N t_aCgc))
- Diagrams.Transform.ScaleInv: scaleInvObj :: forall t_aCpT. Lens' (ScaleInv t_aCpT) t_aCpT
+ Diagrams.Transform.ScaleInv: scaleInvObj :: forall t_aCgc. Lens' (ScaleInv t_aCgc) t_aCgc
- Diagrams.TwoD: _LG :: forall n_a1SeS. Prism' (Texture n_a1SeS) (LGradient n_a1SeS)
+ Diagrams.TwoD: _LG :: forall n_a1S5c. Prism' (Texture n_a1S5c) (LGradient n_a1S5c)
- Diagrams.TwoD: _RG :: forall n_a1SeS. Prism' (Texture n_a1SeS) (RGradient n_a1SeS)
+ Diagrams.TwoD: _RG :: forall n_a1S5c. Prism' (Texture n_a1S5c) (RGradient n_a1S5c)
- Diagrams.TwoD: _SC :: forall n_a1SeS. Prism' (Texture n_a1SeS) SomeColor
+ Diagrams.TwoD: _SC :: forall n_a1S5c. Prism' (Texture n_a1S5c) SomeColor
- Diagrams.TwoD: eColor :: forall n_a2aPg. Lens' (EnvelopeOpts n_a2aPg) (Colour Double)
+ Diagrams.TwoD: eColor :: forall n_a2aFA. Lens' (EnvelopeOpts n_a2aFA) (Colour Double)
- Diagrams.TwoD: eLineWidth :: forall n_a2aPg n_a2aSf. Lens (EnvelopeOpts n_a2aPg) (EnvelopeOpts n_a2aSf) (Measure n_a2aPg) (Measure n_a2aSf)
+ Diagrams.TwoD: eLineWidth :: forall n_a2aFA n_a2aIz. Lens (EnvelopeOpts n_a2aFA) (EnvelopeOpts n_a2aIz) (Measure n_a2aFA) (Measure n_a2aIz)
- Diagrams.TwoD: ePoints :: forall n_a2aPg. Lens' (EnvelopeOpts n_a2aPg) Int
+ Diagrams.TwoD: ePoints :: forall n_a2aFA. Lens' (EnvelopeOpts n_a2aFA) Int
- Diagrams.TwoD: oColor :: forall n_a2aOb. Lens' (OriginOpts n_a2aOb) (Colour Double)
+ Diagrams.TwoD: oColor :: forall n_a2aEv. Lens' (OriginOpts n_a2aEv) (Colour Double)
- Diagrams.TwoD: oMinSize :: forall n_a2aOb. Lens' (OriginOpts n_a2aOb) n_a2aOb
+ Diagrams.TwoD: oMinSize :: forall n_a2aEv. Lens' (OriginOpts n_a2aEv) n_a2aEv
- Diagrams.TwoD: oScale :: forall n_a2aOb. Lens' (OriginOpts n_a2aOb) n_a2aOb
+ Diagrams.TwoD: oScale :: forall n_a2aEv. Lens' (OriginOpts n_a2aEv) n_a2aEv
- Diagrams.TwoD: radiusBL :: forall d_a1GoI. Lens' (RoundedRectOpts d_a1GoI) d_a1GoI
+ Diagrams.TwoD: radiusBL :: forall d_a1Gf1. Lens' (RoundedRectOpts d_a1Gf1) d_a1Gf1
- Diagrams.TwoD: radiusBR :: forall d_a1GoI. Lens' (RoundedRectOpts d_a1GoI) d_a1GoI
+ Diagrams.TwoD: radiusBR :: forall d_a1Gf1. Lens' (RoundedRectOpts d_a1Gf1) d_a1Gf1
- Diagrams.TwoD: radiusTL :: forall d_a1GoI. Lens' (RoundedRectOpts d_a1GoI) d_a1GoI
+ Diagrams.TwoD: radiusTL :: forall d_a1Gf1. Lens' (RoundedRectOpts d_a1Gf1) d_a1Gf1
- Diagrams.TwoD: radiusTR :: forall d_a1GoI. Lens' (RoundedRectOpts d_a1GoI) d_a1GoI
+ Diagrams.TwoD: radiusTR :: forall d_a1Gf1. Lens' (RoundedRectOpts d_a1Gf1) d_a1Gf1
- Diagrams.TwoD: tColor :: forall n_a2aSE. Lens' (TraceOpts n_a2aSE) (Colour Double)
+ Diagrams.TwoD: tColor :: forall n_a2aIY. Lens' (TraceOpts n_a2aIY) (Colour Double)
- Diagrams.TwoD: tMinSize :: forall n_a2aSE. Lens' (TraceOpts n_a2aSE) n_a2aSE
+ Diagrams.TwoD: tMinSize :: forall n_a2aIY. Lens' (TraceOpts n_a2aIY) n_a2aIY
- Diagrams.TwoD: tPoints :: forall n_a2aSE. Lens' (TraceOpts n_a2aSE) Int
+ Diagrams.TwoD: tPoints :: forall n_a2aIY. Lens' (TraceOpts n_a2aIY) Int
- Diagrams.TwoD: tScale :: forall n_a2aSE. Lens' (TraceOpts n_a2aSE) n_a2aSE
+ Diagrams.TwoD: tScale :: forall n_a2aIY. Lens' (TraceOpts n_a2aIY) n_a2aIY
- Diagrams.TwoD.Attributes: _LG :: forall n_a1SeS. Prism' (Texture n_a1SeS) (LGradient n_a1SeS)
+ Diagrams.TwoD.Attributes: _LG :: forall n_a1S5c. Prism' (Texture n_a1S5c) (LGradient n_a1S5c)
- Diagrams.TwoD.Attributes: _RG :: forall n_a1SeS. Prism' (Texture n_a1SeS) (RGradient n_a1SeS)
+ Diagrams.TwoD.Attributes: _RG :: forall n_a1S5c. Prism' (Texture n_a1S5c) (RGradient n_a1S5c)
- Diagrams.TwoD.Attributes: _SC :: forall n_a1SeS. Prism' (Texture n_a1SeS) SomeColor
+ Diagrams.TwoD.Attributes: _SC :: forall n_a1S5c. Prism' (Texture n_a1S5c) SomeColor
- Diagrams.TwoD.Model: eColor :: forall n_a2aPg. Lens' (EnvelopeOpts n_a2aPg) (Colour Double)
+ Diagrams.TwoD.Model: eColor :: forall n_a2aFA. Lens' (EnvelopeOpts n_a2aFA) (Colour Double)
- Diagrams.TwoD.Model: eLineWidth :: forall n_a2aPg n_a2aSf. Lens (EnvelopeOpts n_a2aPg) (EnvelopeOpts n_a2aSf) (Measure n_a2aPg) (Measure n_a2aSf)
+ Diagrams.TwoD.Model: eLineWidth :: forall n_a2aFA n_a2aIz. Lens (EnvelopeOpts n_a2aFA) (EnvelopeOpts n_a2aIz) (Measure n_a2aFA) (Measure n_a2aIz)
- Diagrams.TwoD.Model: ePoints :: forall n_a2aPg. Lens' (EnvelopeOpts n_a2aPg) Int
+ Diagrams.TwoD.Model: ePoints :: forall n_a2aFA. Lens' (EnvelopeOpts n_a2aFA) Int
- Diagrams.TwoD.Model: oColor :: forall n_a2aOb. Lens' (OriginOpts n_a2aOb) (Colour Double)
+ Diagrams.TwoD.Model: oColor :: forall n_a2aEv. Lens' (OriginOpts n_a2aEv) (Colour Double)
- Diagrams.TwoD.Model: oMinSize :: forall n_a2aOb. Lens' (OriginOpts n_a2aOb) n_a2aOb
+ Diagrams.TwoD.Model: oMinSize :: forall n_a2aEv. Lens' (OriginOpts n_a2aEv) n_a2aEv
- Diagrams.TwoD.Model: oScale :: forall n_a2aOb. Lens' (OriginOpts n_a2aOb) n_a2aOb
+ Diagrams.TwoD.Model: oScale :: forall n_a2aEv. Lens' (OriginOpts n_a2aEv) n_a2aEv
- Diagrams.TwoD.Model: tColor :: forall n_a2aSE. Lens' (TraceOpts n_a2aSE) (Colour Double)
+ Diagrams.TwoD.Model: tColor :: forall n_a2aIY. Lens' (TraceOpts n_a2aIY) (Colour Double)
- Diagrams.TwoD.Model: tMinSize :: forall n_a2aSE. Lens' (TraceOpts n_a2aSE) n_a2aSE
+ Diagrams.TwoD.Model: tMinSize :: forall n_a2aIY. Lens' (TraceOpts n_a2aIY) n_a2aIY
- Diagrams.TwoD.Model: tPoints :: forall n_a2aSE. Lens' (TraceOpts n_a2aSE) Int
+ Diagrams.TwoD.Model: tPoints :: forall n_a2aIY. Lens' (TraceOpts n_a2aIY) Int
- Diagrams.TwoD.Model: tScale :: forall n_a2aSE. Lens' (TraceOpts n_a2aSE) n_a2aSE
+ Diagrams.TwoD.Model: tScale :: forall n_a2aIY. Lens' (TraceOpts n_a2aIY) n_a2aIY
- Diagrams.TwoD.Shapes: radiusBL :: forall d_a1GoI. Lens' (RoundedRectOpts d_a1GoI) d_a1GoI
+ Diagrams.TwoD.Shapes: radiusBL :: forall d_a1Gf1. Lens' (RoundedRectOpts d_a1Gf1) d_a1Gf1
- Diagrams.TwoD.Shapes: radiusBR :: forall d_a1GoI. Lens' (RoundedRectOpts d_a1GoI) d_a1GoI
+ Diagrams.TwoD.Shapes: radiusBR :: forall d_a1Gf1. Lens' (RoundedRectOpts d_a1Gf1) d_a1Gf1
- Diagrams.TwoD.Shapes: radiusTL :: forall d_a1GoI. Lens' (RoundedRectOpts d_a1GoI) d_a1GoI
+ Diagrams.TwoD.Shapes: radiusTL :: forall d_a1Gf1. Lens' (RoundedRectOpts d_a1Gf1) d_a1Gf1
- Diagrams.TwoD.Shapes: radiusTR :: forall d_a1GoI. Lens' (RoundedRectOpts d_a1GoI) d_a1GoI
+ Diagrams.TwoD.Shapes: radiusTR :: forall d_a1Gf1. Lens' (RoundedRectOpts d_a1Gf1) d_a1Gf1

Files

CHANGELOG.md view
@@ -1,3 +1,13 @@+## [v1.5](https://github.com/diagrams/diagrams-lib/tree/v1.5) (2025-02-13)++- Allow `base-4.21` and test on GHC 9.12+- Remove looped compilation mode options ([#372](https://github.com/diagrams/diagrams-lib/pull/372))+    - This allows us to remove the `fsnotify` dependency, which in+      turn allows compiling diagrams to Wasm.+    - To recover similar functionality (automatically recompiling+      every time a source file changes), try an external tool like+      `ghcid` or `ghciwatch`, or, more generically, `entr`.+ ## [v1.4.7](https://github.com/diagrams/diagrams-lib/tree/v1.4.7) (2024-10-26)  - Switch to `data-default-0.8` instead of `data-default-class`
diagrams-lib.cabal view
@@ -1,5 +1,5 @@ Name:                diagrams-lib-Version:             1.4.7+Version:             1.5 Synopsis:            Embedded domain-specific language for declarative graphics Description:         Diagrams is a flexible, extensible EDSL for creating                      graphics of many types.  Graphics can be created@@ -21,7 +21,7 @@ Cabal-version:       1.18 Extra-source-files:  diagrams/*.svg Extra-doc-files:     CHANGELOG.md, README.markdown, diagrams/*.svg-Tested-with:         GHC ==8.4.4 || ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.8 || ==9.6.5 || ==9.8.2 || ==9.10.1+Tested-with:         GHC ==8.4.4 || ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.8 || ==9.6.6 || ==9.8.2 || ==9.10.1 || ==9.12.1 Source-repository head   type:     git   location: http://github.com/diagrams/diagrams-lib.git@@ -101,7 +101,7 @@                        Diagrams.TwoD.Vector,                        Diagrams.Util   other-modules:       Linear.Vector.Compat-  Build-depends:       base >= 4.9 && < 4.21,+  Build-depends:       base >= 4.9 && < 4.22,                        containers >= 0.3 && < 0.8,                        array >= 0.3 && < 0.6,                        semigroups >= 0.3.4 && < 0.21,@@ -124,7 +124,6 @@                        adjunctions >= 4.0 && < 5.0,                        distributive >=0.2.2 && < 1.0,                        process >= 1.1 && < 1.7,-                       fsnotify >= 0.4 && < 0.5,                        directory >= 1.2 && < 1.4,                        unordered-containers >= 0.2 && < 0.3,                        text >= 0.7.1 && < 2.2,
src/Diagrams/Backend/CmdLine.hs view
@@ -50,12 +50,6 @@   , diagramAnimOpts   , fpu -    -- ** Loop options-  , DiagramLoopOpts(..)-  , diagramLoopOpts-  , loop-  , src-     -- * Parsing   , Parseable(..)   , readHexColor@@ -70,19 +64,17 @@     -- ** helper functions for implementing @mainRender@   , defaultAnimMainRender   , defaultMultiMainRender-  , defaultLoopRender   ) where  import           Control.Lens              (Lens', makeLenses, (&), (.~), (^.)) import           Diagrams.Animation import           Diagrams.Attributes import           Diagrams.Core             hiding (output)-import           Diagrams.Util  import           Options.Applicative import           Options.Applicative.Types (readerAsk) -import           Control.Monad             (forM_, forever, unless, when)+import           Control.Monad             (forM_)  -- MonadFail comes from Prelude in base-4.13 and up #if !MIN_VERSION_base(4,13,0)@@ -96,27 +88,12 @@ import           Data.Colour.SRGB import           Data.Data import           Data.Functor.Identity-import           Data.IORef import           Data.Kind                 (Type)-import           Data.List                 (delete)-import           Data.Maybe                (fromMaybe) import           Data.Monoid import           Numeric -import           Control.Concurrent        (threadDelay)-import           System.Directory          (canonicalizePath)-import           System.Environment        (getArgs, getProgName)-import           System.Exit               (ExitCode (..))-import           System.FilePath           (addExtension, dropExtension,-                                            replaceExtension, splitExtension,-                                            takeDirectory, takeFileName, (</>))-import           System.FSNotify           (defaultConfig,-                                            eventTime, watchDir,-                                            withManagerConf, confWatchMode, WatchMode(..))-import           System.FSNotify.Devel     (existsEvents)-import           System.Info               (os)-import           System.IO                 (hFlush, stdout)-import           System.Process            (readProcessWithExitCode)+import           System.Environment        (getProgName)+import           System.FilePath           (addExtension, splitExtension)  import           Text.Printf @@ -149,14 +126,6 @@  makeLenses ''DiagramAnimOpts --- | Extra options for command-line looping.-data DiagramLoopOpts = DiagramLoopOpts-  { _loop     :: Bool            -- ^ Flag to indicate that the program should loop creation.-  , _src      :: Maybe FilePath  -- ^ File path for the source file to recompile.-  }--makeLenses ''DiagramLoopOpts- -- | Command line parser for 'DiagramOpts'. --   Width is option @--width@ or @-w@. --   Height is option @--height@ or @-h@ (note we change help to be @-?@ due to this).@@ -199,16 +168,6 @@      <> value 30.0      <> help "Frames per unit time (for animations)") --- | CommandLine parser for 'DiagramLoopOpts'---   Loop is @--loop@ or @-l@.---   Source is @--src@ or @-s@.-diagramLoopOpts :: Parser DiagramLoopOpts-diagramLoopOpts = DiagramLoopOpts-  <$> switch (long "loop" <> short 'l' <> help "Run in a self-recompiling loop")-  <*> (optional . strOption)-      ( long "src" <> short 's'-     <> help "Source file to watch")- -- | A hidden \"helper\" option which always fails. --   Taken from Options.Applicative.Extra but without the --   short option 'h'.  We want the 'h' for Height.@@ -277,11 +236,6 @@ instance Parseable DiagramAnimOpts where   parser = diagramAnimOpts --- | Parse 'DiagramLoopOpts' using the 'diagramLoopOpts' parser.-instance Parseable DiagramLoopOpts where-  parser = diagramLoopOpts-- -- | Parse @'Colour' Double@ as either a named color from "Data.Colour.Names" --   or a hexadecimal color. instance Parseable (Colour Double) where@@ -529,9 +483,8 @@ --   be output for each second (unit time) of animation. -- --   This function requires a lens into the structure that the particular backend---   uses for it's diagram base case.  If @MainOpts (QDiagram b v n Any) ~ DiagramOpts@---   then this lens will simply be 'output'.  For a backend supporting looping---   it will most likely be @_1 . output@.  This lens is required because the+--   uses for its diagram base case.  If @MainOpts (QDiagram b v n Any) ~ DiagramOpts@+--   then this lens will simply be 'output'.  This lens is required because the --   implementation works by modifying the output field and running the base @mainRender@. --   Typically a backend can write its @Animation B V@ instance as --@@ -563,86 +516,3 @@   where fmt         = "%0" ++ show nDigits ++ "d"         output'     = addExtension (base ++ printf fmt i) ext         (base, ext) = splitExtension (opts^.out)--putStrF :: String -> IO ()-putStrF s = putStr s >> hFlush stdout--defaultLoopRender :: DiagramLoopOpts -> IO ()-defaultLoopRender opts = when (opts ^. loop) $ do-  putStrLn "Looping turned on"-  prog <- getProgName-  args <- getArgs--  srcPath <- case opts ^. src of-    Just path -> return path-    Nothing   -> fromMaybe (error nosrc) <$> findHsFile prog-      where-        nosrc = "Unable to find Haskell source file.\n"-             ++ "Specify source file with '-s' or '--src'"-  srcPath' <- canonicalizePath srcPath--  sandbox     <- findSandbox []-  sandboxArgs <- case sandbox of-    Nothing -> return []-    Just sb -> do-      putStrLn ("Using sandbox " ++ takeDirectory sb)-      return ["-package-db", sb]--  let args'       = delete "-l" . delete "--loop" $ args-      newProg     = newProgName (takeFileName srcPath) prog-      timeOfDay   = take 8 . drop 11 . show . eventTime--  withManagerConf defaultConfig $-    \mgr -> do-      lock <- newIORef False--      _ <- watchDir mgr (takeDirectory srcPath') (existsEvents (== srcPath'))-        $ \ev -> do-          running <- atomicModifyIORef lock ((,) True)-          unless running $ do-            putStrF ("Modified " ++ timeOfDay ev ++ " ... ")-            exitCode <- recompile srcPath' newProg sandboxArgs-            -- Call the new program without the looping option-            run newProg args' exitCode-            atomicWriteIORef lock False--      putStrLn $ "Watching source file " ++ srcPath-      putStrLn $ "Compiling target: " ++ newProg-      putStrLn $ "Program args: " ++ unwords args'-      forever . threadDelay $ case os of-         -- https://ghc.haskell.org/trac/ghc/ticket/7325-        "darwin" -> 2000000000-        _        -> maxBound--recompile :: FilePath -> FilePath -> [String] -> IO ExitCode-recompile srcFile outFile args = do-  let ghcArgs = ["--make", srcFile, "-o", outFile] ++ args-  putStrF "compiling ... "-  (exit, _, stderr) <- readProcessWithExitCode "ghc" ghcArgs ""-  when (exit /= ExitSuccess) $ putStrLn ('\n':stderr)-  return exit---- | On Windows, the next compilation must have a different output---   than the currently running program.-newProgName :: FilePath -> String -> String-newProgName srcFile oldName = case os of-  "mingw32" ->-      if oldName == replaceExtension srcFile "exe"-        then replaceExtension srcFile ".1.exe"-        else replaceExtension srcFile "exe"-  _ -> dropExtension srcFile---- | Run the given program with specified arguments, if and only if---   the previous command returned ExitSuccess.-run :: String -> [String] -> ExitCode -> IO ()-run prog args ExitSuccess = do-  let path = "." </> prog-  putStrF "running ... "-  (exit, stdOut, stdErr) <- readProcessWithExitCode path args ""-  case exit of-    ExitSuccess   -> putStrLn "done."-    ExitFailure r -> do-      putStrLn $ prog ++ " failed with exit code " ++ show r-      unless (null stdOut) $ putStrLn "stdout:" >> putStrLn stdOut-      unless (null stdErr) $ putStrLn "stderr:" >> putStrLn stdErr-run _ _ _ = return ()