Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
73937ba
split up modules (languages, directives, expressions)
dschrempf Apr 22, 2025
4a77b03
readme: new languages
dschrempf Apr 22, 2025
2f249c9
changelog and some comments
dschrempf Apr 22, 2025
e5228e7
test: move directives spec
dschrempf Apr 22, 2025
85a7731
tests: fix tests after module-split
dschrempf Apr 22, 2025
05285e2
tests: towards unified testing for all languages
dschrempf Apr 22, 2025
ba2de39
tooling: update nix flake
dschrempf Apr 22, 2025
d75bdaa
tooling: update nix flake
dschrempf Apr 24, 2025
e93f813
tooling: update nix flake
dschrempf Apr 26, 2025
3970b63
tooling: update nix flake
dschrempf Apr 29, 2025
48fd1a3
tooling: update nix flake
dschrempf Apr 30, 2025
73d3962
tooling: update nix flake
dschrempf May 2, 2025
762fd8f
tooling: update nix flake
dschrempf May 3, 2025
bc75dfc
tooling: update nix flake
dschrempf May 5, 2025
9755a9b
tooling: update nix flake
dschrempf May 6, 2025
ded7240
tooling: ghc98
dschrempf May 6, 2025
61feda0
fix foldable once and for all
dschrempf May 6, 2025
22cb3f4
tooling: update nix flake
dschrempf May 9, 2025
b768617
tooling: update nix flake
dschrempf May 12, 2025
1e3107a
tooling: update nix flake
dschrempf May 15, 2025
fc7d3d1
tooling: update nix flake
dschrempf May 17, 2025
596f7df
tooling: update nix flake
dschrempf May 19, 2025
8974e78
tooling: update nix flake
dschrempf May 21, 2025
58e4447
tooling: update nix flake
dschrempf May 25, 2025
30459c4
tooling: update nix flake
dschrempf May 27, 2025
3fc8de4
tooling: update nix flake
dschrempf May 28, 2025
bcd03a5
tooling: update nix flake
dschrempf May 31, 2025
367f578
tooling: update nix flake
dschrempf Jun 1, 2025
3cc18c9
tooling: update nix flake
dschrempf Jun 4, 2025
de01095
tooling: update nix flake
dschrempf Jun 7, 2025
0274827
tooling: update nix flake
dschrempf Jun 9, 2025
2775edb
tooling: update nix flake
dschrempf Jun 16, 2025
36298ad
tooling: update nix flake
dschrempf Jun 18, 2025
49de16d
tooling: update nix flake
dschrempf Jun 20, 2025
8ea2ad2
tooling: update nix flake
dschrempf Jun 23, 2025
ade2929
tooling: update nix flake
dschrempf Jun 26, 2025
c315299
tooling: update nix flake
dschrempf Jun 28, 2025
2e78fee
tooling: update nix flake
dschrempf Jul 1, 2025
b57bdca
tooling: update nix flake
dschrempf Jul 7, 2025
2d4ec61
tooling: update nix flake
dschrempf Jul 10, 2025
5d758ea
tooling: update nix flake
dschrempf Jul 27, 2025
513f89b
tooling: update nix flake
dschrempf Jul 28, 2025
98c8ace
tooling: update nix flake
dschrempf Jul 29, 2025
c67106e
tooling: update nix flake
dschrempf Aug 1, 2025
4d859e9
tooling: update nix flake
dschrempf Aug 5, 2025
0276b6a
tooling: update nix flake
dschrempf Aug 8, 2025
1337da2
tooling: update nix flake
dschrempf Aug 13, 2025
5024f94
tooling: update nix flake
dschrempf Aug 14, 2025
3605e3a
tooling: update nix flake
dschrempf Aug 16, 2025
6eca2e6
tooling: update nix flake
dschrempf Aug 20, 2025
f937374
tooling: update nix flake
dschrempf Aug 26, 2025
c9c8978
version bump, changelog
dschrempf Aug 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Changelog.org
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
* Unreleased

* Version 0.5.0.0
- Split modules so that implementing new languages becomes easier
- More tests
- Language data type
- Toolchain downgrade to GHC 9.8 (dropped into Nixpkgs, and so is easier to use)

* Version 0.4.0.1
- Update and improve GitHub workflows (use Nix and Cachix)
Expand Down
6 changes: 6 additions & 0 deletions Readme.org
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ Available options:
SCRIPT_ARGS Arguments passed on to the script
#+end_example

* New languages
We have designed Magix so that implementing new languages is straightforward. In
particular:
- Change and add modules only within the =src/Magix/Languages/*= namespace.
- Add language-specific tests to =test/Magix/Languages/*=.

* Next steps
- Property-based testing (e.g., generate arbitrary directives or even scripts).
When creating arbitrary directives, one could test if the resulting
Expand Down
22 changes: 16 additions & 6 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,22 @@ import Control.Exception (onException, throwIO)
import Data.ByteString (readFile)
import Data.Text (unpack)
import Data.Text.Encoding (decodeUtf8')
import Magix.Build (BuildStatus (..), build, getBuildStatus, withBuildLock)
import Magix.Config (Config, getConfig)
import Magix.Directives (Directives, getDirectives)
import Magix.Expression (getNixExpression)
import Magix.Options (Options (..), Rebuild (..), Verbosity (..), getOptions)
import Magix.Run (run)
import Magix
( BuildStatus (..),
Config,
Directives,
Options (..),
Rebuild (..),
Verbosity (..),
build,
getBuildStatus,
getConfig,
getDirectives,
getNixExpression,
getOptions,
run,
withBuildLock,
)
import System.Console.ANSI
( Color (Green, Red, White),
ColorIntensity (Dull),
Expand Down
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
theseHpkgNames = [
"magix"
];
# NOTE: When updating GHC, do not forget to also update the CICD script.
thisGhcVersion = "ghc910";
thisGhcVersion = "ghc98";
hOverlay = selfn: supern: {
haskell = supern.haskell // {
packageOverrides =
Expand Down
9 changes: 6 additions & 3 deletions magix.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 3.4
name: magix
version: 0.4.0.1
version: 0.5.0.0
synopsis:
Build, cache, and run possibly compiled scripts with dependencies using the Nix package manager

Expand Down Expand Up @@ -61,13 +61,15 @@ library
Magix.Directives
Magix.Expression
Magix.Hash
Magix.Language
Magix.Languages.Bash.Directives
Magix.Languages.Bash.Expression
Magix.Languages.Common.Directives
Magix.Languages.Common.Expression
Magix.Languages.Directives
Magix.Languages.Expression
Magix.Languages.Haskell.Directives
Magix.Languages.Haskell.Expression
Magix.Languages.Language
Magix.Languages.Python.Directives
Magix.Languages.Python.Expression
Magix.NixpkgsPath
Expand Down Expand Up @@ -118,11 +120,12 @@ test-suite test-magix
Magix.DirectivesSpec
Magix.Languages.Bash.DirectivesSpec
Magix.Languages.Bash.ExpressionSpec
Magix.Languages.DirectivesSpec
Magix.Languages.Common.DirectivesSpec
Magix.Languages.Haskell.DirectivesSpec
Magix.Languages.Haskell.ExpressionSpec
Magix.Languages.Python.DirectivesSpec
Magix.Languages.Python.ExpressionSpec
Magix.Languages.Tools
Magix.NixpkgsPathSpec
Magix.Tools

Expand Down
16 changes: 13 additions & 3 deletions src/Magix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
module Magix
( -- Options.
Options (..),
Rebuild (..),
Verbosity (..),
getOptions,
-- Configuration.
Config,
getConfig,
-- Directives.
getDirectives,
Expand All @@ -23,11 +26,18 @@ module Magix
BuildStatus (..),
getBuildStatus,
build,
withBuildLock,
-- Run.
run,
-- Languages.
Directives,
)
where

import Magix.Build (BuildStatus (..), build, getBuildStatus)
import Magix.Config (getConfig)
import Magix.Build (BuildStatus (..), build, getBuildStatus, withBuildLock)
import Magix.Config (Config, getConfig)
import Magix.Directives (getDirectives)
import Magix.Expression (getNixExpression)
import Magix.Options (Options (..), getOptions)
import Magix.Languages.Directives (Directives)
import Magix.Options (Options (..), Rebuild (..), Verbosity (..), getOptions)
import Magix.Run (run)
47 changes: 17 additions & 30 deletions src/Magix/Directives.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,51 +10,38 @@
--
-- Creation date: Fri Oct 18 09:17:40 2024.
module Magix.Directives
( Directives (..),
getLanguage,
pShebang,
( pShebang,
pMagixDirective,
pLanguageDirectives,
pDirectives,
getDirectives,
)
where

import Control.Applicative (Alternative (..))
import Control.Exception (Exception)
import Data.Bifunctor (Bifunctor (..))
import Data.Text (Text)
import Magix.Language (Language (..), pLanguage)
import Magix.Languages.Bash.Directives (BashDirectives, pBashDirectives)
import Magix.Languages.Directives (Parser, pDirectiveWithValue)
import Magix.Languages.Haskell.Directives (HaskellDirectives, pHaskellDirectives)
import Magix.Languages.Python.Directives (PythonDirectives, pPythonDirectives)
import Text.Megaparsec (MonadParsec (notFollowedBy, try), chunk, errorBundlePretty, parse)
import Text.Megaparsec.Char (hspace, newline, space)
import Magix.Languages.Common.Directives (Parser, pDirectiveWithValue)
import Magix.Languages.Directives (Directives, getDirectivesParser)
import Magix.Languages.Language (Language (..), getLanguageNameLowercase)
import Text.Megaparsec
( MonadParsec (notFollowedBy),
choice,
chunk,
errorBundlePretty,
parse,
)
import Text.Megaparsec.Char (hspace, newline, space, string)
import Prelude hiding (readFile)

data Directives
= BashD !BashDirectives
| HaskellD !HaskellDirectives
| PythonD !PythonDirectives
deriving (Eq, Show)

getDirectivesParser :: Language -> Parser Directives
getDirectivesParser l = case l of
Bash -> BashD <$> withNewline pBashDirectives
Haskell -> HaskellD <$> withNewline pHaskellDirectives
Python -> PythonD <$> withNewline pPythonDirectives
where
withNewline p = try (newline *> p) <|> mempty

getLanguage :: Directives -> Language
getLanguage (BashD _) = Bash
getLanguage (HaskellD _) = Haskell
getLanguage (PythonD _) = Python

pShebang :: Parser Text
pShebang = pDirectiveWithValue "/usr/bin/env" (chunk "magix")

pLanguage :: Parser Language
pLanguage = choice $ map pAnyLanguage [minBound .. maxBound :: Language]
where
pAnyLanguage language = language <$ string (getLanguageNameLowercase language)

pMagixDirective :: Parser Language
pMagixDirective = pDirectiveWithValue "magix" pLanguage <* hspace

Expand Down
18 changes: 6 additions & 12 deletions src/Magix/Expression.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ module Magix.Expression
)
where

import Data.Foldable qualified as Foldable
import Data.Text (Text, replace)
import Data.Text.IO (readFile)
import Magix.Config (Config (..))
import Magix.Directives (Directives (..), getLanguage)
import Magix.Language (Language (..))
import Magix.Languages.Bash.Expression (getBashReplacements)
import Magix.Languages.Expression (Replacement, getCommonReplacements)
import Magix.Languages.Haskell.Expression (getHaskellReplacements)
import Magix.Languages.Python.Expression (getPythonReplacements)
import Magix.Languages.Common.Expression (Replacement, getCommonReplacements)
import Magix.Languages.Directives (Directives (..), getLanguage)
import Magix.Languages.Expression (getLanguageReplacements)
import Magix.Languages.Language (Language (..))
import Paths_magix (getDataFileName)
import Prelude hiding (readFile)

Expand All @@ -34,17 +33,12 @@ getTemplatePath language = "src/Magix/Languages/" <> show language <> "/Template
getTemplate :: Language -> IO Text
getTemplate language = getDataFileName (getTemplatePath language) >>= readFile

getLanguageReplacements :: Directives -> [Replacement]
getLanguageReplacements (BashD ds) = getBashReplacements ds
getLanguageReplacements (HaskellD ds) = getHaskellReplacements ds
getLanguageReplacements (PythonD ds) = getPythonReplacements ds

getReplacements :: Config -> Directives -> [Replacement]
getReplacements c ds = getCommonReplacements c ++ getLanguageReplacements ds

getNixExpression :: Config -> Directives -> IO Text
getNixExpression c ds = do
t <- getTemplate $ getLanguage ds
pure $ foldl' replace' t (getReplacements c ds)
pure $ Foldable.foldl' replace' t (getReplacements c ds)
where
replace' t (x, y) = replace x y t
3 changes: 2 additions & 1 deletion src/Magix/Hash.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ where
import Crypto.Hash.SHA256 (finalize, init, update)
import Data.ByteString (ByteString, toStrict)
import Data.ByteString.Builder (Builder, charUtf8, intDec, toLazyByteString)
import Data.Foldable qualified as Foldable
import Data.Version (Version (versionBranch))
import Paths_magix (version)
import Prelude hiding (init)
Expand All @@ -27,7 +28,7 @@ toByteStringWith f = toStrict . toLazyByteString . mconcat . map f
getMagixHash :: FilePath -> ByteString -> ByteString
getMagixHash nixpkgsPath scriptContents =
finalize $
foldl'
Foldable.foldl'
update
init
[ toByteStringWith charUtf8 nixpkgsPath,
Expand Down
2 changes: 1 addition & 1 deletion src/Magix/Languages/Bash/Directives.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Magix.Languages.Bash.Directives
where

import Data.Text (Text)
import Magix.Languages.Directives
import Magix.Languages.Common.Directives
( Parser,
pDirectiveWithValues,
pManyDirectives,
Expand Down
2 changes: 1 addition & 1 deletion src/Magix/Languages/Bash/Expression.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ where

import Data.Text (unwords)
import Magix.Languages.Bash.Directives (BashDirectives (..))
import Magix.Languages.Expression (Replacement)
import Magix.Languages.Common.Expression (Replacement)
import Prelude hiding (unwords)

getBashReplacements :: BashDirectives -> [Replacement]
Expand Down
52 changes: 52 additions & 0 deletions src/Magix/Languages/Common/Directives.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-- |
-- Module : Magix.Languages.Common.Directives
-- Description : Common tools for parsing directives
-- Copyright : 2024 Dominik Schrempf
-- License : GPL-3.0-or-later
--
-- Maintainer : dominik.schrempf@gmail.com
-- Stability : experimental
-- Portability : portable
--
-- Creation date: Fri Oct 18 09:17:40 2024.
module Magix.Languages.Common.Directives
( Parser,
pDirectiveWithValue,
pDirectiveWithValues,
pManyDirectives,
)
where

import Control.Applicative (Alternative (..))
import Data.Text (Text, pack)
import Data.Void (Void)
import Text.Megaparsec
( Parsec,
chunk,
sepEndBy,
sepEndBy1,
)
import Text.Megaparsec.Char
( alphaNumChar,
hspace,
newline,
punctuationChar,
symbolChar,
)

type Parser = Parsec Void Text

pDirective :: Text -> Parser Text
pDirective d = chunk "#!" *> chunk d

pValue :: Parser Text
pValue = pack <$> some (alphaNumChar <|> punctuationChar <|> symbolChar)

pDirectiveWithValue :: Text -> Parser a -> Parser a
pDirectiveWithValue d p = pDirective d *> hspace *> p

pDirectiveWithValues :: Text -> Parser [Text]
pDirectiveWithValues d = pDirectiveWithValue d (sepEndBy1 pValue hspace)

pManyDirectives :: (Monoid b) => Parser b -> Parser b
pManyDirectives p = mconcat <$> sepEndBy p (hspace <* newline)
27 changes: 27 additions & 0 deletions src/Magix/Languages/Common/Expression.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-- |
-- Module : Magix.Languages.Common.Expression
-- Description : Common definitions related to handling Nix expressions
-- Copyright : 2025 Dominik Schrempf
-- License : GPL-3.0-or-later
--
-- Maintainer : dominik.schrempf@gmail.com
-- Stability : experimental
-- Portability : portable
--
-- Creation date: Fri Apr 11 06:36:34 2025.
module Magix.Languages.Common.Expression
( Replacement,
getCommonReplacements,
)
where

import Data.Text (Text, pack)
import Magix.Config (Config (..))

type Replacement = (Text, Text)

getCommonReplacements :: Config -> [Replacement]
getCommonReplacements c =
[ ("__SCRIPT_NAME__", pack $ scriptName c),
("__SCRIPT_SOURCE__", pack $ scriptLinkPath c)
]
Loading