packages feed

shh 0.4.0.1 → 0.5.0.0

raw patch · 4 files changed

+39/−23 lines, 4 files

Files

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"