shh 0.4.0.1 → 0.5.0.0
raw patch · 4 files changed
+39/−23 lines, 4 files
Files
- ChangeLog.md +5/−0
- shh.cabal +1/−1
- src/Shh/Internal.hs +29/−18
- test/Test.hs +4/−4
ChangeLog.md view
@@ -1,5 +1,10 @@ # Revision history for shh +## 0.5.0.0 -- 2019-05-23++* Change how identifiers are encoded to avoid clashes in all scenarios+ (Potentially breaking change)+ ## 0.4.0.0 -- 2019-04-20 * Pre-compile Shell.hs for faster loading of shh shell
shh.cabal view
@@ -1,5 +1,5 @@ name: shh-version: 0.4.0.1+version: 0.5.0.0 synopsis: Simple shell scripting from Haskell description: Provides a shell scripting environment for Haskell. It helps you use external binaries, and allows you to
src/Shh/Internal.hs view
@@ -20,7 +20,7 @@ import Control.Exception as C import Control.Monad import Control.Monad.IO.Class-import Data.Char (isLower, isSpace, isAlphaNum, isUpper, toLower, isNumber)+import Data.Char (isLower, isSpace, isAlphaNum, ord) import Data.List (dropWhileEnd, intercalate) import Data.List.Split (endBy, splitOn) import qualified Data.Map as Map@@ -43,6 +43,7 @@ import System.IO.Error import System.Posix.Signals import System.Process+import Text.Printf -- $setup -- For doc-tests. Not sure I can use TH in doc tests.@@ -659,26 +660,35 @@ Just absExe -> rawExe fnName (case ref of { Absolute -> absExe; SearchPath -> executable }) --- | Takes a string, and makes a Haskell identifier out of it. There--- is some chance of overlap. If the string is a path, the filename portion--- is used. The transformation replaces all non-alphanumeric characters--- with @'_'@. If the first character is uppercase it is forced into lowercase.--- If it starts with a number, it is prefixed with `_`. If it overlaps with--- a reserved word or a builtin, it is suffixed with an `_`.++-- | Takes a string, and makes a Haskell identifier out of it. If the string+-- is a path, the filename portion is used. The exact transformation is that+-- alphanumeric characters are unchanged, @-@ becomes @_@, and @'@ is used to+-- escape all other characters. @_@ becomes @'_@, @.@ becomes @''@ and+-- anthing else is becomes a hex encoded number surrounded by @'@ characters.+--+-- Justification for changing @-@ to @_@ is that @-@ appears far more commonly+-- in executable names than @_@ does, and so we give it the more ergonomic+-- encoding. encodeIdentifier :: String -> String encodeIdentifier ident = let- i = go (takeFileName ident)- go (c:cs)- | isLower c = c : go' cs- | isUpper c = toLower c : go' cs- | isNumber c = '_' : go' (c : cs)- | otherwise = go' (c:cs)- go [] = "_"- go' (c:cs)- | isAlphaNum c = c : go' cs- | otherwise = '_' : go' cs- go' [] = []+ fixBody :: String -> String+ fixBody (c:cs)+ | isAlphaNum c = c : fixBody cs+ | c == '-' = '_' : fixBody cs+ | c == '_' = '\'' : '_' : fixBody cs+ | c == '.' = '\'' : '\'' : fixBody cs+ | otherwise = printf "'%x'%s" (ord c) (fixBody cs)+ fixBody [] = []++ fixStart :: String -> String+ fixStart s@(c : _)+ | isLower c = s+ | otherwise = '_' : s+ fixStart [] = []++ i = fixStart $ fixBody $ takeFileName ident -- Includes cd, which has to be a built-in reserved = [ "import", "if", "else", "then", "do", "in", "let", "type" , "as", "case", "of", "class", "data", "default", "deriving"@@ -686,6 +696,7 @@ , "infixr", "mdo", "module", "newtype", "proc", "qualified" , "rec", "where", "cd"] in if i `elem` reserved then i ++ "_" else i+ -- | Scans your '$PATH' environment variable and creates a function for each -- executable found. Binaries that would not create valid Haskell identifiers
test/Test.hs view
@@ -39,8 +39,8 @@ properties :: TestTree properties = testGroup "Properties" [ testProperty "trim = trim . trim" $ \l -> trim l == trim (trim l)- , testProperty "encodeIdentifier = encodeIdentifier . encodeIdentifier"- $ \l -> encodeIdentifier l == encodeIdentifier (encodeIdentifier l)+ , testProperty "encodeIdentifier creates a unique encoding"+ $ \(l1,l2) -> (encodeIdentifier l1 == encodeIdentifier l2) == (l1 == l2) , testProperty "writeOutput" $ \s -> ioProperty $ do let s' = bytesToString s@@ -137,8 +137,8 @@ , testCase "Lazy read checks code" $ replicateM_ 30 $ do Left r <- catchFailure $ withRead (cat "/dev/urandom" |> false "dummy") $ pure . take 3 r @?= Shh.Failure "false" ["dummy"] 1- , testCase "Identifier odd chars" $ encodeIdentifier "1@3.-" @?= "_1_3__"- , testCase "Identifier make lower" $ encodeIdentifier "T.est" @?= "t_est"+ , testCase "Identifier odd chars" $ encodeIdentifier "1@3.-" @?= "_1'40'3''_"+ , testCase "Identifier make lower" $ encodeIdentifier "T.est" @?= "_T''est" , testCase "pureProc closes input" $ do r <- readProc $ cat "/dev/urandom" |> pureProc (const "test") r @?= "test"