From 271677ec6e82a5d8fd0103e5a34998a512c360d2 Mon Sep 17 00:00:00 2001 From: Nicolas Mattia Date: Sun, 24 Nov 2019 20:21:35 +0100 Subject: [PATCH] Allow JSON attributes values with -a foo=bar --- README.md | 18 +++++++++++++----- src/Niv/Cli.hs | 45 ++++++++++++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 5cc604d..15c7caf 100644 --- a/README.md +++ b/README.md @@ -227,13 +227,17 @@ Examples: niv add my-package -v alpha-0.1 -t http://example.com/archive/.zip Usage: niv add [-n|--name NAME] PACKAGE ([-a|--attribute KEY=VAL] | - [-b|--branch BRANCH] | [-o|--owner OWNER] | [-r|--repo REPO] | - [-v|--version VERSION] | [-t|--template URL] | [-T|--type TYPE]) + [-s|--string-attribute KEY=VAL] | [-b|--branch BRANCH] | + [-o|--owner OWNER] | [-r|--repo REPO] | [-v|--version VERSION] | + [-t|--template URL] | [-T|--type TYPE]) Add dependency Available options: -n,--name NAME Set the package name to - -a,--attribute KEY=VAL Set the package spec attribute to + -a,--attribute KEY=VAL Set the package spec attribute to , where + may be JSON. + -s,--string-attribute KEY=VAL + Set the package spec attribute to . -b,--branch BRANCH Equivalent to --attribute branch= -o,--owner OWNER Equivalent to --attribute owner= -r,--repo REPO Equivalent to --attribute repo= @@ -256,13 +260,17 @@ Examples: niv update nixpkgs # update nixpkgs niv update my-package -v beta-0.2 # update my-package to version "beta-0.2" -Usage: niv update [PACKAGE] ([-a|--attribute KEY=VAL] | [-b|--branch BRANCH] | +Usage: niv update [PACKAGE] ([-a|--attribute KEY=VAL] | + [-s|--string-attribute KEY=VAL] | [-b|--branch BRANCH] | [-o|--owner OWNER] | [-r|--repo REPO] | [-v|--version VERSION] | [-t|--template URL] | [-T|--type TYPE]) Update dependencies Available options: - -a,--attribute KEY=VAL Set the package spec attribute to + -a,--attribute KEY=VAL Set the package spec attribute to , where + may be JSON. + -s,--string-attribute KEY=VAL + Set the package spec attribute to . -b,--branch BRANCH Equivalent to --attribute branch= -o,--owner OWNER Equivalent to --attribute owner= -r,--repo REPO Equivalent to --attribute repo= diff --git a/src/Niv/Cli.hs b/src/Niv/Cli.hs index 96a705f..7e534ac 100644 --- a/src/Niv/Cli.hs +++ b/src/Niv/Cli.hs @@ -11,6 +11,8 @@ module Niv.Cli where import Control.Applicative import Control.Monad import Data.Aeson ((.=)) +import Data.Bifunctor +import Data.Maybe import Data.Char (isSpace) import Data.Functor import Data.HashMap.Strict.Extended @@ -70,45 +72,57 @@ parsePackageName = PackageName <$> parsePackageSpec :: Opts.Parser PackageSpec parsePackageSpec = - (PackageSpec . HMS.fromList . fmap fixupAttributes) <$> + (PackageSpec . HMS.fromList) <$> many parseAttribute where - parseAttribute :: Opts.Parser (T.Text, T.Text) + parseAttribute :: Opts.Parser (T.Text, Aeson.Value) parseAttribute = - Opts.option (Opts.maybeReader parseKeyVal) + Opts.option (Opts.maybeReader parseKeyValJSON) ( Opts.long "attribute" <> Opts.short 'a' <> Opts.metavar "KEY=VAL" <> - Opts.help "Set the package spec attribute to " - ) <|> shortcutAttributes <|> - (("url_template",) <$> Opts.strOption + Opts.help "Set the package spec attribute to , where may be JSON." + ) <|> + Opts.option (Opts.maybeReader (parseKeyVal (Aeson.String . T.pack))) + ( Opts.long "string-attribute" <> + Opts.short 's' <> + Opts.metavar "KEY=VAL" <> + Opts.help "Set the package spec attribute to ." + ) <|> + shortcutAttributes <|> + ((\x -> ("url_template",Aeson.String x)) <$> Opts.strOption ( Opts.long "template" <> Opts.short 't' <> Opts.metavar "URL" <> Opts.help "Used during 'update' when building URL. Occurrences of are replaced with attribute 'foo'." )) <|> - (("type",) <$> Opts.strOption + ((\x -> ("type", Aeson.String x)) <$> Opts.strOption ( Opts.long "type" <> Opts.short 'T' <> Opts.metavar "TYPE" <> Opts.help "The type of the URL target. The value can be either 'file' or 'tarball'. If not set, the value is inferred from the suffix of the URL." )) - -- Parse "key=val" into ("key", "val") - parseKeyVal :: String -> Maybe (T.Text, T.Text) - parseKeyVal str = case span (/= '=') str of - (key, '=':val) -> Just (T.pack key, T.pack val) + parseKeyValJSON = parseKeyVal $ \x -> + fromMaybe (Aeson.String $ T.pack x) (Aeson.decodeStrict (B8.pack x)) + + -- Parse "key=val" into ("key", val) + parseKeyVal + :: (String -> Aeson.Value) -- ^ how to convert to JSON + -> String -> Maybe (T.Text, Aeson.Value) + parseKeyVal toJSON str = case span (/= '=') str of + (key, '=':val) -> Just (T.pack key, toJSON val) _ -> Nothing -- Shortcuts for common attributes - shortcutAttributes :: Opts.Parser (T.Text, T.Text) + shortcutAttributes :: Opts.Parser (T.Text, Aeson.Value) shortcutAttributes = foldr (<|>) empty $ mkShortcutAttribute <$> [ "branch", "owner", "repo", "version" ] -- TODO: infer those shortcuts from 'Update' keys - mkShortcutAttribute :: T.Text -> Opts.Parser (T.Text, T.Text) + mkShortcutAttribute :: T.Text -> Opts.Parser (T.Text, Aeson.Value) mkShortcutAttribute = \case - attr@(T.uncons -> Just (c,_)) -> (attr,) <$> Opts.strOption + attr@(T.uncons -> Just (c,_)) -> fmap (second Aeson.String) $ (attr,) <$> Opts.strOption ( Opts.long (T.unpack attr) <> Opts.short c <> Opts.metavar (T.unpack $ T.toUpper attr) <> @@ -120,9 +134,6 @@ parsePackageSpec = ) _ -> empty - fixupAttributes :: (T.Text, T.Text) -> (T.Text, Aeson.Value) - fixupAttributes (k, v) = (k, Aeson.String v) - parsePackage :: Opts.Parser (PackageName, PackageSpec) parsePackage = (,) <$> parsePackageName <*> parsePackageSpec