hnix 0.3.4 → 0.4.0
raw patch · 12 files changed
+157/−32 lines, 12 filesdep +regex-tdfadep +regex-tdfa-textdep ~data-fixPVP ok
version bump matches the API change (PVP)
Dependencies added: regex-tdfa, regex-tdfa-text
Dependency ranges changed: data-fix
API changes (from Hackage documentation)
+ Nix.Eval: NVEnvPath :: FilePath -> NValueF m r
- Nix.Expr: Columns :: {-# UNPACK #-} ~Int64 -> {-# UNPACK #-} ~Int64 -> Delta
+ Nix.Expr: Columns :: {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> Delta
- Nix.Expr: Directed :: ~ByteString -> {-# UNPACK #-} ~Int64 -> {-# UNPACK #-} ~Int64 -> {-# UNPACK #-} ~Int64 -> {-# UNPACK #-} ~Int64 -> Delta
+ Nix.Expr: Directed :: !ByteString -> {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> Delta
- Nix.Expr: Lines :: {-# UNPACK #-} ~Int64 -> {-# UNPACK #-} ~Int64 -> {-# UNPACK #-} ~Int64 -> {-# UNPACK #-} ~Int64 -> Delta
+ Nix.Expr: Lines :: {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> Delta
- Nix.Expr: Tab :: {-# UNPACK #-} ~Int64 -> {-# UNPACK #-} ~Int64 -> {-# UNPACK #-} ~Int64 -> Delta
+ Nix.Expr: Tab :: {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> Delta
Files
- LICENSE +23/−16
- Nix/Eval.hs +4/−1
- Nix/Expr/Shorthands.hs +15/−2
- Nix/Expr/Types.hs +21/−1
- Nix/Parser.hs +3/−3
- Nix/Pretty.hs +1/−1
- hnix.cabal +5/−1
- main/Main.hs +6/−7
- tests/Main.hs +4/−0
- tests/ParserTests.hs +8/−0
- tests/PrettyTests.hs +28/−0
- tests/ShorthandTests.hs +39/−0
LICENSE view
@@ -1,19 +1,26 @@-opyright (c) 2014 John Wiegley+Copyright (c) 2014, John Wiegley All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy-of this software and associated documentation files (the "Software"), to deal-in the Software without restriction, including without limitation the rights-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell-copies of the Software, and to permit persons to whom the Software is-furnished to do so, subject to the following conditions:+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met: -The above copyright notice and this permission notice shall be included in-all copies or substantial portions of the Software.+1. Redistributions of source code must retain the above copyright notice, this+list of conditions and the following disclaimer. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN-THE SOFTWARE.+2. Redistributions in binary form must reproduce the above copyright notice,+this list of conditions and the following disclaimer in the documentation+and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its contributors+may be used to endorse or promote products derived from this software without+specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Nix/Eval.hs view
@@ -30,6 +30,7 @@ | NVSet (Map.Map Text r) | NVFunction (Params r) (NValue m -> m r) | NVLiteralPath FilePath+ | NVEnvPath FilePath deriving (Generic, Typeable, Functor) instance Show f => Show (NValueF m f) where@@ -40,6 +41,7 @@ go (NVSet attrs) = showsCon1 "NVSet" attrs go (NVFunction r _) = showsCon1 "NVFunction" r go (NVLiteralPath p) = showsCon1 "NVLiteralPath" p+ go (NVEnvPath p) = showsCon1 "NVEnvPath" p showsCon1 :: Show a => String -> a -> Int -> String -> String showsCon1 con a d = showParen (d > 10) $ showString (con ++ " ") . showsPrec 11 a@@ -54,6 +56,7 @@ phi (NVSet _) = error "Cannot coerce a set to a string" phi (NVFunction _ _) = error "Cannot coerce a function to a string" phi (NVLiteralPath p) = Text.pack p+ phi (NVEnvPath p) = Text.pack p buildArgument :: Params (NValue m) -> NValue m -> NValue m buildArgument paramSpec arg = either error (Fix . NVSet) $ case paramSpec of@@ -79,7 +82,7 @@ phi (NConstant x) = const $ return $ Fix $ NVConstant x phi (NStr str) = fmap (Fix . NVStr) . flip evalString str phi (NLiteralPath p) = const $ return $ Fix $ NVLiteralPath p- phi (NEnvPath _) = error "Path expressions are not yet supported"+ phi (NEnvPath p) = const $ return $ Fix $ NVEnvPath p phi (NUnary op arg) = \env -> arg env >>= \case Fix (NVConstant c) -> pure $ Fix $ NVConstant $ case (op, c) of
Nix/Expr/Shorthands.hs view
@@ -11,6 +11,8 @@ import qualified Data.Map as Map import Nix.Atoms import Nix.Expr.Types+import Text.Regex.TDFA.Text ()+import Text.Regex.TDFA ((=~)) -- | Make an integer literal expression. mkInt :: Integer -> NExpr@@ -126,10 +128,21 @@ mkFunction params = Fix . NAbs params mkDot :: NExpr -> Text -> NExpr-mkDot e key = Fix $ NSelect e [StaticKey key] Nothing+mkDot e key = mkDots e [key] mkDots :: NExpr -> [Text] -> NExpr-mkDots e keys = Fix $ NSelect e (StaticKey <$> keys) Nothing+mkDots e keys = Fix $ NSelect e (toKey <$> keys) Nothing+ where+ toKey :: Text -> NKeyName NExpr+ toKey k = (if isPlainSymbol k then StaticKey else dynamicKey) k+ -- | Make a dynamic key name that is only enclosed in double quotes+ -- (no antiquotes).+ dynamicKey :: Text -> NKeyName NExpr+ dynamicKey k = DynamicKey $ Plain $ DoubleQuoted [Plain k]+ -- | Check if it’s a valid nix symbol+ -- the nix lexer regex for IDs (symbols) is [a-zA-Z\_][a-zA-Z0-9\_\'\-]*+ isPlainSymbol :: Text -> Bool+ isPlainSymbol s = s =~ ("^[a-zA-Z_][a-zA-Z0-9_'-]*$" :: Text) -- | An `inherit` clause without an expression to pull from. inherit :: [NKeyName e] -> Binding e
Nix/Expr/Types.hs view
@@ -12,9 +12,10 @@ import Control.Monad hiding (forM_, mapM, sequence) import Data.Data+import Data.Eq.Deriving import Data.Fix import Data.Foldable-import Data.Functor.Classes (Show1(..), showsUnaryWith, liftShowsPrec2)+import Data.Functor.Classes (Eq1(..), Eq2(..), Show1(..), showsUnaryWith, liftShowsPrec2) import Data.Map (Map, toList) import Data.Text (Text, pack) import Data.Traversable@@ -116,6 +117,13 @@ deriving (Ord, Eq, Generic, Typeable, Data, Functor, Show, Foldable, Traversable) +instance Eq1 ParamSet where+ liftEq eq (FixedParamSet a) (FixedParamSet b) =+ liftEq (liftEq (liftEq eq)) (Data.Map.toList a) (Data.Map.toList b)+ liftEq eq (VariadicParamSet a) (VariadicParamSet b) =+ liftEq (liftEq (liftEq eq)) (Data.Map.toList a) (Data.Map.toList b)+ liftEq _ _ _ = False+ -- It's not possible to derive this automatically as there is no Show1 instance -- for Map. We define one locally here. instance Show1 ParamSet where@@ -187,6 +195,11 @@ instance IsString (NKeyName r) where fromString = StaticKey . fromString +instance Eq1 NKeyName where+ liftEq eq (DynamicKey a) (DynamicKey b) = liftEq2 (liftEq eq) eq a b+ liftEq _ (StaticKey a) (StaticKey b) = a == b+ liftEq _ _ _ = False+ -- Deriving this instance automatically is not possible because @r@ -- occurs not only as last argument in @Antiquoted (NString r) r@ instance Show1 NKeyName where@@ -243,6 +256,13 @@ paramName :: Params r -> Maybe Text paramName (Param n) = Just n paramName (ParamSet _ n) = n++$(deriveEq1 ''NExprF)+$(deriveEq1 ''NString)+$(deriveEq1 ''Binding)+$(deriveEq1 ''Params)+$(deriveEq1 ''Antiquoted)+$(deriveEq2 ''Antiquoted) $(deriveShow1 ''NExprF) $(deriveShow1 ''NString)
Nix/Parser.hs view
@@ -105,11 +105,11 @@ nixBool :: Parser NExprLoc nixBool = annotateLocation1 $ try (true <|> false) <?> "bool" where- true = mkBoolF True <$ symbol "true"- false = mkBoolF False <$ symbol "false"+ true = mkBoolF True <$ reserved "true"+ false = mkBoolF False <$ reserved "false" nixNull :: Parser NExprLoc-nixNull = annotateLocation1 $ mkNullF <$ try (symbol "null") <?> "null"+nixNull = annotateLocation1 $ mkNullF <$ try (reserved "null") <?> "null" nixParens :: Parser NExprLoc nixParens = parens nixExprLoc <?> "parens"
Nix/Pretty.hs view
@@ -70,7 +70,7 @@ f ([Plain t] : xs) | Text.null (strip t) = xs f xs = xs prettyLine = hcat . map prettyPart- prettyPart (Plain t) = text . unpack . replace "$" "''$" . replace "''" "'''" $ t+ prettyPart (Plain t) = text . unpack . replace "${" "''${" . replace "''" "'''" $ t prettyPart (Antiquoted r) = text "$" <> braces (withoutParens r) prettyParams :: Params NixDoc -> Doc
hnix.cabal view
@@ -1,5 +1,5 @@ Name: hnix-Version: 0.3.4+Version: 0.4.0 Synopsis: Haskell implementation of the Nix language Description: Haskell implementation of the Nix language.@@ -62,6 +62,8 @@ , data-fix , deepseq , semigroups >= 0.18 && < 0.19+ , regex-tdfa+ , regex-tdfa-text if flag(parsec) Cpp-options: -DUSE_PARSEC Build-depends: parsec@@ -105,6 +107,8 @@ Other-modules: ParserTests EvalTests+ ShorthandTests+ PrettyTests Build-depends: base >= 4.3 && < 5 , containers
main/Main.hs view
@@ -3,21 +3,20 @@ import Nix.Parser import Nix.Pretty+import Nix.Expr import System.Environment import System.IO import Text.PrettyPrint.ANSI.Leijen nix :: FilePath -> IO ()-nix path = do- res <- parseNixFile path- case res of- Failure e -> hPutStrLn stderr $ "Parse failed: " ++ show e- Success n -> do- displayIO stdout $ renderPretty 0.4 80 (prettyNix n)+nix path = parseNixFile path >>= displayNExpr nixString :: String -> IO ()-nixString s = case parseNixString s of+nixString = displayNExpr . parseNixString++displayNExpr :: Result NExpr -> IO ()+displayNExpr = \case Success n -> displayIO stdout $ renderPretty 0.4 80 (prettyNix n) Failure e -> hPutStrLn stderr $ "Parse failed: " ++ show e
tests/Main.hs view
@@ -4,6 +4,8 @@ import qualified ParserTests import qualified EvalTests+import qualified ShorthandTests+import qualified PrettyTests import Prelude (IO, ($)) @@ -11,4 +13,6 @@ main = defaultMain $ testGroup "hnix" [ ParserTests.tests , EvalTests.tests+ , ShorthandTests.tests+ , PrettyTests.tests ]
tests/ParserTests.hs view
@@ -220,6 +220,14 @@ assertParseFail ".a" assertParseFail "'a" +case_identifier_keyword_prefix :: Assertion+case_identifier_keyword_prefix = do+ assertParseString "true-name" $ mkSym "true-name"+ assertParseString "trueName" $ mkSym "trueName"+ assertParseString "null-name" $ mkSym "null-name"+ assertParseString "nullName" $ mkSym "nullName"+ assertParseString "[ null-name ]" $ mkList [ mkSym "null-name" ]+ makeStringParseTest :: String -> Assertion makeStringParseTest str = assertParseString ("\"" ++ str ++ "\"") $ mkStr $ pack str
+ tests/PrettyTests.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}+module PrettyTests (tests) where++import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.TH++import Nix.Expr+import Nix.Pretty++case_indented_antiquotation :: Assertion+case_indented_antiquotation = do+ assertPretty (mkIndentedStr "echo $foo") "''echo $foo''"+ assertPretty (mkIndentedStr "echo ${foo}") "''echo ''${foo}''"++case_string_antiquotation :: Assertion+case_string_antiquotation = do+ -- TODO: plain $ doesn't need to be escaped here either+ assertPretty (mkStr "echo $foo") "\"echo \\$foo\""+ assertPretty (mkStr "echo ${foo}") "\"echo \\${foo}\""++tests :: TestTree+tests = $testGroupGenerator++--------------------------------------------------------------------------------+assertPretty :: NExpr -> String -> Assertion+assertPretty e s = assertEqual ("When pretty-printing " ++ show e) s . show $ prettyNix e
+ tests/ShorthandTests.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE TemplateHaskell, OverloadedStrings #-}+module ShorthandTests (tests) where++import Prelude++import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.TH++import Control.Monad (forM_)+import Data.Monoid ((<>))+import Data.Fix++import Nix.Expr+++case_mkDotsSymbolEscaping :: Assertion+case_mkDotsSymbolEscaping = do+ let check xs errmsg assert =+ forM_ xs $ \x -> assertBool (errmsg <> ": " <> show x) $ assert x+ check plain "not a plain value" $ assertIsSingle+ check nonPlain "not a non-plain value" $ not . assertIsSingle+ where+ plain = [ "abc09", "_A_'-", "AbC" ]+ nonPlain = [ "abc def", "\\", "'abc", "\"", "-foo", "a.b.c" ]+ assertIsSingle = isPlainSingle . getKey . mkDot "dummy"+ getKey (Fix (NSelect _ [key] _)) = key+ getKey _ = error "invalid"+ isPlainSingle (StaticKey _) = True+ isPlainSingle (DynamicKey (Plain (DoubleQuoted [Plain _]))) = False+ isPlainSingle _ = error "invalid"+++---------------------------++tests :: TestTree+tests = $(testGroupGenerator)++