From 1fb1de3de808eb82f80a4fd3a152f6ce274e49c4 Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:21:19 +0000 Subject: [PATCH 01/14] Remove .tasty-rerun-log from repo (gitignore) --- .gitignore | 2 +- .tasty-rerun-log | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 .tasty-rerun-log diff --git a/.gitignore b/.gitignore index 2ff9982..5bb7e51 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ .stack-work/ .#* -etc-spec/.tasty-rerun-log \ No newline at end of file +.tasty-rerun-log \ No newline at end of file diff --git a/.tasty-rerun-log b/.tasty-rerun-log deleted file mode 100644 index 9e33892..0000000 --- a/.tasty-rerun-log +++ /dev/null @@ -1 +0,0 @@ -fromList [(["etc","cli","command","fails when command not given"],Completed True),(["etc","cli","command","when command given","argument input","entry gets validated with a type"],Completed True),(["etc","cli","command","when command given","argument input","entry with required fails when argument not given"],Completed True),(["etc","cli","command","when command given","argument input","entry with required false does not barf"],Completed True),(["etc","cli","command","when command given","argument input","supports same cli input on multiple arguments"],Completed True),(["etc","cli","command","when command given","option input","entry accepts long"],Completed True),(["etc","cli","command","when command given","option input","entry accepts short"],Completed True),(["etc","cli","command","when command given","option input","entry gets validated with a type"],Completed True),(["etc","cli","command","when command given","option input","entry with required fails when option not given"],Completed True),(["etc","cli","command","when command given","option input","entry with required false does not barf"],Completed True),(["etc","cli","plain","argument input","entry gets validated with a type"],Completed True),(["etc","cli","plain","argument input","entry with required fails when argument not given"],Completed True),(["etc","cli","plain","argument input","entry with required false does not barf"],Completed True),(["etc","cli","plain","option input","entry accepts long"],Completed True),(["etc","cli","plain","option input","entry accepts short"],Completed True),(["etc","cli","plain","option input","entry gets validated with a type"],Completed True),(["etc","cli","plain","option input","entry with required fails when option not given"],Completed True),(["etc","cli","plain","option input","entry with required false does not barf"],Completed True),(["etc","default","default can be raw JSON value on entries spec"],Completed True),(["etc","default","default is used when defined on spec"],Completed True),(["etc","env","does not add entries to config if env var is not present"],Completed True),(["etc","env","env entry is present when env var is defined"],Completed True),(["etc","env","has precedence over default and file values"],Completed True),(["etc","file","does not fail if file doesn't exist"],Completed True),(["etc","file","does not support any other file extension"],Completed True),(["etc","file","supports json, yaml and yml extensions"],Completed True),(["etc","spec","cli","cli entry accepts command"],Completed True),(["etc","spec","cli","cli entry does not accept unrecognized keys"],Completed True),(["etc","spec","cli","cli entry settings requires an input"],Completed True),(["etc","spec","cli","cli option entry requires either short or long"],Completed True),(["etc","spec","cli","cli option entry works when setting long and type"],Completed True),(["etc","spec","cli","cli option entry works when setting short and type"],Completed True),(["etc","spec","env","env key creates an ENV source"],Completed True),(["etc","spec","general","does not fail when etc/entries is not defined"],Completed True),(["etc","spec","general","entries can have many levels of nesting"],Completed True),(["etc","spec","general","entries cannot finish in an array"],Completed True),(["etc","spec","general","entries cannot finish in an empty map"],Completed True),(["etc","spec","general","entries that finish with raw values sets them as default value"],Completed True),(["etc","spec","general","spec map cannot be a JSON array"],Completed True),(["etc","spec","general","spec map cannot be a JSON bool"],Completed True),(["etc","spec","general","spec map cannot be a JSON number"],Completed True),(["etc","spec","general","spec map cannot be a JSON string"],Completed True),(["etc","spec","general","spec map cannot be empty object"],Completed True),(["etc","spec","general","spec map cannot have any other key that is not etc/spec"],Completed True),(["etc","spec","yaml parser","should work with Aeson instances"],Completed True)] \ No newline at end of file From 150c07b2da35c03cb6cf3e1daa47c633ee7607a0 Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:23:24 +0000 Subject: [PATCH 02/14] Rename cabal printer flag to extra --- etc/etc.cabal | 8 ++++---- etc/src/System/Etc.hs | 8 ++++++-- stack.yaml | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/etc/etc.cabal b/etc/etc.cabal index 542906c..3365ac8 100644 --- a/etc/etc.cabal +++ b/etc/etc.cabal @@ -30,8 +30,8 @@ source-repository head type: git location: https://github.com/roman/Haskell-etc -flag printer - description: Include support for config printer +flag extra + description: Include extra utilities manual: False default: False @@ -78,8 +78,8 @@ library default-language: Haskell2010 - if flag(printer) - cpp-options: -DWITH_PRINTER + if flag(extra) + cpp-options: -DWITH_EXTRA build-depends: ansi-wl-pprint >=0.6 && <0.7 exposed-modules: diff --git a/etc/src/System/Etc.hs b/etc/src/System/Etc.hs index 3de716d..0bf1254 100644 --- a/etc/src/System/Etc.hs +++ b/etc/src/System/Etc.hs @@ -46,6 +46,9 @@ module System.Etc ( #ifdef WITH_PRINTER -- * Printer -- $printer +#ifdef WITH_EXTRA + -- * Extra utilities + -- $extra , renderConfig , printPrettyConfig , hPrintPrettyConfig @@ -65,6 +68,7 @@ import System.Etc.Internal.Resolver.Cli.Plain (resolvePlainCli, resolvePlainCl #ifdef WITH_PRINTER import System.Etc.Internal.Printer (hPrintPrettyConfig, printPrettyConfig, renderConfig) +#ifdef WITH_EXTRA #endif import System.Etc.Internal.Config @@ -94,7 +98,7 @@ import System.Etc.Internal.Resolver.File (resolveFiles) -} {- $printer +{- $extra - Use these function to render the configuration map and understand how the - resolving was performed. + Some extra utilities that are great for debugging (miss)-configurations. -} diff --git a/stack.yaml b/stack.yaml index e0c06d4..2b8dc6e 100644 --- a/stack.yaml +++ b/stack.yaml @@ -46,7 +46,7 @@ extra-deps: [] # Override default flag values for local packages and extra-deps flags: etc: - printer: true + extra: true cli: true yaml: true From 57b156160a917c9307c76423308f1675068466b3 Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:28:54 +0000 Subject: [PATCH 03/14] Improvements to the Extra utilities - Created EnvMisspell module - Moved Printer to a Util sub-module --- etc/etc.cabal | 7 +- etc/src/System/Etc.hs | 16 +-- .../System/Etc/Internal/Util/EnvMisspell.hs | 102 ++++++++++++++++++ .../System/Etc/Internal/{ => Util}/Printer.hs | 2 +- etc/test/System/Etc/Util/EnvMisspellTest.hs | 41 +++++++ etc/test/TestSuite.hs | 8 ++ 6 files changed, 167 insertions(+), 9 deletions(-) create mode 100644 etc/src/System/Etc/Internal/Util/EnvMisspell.hs rename etc/src/System/Etc/Internal/{ => Util}/Printer.hs (98%) create mode 100644 etc/test/System/Etc/Util/EnvMisspellTest.hs diff --git a/etc/etc.cabal b/etc/etc.cabal index 3365ac8..d568de3 100644 --- a/etc/etc.cabal +++ b/etc/etc.cabal @@ -81,9 +81,12 @@ library if flag(extra) cpp-options: -DWITH_EXTRA build-depends: - ansi-wl-pprint >=0.6 && <0.7 + ansi-wl-pprint >=0.6 && <0.7, + edit-distance + exposed-modules: - System.Etc.Internal.Printer + System.Etc.Internal.Util.Printer + System.Etc.Internal.Util.Environment if flag(cli) cpp-options: -DWITH_CLI diff --git a/etc/src/System/Etc.hs b/etc/src/System/Etc.hs index 0bf1254..b972051 100644 --- a/etc/src/System/Etc.hs +++ b/etc/src/System/Etc.hs @@ -43,15 +43,19 @@ module System.Etc ( , CliConfigError(..) #endif -#ifdef WITH_PRINTER - -- * Printer - -- $printer #ifdef WITH_EXTRA -- * Extra utilities -- $extra , renderConfig , printPrettyConfig , hPrintPrettyConfig + + , EnvMisspell(..) + , getEnvMisspells + , getEnvMisspellsPure + , renderEnvMisspells + , hPrintEnvMisspells + , printEnvMisspellingWarnings #endif ) where @@ -66,9 +70,10 @@ import System.Etc.Internal.Resolver.Cli.Common (CliConfigError (..), getErrorMe import System.Etc.Internal.Resolver.Cli.Plain (resolvePlainCli, resolvePlainCliPure) #endif -#ifdef WITH_PRINTER -import System.Etc.Internal.Printer (hPrintPrettyConfig, printPrettyConfig, renderConfig) #ifdef WITH_EXTRA +import System.Etc.Internal.Util.Printer (hPrintPrettyConfig, printPrettyConfig, renderConfig) +import System.Etc.Internal.Util.EnvMisspell + (EnvMisspell(..), getEnvMisspellsPure, getEnvMisspells, renderEnvMisspells, hPrintEnvMisspells, printEnvMisspellingWarnings) #endif import System.Etc.Internal.Config @@ -97,7 +102,6 @@ import System.Etc.Internal.Resolver.File (resolveFiles) together using the mappend function -} -{- $printer {- $extra Some extra utilities that are great for debugging (miss)-configurations. diff --git a/etc/src/System/Etc/Internal/Util/EnvMisspell.hs b/etc/src/System/Etc/Internal/Util/EnvMisspell.hs new file mode 100644 index 0000000..180c137 --- /dev/null +++ b/etc/src/System/Etc/Internal/Util/EnvMisspell.hs @@ -0,0 +1,102 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE NoImplicitPrelude #-} +module System.Etc.Internal.Util.EnvMisspell ( + EnvMisspell (..) + , getEnvMisspells + , getEnvMisspellsPure + , renderEnvMisspells + , hPrintEnvMisspells + , printEnvMisspellingWarnings + ) where + +import Protolude hiding ((<$>), (<>)) + +import Data.Vector (Vector) +import System.Environment (getEnvironment) + +import qualified Data.HashMap.Strict as HashMap +import qualified Data.Text as Text +import qualified Data.Vector as Vector +import qualified Text.EditDistance as Distance + +import Text.PrettyPrint.ANSI.Leijen +import System.Etc.Internal.Spec.Types + +data EnvMisspell + = EnvMisspell { + currentText :: Text + , suggestionText :: Text + } + deriving (Show, Eq, Generic) + +lookupSpecEnvKeys :: ConfigSpec a -> Vector Text +lookupSpecEnvKeys spec = + let + foldEnvSettings val acc = + case val of + ConfigValue _ sources -> + maybe acc (flip Vector.cons acc) (envVar sources) + SubConfig hsh -> + HashMap.foldr foldEnvSettings acc hsh + in + foldEnvSettings (SubConfig $ specConfigValues spec) Vector.empty + +{-| + +-} +getEnvMisspellsPure :: ConfigSpec a -> Vector Text -> Vector EnvMisspell +getEnvMisspellsPure spec env = do + specEnvName <- lookupSpecEnvKeys spec + currentEnvName <- env + + let + distance = + Distance.levenshteinDistance + Distance.defaultEditCosts + (Text.unpack specEnvName) + (Text.unpack currentEnvName) + + guard (distance >= 1 && distance < 4) + return $ EnvMisspell currentEnvName specEnvName + +{-| + +-} +getEnvMisspells :: ConfigSpec a -> IO (Vector EnvMisspell) +getEnvMisspells spec = + (Vector.fromList . map (Text.pack . fst)) `fmap` getEnvironment + >>= return . getEnvMisspellsPure spec + +{-| + +-} +renderEnvMisspells :: Vector EnvMisspell -> Doc +renderEnvMisspells misspells = + misspells + & Vector.map + (\misspell -> + text "WARNING: Environment variable `" + <> text (Text.unpack $ currentText misspell) + <> text "' found, perhaps you meant `" + <> text (Text.unpack $ suggestionText misspell) + <> text "'") + & Vector.foldl' (<$>) mempty + & (<$> mempty) + + +{-| + +-} +hPrintEnvMisspells :: Handle -> Vector EnvMisspell -> IO () +hPrintEnvMisspells h = + hPutDoc h . renderEnvMisspells + + +{-| + +-} +printEnvMisspellingWarnings :: ConfigSpec a -> IO () +printEnvMisspellingWarnings spec = + getEnvMisspells spec >>= + hPrintEnvMisspells stderr diff --git a/etc/src/System/Etc/Internal/Printer.hs b/etc/src/System/Etc/Internal/Util/Printer.hs similarity index 98% rename from etc/src/System/Etc/Internal/Printer.hs rename to etc/src/System/Etc/Internal/Util/Printer.hs index 7f6dba3..7f2a59f 100644 --- a/etc/src/System/Etc/Internal/Printer.hs +++ b/etc/src/System/Etc/Internal/Util/Printer.hs @@ -1,7 +1,7 @@ {-# OPTIONS_GHC -fno-warn-deprecations #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} -module System.Etc.Internal.Printer ( +module System.Etc.Internal.Util.Printer ( renderConfig , printPrettyConfig , hPrintPrettyConfig diff --git a/etc/test/System/Etc/Util/EnvMisspellTest.hs b/etc/test/System/Etc/Util/EnvMisspellTest.hs new file mode 100644 index 0000000..60b8afe --- /dev/null +++ b/etc/test/System/Etc/Util/EnvMisspellTest.hs @@ -0,0 +1,41 @@ +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE NoImplicitPrelude #-} +module System.Etc.Util.EnvMisspellTest where + +import Protolude + +import Test.Tasty (TestTree, testGroup) +import Test.Tasty.HUnit (assertBool, assertEqual, testCase) + +import qualified Data.Vector as Vector + +import System.Etc + +tests :: TestTree +tests = + testGroup "env misspells" + [ + testCase "it warns when misspell is present" $ do + let + input = + mconcat + [ + "{\"etc/entries\": {" + , " \"greeting\": { \"etc/spec\": { \"env\": \"GREETING\" }}}}" + ] + + (spec :: ConfigSpec ()) <- parseConfigSpec input + + let + result = + getEnvMisspellsPure spec ["GREEING"] + + assertBool ("expecting to get a warning for typo") + (not $ Vector.null result) + + assertEqual ("expecting to get typo for key GREETING") + (EnvMisspell "GREEING" "GREETING") + (Vector.head result) + ] diff --git a/etc/test/TestSuite.hs b/etc/test/TestSuite.hs index cbd1599..60cf8ef 100644 --- a/etc/test/TestSuite.hs +++ b/etc/test/TestSuite.hs @@ -18,6 +18,10 @@ import qualified System.Etc.SpecTest import qualified System.Etc.Resolver.CliTest #endif +#ifdef WITH_EXTRA +import qualified System.Etc.Util.EnvMisspellTest +#endif + main :: IO () main = defaultMainWithIngredients @@ -29,4 +33,8 @@ main = #ifdef WITH_CLI , System.Etc.Resolver.CliTest.tests #endif + +#ifdef WITH_EXTRA + , System.Etc.Util.EnvMisspellTest.tests +#endif ]) From f8a6effa4aa06e2e284a0978cd32981be36feb30 Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:29:27 +0000 Subject: [PATCH 04/14] Add more useful LANGUAGE pragma to .ghci --- .ghci | 1 + 1 file changed, 1 insertion(+) diff --git a/.ghci b/.ghci index c93c997..e3a7f28 100644 --- a/.ghci +++ b/.ghci @@ -1,5 +1,6 @@ :seti -XNoImplicitPrelude :seti -XOverloadedStrings +:seti -XScopedTypeVariables :set -Wall :set -fno-warn-type-defaults From 22f8fc2ad255ee51db630e7b654a56bef003e5eb Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:31:31 +0000 Subject: [PATCH 05/14] Rename Util sub-module to Extra --- etc/etc.cabal | 4 ++-- etc/src/System/Etc.hs | 4 ++-- etc/src/System/Etc/Internal/{Util => Extra}/EnvMisspell.hs | 2 +- etc/src/System/Etc/Internal/{Util => Extra}/Printer.hs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename etc/src/System/Etc/Internal/{Util => Extra}/EnvMisspell.hs (98%) rename etc/src/System/Etc/Internal/{Util => Extra}/Printer.hs (98%) diff --git a/etc/etc.cabal b/etc/etc.cabal index d568de3..e26c5ec 100644 --- a/etc/etc.cabal +++ b/etc/etc.cabal @@ -85,8 +85,8 @@ library edit-distance exposed-modules: - System.Etc.Internal.Util.Printer - System.Etc.Internal.Util.Environment + System.Etc.Internal.Extra.Printer + System.Etc.Internal.Extra.Environment if flag(cli) cpp-options: -DWITH_CLI diff --git a/etc/src/System/Etc.hs b/etc/src/System/Etc.hs index b972051..15f4d33 100644 --- a/etc/src/System/Etc.hs +++ b/etc/src/System/Etc.hs @@ -71,8 +71,8 @@ import System.Etc.Internal.Resolver.Cli.Plain (resolvePlainCli, resolvePlainCl #endif #ifdef WITH_EXTRA -import System.Etc.Internal.Util.Printer (hPrintPrettyConfig, printPrettyConfig, renderConfig) -import System.Etc.Internal.Util.EnvMisspell +import System.Etc.Internal.Extra.Printer (hPrintPrettyConfig, printPrettyConfig, renderConfig) +import System.Etc.Internal.Extra.EnvMisspell (EnvMisspell(..), getEnvMisspellsPure, getEnvMisspells, renderEnvMisspells, hPrintEnvMisspells, printEnvMisspellingWarnings) #endif diff --git a/etc/src/System/Etc/Internal/Util/EnvMisspell.hs b/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs similarity index 98% rename from etc/src/System/Etc/Internal/Util/EnvMisspell.hs rename to etc/src/System/Etc/Internal/Extra/EnvMisspell.hs index 180c137..5c01a2a 100644 --- a/etc/src/System/Etc/Internal/Util/EnvMisspell.hs +++ b/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs @@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE NoImplicitPrelude #-} -module System.Etc.Internal.Util.EnvMisspell ( +module System.Etc.Internal.Extra.EnvMisspell ( EnvMisspell (..) , getEnvMisspells , getEnvMisspellsPure diff --git a/etc/src/System/Etc/Internal/Util/Printer.hs b/etc/src/System/Etc/Internal/Extra/Printer.hs similarity index 98% rename from etc/src/System/Etc/Internal/Util/Printer.hs rename to etc/src/System/Etc/Internal/Extra/Printer.hs index 7f2a59f..34d45c9 100644 --- a/etc/src/System/Etc/Internal/Util/Printer.hs +++ b/etc/src/System/Etc/Internal/Extra/Printer.hs @@ -1,7 +1,7 @@ {-# OPTIONS_GHC -fno-warn-deprecations #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} -module System.Etc.Internal.Util.Printer ( +module System.Etc.Internal.Extra.Printer ( renderConfig , printPrettyConfig , hPrintPrettyConfig From acee2792fa01ac8861946b51a030d8d332d06e89 Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:32:08 +0000 Subject: [PATCH 06/14] Stylish improvements --- etc/src/System/Etc.hs | 11 +++++++++-- etc/src/System/Etc/Internal/Extra/EnvMisspell.hs | 16 ++++++++-------- etc/test/System/Etc/Util/EnvMisspellTest.hs | 6 +++--- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/etc/src/System/Etc.hs b/etc/src/System/Etc.hs index 15f4d33..d3143a3 100644 --- a/etc/src/System/Etc.hs +++ b/etc/src/System/Etc.hs @@ -71,9 +71,16 @@ import System.Etc.Internal.Resolver.Cli.Plain (resolvePlainCli, resolvePlainCl #endif #ifdef WITH_EXTRA -import System.Etc.Internal.Extra.Printer (hPrintPrettyConfig, printPrettyConfig, renderConfig) import System.Etc.Internal.Extra.EnvMisspell - (EnvMisspell(..), getEnvMisspellsPure, getEnvMisspells, renderEnvMisspells, hPrintEnvMisspells, printEnvMisspellingWarnings) + ( EnvMisspell (..) + , getEnvMisspells + , getEnvMisspellsPure + , hPrintEnvMisspells + , printEnvMisspellingWarnings + , renderEnvMisspells + ) +import System.Etc.Internal.Extra.Printer + (hPrintPrettyConfig, printPrettyConfig, renderConfig) #endif import System.Etc.Internal.Config diff --git a/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs b/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs index 5c01a2a..0458506 100644 --- a/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs +++ b/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs @@ -1,6 +1,6 @@ -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} module System.Etc.Internal.Extra.EnvMisspell ( EnvMisspell (..) , getEnvMisspells @@ -12,20 +12,20 @@ module System.Etc.Internal.Extra.EnvMisspell ( import Protolude hiding ((<$>), (<>)) -import Data.Vector (Vector) +import Data.Vector (Vector) import System.Environment (getEnvironment) import qualified Data.HashMap.Strict as HashMap -import qualified Data.Text as Text -import qualified Data.Vector as Vector -import qualified Text.EditDistance as Distance +import qualified Data.Text as Text +import qualified Data.Vector as Vector +import qualified Text.EditDistance as Distance -import Text.PrettyPrint.ANSI.Leijen import System.Etc.Internal.Spec.Types +import Text.PrettyPrint.ANSI.Leijen data EnvMisspell = EnvMisspell { - currentText :: Text + currentText :: Text , suggestionText :: Text } deriving (Show, Eq, Generic) diff --git a/etc/test/System/Etc/Util/EnvMisspellTest.hs b/etc/test/System/Etc/Util/EnvMisspellTest.hs index 60b8afe..0aa31ef 100644 --- a/etc/test/System/Etc/Util/EnvMisspellTest.hs +++ b/etc/test/System/Etc/Util/EnvMisspellTest.hs @@ -1,7 +1,7 @@ +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE OverloadedLists #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE NoImplicitPrelude #-} module System.Etc.Util.EnvMisspellTest where import Protolude From 210d73975842f315f151db48713708fdae0fa013 Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:36:53 +0000 Subject: [PATCH 07/14] HLint improvements --- etc/src/System/Etc/Internal/Extra/EnvMisspell.hs | 7 ++++--- etc/test/System/Etc/Util/EnvMisspellTest.hs | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs b/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs index 0458506..74756fb 100644 --- a/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs +++ b/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs @@ -36,7 +36,7 @@ lookupSpecEnvKeys spec = foldEnvSettings val acc = case val of ConfigValue _ sources -> - maybe acc (flip Vector.cons acc) (envVar sources) + maybe acc (`Vector.cons` acc) (envVar sources) SubConfig hsh -> HashMap.foldr foldEnvSettings acc hsh in @@ -65,8 +65,9 @@ getEnvMisspellsPure spec env = do -} getEnvMisspells :: ConfigSpec a -> IO (Vector EnvMisspell) getEnvMisspells spec = - (Vector.fromList . map (Text.pack . fst)) `fmap` getEnvironment - >>= return . getEnvMisspellsPure spec + getEnvironment + & fmap (Vector.fromList . map (Text.pack . fst)) + & fmap (getEnvMisspellsPure spec) {-| diff --git a/etc/test/System/Etc/Util/EnvMisspellTest.hs b/etc/test/System/Etc/Util/EnvMisspellTest.hs index 0aa31ef..46f6582 100644 --- a/etc/test/System/Etc/Util/EnvMisspellTest.hs +++ b/etc/test/System/Etc/Util/EnvMisspellTest.hs @@ -32,10 +32,10 @@ tests = result = getEnvMisspellsPure spec ["GREEING"] - assertBool ("expecting to get a warning for typo") + assertBool "expecting to get a warning for typo" (not $ Vector.null result) - assertEqual ("expecting to get typo for key GREETING") + assertEqual "expecting to get typo for key GREETING" (EnvMisspell "GREEING" "GREETING") (Vector.head result) ] From e9b556410d9e01f8c6421d3a65f0ee3be005042a Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:44:24 +0000 Subject: [PATCH 08/14] Fix broken tests on etc --- Makefile | 2 +- etc/etc.cabal | 9 +++++++-- etc/test/System/Etc/{Util => Extra}/EnvMisspellTest.hs | 2 +- etc/test/TestSuite.hs | 4 ++-- 4 files changed, 11 insertions(+), 6 deletions(-) rename etc/test/System/Etc/{Util => Extra}/EnvMisspellTest.hs (95%) diff --git a/Makefile b/Makefile index 64a38bd..2a1fac6 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ help: ## Display this message .DEFAULT_GOAL := help TEST_RESOLVER ?= lts-8 -TEST:=stack build --resolver $(TEST_RESOLVER) --install-ghc --test --haddock --no-haddock-deps --pedantic --flag etc:yaml --flag etc:cli --flag etc:printer +TEST:=stack build --resolver $(TEST_RESOLVER) --install-ghc --test --haddock --no-haddock-deps --pedantic --flag etc:yaml --flag etc:cli --flag etc:extra test: ## Execute test suite with all compiler flags $(TEST) etc:etc-testsuite .PHONY: test diff --git a/etc/etc.cabal b/etc/etc.cabal index e26c5ec..112f80a 100644 --- a/etc/etc.cabal +++ b/etc/etc.cabal @@ -82,11 +82,11 @@ library cpp-options: -DWITH_EXTRA build-depends: ansi-wl-pprint >=0.6 && <0.7, - edit-distance + edit-distance >=0.2 && <0.3 exposed-modules: System.Etc.Internal.Extra.Printer - System.Etc.Internal.Extra.Environment + System.Etc.Internal.Extra.EnvMisspell if flag(cli) cpp-options: -DWITH_CLI @@ -133,6 +133,10 @@ test-suite etc-testsuite cpp-options: -DWITH_YAML build-depends: yaml >=0.8 && <0.9 + if flag(extra) + cpp-options: -DWITH_EXTRA + build-depends: + edit-distance >=0.2 && <0.3 other-modules: Paths_etc System.Etc.Resolver.CliTest @@ -141,5 +145,6 @@ test-suite etc-testsuite System.Etc.Resolver.DefaultTest System.Etc.Resolver.EnvTest System.Etc.Resolver.FileTest + System.Etc.Extra.EnvMisspellTest System.Etc.SpecTest default-language: Haskell2010 diff --git a/etc/test/System/Etc/Util/EnvMisspellTest.hs b/etc/test/System/Etc/Extra/EnvMisspellTest.hs similarity index 95% rename from etc/test/System/Etc/Util/EnvMisspellTest.hs rename to etc/test/System/Etc/Extra/EnvMisspellTest.hs index 46f6582..2866086 100644 --- a/etc/test/System/Etc/Util/EnvMisspellTest.hs +++ b/etc/test/System/Etc/Extra/EnvMisspellTest.hs @@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -module System.Etc.Util.EnvMisspellTest where +module System.Etc.Extra.EnvMisspellTest where import Protolude diff --git a/etc/test/TestSuite.hs b/etc/test/TestSuite.hs index 60cf8ef..ae36f79 100644 --- a/etc/test/TestSuite.hs +++ b/etc/test/TestSuite.hs @@ -19,7 +19,7 @@ import qualified System.Etc.Resolver.CliTest #endif #ifdef WITH_EXTRA -import qualified System.Etc.Util.EnvMisspellTest +import qualified System.Etc.Extra.EnvMisspellTest #endif main :: IO () @@ -35,6 +35,6 @@ main = #endif #ifdef WITH_EXTRA - , System.Etc.Util.EnvMisspellTest.tests + , System.Etc.Extra.EnvMisspellTest.tests #endif ]) From 6d2b0f8a5e3a1738be0aa87d6ed9a4927324e16a Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:53:29 +0000 Subject: [PATCH 09/14] Bump Cabal Version to 0.0.0.2 --- etc/etc.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/etc.cabal b/etc/etc.cabal index 112f80a..cf16b69 100644 --- a/etc/etc.cabal +++ b/etc/etc.cabal @@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: etc -version: 0.0.0.1 +version: 0.0.0.2 synopsis: Declarative configuration spec for Haskell projects description: Please see README.md category: Configuration, System From a45e3988c3df832e1d822d6ad707d34b1a385848 Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:54:32 +0000 Subject: [PATCH 10/14] Rename functions from misspell to misspelling --- etc/src/System/Etc.hs | 16 ++--- .../System/Etc/Internal/Extra/EnvMisspell.hs | 58 ++++++++++--------- etc/test/System/Etc/Extra/EnvMisspellTest.hs | 2 +- 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/etc/src/System/Etc.hs b/etc/src/System/Etc.hs index d3143a3..37f0ded 100644 --- a/etc/src/System/Etc.hs +++ b/etc/src/System/Etc.hs @@ -51,10 +51,10 @@ module System.Etc ( , hPrintPrettyConfig , EnvMisspell(..) - , getEnvMisspells - , getEnvMisspellsPure - , renderEnvMisspells - , hPrintEnvMisspells + , getEnvMisspellings + , getEnvMisspellingsPure + , renderEnvMisspellings + , hPrintEnvMisspellings , printEnvMisspellingWarnings #endif ) where @@ -73,11 +73,11 @@ import System.Etc.Internal.Resolver.Cli.Plain (resolvePlainCli, resolvePlainCl #ifdef WITH_EXTRA import System.Etc.Internal.Extra.EnvMisspell ( EnvMisspell (..) - , getEnvMisspells - , getEnvMisspellsPure - , hPrintEnvMisspells + , getEnvMisspellings + , getEnvMisspellingsPure + , hPrintEnvMisspellings , printEnvMisspellingWarnings - , renderEnvMisspells + , renderEnvMisspellings ) import System.Etc.Internal.Extra.Printer (hPrintPrettyConfig, printPrettyConfig, renderConfig) diff --git a/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs b/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs index 74756fb..dd61ff1 100644 --- a/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs +++ b/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs @@ -3,10 +3,10 @@ {-# LANGUAGE OverloadedStrings #-} module System.Etc.Internal.Extra.EnvMisspell ( EnvMisspell (..) - , getEnvMisspells - , getEnvMisspellsPure - , renderEnvMisspells - , hPrintEnvMisspells + , getEnvMisspellings + , getEnvMisspellingsPure + , renderEnvMisspellings + , hPrintEnvMisspellings , printEnvMisspellingWarnings ) where @@ -45,8 +45,8 @@ lookupSpecEnvKeys spec = {-| -} -getEnvMisspellsPure :: ConfigSpec a -> Vector Text -> Vector EnvMisspell -getEnvMisspellsPure spec env = do +getEnvMisspellingsPure :: ConfigSpec a -> Vector Text -> Vector EnvMisspell +getEnvMisspellingsPure spec env = do specEnvName <- lookupSpecEnvKeys spec currentEnvName <- env @@ -63,41 +63,43 @@ getEnvMisspellsPure spec env = do {-| -} -getEnvMisspells :: ConfigSpec a -> IO (Vector EnvMisspell) -getEnvMisspells spec = +getEnvMisspellings :: ConfigSpec a -> IO (Vector EnvMisspell) +getEnvMisspellings spec = getEnvironment & fmap (Vector.fromList . map (Text.pack . fst)) - & fmap (getEnvMisspellsPure spec) + & fmap (getEnvMisspellingsPure spec) {-| -} -renderEnvMisspells :: Vector EnvMisspell -> Doc -renderEnvMisspells misspells = - misspells - & Vector.map - (\misspell -> - text "WARNING: Environment variable `" - <> text (Text.unpack $ currentText misspell) - <> text "' found, perhaps you meant `" - <> text (Text.unpack $ suggestionText misspell) - <> text "'") - & Vector.foldl' (<$>) mempty - & (<$> mempty) - +renderEnvMisspellings :: Vector EnvMisspell -> Doc +renderEnvMisspellings misspells + | Vector.null misspells = + mempty + | otherwise = + misspells + & Vector.map + (\misspell -> + text "WARNING: Environment variable `" + <> text (Text.unpack $ currentText misspell) + <> text "' found, perhaps you meant `" + <> text (Text.unpack $ suggestionText misspell) + <> text "'") + & Vector.foldl' (<$>) mempty + & (<$> mempty) + & (<$> mempty) {-| -} -hPrintEnvMisspells :: Handle -> Vector EnvMisspell -> IO () -hPrintEnvMisspells h = - hPutDoc h . renderEnvMisspells - +hPrintEnvMisspellings :: Handle -> Vector EnvMisspell -> IO () +hPrintEnvMisspellings h = + hPutDoc h . renderEnvMisspellings {-| -} printEnvMisspellingWarnings :: ConfigSpec a -> IO () printEnvMisspellingWarnings spec = - getEnvMisspells spec >>= - hPrintEnvMisspells stderr + getEnvMisspellings spec >>= + hPrintEnvMisspellings stderr diff --git a/etc/test/System/Etc/Extra/EnvMisspellTest.hs b/etc/test/System/Etc/Extra/EnvMisspellTest.hs index 2866086..0843568 100644 --- a/etc/test/System/Etc/Extra/EnvMisspellTest.hs +++ b/etc/test/System/Etc/Extra/EnvMisspellTest.hs @@ -30,7 +30,7 @@ tests = let result = - getEnvMisspellsPure spec ["GREEING"] + getEnvMisspellingsPure spec ["GREEING"] assertBool "expecting to get a warning for typo" (not $ Vector.null result) From 4d0d7a397bca69bc0beee84493ea671c8c3ac833 Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:54:44 +0000 Subject: [PATCH 11/14] Update examples to warn on typos --- etc-command-example/src/Main.hs | 2 ++ etc-plain-example/src/Main.hs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/etc-command-example/src/Main.hs b/etc-command-example/src/Main.hs index 5a648f2..411b763 100644 --- a/etc-command-example/src/Main.hs +++ b/etc-command-example/src/Main.hs @@ -54,6 +54,8 @@ main = do specPath <- getDataFileName "spec.yaml" configSpec <- Etc.readConfigSpec (Text.pack specPath) + Etc.printEnvMisspellingWarnings configSpec + (configFiles, _fileWarnings) <- Etc.resolveFiles configSpec (cmd, configCli) <- Etc.resolveCommandCli configSpec configEnv <- Etc.resolveEnv configSpec diff --git a/etc-plain-example/src/Main.hs b/etc-plain-example/src/Main.hs index 7422705..50f014e 100644 --- a/etc-plain-example/src/Main.hs +++ b/etc-plain-example/src/Main.hs @@ -18,6 +18,8 @@ main = do specPath <- getDataFileName "spec.yaml" configSpec <- Etc.readConfigSpec (Text.pack specPath) + Etc.printEnvMisspellingWarnings configSpec + (configFiles, _fileWarnings) <- Etc.resolveFiles configSpec configEnv <- Etc.resolveEnv configSpec configOptParser <- Etc.resolvePlainCli configSpec From a65ef0b898a953f9e2443a73e66754a3f45a5a94 Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 21:56:49 +0000 Subject: [PATCH 12/14] Rename printEnvMisspellingWarnings to reportEnvMisspellingWarnings --- README.md | 6 ++++-- etc-command-example/src/Main.hs | 2 +- etc-plain-example/src/Main.hs | 2 +- etc/src/System/Etc.hs | 4 ++-- etc/src/System/Etc/Internal/Extra/EnvMisspell.hs | 6 +++--- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ebe8e2e..8ce73d5 100644 --- a/README.md +++ b/README.md @@ -475,8 +475,8 @@ the exact bits of functionality you need for your application. - `cli`: Provides the CLI functionality explained in this README -- `printer`: Provides helper functions for printing the resolved configuration map - with all its entries + sources +- `extra`: Provides helper functions for inspecting the resolved configuration + as well as providing warning messages for misspelled environment variables ## Full Example @@ -537,6 +537,8 @@ getConfiguration :: IO (Cmd, Etc.Config) getConfiguration = do spec <- Etc.readConfigSpec "./path/to/spec.yaml" + Etc.reportEnvMisspellingWarnings spec + let defaultConfig = Etc.resolveDefault spec diff --git a/etc-command-example/src/Main.hs b/etc-command-example/src/Main.hs index 411b763..0727f2c 100644 --- a/etc-command-example/src/Main.hs +++ b/etc-command-example/src/Main.hs @@ -54,7 +54,7 @@ main = do specPath <- getDataFileName "spec.yaml" configSpec <- Etc.readConfigSpec (Text.pack specPath) - Etc.printEnvMisspellingWarnings configSpec + Etc.reportEnvMisspellingWarnings configSpec (configFiles, _fileWarnings) <- Etc.resolveFiles configSpec (cmd, configCli) <- Etc.resolveCommandCli configSpec diff --git a/etc-plain-example/src/Main.hs b/etc-plain-example/src/Main.hs index 50f014e..f906ae1 100644 --- a/etc-plain-example/src/Main.hs +++ b/etc-plain-example/src/Main.hs @@ -18,7 +18,7 @@ main = do specPath <- getDataFileName "spec.yaml" configSpec <- Etc.readConfigSpec (Text.pack specPath) - Etc.printEnvMisspellingWarnings configSpec + Etc.reportEnvMisspellingWarnings configSpec (configFiles, _fileWarnings) <- Etc.resolveFiles configSpec configEnv <- Etc.resolveEnv configSpec diff --git a/etc/src/System/Etc.hs b/etc/src/System/Etc.hs index 37f0ded..a4e0b5f 100644 --- a/etc/src/System/Etc.hs +++ b/etc/src/System/Etc.hs @@ -55,7 +55,7 @@ module System.Etc ( , getEnvMisspellingsPure , renderEnvMisspellings , hPrintEnvMisspellings - , printEnvMisspellingWarnings + , reportEnvMisspellingWarnings #endif ) where @@ -76,7 +76,7 @@ import System.Etc.Internal.Extra.EnvMisspell , getEnvMisspellings , getEnvMisspellingsPure , hPrintEnvMisspellings - , printEnvMisspellingWarnings + , reportEnvMisspellingWarnings , renderEnvMisspellings ) import System.Etc.Internal.Extra.Printer diff --git a/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs b/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs index dd61ff1..32bb028 100644 --- a/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs +++ b/etc/src/System/Etc/Internal/Extra/EnvMisspell.hs @@ -7,7 +7,7 @@ module System.Etc.Internal.Extra.EnvMisspell ( , getEnvMisspellingsPure , renderEnvMisspellings , hPrintEnvMisspellings - , printEnvMisspellingWarnings + , reportEnvMisspellingWarnings ) where import Protolude hiding ((<$>), (<>)) @@ -99,7 +99,7 @@ hPrintEnvMisspellings h = {-| -} -printEnvMisspellingWarnings :: ConfigSpec a -> IO () -printEnvMisspellingWarnings spec = +reportEnvMisspellingWarnings :: ConfigSpec a -> IO () +reportEnvMisspellingWarnings spec = getEnvMisspellings spec >>= hPrintEnvMisspellings stderr From 19447925d65b7ba6da5cfc98b468c4ed3e623fee Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 23:15:58 +0000 Subject: [PATCH 13/14] Improve README with examples for extra functions --- README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/README.md b/README.md index 8ce73d5..bb6de23 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ these values are to be found and located in a configuration map. * [Reading From Pure Sources](#reading-from-pure-sources) * [Accessing configuration values](#accessing-configuration-values) * [Printing your configuration values](#printing-your-configuration-values) +* [Reporting Misspellings on Environment Variables](#reporting-misspellings-on-environment-variables) * [Cabal Flags](#cabal-flags) * [Full Example](#full-example) @@ -464,6 +465,48 @@ program. You an use the `System.Etc.printPrettyConfig` function to render the configuration map and the different values/sources that were resolved when calculating it. This function is _really_ useful for debugging purposes. +### Example + +Here is the output of one of +the +[example applications](https://github.com/roman/Haskell-etc/tree/master/etc-command-example): + +```bash +$ MY_APP_USERNAME=foo etc-command-example run -u bar -p 123 +Executing main program +credentials.username + bar [ Cli ] + foo [ Env: MY_APP_USERNAME ] + root [ Default ] + +credentials.password + 123 [ Cli ] +``` + +The output displays all the configuration values and their sources, the first +value on the list is the value that `System.Etc.getConfigValue` returns for that +particular key. + +## Report Misspellings on Environment Variables + +When you define `env` keys on the `etc/entries` map of your spec file, we can +infer what are the valid Environment Variables that need to be defined for your +application, knowing this, `etc` can infer when there is a typo on one of this +environment variables and report this. You need to have the `extra` cabal flag and +call the `System.Etc.reportEnvMisspellingWarnings` with the configuration spec as +as an argument. + +### Example + +Here is an example of the output this function prints to `stderr` when the given +Environment Variables are almost identical to the ones found on the spec file: + +```bash +$ MY_AP_USERNAME=foo etc-command-example run -u bar -p 123 + +WARNING: Environment variable `MY_AP_USERNAME' found, perhaps you meant `MY_APP_USERNAME' + +``` ## Cabal Flags From f1a50496f7a75b233fc696217135c95adce5123f Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Sun, 9 Apr 2017 23:21:41 +0000 Subject: [PATCH 14/14] Appease Stylish --- etc/src/System/Etc.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/src/System/Etc.hs b/etc/src/System/Etc.hs index a4e0b5f..beda31e 100644 --- a/etc/src/System/Etc.hs +++ b/etc/src/System/Etc.hs @@ -76,8 +76,8 @@ import System.Etc.Internal.Extra.EnvMisspell , getEnvMisspellings , getEnvMisspellingsPure , hPrintEnvMisspellings - , reportEnvMisspellingWarnings , renderEnvMisspellings + , reportEnvMisspellingWarnings ) import System.Etc.Internal.Extra.Printer (hPrintPrettyConfig, printPrettyConfig, renderConfig)