mirror of
https://github.com/bennofs/nix-script
synced 2025-01-09 20:34:20 +01:00
Properly handle arguments
This commit is contained in:
parent
332c94e05a
commit
8bab98e655
@ -4,4 +4,5 @@
|
|||||||
|
|
||||||
function a { echo "this is zsh!" }
|
function a { echo "this is zsh!" }
|
||||||
a
|
a
|
||||||
|
echo $#
|
||||||
echo "your args: $@"
|
echo "your args: $@"
|
@ -1,13 +1,17 @@
|
|||||||
-- | A shebang for running scripts inside nix-shell with defined dependencies
|
-- | A shebang for running scripts inside nix-shell with defined dependencies
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
import Control.Monad (when)
|
import Control.Monad (when)
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import Data.List (isSuffixOf, isPrefixOf, find)
|
import Data.List (isPrefixOf, find)
|
||||||
import System.Environment (lookupEnv, getProgName, getArgs)
|
import System.Environment (lookupEnv, getProgName, getArgs)
|
||||||
import System.Process (callProcess)
|
import System.Process (callProcess)
|
||||||
import System.Posix.IO (createPipe, fdToHandle)
|
import System.Posix.Escape.Unicode (escapeMany)
|
||||||
import System.IO (hPutStrLn, hClose, hFlush)
|
|
||||||
|
|
||||||
|
type Env = [String]
|
||||||
|
type Args = [String]
|
||||||
|
type Inter = (String, Args)
|
||||||
|
|
||||||
|
|
||||||
-- | Information about a language
|
-- | Information about a language
|
||||||
@ -16,9 +20,9 @@ data Language = Language
|
|||||||
-- ^ Name of the language
|
-- ^ Name of the language
|
||||||
, depsTrans :: [String] -> [String]
|
, depsTrans :: [String] -> [String]
|
||||||
-- ^ Transform language-specific dependencies to nix packages
|
-- ^ Transform language-specific dependencies to nix packages
|
||||||
, run :: FilePath -> (String, [String])
|
, run :: FilePath -> Inter
|
||||||
-- ^ Command to run the given file as script
|
-- ^ Command to run the given file as script
|
||||||
, repl :: FilePath -> (String, [String])
|
, repl :: FilePath -> Inter
|
||||||
-- ^ Command to load the given file in an interpreter
|
-- ^ Command to load the given file in an interpreter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +80,7 @@ lookupLang :: String -> Language
|
|||||||
lookupLang n =
|
lookupLang n =
|
||||||
fromMaybe (passthrough n) (find ((n ==) . name) languages)
|
fromMaybe (passthrough n) (find ((n ==) . name) languages)
|
||||||
|
|
||||||
|
|
||||||
-- | Parse dependencies declaration line
|
-- | Parse dependencies declaration line
|
||||||
parseHeader :: String -> [String]
|
parseHeader :: String -> [String]
|
||||||
parseHeader = uncurry trans . split . words
|
parseHeader = uncurry trans . split . words
|
||||||
@ -86,25 +91,24 @@ parseHeader = uncurry trans . split . words
|
|||||||
|
|
||||||
|
|
||||||
-- | Find command to run/load the script
|
-- | Find command to run/load the script
|
||||||
interpreter :: String -> Bool -> String -> (String, [String])
|
makeInter :: String -> Bool -> String -> Inter
|
||||||
interpreter lang interactive =
|
makeInter lang interactive =
|
||||||
(if interactive then repl else run) (lookupLang lang)
|
(if interactive then repl else run) (lookupLang lang)
|
||||||
|
|
||||||
|
|
||||||
-- | Create command to add the shell environment
|
-- | Create command to add the shell environment
|
||||||
makeCommand :: String -> [String] -> IO String
|
makeCmd :: Inter -> Args -> Env -> String
|
||||||
makeCommand program args = do
|
makeCmd (program, args) args' defs =
|
||||||
(readFd, writeFd) <- createPipe
|
env defs ++ interpreter ++ escapeMany args'
|
||||||
writeH <- fdToHandle writeFd
|
|
||||||
hPutStrLn writeH (unlines args)
|
|
||||||
hFlush writeH >> hClose writeH
|
|
||||||
|
|
||||||
definitions <- mapM format baseEnv
|
|
||||||
return (env definitions ++ xargs readFd ++ program)
|
|
||||||
where
|
where
|
||||||
|
interpreter = program ++ " " ++ unwords args ++ " "
|
||||||
env defs = "env " ++ unwords defs ++ " "
|
env defs = "env " ++ unwords defs ++ " "
|
||||||
xargs fd = "xargs -a /proc/self/fd/" ++ show fd ++ " -d '\\n' "
|
|
||||||
format var = maybe "" (\x -> var ++ "=" ++ x) <$> lookupEnv var
|
|
||||||
|
-- | Create environment variable to run the script with
|
||||||
|
makeEnv :: IO Env
|
||||||
|
makeEnv = mapM format baseEnv where
|
||||||
|
format var = maybe "" (\x -> var ++ "=" ++ x) <$> lookupEnv var
|
||||||
|
|
||||||
|
|
||||||
-- | run a script or load it in an interactive interpreter
|
-- | run a script or load it in an interactive interpreter
|
||||||
@ -115,20 +119,19 @@ main = do
|
|||||||
|
|
||||||
when (null progArgs) (fail $ "usage: " ++ progName ++ " <file>")
|
when (null progArgs) (fail $ "usage: " ++ progName ++ " <file>")
|
||||||
|
|
||||||
let file = head progArgs
|
let shebang = takeWhile (isPrefixOf "#!") . lines
|
||||||
shebang = takeWhile (isPrefixOf "#!") . lines
|
header = drop 1 . map (drop 2) . shebang
|
||||||
header = drop 1 . map (drop 2) . shebang
|
(file:args) = progArgs
|
||||||
|
|
||||||
script <- readFile file
|
script <- readFile file
|
||||||
case header script of
|
case header script of
|
||||||
(('>' : identifier) : lines) -> do
|
(('>':identifier) : lines) -> do
|
||||||
let pkgs = concatMap parseHeader lines
|
let pkgs = concatMap parseHeader lines
|
||||||
language = dropWhile (==' ') identifier
|
language = dropWhile (==' ') identifier
|
||||||
interactive = isSuffixOf "i" progName
|
interactive = last progName == 'i'
|
||||||
(program, args) = interpreter language interactive file
|
interpreter = makeInter language interactive file
|
||||||
|
|
||||||
cmd <- makeCommand program args
|
cmd <- makeCmd interpreter args <$> makeEnv
|
||||||
putStrLn $ unwords ("--pure" : "--command" : cmd : "-p" : pkgs)
|
|
||||||
callProcess "nix-shell" ("--pure" : "--command" : cmd : "-p" : pkgs)
|
callProcess "nix-shell" ("--pure" : "--command" : cmd : "-p" : pkgs)
|
||||||
|
|
||||||
_ -> fail "missing or invalid header"
|
_ -> fail "missing or invalid header"
|
Loading…
Reference in New Issue
Block a user