packages feed

stackctl 1.1.4.0 → 1.2.0.0

raw patch · 13 files changed

+125/−45 lines, 13 filesdep +envparsedep +semigroups

Dependencies added: envparse, semigroups

Files

CHANGELOG.md view
@@ -1,4 +1,9 @@-## [_Unreleased_](https://github.com/freckle/stackctl/compare/v1.1.4.0...main)+## [_Unreleased_](https://github.com/freckle/stackctl/compare/v1.2.0.0...main)++## [v1.2.0.0](https://github.com/freckle/stackctl/compare/v1.1.3.1...v1.2.0.0)++- Use more specific types in `Has{Directory,Filter,Color}Option`+- Add environment variable configuration for `STACKCTL_{DIRECTORY,FILTERS}`  ## [v1.1.4.0](https://github.com/freckle/stackctl/compare/v1.1.3.1...v1.1.4.0) 
src/Stackctl/CLI.hs view
@@ -87,7 +87,7 @@     $ defaultLogSettings    logger <- newLogger $ adjustLogSettings-    (options ^. colorOptionL)+    (options ^. colorOptionL . to unColorOption)     (options ^. verboseOptionL)     envLogSettings 
src/Stackctl/ColorOption.hs view
@@ -1,5 +1,6 @@ module Stackctl.ColorOption-  ( LogColor(..)+  ( ColorOption(..)+  , defaultColorOption   , HasColorOption(..)   , colorOption   , colorHandle@@ -8,29 +9,38 @@ import Stackctl.Prelude  import Blammo.Logging.LogSettings+import Data.Semigroup (Last(..)) import Options.Applicative +newtype ColorOption = ColorOption+  { unColorOption :: LogColor+  }+  deriving Semigroup via Last ColorOption++defaultColorOption :: ColorOption+defaultColorOption = ColorOption LogColorAuto+ class HasColorOption env where-  colorOptionL :: Lens' env LogColor+  colorOptionL :: Lens' env ColorOption -instance HasColorOption LogColor where+instance HasColorOption ColorOption where   colorOptionL = id -colorOption :: Parser LogColor-colorOption = option (eitherReader readLogColor) $ mconcat+colorOption :: Parser ColorOption+colorOption = option (eitherReader $ fmap ColorOption . readLogColor) $ mconcat   [ long "color"   , help "When to colorize output"   , metavar "auto|always|never"-  , value LogColorAuto-  , showDefaultWith showLogColor+  , value defaultColorOption+  , showDefaultWith showColorOption   ] -showLogColor :: LogColor -> String-showLogColor = \case+showColorOption :: ColorOption -> String+showColorOption co = case unColorOption co of   LogColorAuto -> "auto"   LogColorAlways -> "always"   LogColorNever -> "never" -colorHandle :: MonadIO m => Handle -> LogColor -> m Bool-colorHandle h lc = shouldColorHandle settings h-  where settings = setLogSettingsColor lc defaultLogSettings+colorHandle :: MonadIO m => Handle -> ColorOption -> m Bool+colorHandle h co = shouldColorHandle settings h+  where settings = setLogSettingsColor (unColorOption co) defaultLogSettings
src/Stackctl/DirectoryOption.hs view
@@ -1,25 +1,41 @@ module Stackctl.DirectoryOption-  ( HasDirectoryOption(..)+  ( DirectoryOption(..)+  , defaultDirectoryOption+  , HasDirectoryOption(..)+  , envDirectoryOption   , directoryOption   ) where  import Stackctl.Prelude +import Data.Semigroup (Last(..))+import qualified Env import Options.Applicative +newtype DirectoryOption = DirectoryOption+  { unDirectoryOption :: FilePath+  }+  deriving newtype IsString+  deriving Semigroup via Last DirectoryOption++defaultDirectoryOption :: DirectoryOption+defaultDirectoryOption = "."+ class HasDirectoryOption env where-  directoryOptionL :: Lens' env FilePath+  directoryOptionL :: Lens' env DirectoryOption -instance HasDirectoryOption FilePath where+instance HasDirectoryOption DirectoryOption where   directoryOptionL = id -directoryOption :: Parser FilePath+envDirectoryOption :: Env.Parser Env.Error DirectoryOption+envDirectoryOption = Env.var (Env.str <=< Env.nonempty) "DIRECTORY"+  $ Env.help "Operate on specifications in this directory"++directoryOption :: Parser DirectoryOption directoryOption = option str $ mconcat   [ short 'd'   , long "directory"   , metavar "PATH"   , help "Operate on specifications in PATH"-  , value "."-  , showDefault   , action "directory"   ]
src/Stackctl/FilterOption.hs view
@@ -1,6 +1,8 @@ module Stackctl.FilterOption   ( FilterOption+  , defaultFilterOption   , HasFilterOption(..)+  , envFilterOption   , filterOption   , filterOptionFromPaths   , filterOptionFromText@@ -10,7 +12,9 @@ import Stackctl.Prelude  import qualified Data.List.NonEmpty as NE+import Data.Semigroup (Last(..)) import qualified Data.Text as T+import qualified Env import Options.Applicative import Stackctl.AWS.CloudFormation (StackName(..)) import Stackctl.StackSpec@@ -20,6 +24,7 @@ newtype FilterOption = FilterOption   { unFilterOption :: NonEmpty Pattern   }+  deriving Semigroup via Last FilterOption  instance ToJSON FilterOption where   toJSON = toJSON . showFilterOption@@ -31,13 +36,19 @@ instance HasFilterOption FilterOption where   filterOptionL = id +envFilterOption :: String -> Env.Parser Env.Error FilterOption+envFilterOption items =+  Env.var (first Env.UnreadError . readFilterOption) "FILTERS"+    $ Env.help+    $ "Filter "+    <> items+    <> " by patterns"+ filterOption :: String -> Parser FilterOption filterOption items = option (eitherReader readFilterOption) $ mconcat   [ long "filter"   , metavar "PATTERN[,PATTERN]"   , help $ "Filter " <> items <> " to match PATTERN(s)"-  , value defaultFilterOption-  , showDefaultWith showFilterOption   ]  filterOptionFromPaths :: NonEmpty FilePath -> FilterOption
src/Stackctl/Options.hs view
@@ -1,10 +1,13 @@ module Stackctl.Options-  ( Options(..)+  ( Options+  , envParser   , optionsParser   ) where  import Stackctl.Prelude +import Data.Semigroup.Generic+import qualified Env import Options.Applicative import Stackctl.ColorOption import Stackctl.DirectoryOption@@ -12,29 +15,49 @@ import Stackctl.VerboseOption  data Options = Options-  { oDirectory :: FilePath-  , oFilterOption :: FilterOption-  , oColor :: LogColor+  { oDirectory :: Maybe DirectoryOption+  , oFilter :: Maybe FilterOption+  , oColor :: Maybe ColorOption   , oVerbose :: Verbosity   }+  deriving stock Generic+  deriving Semigroup via GenericSemigroupMonoid Options -instance HasDirectoryOption Options where-  directoryOptionL = lens oDirectory $ \x y -> x { oDirectory = y }+directoryL :: Lens' Options (Maybe DirectoryOption)+directoryL = lens oDirectory $ \x y -> x { oDirectory = y } -instance HasColorOption Options where-  colorOptionL = lens oColor $ \x y -> x { oColor = y }+filterL :: Lens' Options (Maybe FilterOption)+filterL = lens oFilter $ \x y -> x { oFilter = y } +colorL :: Lens' Options (Maybe ColorOption)+colorL = lens oColor $ \x y -> x { oColor = y }++instance HasDirectoryOption Options where+  directoryOptionL = directoryL . maybeLens defaultDirectoryOption+ instance HasFilterOption Options where-  filterOptionL = lens oFilterOption $ \x y -> x { oFilterOption = y }+  filterOptionL = filterL . maybeLens defaultFilterOption +instance HasColorOption Options where+  colorOptionL = colorL . maybeLens defaultColorOption+ instance HasVerboseOption Options where   verboseOptionL = lens oVerbose $ \x y -> x { oVerbose = y }  -- brittany-disable-next-binding +envParser :: Env.Parser Env.Error Options+envParser = Env.prefixed "STACKCTL_" $ Options+  <$> optional envDirectoryOption+  <*> optional (envFilterOption "specifications")+  <*> pure mempty -- use LOG_COLOR+  <*> pure mempty -- use LOG_LEVEL++-- brittany-disable-next-binding+ optionsParser :: Parser Options optionsParser = Options-  <$> directoryOption-  <*> filterOption "specifications"-  <*> colorOption+  <$> optional directoryOption+  <*> optional (filterOption "specifications")+  <*> (Just <$> colorOption)   <*> verboseOption
src/Stackctl/Prelude.hs view
@@ -1,6 +1,7 @@ module Stackctl.Prelude   ( module X   , decodeUtf8+  , maybeLens   ) where  import RIO as X hiding@@ -30,3 +31,6 @@  decodeUtf8 :: ByteString -> Text decodeUtf8 = decodeUtf8With lenientDecode++maybeLens :: a -> Lens' (Maybe a) a+maybeLens x = lens (fromMaybe x) $ const Just
src/Stackctl/Spec/Capture.hs view
@@ -10,7 +10,7 @@ import Stackctl.AWS import Stackctl.AWS.Scope import Stackctl.Config (HasConfig)-import Stackctl.DirectoryOption (HasDirectoryOption(..))+import Stackctl.DirectoryOption (HasDirectoryOption(..), unDirectoryOption) import Stackctl.Spec.Generate import Stackctl.StackSpec import System.FilePath.Glob@@ -74,7 +74,7 @@   => CaptureOptions   -> m () runCapture CaptureOptions {..} = do-  dir <- view directoryOptionL+  dir <- unDirectoryOption <$> view directoryOptionL    let     setScopeName scope =
src/Stackctl/Spec/Cat.hs view
@@ -21,7 +21,7 @@ import Stackctl.AWS.Scope import Stackctl.Colors import Stackctl.Config (HasConfig)-import Stackctl.DirectoryOption (HasDirectoryOption(..))+import Stackctl.DirectoryOption (HasDirectoryOption(..), unDirectoryOption) import Stackctl.FilterOption (HasFilterOption) import Stackctl.Spec.Discover import Stackctl.StackSpec@@ -67,7 +67,7 @@   => CatOptions   -> m () runCat CatOptions {..} = do-  dir <- view directoryOptionL+  dir <- unDirectoryOption <$> view directoryOptionL   colors@Colors {..} <- getColorsStdout   tree <- specTree <$> discoverSpecs 
src/Stackctl/Spec/Discover.hs view
@@ -10,7 +10,7 @@ import Stackctl.AWS import Stackctl.AWS.Scope import Stackctl.Config (HasConfig)-import Stackctl.DirectoryOption (HasDirectoryOption(..))+import Stackctl.DirectoryOption (HasDirectoryOption(..), unDirectoryOption) import Stackctl.FilterOption (HasFilterOption(..), filterStackSpecs) import Stackctl.StackSpec import Stackctl.StackSpecPath@@ -29,7 +29,7 @@      )   => m [StackSpec] discoverSpecs = do-  dir <- view directoryOptionL+  dir <- unDirectoryOption <$> view directoryOptionL   scope@AwsScope {..} <- view awsScopeL   paths <- globRelativeTo     dir
src/Stackctl/Subcommand.hs view
@@ -7,6 +7,7 @@  import Stackctl.Prelude +import qualified Env import Options.Applicative import qualified Stackctl.CLI as CLI import Stackctl.Colors@@ -25,17 +26,24 @@   command (unpack name) (run <$> withInfo description parse)  runSubcommand :: Mod CommandFields (CLI.AppT (CLI.App Options) IO ()) -> IO ()-runSubcommand = runSubcommand' "Work with Stack specifications" optionsParser+runSubcommand =+  runSubcommand' "Work with Stack specifications" envParser optionsParser +-- brittany-disable-next-binding+ runSubcommand'-  :: (HasVerboseOption options, HasColorOption options)+  :: (Semigroup options, HasVerboseOption options, HasColorOption options)   => Text+  -> Env.Parser Env.Error options   -> Parser options   -> Mod CommandFields (CLI.AppT (CLI.App options) IO ())   -> IO ()-runSubcommand' x op sp = do-  (options, act) <- execParser $ withInfo x $ (,) <$> op <*> subparser sp+runSubcommand' title parseEnv parseCLI sp = do+  (options, act) <- applyEnv+    <$> Env.parse (Env.header $ unpack title) parseEnv+    <*> execParser (withInfo title $ (,) <$> parseCLI <*> subparser sp)   CLI.runAppT options act+  where applyEnv env = first (env <>)  withInfo :: Text -> Parser a -> ParserInfo a withInfo d p = info (p <**> helper) $ progDesc (unpack d) <> fullDesc
src/Stackctl/VerboseOption.hs view
@@ -11,6 +11,7 @@ import Options.Applicative  newtype Verbosity = Verbosity [()]+  deriving newtype (Semigroup, Monoid)  verbositySetLogLevels :: Verbosity -> (LogSettings -> LogSettings) verbositySetLogLevels (Verbosity bs) = case bs of
stackctl.cabal view
@@ -1,6 +1,6 @@ cabal-version:   1.18 name:            stackctl-version:         1.1.4.0+version:         1.2.0.0 license:         MIT license-file:    LICENSE copyright:       2022 Renaissance Learning Inc@@ -95,6 +95,7 @@         cfn-flip >=0.1.0.3,         conduit,         containers,+        envparse,         errors,         exceptions,         extra,@@ -106,6 +107,7 @@         optparse-applicative,         resourcet,         rio,+        semigroups,         text,         time,         unliftio,