add a formatContainsVar function

Also, the format function gets faster because it checks for "escaped_"
at gen time instead of every time format is called.
This commit is contained in:
Joey Hess 2020-05-19 15:35:00 -04:00
parent 224208a657
commit 30ac015b79
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38

View file

@ -1,6 +1,6 @@
{- Formatted string handling. {- Formatted string handling.
- -
- Copyright 2010, 2011 Joey Hess <id@joeyh.name> - Copyright 2010-2020 Joey Hess <id@joeyh.name>
- -
- License: BSD-2-clause - License: BSD-2-clause
-} -}
@ -9,6 +9,7 @@ module Utility.Format (
Format, Format,
gen, gen,
format, format,
formatContainsVar,
decode_c, decode_c,
encode_c, encode_c,
prop_encode_c_decode_c_roundtrip prop_encode_c_decode_c_roundtrip
@ -29,9 +30,14 @@ type FormatString = String
{- A format consists of a list of fragments. -} {- A format consists of a list of fragments. -}
type Format = [Frag] type Format = [Frag]
{- A fragment is either a constant string, {- A fragment is either a constant string, or a variable. -}
- or a variable, with a justification. -} data Frag
data Frag = Const String | Var String Justify = Const String
| Var
{ varName :: String
, varJustify :: Justify
, varEscaped :: Bool
}
deriving (Show) deriving (Show)
data Justify = LeftJustified Int | RightJustified Int | UnJustified data Justify = LeftJustified Int | RightJustified Int | UnJustified
@ -45,10 +51,8 @@ format :: Format -> Variables -> String
format f vars = concatMap expand f format f vars = concatMap expand f
where where
expand (Const s) = s expand (Const s) = s
expand (Var name j) expand (Var name j esc)
| "escaped_" `isPrefixOf` name = | esc = justify j $ encode_c_strict $ getvar name
justify j $ encode_c_strict $
getvar $ drop (length "escaped_") name
| otherwise = justify j $ getvar name | otherwise = justify j $ getvar name
getvar name = fromMaybe "" $ M.lookup name vars getvar name = fromMaybe "" $ M.lookup name vars
justify UnJustified s = s justify UnJustified s = s
@ -61,6 +65,8 @@ format f vars = concatMap expand f
- format string, such as "${foo} ${bar;10} ${baz;-10}\n" - format string, such as "${foo} ${bar;10} ${baz;-10}\n"
- -
- (This is the same type of format string used by dpkg-query.) - (This is the same type of format string used by dpkg-query.)
-
- Also, "${escaped_foo}" will apply encode_c to the value of variable foo.
-} -}
gen :: FormatString -> Format gen :: FormatString -> Format
gen = filter (not . empty) . fuse [] . scan [] . decode_c gen = filter (not . empty) . fuse [] . scan [] . decode_c
@ -94,12 +100,24 @@ gen = filter (not . empty) . fuse [] . scan [] . decode_c
| i < 0 = LeftJustified (-1 * i) | i < 0 = LeftJustified (-1 * i)
| otherwise = RightJustified i | otherwise = RightJustified i
novar v = "${" ++ reverse v novar v = "${" ++ reverse v
foundvar f v p = scan (Var (reverse v) p : f) foundvar f varname_r p =
let varname = reverse varname_r
var = if "escaped_" `isPrefixOf` varname
then Var (drop (length "escaped_") varname) p True
else Var varname p False
in scan (var : f)
empty :: Frag -> Bool empty :: Frag -> Bool
empty (Const "") = True empty (Const "") = True
empty _ = False empty _ = False
{- Check if a Format contains a variable with a specified name. -}
formatContainsVar :: String -> Format -> Bool
formatContainsVar v = any go
where
go (Var v' _ _) | v' == v = True
go _ = False
{- Decodes a C-style encoding, where \n is a newline (etc), {- Decodes a C-style encoding, where \n is a newline (etc),
- \NNN is an octal encoded character, and \xNN is a hex encoded character. - \NNN is an octal encoded character, and \xNN is a hex encoded character.
-} -}