Skip to content

Commit f9d906e

Browse files
committed
restructure common directives code; simplify language definitions
1 parent 593d2c1 commit f9d906e

File tree

11 files changed

+169
-152
lines changed

11 files changed

+169
-152
lines changed

magix.cabal

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ library
5959
Magix.Build
6060
Magix.Config
6161
Magix.Directives
62-
Magix.Directives.Common
6362
Magix.Expression
6463
Magix.Hash
6564
Magix.Languages.Bash.Directives
6665
Magix.Languages.Bash.Expression
66+
Magix.Languages.Common.Directives
6767
Magix.Languages.Haskell.Directives
6868
Magix.Languages.Haskell.Expression
6969
Magix.Languages.Python.Directives
@@ -113,10 +113,10 @@ test-suite test-magix
113113
hs-source-dirs: test
114114
other-modules:
115115
Magix.BuildSpec
116-
Magix.Directives.CommonSpec
117116
Magix.DirectivesSpec
118117
Magix.Languages.Bash.DirectivesSpec
119118
Magix.Languages.Bash.ExpressionSpec
119+
Magix.Languages.Common.DirectivesSpec
120120
Magix.Languages.Haskell.DirectivesSpec
121121
Magix.Languages.Haskell.ExpressionSpec
122122
Magix.Languages.Python.DirectivesSpec

src/Magix/Directives.hs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ module Magix.Directives
1313
( Directives (..),
1414
getLanguageName,
1515
pShebang,
16+
pMagixDirective,
17+
pLanguageDirectives,
1618
pDirectives,
1719
getDirectives,
1820
)
@@ -21,13 +23,13 @@ where
2123
import Control.Applicative (Alternative (..))
2224
import Control.Exception (Exception)
2325
import Data.Bifunctor (Bifunctor (..))
24-
import Data.Text (Text, unpack)
25-
import Magix.Directives.Common (Parser, pDirectiveWithValue, pMagixDirective)
26+
import Data.Text (Text, pack, unpack)
2627
import Magix.Languages.Bash.Directives (BashDirectives, pBashDirectives)
28+
import Magix.Languages.Common.Directives (Parser, pDirectiveWithValue)
2729
import Magix.Languages.Haskell.Directives (HaskellDirectives, pHaskellDirectives)
2830
import Magix.Languages.Python.Directives (PythonDirectives, pPythonDirectives)
2931
import Text.Megaparsec (MonadParsec (notFollowedBy, try), chunk, errorBundlePretty, parse)
30-
import Text.Megaparsec.Char (hspace, newline, space)
32+
import Text.Megaparsec.Char (alphaNumChar, hspace, newline, space)
3133
import Prelude hiding (readFile)
3234

3335
data Directives
@@ -45,20 +47,26 @@ getLanguageName (Python _) = "Python"
4547
pShebang :: Parser Text
4648
pShebang = pDirectiveWithValue "/usr/bin/env" (chunk "magix")
4749

48-
pLanguageSpecificDirectives :: Parser Directives
49-
pLanguageSpecificDirectives = do
50+
pLanguage :: Parser Text
51+
pLanguage = pack <$> some alphaNumChar
52+
53+
pMagixDirective :: Parser Text
54+
pMagixDirective = pDirectiveWithValue "magix" pLanguage <* hspace
55+
56+
pLanguageDirectives :: Parser Directives
57+
pLanguageDirectives = do
5058
language <- pMagixDirective
51-
let newlineWith parser = try (newline *> parser) <|> mempty
59+
let withNewline p = try (newline *> p) <|> mempty
5260
directives <- case language of
53-
"bash" -> Bash <$> newlineWith pBashDirectives
54-
"haskell" -> Haskell <$> newlineWith pHaskellDirectives
55-
"python" -> Python <$> newlineWith pPythonDirectives
61+
"bash" -> Bash <$> withNewline pBashDirectives
62+
"haskell" -> Haskell <$> withNewline pHaskellDirectives
63+
"python" -> Python <$> withNewline pPythonDirectives
5664
unknownLanguage -> fail $ "unknown language: " <> unpack unknownLanguage
5765
notFollowedBy $ space *> chunk "#!"
5866
pure directives
5967

6068
pDirectives :: Parser Directives
61-
pDirectives = pShebang *> hspace *> newline *> space *> pLanguageSpecificDirectives
69+
pDirectives = pShebang *> hspace *> newline *> pLanguageDirectives
6270

6371
data DirectivesParseError = DirectivesParseError
6472
{ _directives :: !Text,

src/Magix/Languages/Bash/Directives.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ module Magix.Languages.Bash.Directives
1616
where
1717

1818
import Data.Text (Text)
19-
import Magix.Directives.Common (Parser, pDirectiveWithValues, pLanguageDirectives)
19+
import Magix.Languages.Common.Directives
20+
( Parser,
21+
pDirectiveWithValues,
22+
pManyDirectives,
23+
)
2024
import Prelude hiding (readFile)
2125

2226
newtype BashDirectives = BashDirectives {_packages :: [Text]}
2327
deriving (Eq, Show, Semigroup, Monoid)
2428

25-
pPackages :: Parser BashDirectives
26-
pPackages = BashDirectives <$> pDirectiveWithValues "packages"
27-
2829
pBashDirectives :: Parser BashDirectives
29-
pBashDirectives = pLanguageDirectives pPackages
30+
pBashDirectives = pManyDirectives $ BashDirectives <$> pDirectiveWithValues "packages"

src/Magix/Directives/Common.hs renamed to src/Magix/Languages/Common/Directives.hs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-- |
2-
-- Module : Magix.Directives.Common
2+
-- Module : Magix.Languages.Common.Directives
33
-- Description : Common tools for parsing directives
44
-- Copyright : 2024 Dominik Schrempf
55
-- License : GPL-3.0-or-later
@@ -9,12 +9,11 @@
99
-- Portability : portable
1010
--
1111
-- Creation date: Fri Oct 18 09:17:40 2024.
12-
module Magix.Directives.Common
12+
module Magix.Languages.Common.Directives
1313
( Parser,
1414
pDirectiveWithValue,
1515
pDirectiveWithValues,
16-
pMagixDirective,
17-
pLanguageDirectives,
16+
pManyDirectives,
1817
)
1918
where
2019

@@ -40,9 +39,6 @@ type Parser = Parsec Void Text
4039
pDirective :: Text -> Parser Text
4140
pDirective d = chunk "#!" *> chunk d
4241

43-
pLanguage :: Parser Text
44-
pLanguage = pack <$> some alphaNumChar
45-
4642
pValue :: Parser Text
4743
pValue = pack <$> some (alphaNumChar <|> punctuationChar <|> symbolChar)
4844

@@ -52,10 +48,5 @@ pDirectiveWithValue d p = pDirective d *> hspace *> p
5248
pDirectiveWithValues :: Text -> Parser [Text]
5349
pDirectiveWithValues d = pDirectiveWithValue d (sepEndBy1 pValue hspace)
5450

55-
pMagixDirective :: Parser Text
56-
pMagixDirective = pDirectiveWithValue "magix" pLanguage <* hspace
57-
58-
pLanguageDirectives :: (Monoid b) => Parser b -> Parser b
59-
pLanguageDirectives pLanguageDirective =
60-
mconcat
61-
<$> sepEndBy pLanguageDirective (hspace <* newline)
51+
pManyDirectives :: (Monoid b) => Parser b -> Parser b
52+
pManyDirectives p = mconcat <$> sepEndBy p (hspace <* newline)

src/Magix/Languages/Haskell/Directives.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ where
1717

1818
import Control.Applicative (Alternative (..))
1919
import Data.Text (Text)
20-
import Magix.Directives.Common (Parser, pDirectiveWithValues, pLanguageDirectives)
20+
import Magix.Languages.Common.Directives
21+
( Parser,
22+
pDirectiveWithValues,
23+
pManyDirectives,
24+
)
2125
import Text.Megaparsec (try)
2226
import Prelude hiding (readFile)
2327

@@ -46,8 +50,5 @@ pGhcFlags = do
4650
flags <- pDirectiveWithValues "ghcFlags"
4751
pure $ HaskellDirectives [] flags
4852

49-
pHaskellDirective :: Parser HaskellDirectives
50-
pHaskellDirective = try pHaskellPackages <|> pGhcFlags
51-
5253
pHaskellDirectives :: Parser HaskellDirectives
53-
pHaskellDirectives = pLanguageDirectives pHaskellDirective
54+
pHaskellDirectives = pManyDirectives $ try pHaskellPackages <|> pGhcFlags

src/Magix/Languages/Python/Directives.hs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ module Magix.Languages.Python.Directives
1616
where
1717

1818
import Data.Text (Text)
19-
import Magix.Directives.Common (Parser, pDirectiveWithValues, pLanguageDirectives)
19+
import Magix.Languages.Common.Directives
20+
( Parser,
21+
pDirectiveWithValues,
22+
pManyDirectives,
23+
)
2024
import Prelude hiding (readFile)
2125

2226
newtype PythonDirectives = PythonDirectives {_pythonPackages :: [Text]}
2327
deriving (Eq, Show, Semigroup, Monoid)
2428

25-
pPythonPackages :: Parser PythonDirectives
26-
pPythonPackages = PythonDirectives <$> pDirectiveWithValues "pythonPackages"
27-
2829
pPythonDirectives :: Parser PythonDirectives
29-
pPythonDirectives = pLanguageDirectives pPythonPackages
30+
pPythonDirectives =
31+
pManyDirectives $
32+
PythonDirectives <$> pDirectiveWithValues "pythonPackages"

test/Magix/Directives/CommonSpec.hs

Lines changed: 0 additions & 64 deletions
This file was deleted.

test/Magix/DirectivesSpec.hs

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ where
1717
import Data.Either (isLeft, isRight)
1818
import Data.Text (Text, unlines)
1919
import Data.Text.IO (readFile)
20-
import Magix.Directives (Directives (..), pDirectives, pShebang)
20+
import Magix.Directives
21+
( Directives (..),
22+
pDirectives,
23+
pLanguageDirectives,
24+
pMagixDirective,
25+
pShebang,
26+
)
2127
import Magix.Languages.Bash.Directives (BashDirectives (..))
2228
import Magix.Languages.Haskell.Directives (HaskellDirectives (..))
2329
import Magix.Tools (parse')
@@ -37,44 +43,6 @@ fnMinimalHaskell = "test-scripts/haskell/minimal"
3743
readMinimalHaskell :: IO Text
3844
readMinimalHaskell = readFile fnMinimalHaskell
3945

40-
spaceTest :: Text
41-
spaceTest =
42-
unlines
43-
[ "#!/usr/bin/env magix",
44-
"#!magix bash",
45-
"#!packages a ",
46-
""
47-
]
48-
49-
newlineTest :: Text
50-
newlineTest =
51-
unlines
52-
[ "#!/usr/bin/env magix",
53-
"#!magix bash",
54-
"#!packages a",
55-
""
56-
]
57-
58-
newlineEmptyTest :: Text
59-
newlineEmptyTest =
60-
unlines
61-
[ "#!/usr/bin/env magix",
62-
"#!magix bash",
63-
""
64-
]
65-
66-
emptySpaceTest :: Text
67-
emptySpaceTest =
68-
unlines
69-
[ "#!/usr/bin/env \t magix\t ",
70-
"#!magix \t bash \t"
71-
]
72-
73-
directiveNotNewlineTest :: Text
74-
directiveNotNewlineTest =
75-
unlines
76-
["#!/usr/bin/env \t magix\t #!magix \t bash \t"]
77-
7846
spec :: Spec
7947
spec = do
8048
describe "pShebang" $ do
@@ -89,6 +57,31 @@ spec = do
8957
parse pShebang "" "#/usr/bin/env magix" `shouldSatisfy` isLeft
9058
parse pShebang "" "#/usr/bin/env3magix" `shouldSatisfy` isLeft
9159

60+
describe "pMagixDirective" $ do
61+
it "parses sample Magix directives" $ do
62+
parse pMagixDirective "" "#!magix haskell" `shouldBe` Right "haskell"
63+
parse pMagixDirective "" "#!magix foo" `shouldBe` Right "foo"
64+
65+
it "fails on wrong Magix directives" $ do
66+
parse pMagixDirective "" "#!magic haskell" `shouldSatisfy` isLeft
67+
parse pMagixDirective "" "#!magic" `shouldSatisfy` isLeft
68+
69+
describe "pLanguageDirectives" $ do
70+
it "parses sample language directives" $ do
71+
parse pLanguageDirectives "" "#!magix bash\n#!packages bar" `shouldSatisfy` isRight
72+
parse pLanguageDirectives "" "#!magix bash" `shouldSatisfy` isRight
73+
parse pLanguageDirectives "" "#!magix bash\t" `shouldSatisfy` isRight
74+
parse pLanguageDirectives "" "#!magix \tbash\t" `shouldSatisfy` isRight
75+
parse pLanguageDirectives "" "#!magix \tbash\n\n" `shouldSatisfy` isRight
76+
77+
it "fails on wrong language directives" $ do
78+
parse pLanguageDirectives "" "#! bar" `shouldSatisfy` isLeft
79+
parse pLanguageDirectives "" "#!magix bash\n\n#!packages bar" `shouldSatisfy` isLeft
80+
parse pLanguageDirectives "" "#!magix bash #!packages bar" `shouldSatisfy` isLeft
81+
parse pLanguageDirectives "" "#! magix bash\n#!packages bar" `shouldSatisfy` isLeft
82+
parse pLanguageDirectives "" "#!magix bash\n\n#!" `shouldSatisfy` isLeft
83+
parse pLanguageDirectives "" "#!magix bash\n\n#!foo" `shouldSatisfy` isLeft
84+
9285
describe "pDirectives" $ do
9386
it "parses minimal sample scripts" $ do
9487
minimalBash <- readMinimalBash
@@ -99,10 +92,38 @@ spec = do
9992
`shouldBe` Right (Haskell (HaskellDirectives ["bytestring"] ["-threaded"]))
10093

10194
it "parses some edge cases" $ do
95+
let spaceTest :: Text =
96+
unlines
97+
[ "#!/usr/bin/env magix",
98+
"#!magix bash",
99+
"#!packages a ",
100+
""
101+
]
102102
parse' pDirectives spaceTest `shouldBe` Bash (BashDirectives ["a"])
103+
let newlineTest :: Text =
104+
unlines
105+
[ "#!/usr/bin/env magix",
106+
"#!magix bash",
107+
"#!packages a",
108+
""
109+
]
103110
parse' pDirectives newlineTest `shouldBe` Bash (BashDirectives ["a"])
111+
let newlineEmptyTest :: Text =
112+
unlines
113+
[ "#!/usr/bin/env magix",
114+
"#!magix bash",
115+
""
116+
]
104117
parse' pDirectives newlineEmptyTest `shouldBe` Bash (BashDirectives [])
118+
let emptySpaceTest :: Text =
119+
unlines
120+
[ "#!/usr/bin/env \t magix\t ",
121+
"#!magix \t bash \t"
122+
]
105123
parse' pDirectives emptySpaceTest `shouldBe` Bash (BashDirectives [])
106124

107125
it "fails on some edge cases" $
108-
parse pDirectives "" directiveNotNewlineTest `shouldSatisfy` isLeft
126+
let directiveNotNewlineTest :: Text =
127+
unlines
128+
["#!/usr/bin/env \t magix\t #!magix \t bash \t"]
129+
in parse pDirectives "" directiveNotNewlineTest `shouldSatisfy` isLeft

0 commit comments

Comments
 (0)