packages feed

app-settings 0.2.0.3 → 0.2.0.4

raw patch · 4 files changed

+151/−74 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

Data/AppSettings.hs view
@@ -231,6 +231,17 @@ -- --  > testList= --+--  There is also another technique that you can use if you have too long+--  lines: you can put line breaks in the setting values if you start the+--  following lines with spaces, like so:+--+--  > testList=["list1",+--  >   "list2", "list3"]+--+--   In that case don't use the ListSetting option. Also keep the leading+--   spaces consistent in the continuing lines. Note that the library will+--   automatically wrap settings longer than 80 characters when saving.+-- -- Once we declared the settings, we can read the configuration -- from disk (and your settings module should export your wrapper -- around the function offered by this library):
Data/Serialization.hs view
@@ -16,6 +16,7 @@ import Control.Exception (throwIO, Exception) import Data.Typeable (Typeable) import System.Directory (doesFileExist, copyFile)+import Control.Applicative ((<$>))  data SettingInfo = SettingInfo { value :: String, userSet :: Bool } deriving (Show, Eq) @@ -50,20 +51,42 @@ 		(a, SettingInfo {value=b, userSet=True})) configEntries  comment :: T.GenParser st ConfigElement-comment = do-	char '#'-	many $ noneOf "\r\n"-	many1 $ oneOf "\r\n"-	return Comment+comment = char '#' >> finishLine >> return Comment  configEntry :: T.GenParser st ConfigElement configEntry = do 	key <- many1 $ noneOf " \t=\r\n" 	char '='-	val <- many $ noneOf "\r\n"+	val <- finishLine+	-- so now we finished the parsing of the classical+	-- key=value, however we support a little bit more,+	-- you can do something like that:+	-- key=[1,2,+	--      3,4,+	--      5, 6]+	--  In that case the value will be+	--  "[1,2,3,4,5, 6]"+	blanks <- many $ oneOf " \t"+	fullVal <- if null blanks+		then return val+		else do+			firstExtraLine <- finishLine+			rest <- concat <$> many (lineSkipSpaces $ length blanks)+			return $ val ++ firstExtraLine ++ rest+	return $ ConfigEntry key fullVal++finishLine :: T.GenParser st String+finishLine = do+	result <- many $ noneOf "\r\n" 	many1 $ oneOf "\r\n"-	return $ ConfigEntry key val+	return result +lineSkipSpaces :: Int -> T.GenParser st String+lineSkipSpaces spaceCount = do+	count spaceCount (oneOf "\t ")+	result <- finishLine+	return result+ emptyLine :: T.GenParser st ConfigElement emptyLine = do 	many $ oneOf " \t"@@ -82,4 +105,10 @@ writeConfigEntry :: Handle -> String -> SettingInfo -> IO () writeConfigEntry handle key (SettingInfo sValue sUserSet) = do 	unless sUserSet $ hPutStr handle "# "-	hPutStrLn handle $ key ++ "=" ++ sValue+	hPutStrLn handle $ key ++ "=" ++ (wrap sValue)++wrap :: String -> String+wrap str = if null rest+		then str+		else first ++ "\n  " ++ wrap rest+	where (first, rest) = splitAt 80 str
app-settings.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                app-settings-version:             0.2.0.3+version:             0.2.0.4 synopsis:            A library to manage application settings (INI file-like) description:            A library to deal with application settings.@@ -66,6 +66,17 @@   like so:   .   > testList=+  .+  There is also another technique that you can use if you have too long+  lines: you can put line breaks in the setting values if you start the+  following lines with spaces, like so:+  .+  > testList=["list1",+  >   "list2", "list3"]+  .+  In that case don't use the ListSetting option. Also keep the leading+  spaces consistent in the continuing lines. Note that the library will+  automatically wrap setting values longer than 80 characters when saving.   .   Once we declared the settings, we can read the configuration   from disk (and your settings module should export your wrapper
tests/Tests.hs view
@@ -4,7 +4,7 @@ import Data.AppSettingsInternal  import Test.Hspec-import Test.HUnit (assertBool)+import Test.HUnit (assertBool, assertEqual)  import System.Directory (removeFile, copyFile, doesFileExist) import Control.Exception (try, SomeException)@@ -43,71 +43,73 @@ 		testInvalidFile 		testInvalidValue 		testNonExistingFile+		testReadLongSetting 	describe "save config" $ do 		testSaveUserSetAndDefaults 		createBakBeforeSaving+		wrapLongSettings 	describe "set setting" testSetListSetting  testEmptyFileDefaults :: Spec testEmptyFileDefaults = it "parses correctly an empty file with defaults" $ do-	readResult <- try $ readSettings (Path "tests/empty.config")-	case readResult of-		Right (_, GetSetting getSetting) -> do-			getSetting textSizeFromWidth `shouldBe` 0.04-			getSetting textSizeFromHeight `shouldBe` 12.4-			getSetting textFill `shouldBe` (1,1,0,1)-			getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]-			getSetting testList `shouldBe` ["list1", "list2", "list3"]-		Left (x :: SomeException) -> assertBool (show x) False+    readResult <- try $ readSettings (Path "tests/empty.config")+    case readResult of+    	Right (_, GetSetting getSetting) -> do+    		getSetting textSizeFromWidth `shouldBe` 0.04+    		getSetting textSizeFromHeight `shouldBe` 12.4+    		getSetting textFill `shouldBe` (1,1,0,1)+    		getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]+    		getSetting testList `shouldBe` ["list1", "list2", "list3"]+    	Left (x :: SomeException) -> assertBool (show x) False  testPartialFileDefaults :: Spec testPartialFileDefaults = it "parses correctly a partial file with defaults" $ do-	readResult <- try $ readSettings (Path "tests/partial.config")-	case readResult of-		Right (_, GetSetting getSetting) -> do-			getSetting textSizeFromWidth `shouldBe` 1.02-			getSetting textSizeFromHeight `shouldBe` 12.4-			getSetting textFill `shouldBe` (1,2,3,4)-			getSetting testInlineList `shouldBe` ["un", "deux"]-			getSetting testList `shouldBe` ["one", "two"]-		Left (x :: SomeException) -> assertBool (show x) False+    readResult <- try $ readSettings (Path "tests/partial.config")+    case readResult of+    	Right (_, GetSetting getSetting) -> do+    		getSetting textSizeFromWidth `shouldBe` 1.02+    		getSetting textSizeFromHeight `shouldBe` 12.4+    		getSetting textFill `shouldBe` (1,2,3,4)+    		getSetting testInlineList `shouldBe` ["un", "deux"]+    		getSetting testList `shouldBe` ["one", "two"]+    	Left (x :: SomeException) -> assertBool (show x) False  testPartialFileDefaults2 :: Spec testPartialFileDefaults2 = it "parses correctly a partial2 file with defaults" $ do-	readResult <- try $ readSettings (Path "tests/partial2.config")-	case readResult of-		Right (_, GetSetting getSetting) -> do-			getSetting textSizeFromWidth `shouldBe` 1.02-			getSetting textSizeFromHeight `shouldBe` 12.4-			getSetting textFill `shouldBe` (1,2,3,4)-			getSetting testInlineList `shouldBe` ["un", "deux"]-			getSetting testList `shouldBe` []-		Left (x :: SomeException) -> assertBool (show x) False+    readResult <- try $ readSettings (Path "tests/partial2.config")+    case readResult of+    	Right (_, GetSetting getSetting) -> do+    		getSetting textSizeFromWidth `shouldBe` 1.02+    		getSetting textSizeFromHeight `shouldBe` 12.4+    		getSetting textFill `shouldBe` (1,2,3,4)+    		getSetting testInlineList `shouldBe` ["un", "deux"]+    		getSetting testList `shouldBe` []+    	Left (x :: SomeException) -> assertBool (show x) False  testFileWithComments :: Spec testFileWithComments = it "parses correctly a partial file with comments" $ do-	readResult <- try $ readSettings (Path "tests/test-save.txt")-	case readResult of-		Right (_, GetSetting getSetting) -> do-			getSetting textSizeFromWidth `shouldBe` 1.02-			getSetting textSizeFromHeight `shouldBe` 12.4-			getSetting textFill `shouldBe` (1,2,3,4)-			getSetting testInlineList `shouldBe` ["un", "deux"]-			getSetting testList `shouldBe` ["one", "two"]-		Left (x :: SomeException) -> assertBool (show x) False+    readResult <- try $ readSettings (Path "tests/test-save.txt")+    case readResult of+    	Right (_, GetSetting getSetting) -> do+    		getSetting textSizeFromWidth `shouldBe` 1.02+    		getSetting textSizeFromHeight `shouldBe` 12.4+    		getSetting textFill `shouldBe` (1,2,3,4)+    		getSetting testInlineList `shouldBe` ["un", "deux"]+    		getSetting testList `shouldBe` ["one", "two"]+    	Left (x :: SomeException) -> assertBool (show x) False  testInvalidValue :: Spec testInvalidValue = it "parses correctly a file with invalid values" $ do-	readResult <- try $ readSettings (Path "tests/brokenvalue.config")-	case readResult of-		Right (_, GetSetting getSetting) -> do-			-- give the default for the invalid value-			getSetting textSizeFromWidth `shouldBe` 0.04-			getSetting textSizeFromHeight `shouldBe` 12.4-			getSetting textFill `shouldBe` (1,2,3,4)-			getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]-			getSetting testList `shouldBe` ["list1", "list2", "list3"]-		Left (x :: SomeException) -> assertBool (show x) False+    readResult <- try $ readSettings (Path "tests/brokenvalue.config")+    case readResult of+    	Right (_, GetSetting getSetting) -> do+    		-- give the default for the invalid value+    		getSetting textSizeFromWidth `shouldBe` 0.04+    		getSetting textSizeFromHeight `shouldBe` 12.4+    		getSetting textFill `shouldBe` (1,2,3,4)+    		getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]+    		getSetting testList `shouldBe` ["list1", "list2", "list3"]+    	Left (x :: SomeException) -> assertBool (show x) False  testNonExistingFile :: Spec testNonExistingFile = it "returns empty config for a non-existing file" $ do@@ -121,12 +123,22 @@ 			getSetting testList `shouldBe` ["list1", "list2", "list3"] 		Left (x :: SomeException) -> assertBool (show x) False +testReadLongSetting :: Spec+testReadLongSetting = it "Reads setting files with setting values wrapped over several lines" $ do+	readResult <- try $ readSettings (Path "tests/longsetting.conf") +	case readResult of +		Right (_, GetSetting getVal) -> do+			let expected = replicate 20 "longstring"+			let actual = getVal testInlineList+			assertEqual "doesn't match" expected actual+		Left (x :: SomeException) -> assertBool (show x) False+ testInvalidFile :: Spec testInvalidFile = it "reports errors properly for invalid files" $ do-	readResult <- try $ readSettings (Path "tests/broken.config")-	case readResult of-		Left (_ :: SomeException) -> assertBool "ok" True-		Right _ -> assertBool "did not get an error!" False+    readResult <- try $ readSettings (Path "tests/broken.config")+    case readResult of+    	Left (_ :: SomeException) -> assertBool "ok" True+    	Right _ -> assertBool "did not get an error!" False  testSaveUserSetAndDefaults :: Spec testSaveUserSetAndDefaults = it "saves a file with user-set and default settings" $ do@@ -153,22 +165,36 @@ 			removeFile "p.config.bak" 		Left (x :: SomeException) -> assertBool (show x) False +wrapLongSettings :: Spec+wrapLongSettings = it "wraps long settings when saving" $ do+	readResult <- try $ readSettings (Path "tests/partial.config") +	case readResult of +		Right (conf, _) -> do+			let conf1 = setSetting conf testInlineList $ replicate 20 "longstring"+			saveSettings defaultConfig (Path "xx.config") conf1+			expected <- readFile "tests/longsetting.conf"+			actual <- readFile "xx.config"+			assertEqual "doesn't match" expected actual+			removeFile "xx.config"+		Left (x :: SomeException) -> assertBool (show x) False+	+ testSetListSetting :: Spec testSetListSetting = it "overwrites correctly a list setting" $ do-	readResult <- try $ readSettings (Path "tests/empty.config")-	case readResult of-		Right (conf, GetSetting getSetting) -> do-			getSetting testList `shouldBe` ["list1", "list2", "list3"]-			getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]-			let conf0 = setSetting conf testList ["un"]-			let conf1 = setSetting conf0 testInlineList ["one"]-			getSetting' conf1 testList `shouldBe` ["un"]-			getSetting' conf1 testInlineList `shouldBe` ["one"]-			let conf2 = setSetting conf1 testList []-			let conf3 = setSetting conf2 testInlineList []-			getSetting' conf3 testList `shouldBe` []-			getSetting' conf3 testInlineList `shouldBe` []-		Left (x :: SomeException) -> assertBool (show x) False+    readResult <- try $ readSettings (Path "tests/empty.config")+    case readResult of+    	Right (conf, GetSetting getSetting) -> do+    		getSetting testList `shouldBe` ["list1", "list2", "list3"]+    		getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]+    		let conf0 = setSetting conf testList ["un"]+    		let conf1 = setSetting conf0 testInlineList ["one"]+    		getSetting' conf1 testList `shouldBe` ["un"]+    		getSetting' conf1 testInlineList `shouldBe` ["one"]+    		let conf2 = setSetting conf1 testList []+    		let conf3 = setSetting conf2 testInlineList []+    		getSetting' conf3 testList `shouldBe` []+    		getSetting' conf3 testInlineList `shouldBe` []+    	Left (x :: SomeException) -> assertBool (show x) False  testIsKeyForListSetting :: Spec testIsKeyForListSetting = it "checks correctly whether a key is attached to a list setting" $ do