diff options
author | Yorhel <git@yorhel.nl> | 2018-01-24 13:54:45 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2018-01-24 13:54:45 +0100 |
commit | 45297a9097296bbd3f7a008df95da3cfb88ba4b7 (patch) | |
tree | ed77abd845d17bdcc002142524bbbd8439413abf | |
parent | 005acbf1d2bdb56d358d1e4e3a74f498a6e9cbdc (diff) |
Add -I command line flag
-rw-r--r-- | Main.hs | 37 | ||||
-rw-r--r-- | nginx-confgen.cabal | 1 | ||||
-rw-r--r-- | nginx-confgen.pod | 10 | ||||
-rw-r--r-- | test/main.conf | 5 |
4 files changed, 40 insertions, 13 deletions
@@ -3,7 +3,7 @@ module Main where import Control.Applicative (empty) import Control.Exception.Base (throwIO,Exception) -import Control.Monad (void,foldM,join) +import Control.Monad (void,foldM,join,filterM) import qualified Data.Array as A import Data.Char (isSpace) import Data.HashMap.Strict (HashMap) @@ -12,6 +12,7 @@ import Data.Semigroup ((<>)) import Data.Void import Options.Applicative hiding (Parser, ParseError) import System.Directory +import System.FilePath import System.IO (hPutStrLn,stderr) import System.IO.Error (tryIOError) import System.Process @@ -173,6 +174,7 @@ data Error | MacroNoNeedsBlock String | MacroNeedsBlock String | IncludeArg + | IncludeNotFound String | IncludeParse (ParseError (Token String) Void) | IncludeRecurse | SetArg @@ -198,6 +200,7 @@ instance Show Error where show (MacroNoNeedsBlock n) = "Macro '"++n++"' does not accept a block argument" show (MacroNeedsBlock n) = "Macro '"++n++"' requires a block argument, but none given" show IncludeArg = "Invalid argument(s) to 'pre_include'" + show (IncludeNotFound f) = "Can't find include file '"++f++"'" show (IncludeParse e) = parseErrorPretty e show IncludeRecurse = "Recursion depth exceeded with 'pre_include'" show SetArg = "Invalid argument(s) to 'pre_set'" @@ -377,8 +380,24 @@ ifExpand st arg conf = do +includeExpand :: PState -> Int -> String -> IO (PState, [Directive]) +includeExpand st n fn = do + fns <- filterM doesFileExist $ map (</>fn) $ stIncDir st + f <- case fns of + [] -> throwIO (IncludeNotFound fn) + f:_ -> return f + contents <- readFile f + ast <- case parse parser fn contents of + Left e -> throwIO (IncludeParse e) + Right r -> return r + (nst, conf) <- procConf (st { stIncludes = n-1 }) ast + return (nst { stIncludes = n+1 }, conf) + + + data PState = PState - { stVars :: HashMap String [ArgComponent] + { stIncDir :: [String] + , stVars :: HashMap String [ArgComponent] , stMacros :: HashMap String Macro , stArgs :: HashMap String [ArgComponent] -- shadows stVars -- Max 1, but Prelude's 'lookup' isn't generic to work on Maybe, so this'll do @@ -431,13 +450,7 @@ procConf gst gconf = foldM p (gst, []) gconf stmt st (Directive "pre_include" a b) = case (stIncludes st, a, b) of (0, _, _) -> throwIO IncludeRecurse - (i, ArgString [Literal n]:[], Nothing) -> do - contents <- readFile n - ast <- case parse parser n contents of - Left e -> throwIO (IncludeParse e) - Right r -> return r - (nst, conf) <- procConf (st { stIncludes = i-1 }) ast - return (nst { stIncludes = i+1 }, conf) + (i, ArgString [Literal n]:[], Nothing) -> includeExpand st i n _ -> throwIO IncludeArg stmt st (Directive "pre_set" a b) = @@ -486,6 +499,7 @@ data Options = Options { optVersion :: Bool , optInput :: String , optOutput :: String + , optInclude :: [String] } main :: IO () @@ -504,8 +518,11 @@ main = do <$> switch (short 'V' <> long "version" <> hidden <> help "Show program version") <*> strOption (short 'i' <> metavar "FILE" <> value "-" <> showDefault <> help "Input file") <*> strOption (short 'o' <> metavar "FILE" <> value "-" <> showDefault <> help "Output file") + <*> many (strOption (short 'I' <> metavar "DIR" <> help "Add search path for pre_include directives")) prog o = do + let inc = if null (optInclude o) then ["."] else optInclude o + input <- if optInput o == "-" then getContents else readFile (optInput o) @@ -513,7 +530,7 @@ main = do case parse parser (optInput o) input of Left e -> hPutStrLn stderr $ parseErrorPretty e Right r -> do - output <- fmt <$> procConf' (PState mempty mempty mempty mempty mempty 15) r + output <- fmt <$> procConf' (PState inc mempty mempty mempty mempty mempty 15) r if optOutput o == "-" then putStr output else writeFile (optOutput o) output diff --git a/nginx-confgen.cabal b/nginx-confgen.cabal index 8ebb227..5df1bf7 100644 --- a/nginx-confgen.cabal +++ b/nginx-confgen.cabal @@ -20,6 +20,7 @@ executable nginx-confgen array , base , directory + , filepath , megaparsec , optparse-applicative , process diff --git a/nginx-confgen.pod b/nginx-confgen.pod index 2bc0176..d4efeb5 100644 --- a/nginx-confgen.pod +++ b/nginx-confgen.pod @@ -54,6 +54,13 @@ C<->, then the file will be read from standard input. Write the output to the given file. If this option is not given or set to C<->, then the file will be written to standard output. +=item -I I<DIR> + +Set the search path for I<pre_include> directives. This option can be given +multiple times to search several directories in order. If this option is not +given, then include files are resolved relative to the directory that +nginx-confgen is run from (i.e. C<-I .>). + =back @@ -68,8 +75,7 @@ during preprocessing. The included file may contain any preprocessing directives supported by nginx-confgen. Variables and macros defined in the included file will be available in the parent file. -Beware that relative paths are resolved from the working directory that -nginx-confgen is run from. +Relative paths are searched for in the directories given with the C<-I> flag. =head2 pre_set diff --git a/test/main.conf b/test/main.conf index 249d7ad..09cda5b 100644 --- a/test/main.conf +++ b/test/main.conf @@ -24,7 +24,10 @@ pre_exec $nameserver "grep nameserver /etc/resolv.conf \\ | head -n 1 | sed 's/^nameserver //'"; resolver $nameserver; -pre_include test/macros.conf; +# This needs -Itest to resolve +pre_include macros.conf; + +pre_include /dev/null; http { types { |