packages feed

effectful-cli 0.2.7.0 → 0.2.8.0

raw patch · 5 files changed

+80/−10 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Effectful.CLI.Config: showConfig :: forall a (es :: [Effect]). (FromValue a, ToTable a, IOE :> es, Error CLIError :> es) => FilePath -> Eff es Text
- Data.CLI.Config: class FromValue ConfigOf c => ConfigFile c where {
+ Data.CLI.Config: class (FromValue ConfigOf c, ToTable ConfigOf c) => ConfigFile c where {

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+## [2.8.0](https://github.com/haskell-github-trust/effectful-cli/compare/2.7.0...2.8.0) (2026-11-09)++### Features++* show all config in show command ([a9318f7](https://github.com/haskell-github-trust/effectful-cli/commit/a9318f7640627135fc8991f7bd5c835bcc47c55b))+ ## [2.7.0](https://github.com/haskell-github-trust/effectful-cli/compare/2.6.0...2.7.0) (2026-11-07)  ### Features
effectful-cli.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           effectful-cli-version:        0.2.7.0+version:        0.2.8.0 synopsis:       CLI helpers for the effectful ecosystem description:    Please see the README at https://github.com/haskell-github-trust/effectful-cli category:       CLI
src/Data/CLI/Config.hs view
@@ -14,19 +14,24 @@ import Data.Kind (Type) import Data.Text (Text) import Data.Text qualified as T-import Effectful.CLI.Config (getConfigKey, readConfigText, setConfigKey)+import Effectful.CLI.Config (getConfigKey, setConfigKey, showConfig) import Effectful.CLI.Exception (rethrowIO) import Effectful.CLI.IO (printOutputLn) import Effectful.Reader.Static (asks) import GHC.Enum (boundedEnumFrom, boundedEnumFromThen) import Options.Applicative (Parser, completer, listCompleter, metavar, strArgument)-import Toml.Schema (FromValue)+import Toml.Schema (FromValue, ToTable)  -- | Application config @c@ that knows its config file and the type it decodes to. --+-- 'ToTable' is needed by 'ConfigShow'; defaults come from the 'FromValue'+-- instance filling missing keys.+-- -- @since 0.2.6.0-class FromValue (ConfigOf c) => ConfigFile c where+class (FromValue (ConfigOf c), ToTable (ConfigOf c)) => ConfigFile c where   -- | Type the config file decodes to; 'ConfigSet' refuses to write anything else.+  --+  -- @since 0.2.8.0   type ConfigOf c :: Type    -- | Path of the config file.@@ -42,7 +47,7 @@ -- -- @since 0.2.6.0 data ConfigCommand c e-  = -- | Print the config file.+  = -- | Print the effective config: file values over the defaults.     ConfigShow   | -- | Print a dotted key's value.     ConfigGet Text@@ -72,7 +77,7 @@   cmdname (ConfigGet _) = "get"   cmdname (ConfigSet _ _) = "set" -  doc ConfigShow = "Print the config file"+  doc ConfigShow = "Print the effective config (file merged over defaults)"   doc (ConfigGet _) = "Print a dotted key's value (e.g. section.key)"   doc (ConfigSet _ _) = "Set a dotted key to a TOML literal, or a string if not one" @@ -83,7 +88,7 @@   runner cmd = do     path <- asks @c configFilePath     rethrowIO (InputError . ("config file: " <>) . T.show) $ case cmd of-      ConfigShow -> printOutputLn . T.stripEnd =<< readConfigText path+      ConfigShow -> printOutputLn =<< showConfig @(ConfigOf c) path       ConfigGet k -> printOutputLn =<< getConfigKey path k       ConfigSet k v -> setConfigKey @(ConfigOf c) (configKeys @c) path k v 
src/Effectful/CLI/Config.hs view
@@ -4,6 +4,7 @@ -- | Read and edit a TOML config file by dotted key (@github.project.team@). module Effectful.CLI.Config (   readConfigText,+  showConfig,   getConfigKey,   setConfigKey,   lookupKey,@@ -33,7 +34,7 @@  ) import Toml qualified import Toml.Pretty (prettyValue)-import Toml.Schema (FromValue)+import Toml.Schema (FromValue, ToTable (toTable))  -- | The config file's contents, empty if it does not exist. --@@ -45,6 +46,23 @@ readConfigText path = liftIO $ do   exists <- doesFileExist path   if exists then T.readFile path else pure ""++-- | The config file decoded as @a@ (so defaults fill missing keys, and a+-- missing file is all defaults), rendered back as TOML.+--+-- @since 0.2.8.0+showConfig+  :: forall a es+   . FromValue a+  => ToTable a+  => IOE :> es+  => Error CLIError :> es+  => FilePath+  -> Eff es Text+showConfig path =+  readConfigText path >>= \raw -> case Toml.decode @a raw of+    Failure es -> throwError (InputError ("invalid config: " <> T.stripEnd (T.pack (unlines es))))+    Success _ a -> pure (T.stripEnd (T.show (prettyToml (toTable a))))  -- | Render a dotted key's value: strings unquoted, tables as TOML sections. --
test/Spec.hs view
@@ -12,9 +12,17 @@  ) import Data.Error.CLI (CLIError (..), displayCLIError) import Data.List (isInfixOf)+import Data.Maybe (fromMaybe) import Effectful (Eff, IOE, liftIO, runEff) import Effectful.CLI.Conc (batchConcurrentlyWithIndex)-import Effectful.CLI.Config (getConfigKey, lookupKey, parseValue, setConfigKey, setKey)+import Effectful.CLI.Config (+  getConfigKey,+  lookupKey,+  parseValue,+  setConfigKey,+  setKey,+  showConfig,+ ) import Effectful.CLI.Exception (rethrowIO) import Effectful.CLI.IO (resolveIndex) import Effectful.Concurrent (runConcurrent)@@ -25,7 +33,18 @@ import Test.Hspec import Text.Megaparsec.Char (string) import Toml (Table, Table' (..), Value' (..))-import Toml.Schema (FromValue (..), parseTableFromValue, reqKey, reqKeyOf)+import Toml.Schema (+  FromValue (..),+  ToTable (..),+  ToValue (..),+  defaultTableToValue,+  optKey,+  parseTableFromValue,+  reqKey,+  reqKeyOf,+  table,+  (.=),+ )  isInputError :: Either CLIError a -> Bool isInputError (Left (InputError _)) = True@@ -151,6 +170,28 @@       r `shouldSatisfy` \case         Left (InputError m) -> "sec is a section, set one of: sec.x, sec.y" `isInfixOf` show m         _ -> False++    it "shows defaults for a missing file and file values over them" $ do+      dir <- getTemporaryDirectory+      let missing = dir </> "effectful-cli-config-missing.toml"+          present = dir </> "effectful-cli-config-show.toml"+      writeFile present "n = 3\n"+      r <-+        runEff . runErrorNoCallStack @CLIError $+          (,) <$> showConfig @Defaulted missing <*> showConfig @Defaulted present+      removeFile present+      r `shouldBe` Right ("n = 7", "n = 3")++newtype Defaulted = Defaulted Int++instance FromValue Defaulted where+  fromValue = parseTableFromValue (Defaulted . fromMaybe 7 <$> optKey "n")++instance ToValue Defaulted where+  toValue = defaultTableToValue++instance ToTable Defaulted where+  toTable (Defaulted n) = table ["n" .= n]  newtype Section = Section Int