1{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3module Language.Nix.Identifier ( Identifier(..), ident, quote, needsQuoting ) where
7import Data.Function ( on )
9import Distribution.Nixpkgs.Util.PrettyPrinting ( Pretty(..), text )
10import Text.Regex.Posix
12-- | Identifiers in Nix are essentially strings. Reasonable people restrict
13-- themselves to identifiers of the form @[a-zA-Z\_][a-zA-Z0-9\_\'\-]*@,
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.
18-- >>> let i = Identifier "test" in (i, pPrint i)
19-- (Identifier "test",test)
20-- >>> let i = Identifier "foo.bar" in (i, pPrint i)
21-- (Identifier "foo.bar","foo.bar")
23-- The 'Ord' instance for identifiers is unusual in that it's aware of
26-- >>> Identifier "abc" == Identifier "ABC"
28-- >>> Identifier "abc" > Identifier "ABC"
30-- >>> Identifier "abc" > Identifier "ABC"
32-- >>> Identifier "X" > Identifier "a"
34-- >>> Identifier "x" > Identifier "A"
37-- prop> \str -> Identifier str == Identifier str
38-- prop> \str -> any (`elem` ['a'..'z']) str ==> Identifier (map toLower str) /= Identifier (map toUpper str)
40newtype Identifier = Identifier String
41 deriving (Show, Eq, IsString)
43instance Pretty Identifier where
44 pPrint i = text (i ^. ident . to quote)
46instance Ord Identifier where
47 compare (Identifier a) (Identifier b) =
48 case (compare `on` map toLower) a b of
52-- | Checks whether a given string would need quoting when interpreted as an
55needsQuoting :: String -> Bool
56needsQuoting str = not (str =~ grammar)
57 where grammar :: String -- TODO: should be a compiled regular expression
58 grammar = "^[a-zA-Z\\_][a-zA-Z0-9\\_\\'\\-]*$"
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'.
63-- >>> putStrLn $ Identifier "abc.def" ^. ident
66-- >>> pPrint $ undefined & ident .~ "abcdef"
69ident :: Lens' Identifier String
70ident f (Identifier str) = Identifier `fmap` f str
72-- | Help function that quotes a given identifier string (if necessary).
74-- >>> putStrLn (quote "abc")
77-- >>> putStrLn (quote "abc.def")
80quote :: String -> String
81quote s = if needsQuoting s then show s else s
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list