feat: replace __args__ with get_config? + related refactors

This commit is contained in:
tydeu 2022-07-08 19:00:52 -04:00
parent 185e10f6f3
commit 0fbd7a866a
12 changed files with 175 additions and 167 deletions

View file

@ -19,6 +19,7 @@ OPTIONS:
--dir, -d=file use the package configuration in a specific directory
--file, -f=file use a specific file for the package configuration
--lean=cmd specify the `lean` command used by Lake
-K key[=value] set the configuration file option named key
COMMANDS:
new <name> [<temp>] create a Lean package in a new directory
@ -60,7 +61,7 @@ def helpBuild :=
"Build targets
USAGE:
lake build [<targets>...] [-- <args>...]
lake build [<targets>...]
A target is specified with a string of the form:
@ -96,18 +97,16 @@ TARGET EXAMPLES: build the ...
:exe root package's executable
A bare `build` command will build the default facet of the root package.
Arguments to the `Packager` itself can be specified with `args`.
Package dependencies are not updated during a build."
def helpUpdate :=
"Update dependencies
USAGE:
lake update [-- <args>...]
lake update
This command sets up the directory with the package's dependencies
(i.e., `packagesDir`, which is, by default, `lean_packages`).
Passes `args` to the `Packager` if specified.
For each (transitive) git dependency, the specified commit is checked out
into a sub-directory of `packagesDir`. Already checked out dependencies are
@ -122,10 +121,9 @@ def helpClean :=
"Remove build outputs
USAGE:
lake clean [-- <args>...]
lake clean
Deletes the build directory of the package.
Arguments to the `Packager` itself can be specified with `args`."
Deletes the build directory of the package."
def helpScriptCli :=
"Manage Lake scripts

View file

@ -33,11 +33,11 @@ structure LakeConfig where
configFile : FilePath := defaultConfigFile
leanInstall : LeanInstall
lakeInstall : LakeInstall
args : List String := []
options : NameMap String := {}
def loadPkg (config : LakeConfig) : LogIO Package := do
setupLeanSearchPath config.leanInstall config.lakeInstall
Package.load config.rootDir config.args (config.rootDir / config.configFile)
Package.load config.rootDir config.options (config.rootDir / config.configFile)
def loadManifestMap (manifestFile : FilePath) : LogIO (Lean.NameMap PackageEntry) := do
if let Except.ok contents ← IO.FS.readFile manifestFile |>.toBaseIO then
@ -72,6 +72,7 @@ structure LakeOptions where
configFile : FilePath := defaultConfigFile
leanInstall? : Option LeanInstall := none
lakeInstall? : Option LakeInstall := none
configOptions : NameMap String := {}
subArgs : List String := []
wantsHelp : Bool := false
@ -111,12 +112,13 @@ def getInstall (opts : LakeOptions) : Except CliError (LeanInstall × LakeInstal
return (← getLeanInstall opts, ← getLakeInstall opts)
/-- Make a `LakeConfig` from a `LakeOptions`. -/
def mkLakeConfig (opts : LakeOptions) (args : List String := []) : Except CliError LakeConfig := do
def mkLakeConfig (opts : LakeOptions) : Except CliError LakeConfig := do
let (leanInstall, lakeInstall) ← getInstall opts
return {
rootDir := opts.rootDir,
configFile := opts.configFile,
leanInstall, lakeInstall, args
leanInstall, lakeInstall,
options := opts.configOptions
}
/-- Make a Lake `Context` from a `Workspace` and `LakeConfig`. -/
@ -154,10 +156,21 @@ def noArgsRem (act : CliStateM α) : CliM α := do
-- ## Option Parsing
def setConfigOption (kvPair : String) : CliM PUnit :=
let pos := kvPair.posOf '='
let (key, val) :=
if pos = kvPair.endPos then
(kvPair.toName, "")
else
(kvPair.extract 0 pos |>.toName, kvPair.extract (kvPair.next pos) kvPair.endPos)
modifyThe LakeOptions fun opts =>
{opts with configOptions := opts.configOptions.insert key val}
def shortOption : (opt : Char) → CliM PUnit
| 'h' => modifyThe LakeOptions ({· with wantsHelp := true})
| 'd' => do let rootDir ← takeOptArg "-d" "path"; modifyThe LakeOptions ({· with rootDir})
| 'f' => do let configFile ← takeOptArg "-f" "path"; modifyThe LakeOptions ({· with configFile})
| 'K' => do setConfigOption <| ← takeOptArg "-K" "key-value pair"
| opt => throw <| CliError.unknownShortOption opt
def longOption : (opt : String) → CliM PUnit
@ -256,7 +269,7 @@ def script : (cmd : String) → CliM PUnit
IO.println s!"{pkgName}/{scriptName}"
| "run" => do
processOptions lakeOption
let spec ← takeArg "script spec"; let args ← takeArgs
let spec ← takeArg "script name"; let args ← takeArgs
let config ← mkLakeConfig (← getThe LakeOptions)
let ws ← loadWorkspace config
let (pkg, scriptName) ← parseScriptSpec ws spec
@ -270,7 +283,7 @@ def script : (cmd : String) → CliM PUnit
throw <| CliError.unknownScript scriptName
| "doc" => do
processOptions lakeOption
let spec ← takeArg "script spec"
let spec ← takeArg "script name"
let config ← mkLakeConfig (← getThe LakeOptions)
noArgsRem do
let ws ← loadWorkspace config
@ -308,7 +321,7 @@ def command : (cmd : String) → CliM PUnit
| "build" => do
processOptions lakeOption
let opts ← getThe LakeOptions
let config ← mkLakeConfig opts opts.subArgs
let config ← mkLakeConfig opts
let ws ← loadWorkspace config
let targetSpecs ← takeArgs
let target ← show Except _ _ from do
@ -322,7 +335,7 @@ def command : (cmd : String) → CliM PUnit
| "update" => do
processOptions lakeOption
let opts ← getThe LakeOptions
let config ← mkLakeConfig opts opts.subArgs
let config ← mkLakeConfig opts
noArgsRem <| discard <| loadWorkspace config (updateDeps := true)
| "print-paths" => do
processOptions lakeOption
@ -331,7 +344,7 @@ def command : (cmd : String) → CliM PUnit
| "clean" => do
processOptions lakeOption
let opts ← getThe LakeOptions
let config ← mkLakeConfig opts opts.subArgs
let config ← mkLakeConfig opts
noArgsRem <| (← loadPkg config).clean
| "script" => do
if let some cmd ← takeArg? then

View file

@ -3,6 +3,7 @@ Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Gabriel Ebner, Sebastian Ullrich, Mac Malone
-/
import Lean.Data.Name
namespace Lake
open Lean System
@ -17,7 +18,7 @@ In Lake, dependency sources currently come into flavors:
-/
inductive Source where
| path (dir : FilePath)
| git (url : String) (rev : Option String)
| git (url : String) (rev : Option String) (subDir : Option FilePath)
deriving Inhabited, Repr
/-- A `Dependency` of a package. -/
@ -33,13 +34,8 @@ structure Dependency where
-/
src : Source
/--
The subdirectory of the dependency's source where
the dependency's package configuration is located.
-/
dir : FilePath := "."
/--
Arguments to pass to the dependency's package configuration.
-/
args : List String := []
options : NameMap String := {}
deriving Inhabited, Repr
deriving Inhabited

View file

@ -38,10 +38,10 @@ def processHeader (header : Syntax) (opts : Options) (trustLevel : UInt32)
modify (·.add { fileName := inputCtx.fileName, data := toString e, pos })
mkEmptyEnvironment
/-- Lake `Lean.Environment.evalConstCheck` but with plain universe-polymorphic `Except`. -/
/-- Like `Lean.Environment.evalConstCheck` but with plain universe-polymorphic `Except`. -/
unsafe def evalConstCheck (α) (env : Environment) (opts : Options) (type : Name) (const : Name) : Except String α :=
match env.find? const with
| none => throw (s!"unknown constant '{const}'")
| none => throw s!"unknown constant '{const}'"
| some info =>
match info.type with
| Expr.const c _ _ =>
@ -57,7 +57,7 @@ where
namespace Package
/-- Unsafe implementation of `load`. -/
unsafe def loadUnsafe (dir : FilePath) (args : List String := [])
unsafe def loadUnsafe (dir : FilePath) (configOpts : NameMap String)
(configFile := dir / defaultConfigFile) (leanOpts := Options.empty)
: LogIO Package := do
@ -70,7 +70,7 @@ unsafe def loadUnsafe (dir : FilePath) (args : List String := [])
-- Configure Extensions
let env := dirExt.setState env dir
let env := argsExt.setState env args
let env := optsExt.setState env configOpts
-- Elaborate File
let commandState := Elab.Command.mkState env messages leanOpts
@ -81,82 +81,89 @@ unsafe def loadUnsafe (dir : FilePath) (args : List String := [])
| MessageSeverity.warning => logWarning (← msg.toString)
| MessageSeverity.error => logError (← msg.toString)
-- Extract Configuration
-- Extract Configuration
if s.commandState.messages.hasErrors then
error s!"package configuration `{configFile}` has errors"
-- Load Package Configuration
let env := s.commandState.env
if !s.commandState.messages.hasErrors then
let pkgDeclName ←
match packageAttr.ext.getState env |>.toList with
| [] => error s!"configuration file is missing a `package` declaration"
| [pkgDeclName] =>
-- Load Package Configuration
let config ← IO.ofExcept <| Id.run <| ExceptT.run <|
env.evalConstCheck PackageConfig leanOpts ``PackageConfig pkgDeclName
if config.extraDepTarget.isSome then
logWarning <| "`extraDepTarget` has been deprecated. " ++
"Try to use a custom target or raise an issue about your use case."
-- Tag Load Helpers
let mkTagMap {α} (attr) (f : Name → IO α) : IO (NameMap α) :=
attr.ext.getState env |>.foldM (init := {}) fun map declName =>
return map.insert declName <| ← f declName
let mkDTagMap {β} (attr : TagAttribute) (f : (n : WfName) → IO (β n)) : IO (DNameMap β) :=
attr.ext.getState env |>.foldM (init := {}) fun map declName =>
let declName := WfName.ofName declName
return map.insert declName <| ← f declName
let evalConst (α typeName declName) : IO α :=
IO.ofExcept (evalConstCheck α env leanOpts typeName declName)
let evalConstMap {α β} (f : α → β) (declName) : IO β :=
match env.evalConst α leanOpts declName with
| .ok a => pure <| f a
| .error e => throw <| IO.userError e
-- Load Target & Script Configurations
let scripts ← mkTagMap scriptAttr fun declName => do
let fn ← IO.ofExcept <| evalConstCheck ScriptFn env leanOpts ``ScriptFn declName
return {fn, doc? := (← findDocString? env declName)}
let leanLibConfigs ← mkTagMap leanLibAttr
(evalConst LeanLibConfig ``LeanLibConfig)
let leanExeConfigs ← mkTagMap leanExeAttr
(evalConst LeanExeConfig ``LeanExeConfig)
let externLibConfigs ← mkTagMap externLibAttr
(evalConst ExternLibConfig ``ExternLibConfig)
let opaqueModuleFacetConfigs ← mkDTagMap moduleFacetAttr fun name => do
match evalConstCheck ModuleFacetDecl env leanOpts ``ModuleFacetDecl name with
| .ok decl =>
if h : name = decl.name then
return OpaqueModuleFacetConfig.mk (h ▸ decl.config)
else
error s!"Facet was defined as `{decl.1}`, but was registered as `{name}`"
| .error e => throw <| IO.userError e
let opaquePackageFacetConfigs ← mkDTagMap packageFacetAttr fun name => do
match evalConstCheck PackageFacetDecl env leanOpts ``PackageFacetDecl name with
| .ok decl =>
if h : name = decl.name then
return OpaquePackageFacetConfig.mk (h ▸ decl.config)
else
error s!"Facet was defined as `{decl.1}`, but was registered as `{name}`"
| .error e => throw <| IO.userError e
let opaqueTargetConfigs ← mkTagMap targetAttr
(evalConstMap OpaqueTargetConfig.mk)
let defaultTargets :=
defaultTargetAttr.ext.getState env |>.fold (init := #[]) fun arr name =>
arr.push <| WfName.ofName name
-- Construct the Package
if leanLibConfigs.isEmpty && leanExeConfigs.isEmpty && config.defaultFacet ≠ .none then
logWarning <| "Package targets are deprecated. " ++
"Add a `lean_exe` and/or `lean_lib` default target to the package instead."
return {
dir, config, scripts,
dependencies := depsExt.getState env,
leanLibConfigs, leanExeConfigs, externLibConfigs,
opaqueModuleFacetConfigs, opaquePackageFacetConfigs, opaqueTargetConfigs,
defaultTargets
}
| [name] => pure name
| _ => error s!"configuration file has multiple `package` declarations"
else
error s!"package configuration `{configFile}` has errors"
let config ← IO.ofExcept <|
evalConstCheck PackageConfig env leanOpts ``PackageConfig pkgDeclName
if config.extraDepTarget.isSome then
logWarning <| "`extraDepTarget` has been deprecated. " ++
"Try to use a custom target or raise an issue about your use case."
-- Tag Load Helpers
let mkTagMap {α} (attr) (f : Name → IO α) : IO (NameMap α) :=
attr.ext.getState env |>.foldM (init := {}) fun map declName =>
return map.insert declName <| ← f declName
let mkDTagMap {β} (attr : TagAttribute) (f : (n : WfName) → IO (β n)) : IO (DNameMap β) :=
attr.ext.getState env |>.foldM (init := {}) fun map declName =>
let declName := WfName.ofName declName
return map.insert declName <| ← f declName
let evalConst (α typeName declName) : IO α :=
IO.ofExcept (evalConstCheck α env leanOpts typeName declName)
let evalConstMap {α β} (f : α → β) (declName) : IO β :=
match env.evalConst α leanOpts declName with
| .ok a => pure <| f a
| .error e => throw <| IO.userError e
-- Load Dependency, Script, Facet, & Target Configurations
let dependencies ←
packageDepAttr.ext.getState env |>.foldM (init := #[]) fun arr name => do
return arr.push <| ← evalConst Dependency ``Dependency name
let scripts ← mkTagMap scriptAttr fun declName => do
let fn ← IO.ofExcept <| evalConstCheck ScriptFn env leanOpts ``ScriptFn declName
return {fn, doc? := (← findDocString? env declName)}
let leanLibConfigs ← mkTagMap leanLibAttr
(evalConst LeanLibConfig ``LeanLibConfig)
let leanExeConfigs ← mkTagMap leanExeAttr
(evalConst LeanExeConfig ``LeanExeConfig)
let externLibConfigs ← mkTagMap externLibAttr
(evalConst ExternLibConfig ``ExternLibConfig)
let opaqueModuleFacetConfigs ← mkDTagMap moduleFacetAttr fun name => do
match evalConstCheck ModuleFacetDecl env leanOpts ``ModuleFacetDecl name with
| .ok decl =>
if h : name = decl.name then
return OpaqueModuleFacetConfig.mk (h ▸ decl.config)
else
error s!"Facet was defined as `{decl.name}`, but was registered as `{name}`"
| .error e => throw <| IO.userError e
let opaquePackageFacetConfigs ← mkDTagMap packageFacetAttr fun name => do
match evalConstCheck PackageFacetDecl env leanOpts ``PackageFacetDecl name with
| .ok decl =>
if h : name = decl.name then
return OpaquePackageFacetConfig.mk (h ▸ decl.config)
else
error s!"Facet was defined as `{decl.name}`, but was registered as `{name}`"
| .error e => throw <| IO.userError e
let opaqueTargetConfigs ← mkTagMap targetAttr
(evalConstMap OpaqueTargetConfig.mk)
let defaultTargets :=
defaultTargetAttr.ext.getState env |>.fold (init := #[]) fun arr name =>
arr.push <| WfName.ofName name
-- Construct the Package
if leanLibConfigs.isEmpty && leanExeConfigs.isEmpty && config.defaultFacet ≠ .none then
logWarning <| "Package targets are deprecated. " ++
"Add a `lean_exe` and/or `lean_lib` default target to the package instead."
return {
dir, config, scripts, dependencies,
leanLibConfigs, leanExeConfigs, externLibConfigs,
opaqueModuleFacetConfigs, opaquePackageFacetConfigs, opaqueTargetConfigs,
defaultTargets
}
/--
Load the package located in
the given directory with the given configuration file.
-/
@[implementedBy loadUnsafe]
opaque load (dir : FilePath) (args : List String := [])
(configFile := dir / defaultConfigFile) (leanOpts := Options.empty) : LogIO Package
opaque load (dir : FilePath) (configOpts : NameMap String)
(configFile := dir / defaultConfigFile) (leanOpts := Options.empty) : LogIO Package

View file

@ -81,11 +81,11 @@ def materializeDep (ws : Workspace)
(pkg : Package) (dep : Dependency) (shouldUpdate := true) : ResolveM FilePath :=
match dep.src with
| Source.path dir => return pkg.dir / dir
| Source.git url rev? => do
| Source.git url rev? subDir? => do
let name := dep.name.toString (escape := false)
let depDir := ws.packagesDir / name
materializeGitPkg name depDir url rev? shouldUpdate
return depDir
let gitDir := ws.packagesDir / name
materializeGitPkg name gitDir url rev? shouldUpdate
return match subDir? with | some subDir => gitDir / subDir | none => gitDir
/--
Resolves a `Dependency` relative to the given `Package`
@ -94,7 +94,7 @@ in the same `Workspace`, downloading and/or updating it as necessary.
def resolveDep (ws : Workspace)
(pkg : Package) (dep : Dependency) (shouldUpdate := true) : ResolveM Package := do
let dir ← materializeDep ws pkg dep shouldUpdate
let depPkg ← Package.load (dir / dep.dir) dep.args
let depPkg ← Package.load dir dep.options
unless depPkg.name == dep.name do
throw <| IO.userError <|
s!"{pkg.name} (in {pkg.dir}) depends on {dep.name}, " ++

View file

@ -11,6 +11,9 @@ namespace Lake
initialize packageAttr : TagAttribute ←
registerTagAttribute `package "mark a definition as a Lake package configuration"
initialize packageDepAttr : TagAttribute ←
registerTagAttribute `packageDep "mark a definition as a Lake package dependency"
initialize scriptAttr : TagAttribute ←
registerTagAttribute `script "mark a definition as a Lake script"

View file

@ -16,10 +16,10 @@ outside Lakefile elaboration (e.g., when editing).
opaque dummyDir : System.FilePath
/--
A dummy default constant for `__args__` to make it type check
A dummy default constant for `get_config` to make it type check
outside Lakefile elaboration (e.g., when editing).
-/
opaque dummyArgs : List String
opaque dummyGetConfig? : Name → Option String
/--
A macro that expands to the path of package's directory
@ -39,17 +39,22 @@ def elabDirConst : TermElab := fun stx expectedType? => do
withMacroExpansion stx exp <| elabTerm exp expectedType?
/--
A macro that expands to the configuration arguments passed
via the Lake command line during the Lakefile's elaboration.
-/
scoped syntax (name := argsConst) "__args__" :term
A macro that expands to the specified configuration option (or `none`,
if not the option has not been set) during the Lakefile's elaboration.
@[termElab argsConst]
def elabArgsConst : TermElab := fun stx expectedType? => do
let exp :=
if let some args := argsExt.getState (← getEnv) then
quote (k := `term) args
else
-- `id` app forces Lean to show macro's doc rather than the constant's
Syntax.mkApp (mkCIdentFrom stx ``id) #[mkCIdentFrom stx ``dummyArgs]
withMacroExpansion stx exp <| elabTerm exp expectedType?
Configuration arguments are set either via the Lake CLI (by the `-K` option)
or via the `with` clause in a `require` statement.
-/
scoped syntax (name := getConfig) "get_config? " ident :term
@[termElab getConfig]
def elabGetConfig : TermElab := fun stx expectedType? => do
match stx with
| `(getConfig| get_config? $key) =>
let exp :=
if let some opts := optsExt.getState (← getEnv) then
quote (k := `term) <| opts.find? key.getId
else
Syntax.mkApp (mkCIdentFrom stx ``dummyGetConfig?) #[quote key.getId]
withMacroExpansion stx exp <| elabTerm exp expectedType?
| _ => throwUnsupportedSyntax

View file

@ -10,11 +10,8 @@ open Lean
namespace Lake
initialize depsExt : EnvExtension (Array Dependency) ←
registerEnvExtension (pure #[])
initialize dirExt : EnvExtension (Option System.FilePath) ←
registerEnvExtension (pure none)
initialize argsExt : EnvExtension (Option (List String)) ←
initialize optsExt : EnvExtension (Option (NameMap String)) ←
registerEnvExtension (pure none)

View file

@ -3,12 +3,11 @@ Copyright (c) 2021 Mac Malone. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mac Malone
-/
import Lean.Elab.Command
import Lake.Util.EvalTerm
import Lean.Parser.Command
import Lake.DSL.Extensions
namespace Lake.DSL
open Lean Meta Elab Command
open Lean Parser Command
syntax fromPath :=
term
@ -16,34 +15,27 @@ syntax fromPath :=
syntax fromGit :=
&" git " term:max ("@" term:max)? ("/" term)?
syntax fromClause :=
fromGit <|> fromPath
syntax depSpec :=
ident " from " fromClause (" with " term)?
ident " from " (fromGit <|> fromPath) (" with " term)?
def evalDepSpec : Syntax → TermElabM Dependency
| `(depSpec| $name:ident from git $url $[@ $rev?]? $[/ $path?]? $[with $args?:term]?) => do
let url ← evalTerm String url
let rev ←
match rev? with
| some rev => some <$> evalTerm String rev
| none => pure none
let path ←
match path? with
| some path => evalTerm System.FilePath path
| none => pure "."
let args ← match args? with
| some args => evalTerm (List String) args
| none => pure []
return {name := name.getId, src := Source.git url rev, dir := path, args}
| `(depSpec| $name:ident from $path:term $[with $args?:term]?) => do
let path ← evalTerm System.FilePath path
let args ← match args? with
| some args => evalTerm (List String) args
| none => pure []
return {name := name.getId, src := Source.path path, args}
| _ => throwUnsupportedSyntax
def expandDepSpec : TSyntax ``depSpec → MacroM Command
| `(depSpec| $name:ident from git $url $[@ $rev?]? $[/ $path?]? $[with $opts?]?) => do
let rev ← match rev? with | some rev => `(some $rev) | none => `(none)
let path ← match path? with | some path => `(some $path) | none => `(none)
let opts := opts?.getD <| ← `({})
`(@[packageDep] def $name : Dependency := {
name := $(quote name.getId),
src := Source.git $url $rev $path,
options := $opts
})
| `(depSpec| $name:ident from $path:term $[with $opts?]?) => do
let opts := opts?.getD <| ← `({})
`(@[packageDep] def $name : Dependency := {
name := $(quote name.getId),
src := Source.path $path,
options := $opts
})
| _ => Macro.throwUnsupported
/--
Adds a mew package dependency to the workspace. Has two forms:
@ -61,6 +53,5 @@ The elements of both the `from` and `with` clauses are proper terms so
normal computation is supported within them (though parentheses made be
required to disambiguate the syntax).
-/
scoped elab (name := requireDecl) "require " spec:depSpec : command => do
let dep ← runTermElabM none <| fun _ => evalDepSpec spec
modifyEnv (depsExt.modifyState · (·.push dep))
scoped macro (name := requireDecl) "require " spec:depSpec : command =>
expandDepSpec spec

View file

@ -77,22 +77,20 @@ variable [Monad m] [MonadStateOf ArgList m]
/-- Splits a long option of the form `"--long foo bar"` into `--long` and `"foo bar"`. -/
@[inline] def longOptionOrSpace (handle : String → m α) (opt : String) : m α :=
let pos := opt.posOf ' '
let arg := opt.drop pos.byteIdx.succ -- TODO: this code is only correct if all characters in `opt` have size 1
if arg.isEmpty then
if pos = opt.endPos then
handle opt
else do
consArg arg
handle <| opt.take pos.byteIdx |>.trimLeft -- TODO: this code is only correct if all characters in `opt` have size 1
consArg <| opt.extract (opt.next pos) opt.endPos
handle <| opt.extract 0 pos
/-- Splits a long option of the form `--long=arg` into `--long` and `arg`. -/
@[inline] def longOptionOrEq (handle : String → m α) (opt : String) : m α :=
let pos := opt.posOf '='
let arg := opt.drop pos.byteIdx.succ -- TODO: this code is only correct if all characters in `opt` have size 1
if arg.isEmpty then
if pos = opt.endPos then
handle opt
else do
consArg arg
handle <| opt.take pos.byteIdx -- TODO: this code is only correct if all characters in `opt` have size 1
consArg <| opt.extract (opt.next pos) opt.endPos
handle <| opt.extract 0 pos
/-- Process a long option of the form `--long`, `--long=arg`, `"--long arg"`. -/
@[inline] def longOption (handle : String → m α) : String → m α :=

View file

@ -2,8 +2,8 @@ import Lake
open Lake DSL
package foo where
moreLeanArgs := #[(__args__).get! 0]
moreLeancArgs := #[(__args__).get! 1]
moreLeanArgs := get_config? leanArgs |>.getD "" |>.splitOn " " |>.toArray
moreLeancArgs := get_config? leancArgs |>.getD "" |>.splitOn " " |>.toArray
@[defaultTarget]
lean_exe foo

View file

@ -5,7 +5,7 @@ LAKE=${LAKE:-../../../build/bin/lake}
cd foo
rm -rf build
${LAKE} build -- -Dhygiene=true -DBAR | grep -m2 foo.c
${LAKE} build -- -Dhygiene=false -DBAZ | grep -m2 foo.c
${LAKE} build -- -Dhygiene=false -DBAR | grep -m1 foo.o
${LAKE} build -- -Dhygiene=true -DBAR | grep -m1 foo.olean
${LAKE} build -KleanArgs=-Dhygiene=true -K leancArgs=-DBAR | grep -m2 foo.c
${LAKE} build -KleanArgs=-Dhygiene=false -K leancArgs=-DBAZ | grep -m2 foo.c
${LAKE} build -KleanArgs=-Dhygiene=false -K leancArgs=-DBAR | grep -m1 foo.o
${LAKE} build -KleanArgs=-Dhygiene=true -K leancArgs=-DBAR | grep -m1 foo.olean