1{-# LANGUAGE DeriveGeneric #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4module Language.Nix.Identifier ( Identifier, ident, quote, needsQuoting ) where
6import Control.DeepSeq.Generics
8import Distribution.Nixpkgs.Util.PrettyPrinting ( Pretty(..), text )
9import GHC.Generics ( Generic )
11import Text.Regex.Posix
13-- | Identifiers in Nix are essentially strings. Reasonable people restrict
14-- themselves to identifiers of the form @[a-zA-Z\_][a-zA-Z0-9\_\'\-]*@,
15-- because these don't need quoting. The @Identifier@ type is an instance of
16-- the 'IsString' class for convenience. The methods of the 'Pretty' class can
17-- be used to pretty-print an identifier with proper quoting.
19-- >>> let i = Identifier "test" in (i, pPrint i)
20-- (Identifier "test",test)
21-- >>> let i = Identifier "foo.bar" in (i, pPrint i)
22-- (Identifier "foo.bar","foo.bar")
24newtype Identifier = Identifier String
25 deriving (Show, Eq, IsString, Generic)
27instance Default Identifier where def = Identifier ""
29instance Pretty Identifier where
30 pPrint i = text (i ^. ident . to quote)
32instance Ord Identifier where
33 compare (Identifier a) (Identifier b) = compare a b
35instance NFData Identifier where rnf = genericRnf
37-- | Checks whether a given string would need quoting when interpreted as an
40needsQuoting :: String -> Bool
41needsQuoting str = not (str =~ grammar)
42 where grammar :: String -- TODO: should be a compiled regular expression
43 grammar = "^[a-zA-Z\\_][a-zA-Z0-9\\_\\'\\-]*$"
45-- | Lens that allows conversion from/to the standard 'String' type. The setter
46-- does not evaluate its input, so it's safe to use with 'undefined'.
48-- >>> putStrLn $ Identifier "abc.def" ^. ident
51-- >>> pPrint $ undefined & ident .~ "abcdef"
54ident :: Lens' Identifier String
55ident f (Identifier str) = Identifier `fmap` f str
57-- | Helper function to quote a given identifier string if necessary.
59-- >>> putStrLn (quote "abc")
62-- >>> putStrLn (quote "abc.def")
65quote :: String -> String
66quote 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