lean4-htt/Lake/Cli.lean

130 lines
3.9 KiB
Text

/-
Copyright (c) 2021 Mac Malone. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mac Malone
-/
import Lake.Init
import Lake.Help
import Lake.BuildBin
import Lake.LeanConfig
import Lake.CliT
open System
namespace Lake
-- # Utilities
def Package.run (script : String) (args : List String) (self : Package) : IO PUnit :=
if let some script := self.scripts.find? script then
script args
else
self.scripts.forM fun name _ => IO.println name
def Package.clean (self : Package) : IO PUnit :=
IO.FS.removeDirAll self.buildDir
-- # CLI
structure CliOptions where
wantsHelp : Bool := false
dir : FilePath := "."
file : FilePath := defaultConfigFile
subArgs : List String := []
abbrev CliM := CliT (StateT CliOptions IO)
-- abbrev LakeCliMethods := CliMethods (StateT CliState IO)
namespace CliM
open CliT
def getDir : CliM FilePath :=
getThe CliOptions >>= (·.dir)
def setDir (dir : FilePath) : CliM PUnit :=
modifyThe CliOptions fun st => {st with dir := dir}
def getFile : CliM FilePath :=
getThe CliOptions >>= (·.file)
def setFile (file : FilePath) : CliM PUnit :=
modifyThe CliOptions fun st => {st with file := file}
def getSubArgs : CliM (List String) :=
getThe CliOptions >>= (·.subArgs)
def setSubArgs (args : List String) : CliM PUnit :=
modifyThe CliOptions fun st => {st with subArgs := args}
def getWantsHelp : CliM Bool :=
getThe CliOptions >>= (·.wantsHelp)
def setWantsHelp : CliM PUnit :=
modifyThe CliOptions fun st => {st with wantsHelp := true}
def getPkg (args : List String) : CliM Package := do
Package.fromDir (← getDir) args (← getFile)
def takeArg : CliM String := do
match (← takeArg?) with
| none => throw <| IO.userError "missing argument"
| some arg => arg
def takeFileArg : CliM FilePath := do
match (← takeArg?) with
| none => throw <| IO.userError "missing file argument"
| some arg => arg
def unknownShortOption (opt : Char) : CliM PUnit :=
throw <| IO.userError s!"unknown short option '-{opt}'"
def shortOption : (opt : Char) → CliM PUnit
| 'h' => setWantsHelp
| 'd' => do setDir (← takeFileArg)
| 'f' => do setFile (← takeFileArg)
| opt => unknownShortOption opt
def unknownLongOption (opt : String) : CliM PUnit :=
throw <| IO.userError s!"unknown long option '{opt}'"
def longOption : (opt : String) → CliM PUnit
| "--help" => setWantsHelp
| "--dir" => do setDir (← takeFileArg)
| "--file" => do setFile (← takeFileArg)
| "--" => do setSubArgs (← takeArgs)
| opt => unknownLongOption opt
def command : (cmd : String) → CliM PUnit
| "new" => do new (← takeArg)
| "init" => do init (← takeArg)
| "run" => do (← getPkg []).run (← takeArg) (← getSubArgs)
| "configure" => do configure (← getPkg (← getSubArgs))
| "print-paths" => do printPaths (← getPkg (← getSubArgs)) (← takeArgs)
| "build" => do build (← getPkg (← getSubArgs))
| "build-lib" => do buildLib (← getPkg (← getSubArgs))
| "build-bin" => do buildBin (← getPkg (← getSubArgs))
| "clean" => do (← getPkg (← getSubArgs)).clean
| "help" => do IO.println <| help (← takeArg?)
| "self-check" => verifyLeanVersion
| cmd => throw <| IO.userError s!"unknown command '{cmd}'"
def processArgs : CliM PUnit := do
match (← getArgs) with
| [] => IO.println usage
| ["--version"] => IO.println uiVersionString
| _ => -- normal CLI
processOptions
match (← takeArg?) with
| none =>
if (← getWantsHelp) then IO.println usage else
throw <| IO.userError "expected command"
| some cmd =>
if (← getWantsHelp) then IO.println (help cmd) else
command cmd
def run (self : CliM PUnit) (args : List String) : IO PUnit :=
CliT.run self args {shortOption, longOption, longShortOption := unknownLongOption} |>.run' {}
end CliM
def cli (args : List String) : IO PUnit :=
CliM.processArgs.run args