1
1
mirror of https://github.com/anoma/juvix.git synced 2024-12-02 10:47:32 +03:00
juvix/app/TopCommand/Options.hs
Jan Mas Rovira bad61a797f
Export Juvix source code to latex (#2917)
This pr adds two new commands related to latex.
1. `juvix dev latex getJuvixSty`. This command prints the contents of
the `juvix.sty` latex package to stdout. It has no options and the
expected usage is `juvix dev latex getJuvixSty > juvix.sty`.
2. `juvix dev latex export`. Expects a .juvix file as an argument and
outputs to stdout the highlighted module in latex format. Optional flags
`--from LINE`, `--to LINE` to output only the specified line range.
There is a `--mode` flag to choose how you want the output.
   ```
   • standalone: Output a ready to compile LaTeX file
   • wrap: Wrap the code in a Verbatim environment
   • raw: Output only the code (default: standalone)
   ```
4. As shown in the standalone output, one is allowed to choose the theme
when importing the juvix package like this: `\usepackage[theme =
latte]{juvix}`. Available themes are `latte`, `frappe`, `macchiato`,
`mocha`.

Examples:
To generate the following output I ran these commands:
```
cd examples/milestones/HelloWorld
mkdir latex
juvix dev latex getJuvixSty > latex/juvix.sty
juvix dev latex export HelloWorld.juvix > latex/main.tex
cd latex
xelatex main.tex
open main.pdf
```
1. with `\usepackage[theme = latte]{juvix}`:

![image](https://github.com/user-attachments/assets/200c212f-cc18-4dac-95fe-b3828346e7fa)
1. with `\usepackage[theme = frappe]{juvix}`:

![image](https://github.com/user-attachments/assets/a71d07aa-8adc-485c-a41d-3ea62dc2c5a3)
1. with `\usepackage[theme = macchiato]{juvix}`:

![image](https://github.com/user-attachments/assets/e7e878cf-3c2b-4497-a06c-0e8a445b5116)
1. with `\usepackage[theme = mocha]{juvix}`:

![image](https://github.com/user-attachments/assets/79a4c82c-c90e-4844-baf4-f107d8b8ae20)
2024-08-05 11:28:19 +02:00

250 lines
6.7 KiB
Haskell

module TopCommand.Options where
import Commands.Clean.Options
import Commands.Compile.Options
import Commands.Dependencies.Options qualified as Dependencies
import Commands.Dev.Options qualified as Dev
import Commands.Doctor.Options
import Commands.Eval.Options
import Commands.Format.Options
import Commands.Html.Options
import Commands.Init.Options
import Commands.Isabelle.Options
import Commands.Markdown.Options
import Commands.Repl.Options
import Commands.Typecheck.Options
import CommonOptions hiding (Doc)
import Data.Generics.Uniplate.Data
import GlobalOptions
data TopCommand
= DisplayVersion
| DisplayNumericVersion
| DisplayHelp
| Typecheck TypecheckOptions
| Compile CompileCommand
| Clean CleanOptions
| Eval EvalOptions
| Html HtmlOptions
| Markdown MarkdownOptions
| Isabelle IsabelleOptions
| Dev Dev.DevCommand
| Doctor DoctorOptions
| Init InitOptions
| JuvixRepl ReplOptions
| JuvixFormat FormatOptions
| Dependencies Dependencies.DependenciesCommand
deriving stock (Data)
topCommandInputPath :: TopCommand -> IO (Maybe (SomePath Abs))
topCommandInputPath t = do
d <- firstJustM getInputFileOrDir (universeBi t)
f <- firstJustM getInputFile (universeBi t)
return (f <|> d)
where
getInputFile :: AppPath File -> IO (Maybe (SomePath Abs))
getInputFile p
| p ^. pathIsInput = do
cwd <- getCurrentDir
Just . File <$> prepathToAbsFile cwd (p ^. pathPath)
| otherwise = return Nothing
getInputFileOrDir :: AppPath FileOrDir -> IO (Maybe (SomePath Abs))
getInputFileOrDir p
| p ^. pathIsInput = getInputPathFromPrepathFileOrDir (p ^. pathPath)
| otherwise = return Nothing
getInputPathFromPrepathFileOrDir :: Prepath FileOrDir -> IO (Maybe (SomePath Abs))
getInputPathFromPrepathFileOrDir p = do
cwd <- getCurrentDir
lr <- fromPreFileOrDir cwd p
return . Just $ case lr of
Left file -> File file
Right dir -> Dir dir
parseDisplayVersion :: Parser TopCommand
parseDisplayVersion =
flag'
DisplayVersion
( long "version"
<> short 'v'
<> help "Show version information"
)
parseDisplayNumericVersion :: Parser TopCommand
parseDisplayNumericVersion =
flag'
DisplayNumericVersion
( long "numeric-version"
<> help "Show only the version number"
)
parseDisplayHelp :: Parser TopCommand
parseDisplayHelp =
flag'
DisplayHelp
( long "help"
<> short 'h'
<> help "Show the help text"
)
parseUtility :: Parser TopCommand
parseUtility =
hsubparser
( mconcat
[ commandGroup "Utility commands:",
metavar "UTILITY_CMD",
commandInit,
commandRepl,
commandFormat,
commandClean,
commandDependencies,
commandDoctor,
commandDev
]
)
where
commandInit :: Mod CommandFields TopCommand
commandInit =
command
"init"
( info
(Init <$> parseInitOptions)
(progDesc "Interactively initialize a Juvix project in the current directory")
)
commandDoctor :: Mod CommandFields TopCommand
commandDoctor =
command
"doctor"
( info
(Doctor <$> parseDoctorOptions)
(progDesc "Perform checks on your Juvix development environment")
)
commandRepl :: Mod CommandFields TopCommand
commandRepl =
command
"repl"
( info
(JuvixRepl <$> parseRepl)
(progDesc "Run the Juvix REPL")
)
commandFormat :: Mod CommandFields TopCommand
commandFormat =
command "format" $
info
(JuvixFormat <$> parseFormat)
( headerDoc
( Just
( vsep
[ "juvix format is used to format Juvix source files.",
"",
"Given a file, it prints the reformatted source to standard output.",
"Given a project directory it prints a list of unformatted files in the project.",
"Given no argument it prints a list of unformatted files in the project which contains the current directory."
]
)
)
<> progDesc "Format a Juvix file or Juvix project"
)
commandClean :: Mod CommandFields TopCommand
commandClean =
command
"clean"
(info (Clean <$> parseCleanOptions) (progDesc "Delete build artifacts"))
commandDependencies :: Mod CommandFields TopCommand
commandDependencies =
command
"dependencies"
(info (Dependencies <$> Dependencies.parseDependenciesCommand) (progDesc "Subcommands related to dependencies"))
commandCheck :: Mod CommandFields TopCommand
commandCheck =
command "typecheck" $
info
(Typecheck <$> parseTypecheck)
(progDesc "Typecheck a Juvix file")
commandCompile :: Mod CommandFields TopCommand
commandCompile =
command "compile" $
info
(Compile <$> parseCompileCommand)
(progDesc "Compile a Juvix file")
commandEval :: Mod CommandFields TopCommand
commandEval =
command "eval" $
info
(Eval <$> parseEvalOptions)
(progDesc "Evaluate a Juvix file")
commandHtml :: Mod CommandFields TopCommand
commandHtml =
command "html" $
info
(Html <$> parseHtml)
(progDesc "Generate HTML for a Juvix file")
commandMarkdown :: Mod CommandFields TopCommand
commandMarkdown =
command "markdown" $
info
(Markdown <$> parseJuvixMarkdown)
(progDesc "Translate Juvix code blocks in a Markdown file to Markdown")
commandIsabelle :: Mod CommandFields TopCommand
commandIsabelle =
command "isabelle" $
info
(Isabelle <$> parseIsabelle)
(progDesc "Translate a Juvix file to Isabelle/HOL")
commandDev :: Mod CommandFields TopCommand
commandDev =
command "dev" $
info
(Dev <$> Dev.parseDevCommand)
(progDesc "Commands for the Juvix compiler developers")
parseCompilerCommand :: Parser TopCommand
parseCompilerCommand =
hsubparser
( mconcat
[ commandGroup "Compiler commands:",
metavar "COMPILER_CMD",
commandCheck,
commandCompile,
commandEval,
commandHtml,
commandMarkdown,
commandIsabelle
]
)
parseTopCommand :: Parser TopCommand
parseTopCommand =
parseDisplayVersion
<|> parseDisplayNumericVersion
<|> parseDisplayHelp
<|> parseCompilerCommand
<|> parseUtility
descr :: ParserInfo (GlobalOptions, TopCommand)
descr =
info
( do
cli <- parseTopCommand
opts <- parseGlobalFlags
return (opts, cli)
)
( fullDesc
<> progDesc "The Juvix compiler."
<> footerDoc (Just foot)
)
where
foot :: AnsiDoc
foot = annotate bold "maintainers: " <> "The Juvix Team"