@@ -5,11 +5,12 @@ Authors: Arthur Paulino, Jon Eugster
55-/
66import Std.Data.TreeSet
77import Cache.Lean
8+ import Lake.Load.Toml
9+ import Batteries.Tactic.OpenPrivate
810
911variable {α : Type }
1012
1113open Lean
12-
1314namespace Cache.IO
1415
1516open System (FilePath)
@@ -483,22 +484,27 @@ def lookup (hashMap : ModuleHashMap) (modules : List Name) : IO Unit := do
483484 println! " comment: {line}"
484485 if err then IO.Process.exit 1
485486
487+ open private Lake.Glob.ofString? from Lake.Load.Toml in
488+
486489/--
487490Parse a string as either a path or a Lean module name.
488- TODO: If the argument describes a folder, use `walkDir` to find all `.lean` files within.
491+ If the argument describes a folder, use `walkDir` to find all `.lean` files within.
489492
490493Return tuples of the form ("module name", "path to .lean file").
491494
492495The input string `arg` takes one of the following forms:
493496
4944971. `Mathlib.Algebra.Field.Basic`: there exists such a Lean file
495- 2. `Mathlib.Algebra.Field`: no Lean file exists but a folder (TODO)
496- 3. `Mathlib/Algebra/Field/Basic.lean`: the file exists (note potentially `\` on Windows)
497- 4. `Mathlib/Algebra/Field/`: the folder exists (TODO)
498+ 2. `Mathlib.Algebra.Field.+`: no Lean file exists but a folder `Field`
499+ 3. `Mathlib.Algebra.Field.*`: either a file or a folder
500+ (note in some shells escaping as `.\*` might be necessary)
501+ 4. `Mathlib/Algebra/Field/Basic.lean`: the file exists
502+ (note potentially `\` on Windows)
503+ 5. `Mathlib/Algebra/Field/`: the folder exists
498504
499505 Not supported yet:
500506
501- 5 . `Aesop/Builder.lean`: the file does not exist, it's actually somewhere in `.lake`.
507+ 6 . `Aesop/Builder.lean`: the file does not exist, it's actually somewhere in `.lake`.
502508
503509 Note: An argument like `Archive` is treated as module, not a path.
504510-/
@@ -514,39 +520,73 @@ def leanModulesFromSpec (sp : SearchPath) (argₛ : String) :
514520 -- provided file name of a Lean file
515521 let mod : Name := arg.withExtension "" |>.components.foldl .str .anonymous
516522 if !(← arg.pathExists) then
517- -- TODO: (5 .) We could use `getSrcDir` to allow arguments like `Aesop/Builder.lean` which
523+ -- TODO: (6 .) We could use `getSrcDir` to allow arguments like `Aesop/Builder.lean` which
518524 -- refer to a file located under `.lake/packages/...`
519525 return .error s! "Invalid argument: non-existing path { arg} "
520526 if arg.extension == "lean" then
521- -- (3 .) provided existing `.lean` file
527+ -- (4 .) provided existing `.lean` file
522528 return .ok #[(mod, arg)]
523529 else
524- -- (4.) provided existing directory: walk it
525- return .error "Searching lean files in a folder is not supported yet!"
530+ -- (5.) provided existing directory: walk it
531+ IO.println s! "Searching directory { arg} for .lean files"
532+ let leanModulesInFolder ← walkDir sp arg mod
533+ return .ok leanModulesInFolder
526534 else
527535 -- provided a module
528- let mod := argₛ.toName
529- if mod.isAnonymous then
530- -- provided a module name which is not a valid Lean identifier
536+ -- user might provide `.*` or `.+` to include folders
537+ match Lake.Glob.ofString? argₛ with
538+ | none =>
531539 return .error s! "Invalid argument: expected path or module name, not { argₛ} "
532- let sourceFile ← Lean.findLean sp mod
533- if ← sourceFile.pathExists then
534- -- (1.) provided valid module
535- return .ok #[(mod, sourceFile)]
536- else
537- -- provided "pseudo-module" (like `Mathlib.Data`) which
538- -- does not correspond to a Lean file, but to an existing folder
539- -- `Mathlib/Data/`
540- let folder := sourceFile.withExtension ""
541- IO.println s! "Searching directory { folder} for .lean files"
542- if ← folder.pathExists then
543- -- (2.) provided "module name" of an existing folder: walk dir
544- -- TODO: will be implemented in https://github.com/leanprover-community/mathlib4/issues/21838
545- return .error "Entering a part of a module name \
546- (i.e. `Mathlib.Data` when only the folder `Mathlib/Data/` but no \
547- file `Mathlib/Data.lean` exists) is not supported yet!"
540+ | some glob =>
541+ let modules ← match glob with
542+ | .one mod =>
543+ let sourceFile ← Lean.findLean sp mod
544+ pure #[(mod, sourceFile)]
545+ | .submodules mod =>
546+ let sourceFile ← Lean.findLean sp mod
547+ let folder := sourceFile.withExtension ""
548+ if ← folder.pathExists then
549+ IO.println s! "Searching directory { folder} for .lean files"
550+ let leanModulesInFolder ← walkDir sp folder mod
551+ pure leanModulesInFolder
552+ else
553+ pure #[]
554+ | .andSubmodules mod =>
555+ let sourceFile ← Lean.findLean sp mod
556+ let folder := sourceFile.withExtension ""
557+ if ← folder.pathExists then
558+ IO.println s! "Searching directory { folder} for .lean files"
559+ let leanModulesInFolder ← walkDir sp folder mod
560+ pure <| #[(mod, sourceFile)] ++ leanModulesInFolder
561+ else
562+ pure #[]
563+ if !modules.isEmpty then
564+ return .ok modules
548565 else
549- return .error s! "Invalid argument: non-existing module { mod} "
566+ return .error s! "Invalid argument: { argₛ} "
567+
568+ where
569+ /--
570+ Search all `.lean` files inside `folder`.
571+
572+ In order to figure out the module name corresponding
573+ to the found files, we use `mod` and the search path `sp` to figure out how much of
574+ the relative path needs to be trimmed.
575+
576+ This assumes the `folder` exists.
577+ -/
578+ walkDir (sp : SearchPath) (folder : FilePath) (mod : Name) : IO <| Array (Name × FilePath) := do
579+ -- The source direcory where `mod` is located
580+ let srcDir ← getSrcDir sp mod
581+ -- find all Lean files in the folder only skipping special entries such as `.` and `..`
582+ let files ← folder.walkDir (pure ·.fileName.isSome)
583+ let leanFiles := files.filter (·.extension == some "lean" )
584+ let mut leanModulesInFolder : Array (Name × FilePath) := #[]
585+ for file in leanFiles do
586+ let path := file.withoutParent srcDir
587+ let mod : Name := path.withExtension "" |>.components.foldl .str .anonymous
588+ leanModulesInFolder := leanModulesInFolder.push (mod, file)
589+ pure leanModulesInFolder
550590
551591/--
552592Parse command line arguments.
0 commit comments