From 41aeca6a8caf1a489ef6dae86c1de28da64f3e42 Mon Sep 17 00:00:00 2001 From: Gabriel Volpe Date: Thu, 6 Aug 2020 23:25:35 +0200 Subject: [PATCH] Support for stdin & stdout support --- README.md | 16 ++++++++++++--- app/Main.hs | 26 ++++++++++++++++------- src/CommandLine.hs | 51 ++++++++++++++++++++++++++++++++-------------- src/DConf2Nix.hs | 34 +++++++++++++++++++++++-------- 4 files changed, 93 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index c62f398..85b82b5 100644 --- a/README.md +++ b/README.md @@ -84,18 +84,28 @@ Once compiled and installed (via `nix-build` or `cabal new-install`), you can us dconf2nix -i data/dconf.settings -o output/dconf.nix ``` +It is also possible to pipe the standard input to `dconf2nix` and expect the result in the standard output: + +```shell +dconf dump / | dconf2nix > dconf.nix +``` + Type `--help` for some more information. ```shell -dconf2nix - Convert dconf files to Nix +dconf2nix - Nixify dconf configuration files -Usage: dconf2nix [-v|--version] (-i|--input ARG) (-o|--output ARG) - [-t|--timeout ARG] [--verbose] +Usage: dconf2nix [-v|--version] + [[-t|--timeout ARG] [--verbose] | (-i|--input ARG) + (-o|--output ARG) [-t|--timeout ARG] [--verbose]] Convert a dconf file into a Nix file, as expected by Home Manager. Available options: -h,--help Show this help text -v,--version Show the current version + -t,--timeout ARG Timeout in seconds for the conversion + process (default: 5) + --verbose Verbose mode (debug) -i,--input ARG Path to the dconf file (input) -o,--output ARG Path to the Nix output file (to be created) -t,--timeout ARG Timeout in seconds for the conversion diff --git a/app/Main.hs b/app/Main.hs index 9568c74..a780624 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -2,11 +2,18 @@ module Main where -import CommandLine ( Args(..) +import CommandLine ( FileArgs(..) + , Input(..) + , StdinArgs(..) , runArgs ) -import DConf.Data ( ProcessTimeout(..) ) -import DConf2Nix ( dconf2nix ) +import Data.Foldable ( traverse_ ) +import DConf.Data ( ProcessTimeout(..) + , Verbosity(..) + ) +import DConf2Nix ( dconf2nixFile + , dconf2nixStdin + ) import System.Timeout ( timeout ) timeoutMessage = unlines @@ -17,9 +24,14 @@ timeoutMessage = unlines , " ⛔ If the issue persists, run it again using --verbose and report the issue on Github. Sorry 😞." ] +dconf2nix :: ProcessTimeout -> IO () -> Maybe String -> IO () +dconf2nix (ProcessTimeout t) fa successMsg = timeout (t * 1000000) fa >>= \case + Just _ -> traverse_ putStrLn successMsg + Nothing -> error timeoutMessage + main :: IO () main = runArgs >>= \case - (Args i o (ProcessTimeout t) v) -> - timeout (t * 1000000) (dconf2nix i o v) >>= \case - Just _ -> putStrLn "🚀 Successfully Nixified! ❄️" - Nothing -> error timeoutMessage + FileInput (FileArgs i o t v) -> + dconf2nix t (dconf2nixFile i o v) (Just "🚀 Successfully Nixified! ❄️") + StdinInput (StdinArgs t v) -> + dconf2nix t (dconf2nixStdin v) Nothing diff --git a/src/CommandLine.hs b/src/CommandLine.hs index 2327bbe..7ba1e02 100644 --- a/src/CommandLine.hs +++ b/src/CommandLine.hs @@ -1,5 +1,7 @@ module CommandLine - ( Args(..) + ( FileArgs(..) + , Input(..) + , StdinArgs(..) , runArgs ) where @@ -13,16 +15,35 @@ import DConf.Data ( InputFilePath(..) import Options.Applicative import Paths_dconf2nix ( version ) -data Args = Args +data Input = FileInput FileArgs | StdinInput StdinArgs + +data FileArgs = FileArgs { input :: InputFilePath , output :: OutputFilePath , processTimeout :: ProcessTimeout , verbose :: Verbosity } -args :: Parser Args -args = - Args +data StdinArgs = StdinArgs + { stdinTimeout :: ProcessTimeout + , stdinVerbose :: Verbosity + } + +timeoutArgs :: Parser ProcessTimeout +timeoutArgs = ProcessTimeout <$> option + auto + (long "timeout" <> short 't' <> showDefault <> value 5 <> help + "Timeout in seconds for the conversion process" + ) + +verbosityArgs :: Parser Verbosity +verbosityArgs = + flag Normal Verbose (long "verbose" <> help "Verbose mode (debug)") + +fileArgs :: Parser Input +fileArgs = + fmap FileInput + $ FileArgs <$> (InputFilePath <$> strOption (long "input" <> short 'i' <> help "Path to the dconf file (input)") ) @@ -31,12 +52,11 @@ args = "Path to the Nix output file (to be created)" ) ) - <*> (ProcessTimeout <$> option auto - (long "timeout" <> short 't' <> showDefault <> value 5 <> help - "Timeout in seconds for the conversion process" - ) - ) - <*> flag Normal Verbose (long "verbose" <> help "Verbose mode (debug)") + <*> timeoutArgs + <*> verbosityArgs + +stdinArgs :: Parser Input +stdinArgs = StdinInput <$> (StdinArgs <$> timeoutArgs <*> verbosityArgs) versionInfo :: String versionInfo = unlines @@ -54,16 +74,17 @@ versionInfo = unlines ] versionOpt :: Parser (a -> a) -versionOpt = infoOption versionInfo +versionOpt = infoOption + versionInfo (long "version" <> short 'v' <> help "Show the current version") -runArgs :: IO Args +runArgs :: IO Input runArgs = execParser opts where opts = info - (helper <*> versionOpt <*> args) + (helper <*> versionOpt <*> (stdinArgs <|> fileArgs)) ( fullDesc <> progDesc "Convert a dconf file into a Nix file, as expected by Home Manager." - <> header "dconf2nix - Convert dconf files to Nix" + <> header "dconf2nix - Nixify dconf configuration files" ) diff --git a/src/DConf2Nix.hs b/src/DConf2Nix.hs index 3093dcd..70ddff0 100644 --- a/src/DConf2Nix.hs +++ b/src/DConf2Nix.hs @@ -1,18 +1,34 @@ -{-# LANGUAGE LambdaCase #-} - module DConf2Nix where +import qualified Data.Text as T import qualified Data.Text.IO as T import DConf.Data import DConf ( dconfParser ) import qualified Nix import Text.Parsec.Text ( parseFromFile ) +import Text.Parsec ( ParseError + , runParser + ) + +dconf2nixFile :: InputFilePath -> OutputFilePath -> Verbosity -> IO () +dconf2nixFile (InputFilePath input) (OutputFilePath output) v = do + parsed <- parseFromFile (dconfParser v) input + handler (T.writeFile output) (T.appendFile output) parsed + +dconf2nixStdin :: Verbosity -> IO () +dconf2nixStdin v = do + input <- T.getContents + handler T.putStr T.putStr $ runParser (dconfParser v) () "" input -dconf2nix :: InputFilePath -> OutputFilePath -> Verbosity -> IO () -dconf2nix (InputFilePath input) (OutputFilePath output) v = do - parseFromFile (dconfParser v) input >>= \case - Left err -> error (show err) +handler + :: (T.Text -> IO ()) + -> (T.Text -> IO ()) + -> Either ParseError [Entry] + -> IO () +handler writer appender parsed = do + case parsed of + Left err -> error $ show err Right xs -> do - T.writeFile output Nix.renderHeader - traverse (\e -> T.appendFile output (unNix $ Nix.renderEntry e)) xs - T.appendFile output Nix.renderFooter + writer Nix.renderHeader + traverse (\e -> appender (unNix $ Nix.renderEntry e)) xs + appender Nix.renderFooter