mirror of
https://github.com/anoma/juvix.git
synced 2024-12-14 08:27:03 +03:00
3d012cc8fb
- Closes #1993 This pr makes it possible to use `~`, `..` and environment variables in the `juvix.yaml` and all flags / input of the cli. In the CLI, the shell will be responsible for replacing environment variables with their value, so the usual syntax can be used. For the `dependencies` field, I have implemented a parser that has some restrictions: 1. Environment variables are given with the makefile-like syntax `$(VAR)` 2. The three characters `$` `(` `)` are reserved for the environment variables syntax. They cannot be part of the path. 3. `~` is reserved for `$(HOME)`. I.e. the prepath `~~` will expand to `$HOME$HOME`. 4. Nested environment variables are not allowed. Thanks @paulcadman for the feedback. I think we are ready to merge this nightmarish pr 👻 --------- Co-authored-by: Paul Cadman <git@paulcadman.dev>
66 lines
2.3 KiB
Haskell
66 lines
2.3 KiB
Haskell
module Commands.Format where
|
|
|
|
import Commands.Base
|
|
import Commands.Format.Options
|
|
import Juvix.Formatter
|
|
import Juvix.Prelude.Pretty
|
|
|
|
data FormatNoEditRenderMode
|
|
= ReformattedFile (NonEmpty AnsiText)
|
|
| InputPath (Path Abs File)
|
|
| Silent
|
|
|
|
data FormatRenderMode
|
|
= EditInPlace FormattedFileInfo
|
|
| NoEdit FormatNoEditRenderMode
|
|
|
|
data FormatTarget
|
|
= TargetFile
|
|
| TargetDir
|
|
|
|
runCommand :: forall r. Members '[Embed IO, App, Resource, Files] r => FormatOptions -> Sem r ()
|
|
runCommand opts = do
|
|
f <- filePathToAbs (opts ^. formatInput)
|
|
let target = case f of
|
|
Left {} -> TargetFile
|
|
Right {} -> TargetDir
|
|
runOutputSem (renderFormattedOutput target opts) $ runScopeFileApp $ do
|
|
res <- case f of
|
|
Left p -> format p
|
|
Right p -> formatProject p
|
|
when (res == FormatResultFail) (embed (exitWith (ExitFailure 1)))
|
|
|
|
renderModeFromOptions :: FormatTarget -> FormatOptions -> FormattedFileInfo -> FormatRenderMode
|
|
renderModeFromOptions target opts formattedInfo
|
|
| opts ^. formatInPlace = EditInPlace formattedInfo
|
|
| opts ^. formatCheck = NoEdit Silent
|
|
| otherwise = case target of
|
|
TargetFile -> NoEdit (ReformattedFile (formattedInfo ^. formattedFileInfoContentsAnsi))
|
|
TargetDir -> NoEdit (InputPath (formattedInfo ^. formattedFileInfoPath))
|
|
|
|
renderFormattedOutput :: forall r. Members '[Embed IO, App, Resource, Files] r => FormatTarget -> FormatOptions -> FormattedFileInfo -> Sem r ()
|
|
renderFormattedOutput target opts fInfo = do
|
|
let renderMode = renderModeFromOptions target opts fInfo
|
|
outputResult renderMode
|
|
where
|
|
outputResult :: FormatRenderMode -> Sem r ()
|
|
outputResult = \case
|
|
EditInPlace i@(FormattedFileInfo {..}) ->
|
|
runTempFileIO $
|
|
restoreFileOnError _formattedFileInfoPath $
|
|
writeFile' _formattedFileInfoPath (i ^. formattedFileInfoContentsText)
|
|
NoEdit m -> case m of
|
|
ReformattedFile ts -> forM_ ts renderStdOut
|
|
InputPath p -> say (pack (toFilePath p))
|
|
Silent -> return ()
|
|
|
|
runScopeFileApp :: Member App r => Sem (ScopeEff ': r) a -> Sem r a
|
|
runScopeFileApp = interpret $ \case
|
|
ScopeFile p -> do
|
|
let appFile =
|
|
AppPath
|
|
{ _pathPath = mkPrepath (toFilePath p),
|
|
_pathIsInput = False
|
|
}
|
|
runPipeline appFile upToScoping
|