diff --git a/hledger-lib/Hledger.hs b/hledger-lib/Hledger.hs index 089df4ffb..8ff39b5f9 100644 --- a/hledger-lib/Hledger.hs +++ b/hledger-lib/Hledger.hs @@ -17,4 +17,5 @@ tests_Hledger = TestList ,tests_Hledger_Query ,tests_Hledger_Read ,tests_Hledger_Reports + ,tests_Hledger_Utils ] diff --git a/hledger-lib/Hledger/Utils.hs b/hledger-lib/Hledger/Utils.hs index ef94797c1..41fb48129 100644 --- a/hledger-lib/Hledger/Utils.hs +++ b/hledger-lib/Hledger/Utils.hs @@ -33,6 +33,8 @@ module Hledger.Utils (---- provide these frequently used modules - or not, for c -- the rest need to be done in each module I think ) where +import Test.HUnit + import Control.Monad (liftM, when) -- import Data.Char import Data.Default @@ -212,3 +214,8 @@ sequence' ms = do {-# INLINABLE mapM' #-} mapM' :: Monad f => (a -> f b) -> [a] -> f [b] mapM' f = sequence' . map f + +tests_Hledger_Utils :: Test +tests_Hledger_Utils = TestList [ + tests_Hledger_Utils_Text + ] \ No newline at end of file diff --git a/hledger-lib/Hledger/Utils/Text.hs b/hledger-lib/Hledger/Utils/Text.hs index 07e45408e..e84fed92b 100644 --- a/hledger-lib/Hledger/Utils/Text.hs +++ b/hledger-lib/Hledger/Utils/Text.hs @@ -53,9 +53,11 @@ module Hledger.Utils.Text -- fitString, -- fitStringMulti, textPadLeftWide, - textPadRightWide + textPadRightWide, + tests_Hledger_Utils_Text ) where +import Test.HUnit -- import Data.Char import Data.List @@ -124,7 +126,7 @@ textElideRight width t = quoteIfSpaced :: T.Text -> T.Text quoteIfSpaced s | isSingleQuoted s || isDoubleQuoted s = s | not $ any (`elem` (T.unpack s)) whitespacechars = s - | otherwise = "'"<>escapeSingleQuotes s<>"'" + | otherwise = quoteIfNeeded s -- -- | Wrap a string in double quotes, and \-prefix any embedded single -- -- quotes, if it contains whitespace and is not already single- or @@ -136,9 +138,9 @@ quoteIfSpaced s | isSingleQuoted s || isDoubleQuoted s = s -- -- | Double-quote this string if it contains whitespace, single quotes -- -- or double-quotes, escaping the quotes as needed. --- quoteIfNeeded :: T.Text -> T.Text --- quoteIfNeeded s | any (`elem` T.unpack s) (quotechars++whitespacechars) = "\"" <> escapeDoubleQuotes s <> "\"" --- | otherwise = s +quoteIfNeeded :: T.Text -> T.Text +quoteIfNeeded s | any (`elem` T.unpack s) (quotechars++whitespacechars) = "\"" <> escapeDoubleQuotes s <> "\"" + | otherwise = s -- -- | Single-quote this string if it contains whitespace or double-quotes. -- -- No good for strings containing single quotes. @@ -151,10 +153,10 @@ quotechars = "'\"" whitespacechars = " \t\n\r" escapeDoubleQuotes :: T.Text -> T.Text -escapeDoubleQuotes = T.replace "\"" "\"" +escapeDoubleQuotes = T.replace "\"" "\\\"" -escapeSingleQuotes :: T.Text -> T.Text -escapeSingleQuotes = T.replace "'" "\'" +-- escapeSingleQuotes :: T.Text -> T.Text +-- escapeSingleQuotes = T.replace "'" "\'" -- escapeQuotes :: String -> String -- escapeQuotes = regexReplace "([\"'])" "\\1" @@ -295,7 +297,7 @@ difforzero a b = maximum [(a - b), 0] -- It clips and pads on the right when the fourth argument is true, otherwise on the left. -- It treats wide characters as double width. fitText :: Maybe Int -> Maybe Int -> Bool -> Bool -> Text -> Text -fitText mminwidth mmaxwidth ellipsify rightside s = (clip . pad) s +fitText mminwidth mmaxwidth ellipsify rightside = clip . pad where clip :: Text -> Text clip s = @@ -416,3 +418,13 @@ textWidth s = maximum $ map (T.foldr (\a b -> charWidth a + b) 0) $ T.lines s -- | c >= '\x20000' && c <= '\x3FFFD' -> 2 -- | otherwise -> 1 + +tests_Hledger_Utils_Text = TestList [ + quoteIfSpaced "a'a" ~?= "a'a" + , quoteIfSpaced "a\"a" ~?= "a\"a" + , quoteIfSpaced "a a" ~?= "\"a a\"" + , quoteIfSpaced "mimi's cafe" ~?= "\"mimi's cafe\"" + , quoteIfSpaced "\"alex\" cafe" ~?= "\"\\\"alex\\\" cafe\"" + , quoteIfSpaced "le'shan's cafe" ~?= "\"le'shan's cafe\"" + , quoteIfSpaced "\"be'any's\" cafe" ~?= "\"\\\"be'any's\\\" cafe\"" + ] \ No newline at end of file