------------------------------------------------------------------------------
-- |
-- Module      : PhatSort.Script
-- Description : script API
-- Copyright   : Copyright (c) 2019-2022 Travis Cardwell
-- License     : MIT
------------------------------------------------------------------------------

module PhatSort.Script
  ( -- * API
    formatCommand
  ) where

-- https://hackage.haskell.org/package/base
import Data.Char (ord)

------------------------------------------------------------------------------

-- | Format a shell command, escaping when necessary
--
-- @since 0.5.0.0
formatCommand
  :: [String]  -- ^ command and arguments
  -> String
formatCommand :: [String] -> String
formatCommand = [String] -> String
unwords ([String] -> String)
-> ([String] -> [String]) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map String -> String
escape
  where
    escape :: String -> String
    escape :: String -> String
escape String
s
      | (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isOkChar String
s = String
s
      | Bool
otherwise = String
"'" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> String
tr String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"'"

    isOkChar :: Char -> Bool
    isOkChar :: Char -> Bool
isOkChar Char
c =
      let c' :: Int
c' = Char -> Int
ord Char
c
      in  [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or
            [ (Int
c' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Char -> Int
ord Char
'a') Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
25
            , (Int
c' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Char -> Int
ord Char
'A') Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
25
            , (Int
c' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Char -> Int
ord Char
'0') Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
9
            , Char
c Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (String
".-+_/" :: String)
            ]

    tr :: Char -> String
    tr :: Char -> String
tr Char
'\'' = String
"'\"'\"'"
    tr Char
'\0' = String
""
    tr Char
c    = [Char
c]