git.iko.soy/typeable/cabal2nix
on master help sign in
Clean up the Identified type.
commit55ab8102a6de3a616b761a55f5c8e6a29e0d5a86 authorPeter Simons <simons@cryp.to> dateMon 26 Jan 2015, 12:37 (12 years ago) parent18c2240
1 file changed+32−36
src/Language/Nix/Identifier.hs+32−36
src/Language/Nix/Identifier.hs+32−36
@@ -1,6 +1,6 @@
11{-# LANGUAGE GeneralizedNewtypeDeriving #-}
22
3−module Language.Nix.Identifier ( Identifier, string, quotedString, needsQuoting ) where
3+module Language.Nix.Identifier ( Identifier(..), ident, quote, needsQuoting ) where
44
55import Data.Char
66import Data.Function
@@ -11,41 +11,37 @@ import Text.Regex.Posix
1111
1212-- | Identifiers in Nix are essentially strings. Reasonable people restrict
1313-- themselves to identifiers of the form @[a-zA-Z\_][a-zA-Z0-9\_\'\-]*@,
14−-- though, because these don't need quoting. The @Identifier@ type is an
15−-- instance of the 'IsString' class for construction. The methods of the
16−-- 'Pretty' class can be used to pretty-print an identifier with proper
17−-- quoting.
14+-- because these don't need quoting. The @Identifier@ type is an instance of
15+-- the 'IsString' class for convenience. The methods of the 'Pretty' class can
16+-- be used to pretty-print an identifier with proper quoting.
1817--
19−-- >>> let i = fromString "test" :: Identifier in (i, pPrint i)
18+-- >>> let i = Identifier "test" in (i, pPrint i)
2019-- (Identifier "test",test)
21−-- >>> let i = fromString "foo.bar" :: Identifier in (i, pPrint i)
20+-- >>> let i = Identifier "foo.bar" in (i, pPrint i)
2221-- (Identifier "foo.bar","foo.bar")
2322--
2423-- The 'Ord' instance for identifiers is unusual in that it's aware of
2524-- character's case:
2625--
27−-- >>> (fromString "abc" :: Identifier) == fromString "abc"
28−-- True
29−-- >>> (fromString "abc" :: Identifier) == fromString "ABC"
26+-- >>> Identifier "abc" == Identifier "ABC"
3027-- False
31−-- >>> (fromString "abc" :: Identifier) > fromString "ABC"
28+-- >>> Identifier "abc" > Identifier "ABC"
3229-- True
33−-- >>> (fromString "abc" :: Identifier) > fromString "ABC"
30+-- >>> Identifier "abc" > Identifier "ABC"
3431-- True
35−-- >>> (fromString "X" :: Identifier) > fromString "a"
32+-- >>> Identifier "X" > Identifier "a"
3633-- True
37−-- >>> (fromString "x" :: Identifier) > fromString "A"
34+-- >>> Identifier "x" > Identifier "A"
3835-- True
3936--
4037-- prop> \str -> Identifier str == Identifier str
4138-- prop> \str -> any (`elem` ['a'..'z']) str ==> Identifier (map toLower str) /= Identifier (map toUpper str)
42−-- prop> \(NonEmpty str) -> head str `elem` ['a'..'z'] ==> Identifier (map toLower str) >= Identifier (map toUpper str)
4339
4440newtype Identifier = Identifier String
4541 deriving (Show, Eq, IsString)
4642
4743instance Pretty Identifier where
48− pPrint i = text (i ^. string)
44+ pPrint i = text (i ^. ident . to quote)
4945
5046instance Ord Identifier where
5147 compare (Identifier a) (Identifier b) =
@@ -53,33 +49,33 @@ instance Ord Identifier where
5349 EQ -> compare a b
5450 r -> r
5551
56−needsQuoting :: Identifier -> Bool
57−needsQuoting (Identifier str) = not (str =~ "^[a-zA-Z\\_][a-zA-Z0-9\\_\\'\\-]*$")
52+-- | Checks whether a given string would need quoting when interpreted as an
53+-- intentifier.
5854
59−-- | Lens that allows conversion from/to the standard 'String' type.
60−--
61−-- >>> putStrLn $ fromString "abc" ^. string
62−-- abc
55+needsQuoting :: String -> Bool
56+needsQuoting str = not (str =~ grammar)
57+ where grammar :: String -- TODO: should be a compiled regular expression
58+ grammar = "^[a-zA-Z\\_][a-zA-Z0-9\\_\\'\\-]*$"
59+
60+-- | Lens that allows conversion from/to the standard 'String' type. The setter
61+-- does not evaluate its input, so it's safe to use with 'undefined'.
6362--
64−-- >>> putStrLn $ fromString "abc.def" ^. string
65−-- "abc.def"
63+-- >>> putStrLn $ Identifier "abc.def" ^. ident
64+-- abc.def
6665--
67−-- >>> pPrint $ fromString "" & string .~ "abcdef"
66+-- >>> pPrint $ undefined & ident .~ "abcdef"
6867-- abcdef
6968
70−string :: Lens' Identifier String
71−string f (Identifier str) = (\str' -> fromString str') `fmap` f s
72− where s = if needsQuoting (Identifier str) then show str else str
69+ident :: Lens' Identifier String
70+ident f (Identifier str) = Identifier `fmap` f str
7371
74−-- | A variant of 'string' that gives read-only access to a string-representation
75−-- of the identifier that is always quoted, even if the identifier actually
76−-- doesn't need quoting.
72+-- | Help function that quotes a given identifier string (if necessary).
7773--
78−-- >>> putStrLn $ fromString "abc" ^. quotedString
79−-- "abc"
74+-- >>> putStrLn (quote "abc")
75+-- abc
8076--
81−-- >>> putStrLn $ fromString "abc.def" ^. quotedString
77+-- >>> putStrLn (quote "abc.def")
8278-- "abc.def"
8379
84−quotedString :: Getter Identifier String
85−quotedString f (Identifier str) = fmap fromString (f (show str))
80+quote :: String -> String
81+quote s = if needsQuoting s then show s else s